avro-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From blachn...@apache.org
Subject [avro] branch branch-1.9 updated: AVRO-2496: Report JSON path for schema and protocol parsing exceptions in C# bindings (#600)
Date Sat, 10 Aug 2019 17:24:01 GMT
This is an automated email from the ASF dual-hosted git repository.

blachniet pushed a commit to branch branch-1.9
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/branch-1.9 by this push:
     new 820d86f  AVRO-2496: Report JSON path for schema and protocol parsing exceptions in
C# bindings (#600)
820d86f is described below

commit 820d86f4a252783ddf2a49a109165309ade11a1e
Author: pa009fa <34035378+pa009fa@users.noreply.github.com>
AuthorDate: Sat Aug 10 10:18:27 2019 -0700

    AVRO-2496: Report JSON path for schema and protocol parsing exceptions in C# bindings
(#600)
    
    (cherry picked commit from 1b96b5bdf7d361bd25e1c2ef1697f0bc1d4a6e9d)
---
 lang/csharp/src/apache/codegen/Avro.codegen.csproj |   1 -
 lang/csharp/src/apache/main/Avro.main.csproj       |   4 +-
 lang/csharp/src/apache/main/Protocol/Message.cs    |  12 ++-
 lang/csharp/src/apache/main/Protocol/Protocol.cs   |   3 +-
 lang/csharp/src/apache/main/Schema/ArraySchema.cs  |   6 +-
 lang/csharp/src/apache/main/Schema/EnumSchema.cs   |  15 ++-
 lang/csharp/src/apache/main/Schema/Field.cs        |   4 +-
 lang/csharp/src/apache/main/Schema/FixedSchema.cs  |  12 ++-
 lang/csharp/src/apache/main/Schema/JsonHelper.cs   |  27 ++----
 lang/csharp/src/apache/main/Schema/MapSchema.cs    |  12 ++-
 lang/csharp/src/apache/main/Schema/NamedSchema.cs  |   4 +-
 lang/csharp/src/apache/main/Schema/RecordSchema.cs |  36 ++++---
 lang/csharp/src/apache/main/Schema/Schema.cs       |  14 +--
 .../src/apache/main/Schema/SchemaParseException.cs |  12 +++
 lang/csharp/src/apache/main/Schema/UnionSchema.cs  |   5 +-
 .../test/Protocol/ProtocolParseExceptionTest.cs    | 108 +++++++++++++++++++++
 16 files changed, 211 insertions(+), 64 deletions(-)

diff --git a/lang/csharp/src/apache/codegen/Avro.codegen.csproj b/lang/csharp/src/apache/codegen/Avro.codegen.csproj
index de7fd51..80329cc 100644
--- a/lang/csharp/src/apache/codegen/Avro.codegen.csproj
+++ b/lang/csharp/src/apache/codegen/Avro.codegen.csproj
@@ -54,4 +54,3 @@
   </ItemGroup>
 
 </Project>
-
diff --git a/lang/csharp/src/apache/main/Avro.main.csproj b/lang/csharp/src/apache/main/Avro.main.csproj
index 4742385..2dd06eb 100644
--- a/lang/csharp/src/apache/main/Avro.main.csproj
+++ b/lang/csharp/src/apache/main/Avro.main.csproj
@@ -47,9 +47,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Newtonsoft.Json" Version="3.5.8">
-      <NoWarn>NU1701</NoWarn>
-    </PackageReference>
+    <PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
     <PackageReference Include="System.CodeDom" Version="4.4.0" />
     <PackageReference Include="System.Reflection" Version="4.3.0" />
     <PackageReference Include="System.Reflection.Emit.ILGeneration" Version="4.3.0" />
diff --git a/lang/csharp/src/apache/main/Protocol/Message.cs b/lang/csharp/src/apache/main/Protocol/Message.cs
index 49b53f8..9df50ec 100644
--- a/lang/csharp/src/apache/main/Protocol/Message.cs
+++ b/lang/csharp/src/apache/main/Protocol/Message.cs
@@ -126,12 +126,18 @@ namespace Avro
             {
                 Schema errorSchema = Schema.ParseJson(jerrors, names, encspace);
                 if (!(errorSchema is UnionSchema))
-                    throw new AvroException("");
+                    throw new AvroException($"Not a UnionSchema at {jerrors.Path}");
 
                 uerrorSchema = errorSchema as UnionSchema;
             }
-
-            return new Message(name, doc, schema, response, uerrorSchema, oneway);
+            try
+            {
+                return new Message(name, doc, schema, response, uerrorSchema, oneway);
+            }
+            catch (Exception e)
+            {
+                throw new ProtocolParseException($"Error creating Message at {jmessage.Path}",
e);
+            }
         }
 
         /// <summary>
diff --git a/lang/csharp/src/apache/main/Protocol/Protocol.cs b/lang/csharp/src/apache/main/Protocol/Protocol.cs
index 8845c1a..94fa51c 100644
--- a/lang/csharp/src/apache/main/Protocol/Protocol.cs
+++ b/lang/csharp/src/apache/main/Protocol/Protocol.cs
@@ -113,7 +113,7 @@ namespace Avro
             }
             catch (Exception ex)
             {
-                throw new ProtocolParseException("Invalid JSON format: " + jstring, ex);
+                throw new ProtocolParseException($"Invalid JSON format: {jstring} at '{jtok.Path}'",
ex);
             }
             return Parse(jtok);
         }
@@ -152,7 +152,6 @@ namespace Avro
                     messages.Add(message.Name, message);
                 }
             }
-
             return new Protocol(name, space, doc, types, messages);
         }
 
diff --git a/lang/csharp/src/apache/main/Schema/ArraySchema.cs b/lang/csharp/src/apache/main/Schema/ArraySchema.cs
index ea8dc7a..0976ed7 100644
--- a/lang/csharp/src/apache/main/Schema/ArraySchema.cs
+++ b/lang/csharp/src/apache/main/Schema/ArraySchema.cs
@@ -42,9 +42,9 @@ namespace Avro
         internal static ArraySchema NewInstance(JToken jtok, PropertyMap props, SchemaNames
names, string encspace)
         {
             JToken jitem = jtok["items"];
-            if (null == jitem) throw new AvroTypeException("Array does not have 'items'");
-
-            return new ArraySchema(Schema.ParseJson(jitem, names, encspace), props);
+            if (null == jitem) throw new AvroTypeException($"Array does not have 'items'
at '{jtok.Path}'");
+            var schema = Schema.ParseJson(jitem, names, encspace);
+            return new ArraySchema(schema, props);
         }
 
         /// <summary>
diff --git a/lang/csharp/src/apache/main/Schema/EnumSchema.cs b/lang/csharp/src/apache/main/Schema/EnumSchema.cs
index 5a4f5c8..4344e41 100644
--- a/lang/csharp/src/apache/main/Schema/EnumSchema.cs
+++ b/lang/csharp/src/apache/main/Schema/EnumSchema.cs
@@ -57,7 +57,7 @@ namespace Avro
 
             JArray jsymbols = jtok["symbols"] as JArray;
             if (null == jsymbols)
-                throw new SchemaParseException("Enum has no symbols: " + name);
+                throw new SchemaParseException($"Enum has no symbols: {name} at '{jtok.Path}'");
 
             List<string> symbols = new List<string>();
             IDictionary<string, int> symbolMap = new Dictionary<string, int>();
@@ -66,13 +66,20 @@ namespace Avro
             {
                 string s = (string)jsymbol.Value;
                 if (symbolMap.ContainsKey(s))
-                    throw new SchemaParseException("Duplicate symbol: " + s);
+                    throw new SchemaParseException($"Duplicate symbol: {s} at '{jtok.Path}'");
 
                 symbolMap[s] = i++;
                 symbols.Add(s);
             }
-            return new EnumSchema(name, aliases, symbols, symbolMap, props, names,
-                JsonHelper.GetOptionalString(jtok, "doc"));
+            try
+            {
+                return new EnumSchema(name, aliases, symbols, symbolMap, props, names,
+                    JsonHelper.GetOptionalString(jtok, "doc"));
+            }
+            catch (SchemaParseException e)
+            {
+                throw new SchemaParseException($"{e.Message} at '{jtok.Path}'", e);
+            }
         }
 
         /// <summary>
diff --git a/lang/csharp/src/apache/main/Schema/Field.cs b/lang/csharp/src/apache/main/Schema/Field.cs
index e83ee7c..1a441c8 100644
--- a/lang/csharp/src/apache/main/Schema/Field.cs
+++ b/lang/csharp/src/apache/main/Schema/Field.cs
@@ -178,13 +178,13 @@ namespace Avro
                 return null;
 
             if (jaliases.Type != JTokenType.Array)
-                throw new SchemaParseException("Aliases must be of format JSON array of strings");
+                throw new SchemaParseException($"Aliases must be of format JSON array of
strings at '{jtok.Path}'");
 
             var aliases = new List<string>();
             foreach (JToken jalias in jaliases)
             {
                 if (jalias.Type != JTokenType.String)
-                    throw new SchemaParseException("Aliases must be of format JSON array
of strings");
+                    throw new SchemaParseException($"Aliases must be of format JSON array
of strings at '{jtok.Path}'");
 
                 aliases.Add((string)jalias);
             }
diff --git a/lang/csharp/src/apache/main/Schema/FixedSchema.cs b/lang/csharp/src/apache/main/Schema/FixedSchema.cs
index cc10e3b..098e32c 100644
--- a/lang/csharp/src/apache/main/Schema/FixedSchema.cs
+++ b/lang/csharp/src/apache/main/Schema/FixedSchema.cs
@@ -44,9 +44,15 @@ namespace Avro
         {
             SchemaName name = NamedSchema.GetName(jtok, encspace);
             var aliases = NamedSchema.GetAliases(jtok, name.Space, name.EncSpace);
-
-            return new FixedSchema(name, aliases, JsonHelper.GetRequiredInteger(jtok, "size"),
props, names,
-                JsonHelper.GetOptionalString(jtok, "doc"));
+            try
+            {
+                return new FixedSchema(name, aliases, JsonHelper.GetRequiredInteger(jtok,
"size"), props, names,
+                    JsonHelper.GetOptionalString(jtok, "doc"));
+            }
+            catch (Exception e)
+            {
+                throw new SchemaParseException($"{e.Message} at '{jtok.Path}'", e);
+            }
         }
 
         /// <summary>
diff --git a/lang/csharp/src/apache/main/Schema/JsonHelper.cs b/lang/csharp/src/apache/main/Schema/JsonHelper.cs
index a606f54..7cbea49 100644
--- a/lang/csharp/src/apache/main/Schema/JsonHelper.cs
+++ b/lang/csharp/src/apache/main/Schema/JsonHelper.cs
@@ -17,7 +17,7 @@
  */
 using System;
 using System.Collections.Generic;
-using System.Text;
+using System.Text.RegularExpressions;
 using Newtonsoft.Json.Linq;
 using Newtonsoft.Json;
 
@@ -35,7 +35,7 @@ namespace Avro
         public static string GetOptionalString(JToken jtok, string field)
         {
             if (null == jtok) throw new ArgumentNullException("jtok", "jtok cannot be null.");
-            if (string.IsNullOrEmpty(field)) throw new ArgumentNullException("field", "field
cannot be null.");
+            if (string.IsNullOrEmpty(field)) throw new ArgumentNullException("field", $"field
cannot be null at '{jtok.Path}'");
 
             JToken child = jtok[field];
             if (null == child) return null;
@@ -44,7 +44,7 @@ namespace Avro
             {
                 return child.Value<string>();
             }
-            throw new SchemaParseException("Field " + field + " is not a string");
+            throw new SchemaParseException($"Field {field} is not a string at '{jtok.Path}'");
         }
 
         /// <summary>
@@ -56,7 +56,7 @@ namespace Avro
         public static string GetRequiredString(JToken jtok, string field)
         {
             string value = GetOptionalString(jtok, field);
-            if (string.IsNullOrEmpty(value)) throw new SchemaParseException(string.Format("No
\"{0}\" JSON field: {1}", field, jtok));
+            if (string.IsNullOrEmpty(value)) throw new SchemaParseException($"No \"{field}\"
JSON field: {Regex.Replace(jtok.ToString(), @"\r\n?|\n", "")} at '{jtok.Path}'");
             return value;
         }
 
@@ -68,12 +68,13 @@ namespace Avro
         /// <returns>property value</returns>
         public static int GetRequiredInteger(JToken jtok, string field)
         {
-            ensureValidFieldName(field);
+            if (string.IsNullOrEmpty(field)) throw new ArgumentNullException(nameof(field));
+
             JToken child = jtok[field];
-            if (null == child) throw new SchemaParseException(string.Format("No \"{0}\" JSON
field: {1}", field, jtok));
+            if (null == child) throw new SchemaParseException($"No \"{field}\" JSON field:
{Regex.Replace(jtok.ToString(), @"\r\n?|\n", "")} at '{jtok.Path}'");
 
             if (child.Type == JTokenType.Integer) return (int) child;
-            throw new SchemaParseException("Field " + field + " is not an integer");
+            throw new SchemaParseException($"Field {field} is not an integer at '{jtok.Path}'");
         }
 
         /// <summary>
@@ -85,7 +86,7 @@ namespace Avro
         public static bool? GetOptionalBoolean(JToken jtok, string field)
         {
             if (null == jtok) throw new ArgumentNullException("jtok", "jtok cannot be null.");
-            if (string.IsNullOrEmpty(field)) throw new ArgumentNullException("field", "field
cannot be null.");
+            if (string.IsNullOrEmpty(field)) throw new ArgumentNullException("field", $"field
cannot be null at '{jtok.Path}'");
 
             JToken child = jtok[field];
             if (null == child) return null;
@@ -93,7 +94,7 @@ namespace Avro
             if (child.Type == JTokenType.Boolean)
                 return (bool)child;
 
-            throw new SchemaParseException("Field " + field + " is not a boolean");
+            throw new SchemaParseException($"Field {field} is not a boolean at '{jtok.Path}'");
         }
 
         /// <summary>
@@ -109,13 +110,5 @@ namespace Avro
             writer.WriteValue(value);
         }
 
-        /// <summary>
-        /// Checks if given name is not null or empty
-        /// </summary>
-        /// <param name="name"></param>
-        private static void ensureValidFieldName(string name)
-        {
-            if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("name");
-        }
     }
 }
diff --git a/lang/csharp/src/apache/main/Schema/MapSchema.cs b/lang/csharp/src/apache/main/Schema/MapSchema.cs
index 4da82c2..e50b04e 100644
--- a/lang/csharp/src/apache/main/Schema/MapSchema.cs
+++ b/lang/csharp/src/apache/main/Schema/MapSchema.cs
@@ -53,9 +53,15 @@ namespace Avro
         internal static MapSchema NewInstance(JToken jtok, PropertyMap props, SchemaNames
names, string encspace)
         {
             JToken jvalue = jtok["values"];
-            if (null == jvalue) throw new AvroTypeException("Map does not have 'values'");
-
-            return new MapSchema(Schema.ParseJson(jvalue, names, encspace), props);
+            if (null == jvalue) throw new AvroTypeException($"Map does not have 'values'
at '{jtok.Path}'");
+            try
+            {
+                return new MapSchema(ParseJson(jvalue, names, encspace), props);
+            }
+            catch (Exception e)
+            {
+                throw new SchemaParseException($"Error creating MapSchema at '{jtok.Path}'",
e);
+            }
         }
 
         /// <summary>
diff --git a/lang/csharp/src/apache/main/Schema/NamedSchema.cs b/lang/csharp/src/apache/main/Schema/NamedSchema.cs
index 2c73210..ca54440 100644
--- a/lang/csharp/src/apache/main/Schema/NamedSchema.cs
+++ b/lang/csharp/src/apache/main/Schema/NamedSchema.cs
@@ -145,13 +145,13 @@ namespace Avro
                 return null;
 
             if (jaliases.Type != JTokenType.Array)
-                throw new SchemaParseException("Aliases must be of format JSON array of strings");
+                throw new SchemaParseException($"Aliases must be of format JSON array of
strings at '{jtok.Path}'");
 
             var aliases = new List<SchemaName>();
             foreach (JToken jalias in jaliases)
             {
                 if (jalias.Type != JTokenType.String)
-                    throw new SchemaParseException("Aliases must be of format JSON array
of strings");
+                    throw new SchemaParseException($"Aliases must be of format JSON array
of strings at '{jtok.Path}'");
 
                 aliases.Add(new SchemaName((string)jalias, space, encspace));
             }
diff --git a/lang/csharp/src/apache/main/Schema/RecordSchema.cs b/lang/csharp/src/apache/main/Schema/RecordSchema.cs
index b451d3a..a089f05 100644
--- a/lang/csharp/src/apache/main/Schema/RecordSchema.cs
+++ b/lang/csharp/src/apache/main/Schema/RecordSchema.cs
@@ -65,17 +65,25 @@ namespace Avro
                 if (null != jfields) request = true;
             }
             if (null == jfields)
-                throw new SchemaParseException("'fields' cannot be null for record");
+                throw new SchemaParseException($"'fields' cannot be null for record at '{jtok.Path}'");
             if (jfields.Type != JTokenType.Array)
-                throw new SchemaParseException("'fields' not an array for record");
+                throw new SchemaParseException($"'fields' not an array for record at '{jtok.Path}'");
 
             var name = GetName(jtok, encspace);
             var aliases = NamedSchema.GetAliases(jtok, name.Space, name.EncSpace);
             var fields = new List<Field>();
             var fieldMap = new Dictionary<string, Field>();
             var fieldAliasMap = new Dictionary<string, Field>();
-            var result = new RecordSchema(type, name, aliases, props, fields, request, fieldMap,
fieldAliasMap, names,
-                JsonHelper.GetOptionalString(jtok, "doc"));
+            RecordSchema result;
+            try
+            {
+                result = new RecordSchema(type, name, aliases, props, fields, request, fieldMap,
fieldAliasMap, names,
+                    JsonHelper.GetOptionalString(jtok, "doc"));
+            }
+            catch (SchemaParseException e)
+            {
+                throw new SchemaParseException($"{e.Message} at '{jtok.Path}'", e);
+            }
 
             int fieldPos = 0;
             foreach (JObject jfield in jfields)
@@ -83,12 +91,19 @@ namespace Avro
                 string fieldName = JsonHelper.GetRequiredString(jfield, "name");
                 Field field = createField(jfield, fieldPos++, names, name.Namespace);  //
add record namespace for field look up
                 fields.Add(field);
-                addToFieldMap(fieldMap, fieldName, field);
-                addToFieldMap(fieldAliasMap, fieldName, field);
+                try
+                {
+                    addToFieldMap(fieldMap, fieldName, field);
+                    addToFieldMap(fieldAliasMap, fieldName, field);
 
-                if (null != field.aliases)    // add aliases to field lookup map so reader
function will find it when writer field name appears only as an alias on the reader field
-                    foreach (string alias in field.aliases)
-                        addToFieldMap(fieldAliasMap, alias, field);
+                    if (null != field.aliases)    // add aliases to field lookup map so reader
function will find it when writer field name appears only as an alias on the reader field
+                        foreach (string alias in field.aliases)
+                            addToFieldMap(fieldAliasMap, alias, field);
+                }
+                catch (SchemaParseException e)
+                {
+                    throw new SchemaParseException($"{e.Message} at '{jfield.Path}'", e);
+                }
             }
             return result;
         }
@@ -142,9 +157,8 @@ namespace Avro
 
             JToken jtype = jfield["type"];
             if (null == jtype)
-                throw new SchemaParseException("'type' was not found for field: " + name);
+                throw new SchemaParseException($"'type' was not found for field: name at
'{jfield.Path}'");
             var schema = Schema.ParseJson(jtype, names, encspace);
-
             return new Field(schema, name, aliases, pos, doc, defaultValue, sortorder, props);
         }
 
diff --git a/lang/csharp/src/apache/main/Schema/Schema.cs b/lang/csharp/src/apache/main/Schema/Schema.cs
index 9f4fcb8..9e5ac3c 100644
--- a/lang/csharp/src/apache/main/Schema/Schema.cs
+++ b/lang/csharp/src/apache/main/Schema/Schema.cs
@@ -131,19 +131,19 @@ namespace Avro
         }
 
         /// <summary>
-        /// If this is a record, enum or fixed, returns its name, otherwise the name the
primitive type. 
+        /// If this is a record, enum or fixed, returns its name, otherwise the name the
primitive type.
         /// </summary>
         public abstract string Name { get; }
-        
+
         /// <summary>
         /// The name of this schema. If this is a named schema such as an enum, it returns
the fully qualified
         /// name for the schema. For other schemas, it returns the type of the schema.
         /// </summary>
-        public virtual string Fullname 
+        public virtual string Fullname
         {
             get { return Name; }
         }
-        
+
         /// <summary>
         /// Static class to return new instance of schema object
         /// </summary>
@@ -165,7 +165,7 @@ namespace Avro
                 NamedSchema schema = null;
                 if (names.TryGetValue(value, null, encspace, out schema)) return schema;
 
-                throw new SchemaParseException("Undefined name: " + value);
+                throw new SchemaParseException($"Undefined name: {value} at '{jtok.Path}'");
             }
 
             if (jtok is JArray) // union schema with no 'type' property or union type for
a record field
@@ -177,7 +177,7 @@ namespace Avro
 
                 JToken jtype = jo["type"];
                 if (null == jtype)
-                    throw new SchemaParseException("Property type is required");
+                    throw new SchemaParseException($"Property type is required at '{jtok.Path}'");
 
                 var props = Schema.GetProperties(jtok);
 
@@ -198,7 +198,7 @@ namespace Avro
                 else if (jtype.Type == JTokenType.Array)
                     return UnionSchema.NewInstance(jtype as JArray, props, names, encspace);
             }
-            throw new AvroTypeException("Invalid JSON for schema: " + jtok);
+            throw new AvroTypeException($"Invalid JSON for schema: {jtok} at '{jtok.Path}'");
         }
 
         /// <summary>
diff --git a/lang/csharp/src/apache/main/Schema/SchemaParseException.cs b/lang/csharp/src/apache/main/Schema/SchemaParseException.cs
index 987b2e2..4a6be90 100644
--- a/lang/csharp/src/apache/main/Schema/SchemaParseException.cs
+++ b/lang/csharp/src/apache/main/Schema/SchemaParseException.cs
@@ -16,6 +16,8 @@
  * limitations under the License.
  */
 
+using System;
+
 namespace Avro
 {
     /// <summary>
@@ -31,5 +33,15 @@ namespace Avro
             : base(s)
         {
         }
+        /// <summary>
+        /// Exception while parsing
+        /// </summary>
+        /// <param name="s">Message</param>
+        /// <param name="inner">Inner Exception</param>
+        public SchemaParseException(string s, Exception inner)
+            : base(s, inner)
+        {
+        }
+
     }
 }
diff --git a/lang/csharp/src/apache/main/Schema/UnionSchema.cs b/lang/csharp/src/apache/main/Schema/UnionSchema.cs
index 3bdc8ea..e3a0fe1 100644
--- a/lang/csharp/src/apache/main/Schema/UnionSchema.cs
+++ b/lang/csharp/src/apache/main/Schema/UnionSchema.cs
@@ -55,16 +55,15 @@ namespace Avro
             {
                 Schema unionType = Schema.ParseJson(jvalue, names, encspace);
                 if (null == unionType)
-                    throw new SchemaParseException("Invalid JSON in union" + jvalue.ToString());
+                    throw new SchemaParseException($"Invalid JSON in union {jvalue.ToString()}
at '{jvalue.Path}'");
 
                 string name = unionType.Fullname;
                 if (uniqueSchemas.ContainsKey(name))
-                    throw new SchemaParseException("Duplicate type in union: " + name);
+                    throw new SchemaParseException($"Duplicate type in union: {name} at '{jvalue.Path}'");
 
                 uniqueSchemas.Add(name, name);
                 schemas.Add(unionType);
             }
-
             return new UnionSchema(schemas, props);
         }
 
diff --git a/lang/csharp/src/apache/test/Protocol/ProtocolParseExceptionTest.cs b/lang/csharp/src/apache/test/Protocol/ProtocolParseExceptionTest.cs
new file mode 100644
index 0000000..d0d4bdd
--- /dev/null
+++ b/lang/csharp/src/apache/test/Protocol/ProtocolParseExceptionTest.cs
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using NUnit.Framework;
+
+namespace Avro.Test
+{
+    [TestFixture]
+    public class ProtocolParseExceptionTest
+    {
+        [TestCase]
+        public void TestProtocolParseExceptions()
+        {
+            var protocol = @"{
+                ""protocol"": ""TestProtocol"",
+                ""types"": [
+                    {""name"": ""Greeting"", ""XXX"": ""record"", ""fields"":
+                    [
+                        {""name"": ""message"", ""type"": ""string""}
+                    ]}
+                ]}";
+            SchemaParseException ex = Assert.Throws<SchemaParseException>(()=>Protocol.Parse(protocol)
);
+            Assert.That( ex.Message, Is.EqualTo( "Property type is required at 'types[0]'"
) );
+
+            protocol = @"{
+                ""protocol"": ""TestProtocol"",
+                ""types"": [
+                    {""name"": ""Greeting"", ""type"": ""record"", ""fields"":
+                    [
+                        {""name"": ""message"", ""XXX"": ""string""}
+                    ]}
+                ]}";
+            ex = Assert.Throws<SchemaParseException>(()=>Protocol.Parse(protocol)
);
+            Assert.That( ex.Message, Is.EqualTo( "'type' was not found for field: name at
'types[0].fields[0]'" ) );
+
+            protocol = @"{
+                ""protocol"": ""TestProtocol"",
+                ""types"": [
+                    {""name"": ""Greeting"", ""type"": ""record"", ""fields"":
+                    [
+                        {""name"": """", ""type"": ""string""}
+                    ]}
+                ]}";
+            ex = Assert.Throws<SchemaParseException>(()=>Protocol.Parse(protocol)
);
+            Assert.That( ex.Message, Is.EqualTo( "No \"name\" JSON field: {  \"name\": \"\",
 \"type\": \"string\"} at 'types[0].fields[0]'" ) );
+
+            protocol = @"{
+                ""protocol"": ""TestProtocol"",
+                ""types"": [
+                    {""name"": ""Greeting"", ""type"": ""record"", ""fields"":
+                    [
+                        {""name"": ""message"", ""type"": ""string"", ""aliases"": ""not
a list"" }
+                    ]}
+                ]}";
+            ex = Assert.Throws<SchemaParseException>(()=>Protocol.Parse(protocol)
);
+            Assert.That( ex.Message, Is.EqualTo( "Aliases must be of format JSON array of
strings at 'types[0].fields[0]'" ) );
+
+            protocol = @"{
+                ""protocol"": ""TestProtocol"",
+                ""types"": [
+                    {""name"": 234, ""type"": ""record"", ""fields"":
+                    [
+                        {""name"": ""message"", ""type"": ""string"" }
+                    ]}
+                ]}";
+            ex = Assert.Throws<SchemaParseException>(()=>Protocol.Parse(protocol)
);
+            Assert.That( ex.Message, Is.EqualTo( "Field name is not a string at 'types[0]'"
) );
+
+            protocol = @"{
+                ""protocol"": ""TestProtocol"",
+                ""types"": [
+                    {""name"": ""Greeting"", ""type"": ""record"", ""fields"":
+                    [
+                        {""name"": 123, ""type"": ""string"" }
+                    ]}
+                ]}";
+            ex = Assert.Throws<SchemaParseException>(()=>Protocol.Parse(protocol)
);
+            Assert.That( ex.Message, Is.EqualTo( "Field name is not a string at 'types[0].fields[0]'"
) );
+
+            protocol = @"{
+                ""protocol"": ""TestProtocol"",
+                ""types"": [
+                    {""name"": ""Greeting"", ""type"": ""record"", ""fields"":
+                    [
+                        {""name"": ""message"", ""type"": ""abc"" }
+                    ]}
+                ]}";
+            ex = Assert.Throws<SchemaParseException>(()=>Protocol.Parse(protocol)
);
+            Assert.That( ex.Message, Is.EqualTo( "Undefined name: abc at 'types[0].fields[0].type'"
) );
+
+        }
+    }
+}


Mime
View raw message