You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by cu...@apache.org on 2011/03/31 23:16:49 UTC
svn commit: r1087439 [5/6] - in /avro/trunk: ./ lang/csharp/
lang/csharp/lib/ lang/csharp/lib/main/ lang/csharp/lib/test/
lang/csharp/src/ lang/csharp/src/apache/ lang/csharp/src/apache/codegen/
lang/csharp/src/apache/codegen/Properties/ lang/csharp/sr...
Added: avro/trunk/lang/csharp/src/apache/main/Specific/SpecificWriter.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Specific/SpecificWriter.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Specific/SpecificWriter.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Specific/SpecificWriter.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,212 @@
+/**
+ * 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
+ *
+ * http://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 System;
+using System.Collections.Generic;
+using System.Linq;
+using Avro;
+using Avro.IO;
+using Avro.Generic;
+
+namespace Avro.Specific
+{
+ /// <summary>
+ /// Generic wrapper class for writing data from specific objects
+ /// </summary>
+ /// <typeparam name="T">type name of specific object</typeparam>
+ public class SpecificWriter<T> : GenericWriter<T>
+ {
+ public SpecificWriter(Schema schema) : base(new SpecificDefaultWriter(schema)) { }
+ }
+
+ /// <summary>
+ /// Class for writing data from any specific objects
+ /// </summary>
+ public class SpecificDefaultWriter : DefaultWriter
+ {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="schema">schema of the object to be written</param>
+ public SpecificDefaultWriter(Schema schema) : base(schema) { }
+
+ /// <summary>
+ /// Serialized a record using the given RecordSchema. It uses GetField method
+ /// to extract the field value from the given object.
+ /// </summary>
+ /// <param name="schema">The RecordSchema to use for serialization</param>
+ /// <param name="value">The value to be serialized</param>
+ /// <param name="encoder">The Encoder for serialization</param>
+
+ protected override void WriteRecord(RecordSchema schema, object value, Encoder encoder)
+ {
+ var rec = value as SpecificRecord;
+ if (rec == null)
+ throw new AvroTypeException("Record object is not derived from SpecificRecord");
+
+ foreach (Field field in schema)
+ {
+ try
+ {
+ Write(field.Schema, rec.Get(field.Pos), encoder);
+ }
+ catch (Exception ex)
+ {
+ throw new AvroException(ex.Message + " in field " + field.Name);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Validates that the record is a fixed record object and that the schema in the object is the
+ /// same as the given writer schema. Writes the given fixed record into the given encoder
+ /// </summary>
+ /// <param name="schema">writer schema</param>
+ /// <param name="value">fixed object to write</param>
+ /// <param name="encoder">encoder to write to</param>
+ protected override void WriteFixed(FixedSchema schema, object value, Encoder encoder)
+ {
+ var fixedrec = value as SpecificFixed;
+ if (fixedrec == null)
+ throw new AvroTypeException("Fixed object is not derived from SpecificFixed");
+
+ encoder.WriteFixed(fixedrec.Value);
+ }
+
+ /// <summary>
+ /// Writes the given enum value into the given encoder.
+ /// </summary>
+ /// <param name="schema">writer schema</param>
+ /// <param name="value">enum value</param>
+ /// <param name="encoder">encoder to write to</param>
+ protected override void WriteEnum(EnumSchema schema, object value, Encoder encoder)
+ {
+ if (value == null)
+ throw new AvroTypeException("value is null in SpecificDefaultWriter.WriteEnum");
+
+ encoder.WriteEnum(schema.Ordinal(value.ToString()));
+ }
+
+ /// <summary>
+ /// Serialized an array. The default implementation calls EnsureArrayObject() to ascertain that the
+ /// given value is an array. It then calls GetArrayLength() and GetArrayElement()
+ /// to access the members of the array and then serialize them.
+ /// </summary>
+ /// <param name="schema">The ArraySchema for serialization</param>
+ /// <param name="value">The value being serialized</param>
+ /// <param name="encoder">The encoder for serialization</param>
+ protected override void WriteArray(ArraySchema schema, object value, Encoder encoder)
+ {
+ var arr = value as System.Collections.IList;
+ if (arr == null)
+ throw new AvroTypeException("Array does not implement non-generic IList");
+
+ long l = arr.Count;
+ encoder.WriteArrayStart();
+ encoder.SetItemCount(l);
+ for (int i = 0; i < l; i++)
+ {
+ encoder.StartItem();
+ Write(schema.ItemSchema, arr[i], encoder);
+ }
+ encoder.WriteArrayEnd();
+ }
+
+ /// <summary>
+ /// Writes the given map into the given encoder.
+ /// </summary>
+ /// <param name="schema">writer schema</param>
+ /// <param name="value">map to write</param>
+ /// <param name="encoder">encoder to write to</param>
+ protected override void WriteMap(MapSchema schema, object value, Encoder encoder)
+ {
+ var map = value as System.Collections.IDictionary;
+ if (map == null)
+ throw new AvroTypeException("Map does not implement non-generic IDictionary");
+
+ encoder.WriteArrayStart();
+ encoder.SetItemCount(map.Count);
+ foreach (System.Collections.DictionaryEntry de in map)
+ {
+ encoder.StartItem();
+ encoder.WriteString(de.Key as string);
+ Write(schema.ValueSchema, de.Value, encoder);
+ }
+ encoder.WriteMapEnd();
+ }
+
+ /// <summary>
+ /// Resolves the given value against the given UnionSchema and serializes the object against
+ /// the resolved schema member. The default implementation of this method uses
+ /// ResolveUnion to find the member schema within the UnionSchema.
+ /// </summary>
+ /// <param name="us">The UnionSchema to resolve against</param>
+ /// <param name="value">The value to be serialized</param>
+ /// <param name="encoder">The encoder for serialization</param>
+ protected override void WriteUnion(UnionSchema us, object value, Encoder encoder)
+ {
+ for (int i = 0; i < us.Count; i++)
+ {
+ if (Matches(us[i], value))
+ {
+ encoder.WriteUnionIndex(i);
+ Write(us[i], value, encoder);
+ return;
+ }
+ }
+ throw new AvroException("Cannot find a match for " + value.GetType() + " in " + us);
+ }
+
+ protected override bool Matches(Schema sc, object obj)
+ {
+ if (obj == null && sc.Tag != Avro.Schema.Type.Null) return false;
+ switch (sc.Tag)
+ {
+ case Schema.Type.Null:
+ return obj == null;
+ case Schema.Type.Boolean:
+ return obj is bool;
+ case Schema.Type.Int:
+ return obj is int;
+ case Schema.Type.Long:
+ return obj is long;
+ case Schema.Type.Float:
+ return obj is float;
+ case Schema.Type.Double:
+ return obj is double;
+ case Schema.Type.Bytes:
+ return obj is byte[];
+ case Schema.Type.String:
+ return obj is string;
+ case Schema.Type.Record:
+ return obj is SpecificRecord && (obj as SpecificRecord).Schema.Name.Equals(sc.Name);
+ case Schema.Type.Enumeration:
+ return obj.GetType().IsEnum && (sc as EnumSchema).Symbols.Contains(obj.ToString());
+ case Schema.Type.Array:
+ return obj is System.Collections.IList;
+ case Schema.Type.Map:
+ return obj is System.Collections.IDictionary;
+ case Schema.Type.Union:
+ return false; // Union directly within another union not allowed!
+ case Schema.Type.Fixed:
+ return obj is SpecificFixed && (obj as SpecificFixed).Schema.Name.Equals(sc.Name);
+ default:
+ throw new AvroException("Unknown schema type: " + sc.Tag);
+ }
+ }
+ }
+}
Added: avro/trunk/lang/csharp/src/apache/test/Avro.test.csproj
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/test/Avro.test.csproj?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/test/Avro.test.csproj (added)
+++ avro/trunk/lang/csharp/src/apache/test/Avro.test.csproj Thu Mar 31 21:16:28 2011
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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
+
+ http://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.
+-->
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{911D56AB-587B-4E5F-B5EA-D47D8A46F1FA}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Avro.test</RootNamespace>
+ <AssemblyName>Avro.test</AssemblyName>
+ <TargetFrameworkVersion Condition=" '$(TargetFrameworkVersion)' == '' ">v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\build\test\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\..\build\test\Release\</OutputPath>
+ <DefineConstants>
+ </DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="nunit.framework, Version=2.5.7.10213, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\lib\test\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="CodGen\CodeGenTest.cs" />
+ <Compile Include="Generic\GenericTests.cs" />
+ <Compile Include="IO\BinaryCodecTests.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Protocol\ProtocolTest.cs" />
+ <Compile Include="Schema\AliasTest.cs" />
+ <Compile Include="Schema\SchemaTests.cs" />
+ <Compile Include="Specific\SpecificTests.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\main\Avro.main.csproj">
+ <Project>{A0A5CA3C-F58C-4D07-98B0-2C7B62AB20F0}</Project>
+ <Name>Avro.main</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include=".NETFramework,Version=v3.5">
+ <Visible>False</Visible>
+ <ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
Added: avro/trunk/lang/csharp/src/apache/test/CodGen/CodeGenTest.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/test/CodGen/CodeGenTest.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/test/CodGen/CodeGenTest.cs (added)
+++ avro/trunk/lang/csharp/src/apache/test/CodGen/CodeGenTest.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,122 @@
+/**
+ * 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
+ *
+ * http://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 System;
+using System.Collections.Generic;
+using System.Text;
+using System.CodeDom;
+using System.CodeDom.Compiler;
+using Microsoft.CSharp;
+using NUnit.Framework;
+using Avro;
+using Avro.Specific;
+using System.Reflection;
+
+namespace Avro.Test
+{
+ [TestFixture]
+
+ class CodeGenTest
+ {
+ [TestCase(@"{
+""type"" : ""record"",
+""name"" : ""ClassKeywords"",
+""namespace"" : ""com.base"",
+""fields"" :
+ [
+ { ""name"" : ""int"", ""type"" : ""int"" },
+ { ""name"" : ""base"", ""type"" : ""long"" },
+ { ""name"" : ""event"", ""type"" : ""boolean"" },
+ { ""name"" : ""foreach"", ""type"" : ""double"" },
+ { ""name"" : ""bool"", ""type"" : ""float"" },
+ { ""name"" : ""internal"", ""type"" : ""bytes"" },
+ { ""name"" : ""while"", ""type"" : ""string"" },
+ { ""name"" : ""return"", ""type"" : ""null"" },
+ { ""name"" : ""enum"", ""type"" : { ""type"" : ""enum"", ""name"" : ""class"", ""symbols"" : [ ""A"", ""B"" ] } },
+ { ""name"" : ""string"", ""type"" : { ""type"": ""fixed"", ""size"": 16, ""name"": ""static"" } }
+ ]
+}
+", new object[] {"com.base.ClassKeywords", typeof(int), typeof(long), typeof(bool), typeof(double), typeof(float), typeof(byte[]), typeof(string),typeof(object),"com.base.class", "com.base.static"})]
+ [TestCase(@"{
+""type"" : ""record"",
+""name"" : ""SchemaObject"",
+""namespace"" : ""schematest"",
+""fields"" :
+ [
+ { ""name"" : ""myobject"", ""type"" :
+ [
+ ""null"",
+ {""type"" : ""array"", ""items"" : [ ""null"",
+ { ""type"" : ""enum"", ""name"" : ""MyEnum"", ""symbols"" : [ ""A"", ""B"" ] },
+ { ""type"": ""fixed"", ""size"": 16, ""name"": ""MyFixed"" }
+ ]
+ }
+ ]
+ }
+ ]
+}
+", new object[] { "schematest.SchemaObject", typeof(IList<object>) })]
+ public static void TestCodeGen(string str, object[] result)
+ {
+ Schema schema = Schema.Parse(str);
+
+ var codegen = new CodeGen();
+ codegen.AddSchema(schema);
+ var compileUnit = codegen.GenerateCode();
+
+ var comparam = new CompilerParameters(new string[] {"mscorlib.dll"});
+ comparam.ReferencedAssemblies.Add("System.dll");
+ comparam.ReferencedAssemblies.Add("System.Core.dll");
+ comparam.ReferencedAssemblies.Add(Type.GetType("Mono.Runtime") != null ? "Mono.CSharp.dll" : "Microsoft.CSharp.dll");
+ comparam.ReferencedAssemblies.Add("Avro.dll");
+ comparam.GenerateInMemory = true;
+ var ccp = new Microsoft.CSharp.CSharpCodeProvider();
+ var units = new CodeCompileUnit[] { compileUnit };
+ var compres = ccp.CompileAssemblyFromDom(comparam, units);
+ if (compres == null || compres.Errors.Count>0)
+ {
+ for (int i=0; i<compres.Errors.Count;i++)
+ Console.WriteLine(compres.Errors[i]);
+ }
+ if (null != compres)
+ Assert.AreEqual(0, compres.Errors.Count);
+
+ // instantiate object
+ SpecificRecord rec = compres.CompiledAssembly.CreateInstance((string)result[0]) as SpecificRecord;
+ Assert.IsNotNull(rec);
+
+ // test type of each fields
+ for (int i = 1; i < result.Length; ++i)
+ {
+ object field = rec.Get(i - 1);
+ Type stype;
+ if (result[i].GetType() == typeof(string))
+ {
+ object obj = compres.CompiledAssembly.CreateInstance((string)result[i]);
+ Assert.IsNotNull(obj);
+ stype = obj.GetType();
+ }
+ else
+ stype = (Type)result[i];
+ if (!stype.IsValueType)
+ Assert.IsNull(field); // can't test reference type, it will be null
+ else
+ Assert.AreEqual(stype, field.GetType());
+ }
+ }
+ }
+}
Added: avro/trunk/lang/csharp/src/apache/test/Generic/GenericTests.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/test/Generic/GenericTests.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/test/Generic/GenericTests.cs (added)
+++ avro/trunk/lang/csharp/src/apache/test/Generic/GenericTests.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,455 @@
+/**
+ * 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
+ *
+ * http://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 System;
+using System.IO;
+using Avro.IO;
+using System.Collections.Generic;
+using Avro.Generic;
+using NUnit.Framework;
+
+namespace Avro.Test.Generic
+{
+ class GenericTests
+ {
+ private static void test<T>(string s, T value)
+ {
+ Stream ms;
+ Schema ws;
+ serialize(s, value, out ms, out ws);
+ Schema rs = Schema.Parse(s);
+ T output = deserialize<T>(ms, ws, rs);
+ Assert.AreEqual(value, output);
+ }
+
+ [TestCase("{\"type\": \"boolean\"}", true)]
+ [TestCase("{\"type\": \"boolean\"}", false)]
+
+ // Union
+ [TestCase("[\"boolean\", \"null\"]", null)]
+ [TestCase("[\"boolean\", \"null\"]", true)]
+ [TestCase("[\"int\", \"long\"]", 100)]
+ [TestCase("[\"int\", \"long\"]", 100L)]
+ [TestCase("[\"float\", \"double\"]", 100.75)]
+ [TestCase("[\"float\", \"double\"]", 23.67f)]
+ [TestCase("[{\"type\": \"array\", \"items\": \"float\"}, \"double\"]", new float[] { 23.67f, 22.78f })]
+ [TestCase("[{\"type\": \"array\", \"items\": \"float\"}, \"double\"]", 100.89)]
+ [TestCase("[{\"type\": \"array\", \"items\": \"string\"}, \"string\"]", "a")]
+ [TestCase("[{\"type\": \"array\", \"items\": \"string\"}, \"string\"]", new string[] { "a", "b" })]
+ [TestCase("[{\"type\": \"array\", \"items\": \"bytes\"}, \"bytes\"]", new byte[] { 1, 2, 3 })]
+ [TestCase("[{\"type\": \"array\", \"items\": \"bytes\"}, \"bytes\"]",
+ new object[] { new byte[] { 1, 2 }, new byte[] { 3, 4 } })]
+ [TestCase("[{\"type\": \"enum\", \"symbols\": [\"s1\", \"s2\"], \"name\": \"e\"}, \"string\"]", "h1")]
+ public void TestPrimitive(string schema, object value)
+ {
+ test(schema, value);
+ }
+
+ [TestCase("{\"type\":\"record\", \"name\":\"n\", \"fields\":[{\"name\":\"f1\", \"type\":\"null\"}]}",
+ new object[] { "f1", null })]
+ [TestCase("{\"type\":\"record\", \"name\":\"n\", \"fields\":[{\"name\":\"f1\", \"type\":\"boolean\"}]}",
+ new object[] { "f1", true })]
+ [TestCase("{\"type\":\"record\", \"name\":\"n\", \"fields\":[{\"name\":\"f1\", \"type\":\"boolean\"}]}",
+ new object[] { "f1", false })]
+ [TestCase("{\"type\":\"record\", \"name\":\"n\", \"fields\":[{\"name\":\"f1\", \"type\":\"int\"}]}",
+ new object[] { "f1", 101 })]
+ [TestCase("{\"type\":\"record\", \"name\":\"n\", \"fields\":[{\"name\":\"f1\", \"type\":\"long\"}]}",
+ new object[] { "f1", 101L })]
+ [TestCase("{\"type\":\"record\", \"name\":\"n\", \"fields\":[{\"name\":\"f1\", \"type\":\"float\"}]}",
+ new object[] { "f1", 101.78f })]
+ [TestCase("{\"type\":\"record\", \"name\":\"n\", \"fields\":[{\"name\":\"f1\", \"type\":\"double\"}]}",
+ new object[] { "f1", 101.78 })]
+ [TestCase("{\"type\":\"record\", \"name\":\"n\", \"fields\":[{\"name\":\"f1\", \"type\":\"string\"}]}",
+ new object[] { "f1", "A" })]
+ [TestCase("{\"type\":\"record\", \"name\":\"n\", \"fields\":[{\"name\":\"f1\", \"type\":\"bytes\"}]}",
+ new object[] { "f1", new byte[] { 0, 1 } })]
+ [TestCase("{\"type\":\"record\", \"name\":\"n\", \"fields\":" +
+ "[{\"name\":\"f1\", \"type\":{\"type\": \"enum\", \"name\": \"e\", \"symbols\":[\"s1\", \"s2\"]}}]}",
+ new object[] { "f1", "s2" })]
+ [TestCase("{\"type\":\"record\", \"name\":\"n\", \"fields\":" +
+ "[{\"name\":\"f1\", \"type\":{\"type\": \"array\", \"items\": \"int\"}}]}",
+ new object[] { "f1", new object[] { 0, 1, 101 } })]
+ [TestCase("{\"type\":\"record\", \"name\":\"n\", \"fields\":" +
+ "[{\"name\":\"f1\", \"type\":{\"type\": \"array\", \"items\": \"int\"}}]}",
+ new object[] { "f1", new int[] { 0, 1, 101 } })]
+ [TestCase("{\"type\":\"record\", \"name\":\"n\", \"fields\":" +
+ "[{\"name\":\"f1\", \"type\":[\"int\", \"long\"]}]}",
+ new object[] { "f1", 100 })]
+ [TestCase("{\"type\":\"record\", \"name\":\"n\", \"fields\":" +
+ "[{\"name\":\"f1\", \"type\":[\"int\", \"long\"]}]}",
+ new object[] { "f1", 100L })]
+ [TestCase("{\"type\":\"record\", \"name\":\"n\", \"fields\":" +
+ "[{\"name\":\"f1\", \"type\":{\"type\": \"fixed\", \"name\": \"f\", \"size\": 2}}]}",
+ new object[] { "f1", new byte[] { 1, 2 } })]
+ public void TestRecord(string schema, object[] kv)
+ {
+ test(schema, mkRecord(kv, Schema.Parse(schema) as RecordSchema));
+ }
+
+ [TestCase("{\"type\": \"map\", \"values\": \"string\"}",
+ new object[] { "a", "0", "b", "1", "c", "101" })]
+ public void TestMap(string schema, object[] values)
+ {
+ test(schema, mkMap(values));
+ }
+
+ [TestCase("[{\"type\":\"record\", \"name\":\"n\", \"fields\":[{\"name\":\"f1\", \"type\":\"string\"}]}, \"string\"]",
+ "{\"type\":\"record\", \"name\":\"n\", \"fields\":[{\"name\":\"f1\", \"type\":\"string\"}]}",
+ new object[] { "f1", "v1" })]
+ public void TestUnion_record(string unionSchema, string recordSchema, object[] value)
+ {
+ test(unionSchema, mkRecord(value, Schema.Parse(recordSchema) as RecordSchema));
+ }
+
+ [TestCase("[{\"type\": \"enum\", \"symbols\": [\"s1\", \"s2\"], \"name\": \"e\"}, \"string\"]",
+ "{\"type\": \"enum\", \"symbols\": [\"s1\", \"s2\"], \"name\": \"e\"}", "s1")]
+ [TestCase("[{\"type\": \"enum\", \"symbols\": [\"s1\", \"s2\"], \"name\": \"e\"}, \"string\"]",
+ "{\"type\": \"enum\", \"symbols\": [\"s1\", \"s2\"], \"name\": \"e\"}", "s2")]
+ [TestCase("[{\"type\": \"enum\", \"symbols\": [\"s1\", \"s2\"], \"name\": \"e\"}, \"string\"]",
+ "{\"type\": \"enum\", \"symbols\": [\"s1\", \"s2\"], \"name\": \"e\"}", "s3",
+ ExpectedException = typeof(AvroException))]
+ public void TestUnion_enum(string unionSchema, string enumSchema, string value)
+ {
+ test(unionSchema, mkEnum(enumSchema, value));
+ }
+
+
+ [TestCase("[{\"type\": \"map\", \"values\": \"int\"}, \"string\"]",
+ "{\"type\": \"map\", \"values\": \"int\"}", new object[] { "a", 1, "b", 2 })]
+ public void TestUnion_map(string unionSchema, string mapSchema, object[] value)
+ {
+ test(unionSchema, mkMap(value));
+ }
+
+ [TestCase("[{\"type\": \"fixed\", \"size\": 2, \"name\": \"f\"}, \"string\"]",
+ "{\"type\": \"fixed\", \"size\": 2, \"name\": \"f\"}", new byte[] { 1, 2 })]
+ [TestCase("[{\"type\": \"fixed\", \"size\": 2, \"name\": \"f\"}, \"string\"]",
+ "{\"type\": \"fixed\", \"size\": 2, \"name\": \"f\"}", new byte[] { 1, 2, 3 },
+ ExpectedException = typeof(AvroException))]
+ [TestCase("[{\"type\": \"fixed\", \"size\": 2, \"name\": \"f\"}, \"string\"]",
+ "{\"type\": \"fixed\", \"size\": 3, \"name\": \"f\"}", new byte[] { 1, 2, 3 },
+ ExpectedException = typeof(AvroException))]
+ public void TestUnion_fixed(string unionSchema, string fixedSchema, byte[] value)
+ {
+ test(unionSchema, mkFixed(fixedSchema, value));
+ }
+
+ public void TestResolution<T, S>(string writerSchema, T actual, string readerSchema, S expected)
+ {
+ Stream ms;
+ Schema ws;
+ serialize<T>(writerSchema, actual, out ms, out ws);
+ Schema rs = Schema.Parse(readerSchema);
+ S output = deserialize<S>(ms, ws, rs);
+ Assert.AreEqual(expected, output);
+ }
+
+ [TestCase("int", 10, "long", 10L)]
+ [TestCase("int", 10, "float", 10.0f)]
+ [TestCase("int", 10, "double", 10.0)]
+ [TestCase("long", 10L, "float", 10.0f)]
+ [TestCase("long", 10L, "double", 10.0)]
+ [TestCase("float", 10.0f, "double", 10.0)]
+ [TestCase("{\"type\":\"array\", \"items\":\"int\"}", new int[] { 10, 20 },
+ "{\"type\":\"array\", \"items\":\"long\"}", new object[] { 10L, 20L })]
+ [TestCase("[\"int\", \"boolean\"]", true, "[\"boolean\", \"double\"]", true)]
+ [TestCase("[\"int\", \"boolean\"]", 10, "[\"boolean\", \"double\"]", 10.0)]
+ [TestCase("[\"int\", \"boolean\"]", 10, "\"int\"", 10)]
+ [TestCase("[\"int\", \"boolean\"]", 10, "\"double\"", 10.0)]
+ [TestCase("\"int\"", 10, "[\"int\", \"boolean\"]", 10)]
+ [TestCase("\"int\"", 10, "[\"long\", \"boolean\"]", 10L)]
+ public void TestResolution_simple(string writerSchema, object actual, string readerSchema, object expected)
+ {
+ TestResolution(writerSchema, actual, readerSchema, expected);
+ }
+
+ [Test]
+ public void TestResolution_intMapToLongMap()
+ {
+ TestResolution("{\"type\":\"map\", \"values\":\"int\"}", mkMap(new object[] { "a", 10, "b", 20 }),
+ "{\"type\":\"map\", \"values\":\"long\"}", mkMap(new object[] { "a", 10L, "b", 20L }));
+ }
+
+ [Test]
+ public void TestResolution_enum()
+ {
+ string ws = "{\"type\":\"enum\", \"symbols\":[\"a\", \"b\"], \"name\":\"e\"}";
+ string rs = "{\"type\":\"enum\", \"symbols\":[\"a\", \"b\"], \"name\":\"e\"}";
+ TestResolution(ws, mkEnum(ws, "a"), rs, mkEnum(rs, "a"));
+ }
+
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":\"boolean\"},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", true, "f2", 100 },
+ "{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f2\",\"type\":\"int\"},{\"name\":\"f1\",\"type\":\"boolean\"}]}",
+ new object[] { "f1", true, "f2", 100 }, Description = "Out of order fields")]
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":\"boolean\"},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", true, "f2", 100 },
+ "{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":\"boolean\"},{\"name\":\"f2\",\"type\":\"long\"}]}",
+ new object[] { "f1", true, "f2", 100L }, Description = "Field promotion")]
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":\"boolean\"},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", true, "f2", 100 },
+ "{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":\"boolean\"}]}",
+ new object[] { "f1", true }, Description = "Missing fields - 1")]
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":\"null\"},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", null, "f2", 100 },
+ "{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f2", 100 }, Description = "Missing fields - null")]
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":\"boolean\"},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", true, "f2", 100 },
+ "{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f2", 100 }, Description = "Missing fields - boolean")]
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":\"int\"},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", 1, "f2", 100 },
+ "{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f2", 100 }, Description = "Missing fields - int")]
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":\"long\"},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", 1L, "f2", 100 },
+ "{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f2", 100 }, Description = "Missing fields - long")]
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":\"float\"},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", 1.0f, "f2", 100 },
+ "{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f2", 100 }, Description = "Missing fields - float")]
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":\"double\"},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", 1.0, "f2", 100 },
+ "{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f2", 100 }, Description = "Missing fields - double")]
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":\"bytes\"},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", new byte[] { 1 , 0 }, "f2", 100 },
+ "{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f2", 100 }, Description = "Missing fields - bytes")]
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":\"string\"},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", "h", "f2", 100 },
+ "{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f2", 100 }, Description = "Missing fields - string")]
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":{\"type\":\"array\",\"items\":\"int\"}},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", new int[] { 100, 101 }, "f2", 100 },
+ "{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f2", 100 }, Description = "Missing fields - array")]
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":[\"int\", \"null\"]},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", 101, "f2", 100 },
+ "{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f2", 100 }, Description = "Missing fields - union")]
+ // TODO: Missing fields - record, enum, map, fixed
+ /* FIXME: Resolution using defaults don't work yet.
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":\"boolean\"}]}",
+ new object[] { "f1", true },
+ "{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":\"boolean\"},{\"name\":\"f2\",\"type\":\"string\",\"default\":\"d\"}]}",
+ new object[] { "f1", true, "f2", "d" }, Description = "Default field")]
+ */
+ public void TestResolution_record(string ws, object[] actual, string rs, object[] expected)
+ {
+ TestResolution(ws, mkRecord(actual, Schema.Parse(ws) as RecordSchema), rs,
+ mkRecord(expected, Schema.Parse(rs) as RecordSchema));
+ }
+
+ [TestCase("{\"type\":\"map\",\"values\":\"int\"}", new object[] { "a", 100, "b", -202 },
+ "{\"type\":\"map\",\"values\":\"long\"}", new object[] { "a", 100L, "b", -202L })]
+ public void TestResolution_intMapToLongMap(string ws, object[] value, string rs, object[] expected)
+ {
+ TestResolution(ws, mkMap(value), rs, mkMap(expected));
+ }
+
+
+ private static void testResolutionMismatch<T>(string writerSchema, T value, string readerSchema)
+ {
+ Stream ms;
+ Schema ws;
+ serialize(writerSchema, value, out ms, out ws);
+ deserialize<object>(ms, ws, Schema.Parse(readerSchema));
+ }
+
+ [TestCase("boolean", true, "null", ExpectedException = typeof(AvroException))]
+ [TestCase("int", 10, "boolean", ExpectedException = typeof(AvroException))]
+ [TestCase("int", 10, "string", ExpectedException = typeof(AvroException))]
+ [TestCase("int", 10, "bytes", ExpectedException = typeof(AvroException))]
+ [TestCase("int", 10, "{\"type\":\"record\",\"name\":\"r\",\"fields\":[{\"name\":\"f\", \"type\":\"int\"}]}",
+ ExpectedException = typeof(AvroException))]
+ [TestCase("int", 10, "{\"type\":\"enum\",\"name\":\"e\",\"symbols\":[\"s\", \"t\"]}", ExpectedException = typeof(AvroException))]
+ [TestCase("int", 10, "{\"type\":\"array\",\"items\":\"int\"}", ExpectedException = typeof(AvroException))]
+ [TestCase("int", 10, "{\"type\":\"map\",\"values\":\"int\"}", ExpectedException = typeof(AvroException))]
+ [TestCase("int", 10, "[\"string\", \"bytes\"]", ExpectedException = typeof(AvroException))]
+ [TestCase("int", 10, "{\"type\":\"fixed\",\"name\":\"f\",\"size\":2}", ExpectedException = typeof(AvroException))]
+ [TestCase("{\"type\":\"array\",\"items\":\"int\"}", new int[] { 10 },
+ "\"boolean\"", ExpectedException = typeof(AvroException))]
+ [TestCase("{\"type\":\"array\",\"items\":\"int\"}", new int[] { 10 },
+ "{\"type\":\"array\",\"items\":\"string\"}", ExpectedException = typeof(AvroException))]
+ [TestCase("[\"int\", \"boolean\"]", 10, "[\"string\", \"bytes\"]", ExpectedException = typeof(AvroException))]
+ [TestCase("[\"int\", \"boolean\"]", 10, "\"string\"", ExpectedException = typeof(AvroException))]
+ public void TestResolutionMismatch_simple(string writerSchema, object value, string readerSchema)
+ {
+ testResolutionMismatch(writerSchema, value, readerSchema);
+ }
+
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":[\"int\", \"null\"]},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", 101, "f2", 100 }, "int",
+ ExpectedException = typeof(AvroException), Description = "Non-record schema")]
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":[\"int\", \"null\"]},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", 101, "f2", 100 },
+ "{\"type\":\"record\",\"name\":\"s\",\"fields\":" +
+ "[{\"name\":\"f2\",\"type\":\"int\"}]}",
+ ExpectedException = typeof(AvroException), Description = "Name mismatch")]
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":[\"int\", \"null\"]},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", 101, "f2", 100 },
+ "{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f2\",\"type\":\"string\"}]}",
+ ExpectedException = typeof(AvroException), Description = "incompatible field")]
+ [TestCase("{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f1\",\"type\":[\"int\", \"null\"]},{\"name\":\"f2\",\"type\":\"int\"}]}",
+ new object[] { "f1", 101, "f2", 100 },
+ "{\"type\":\"record\",\"name\":\"r\",\"fields\":" +
+ "[{\"name\":\"f3\",\"type\":\"string\"}]}",
+ ExpectedException = typeof(AvroException), Description = "new field without default")]
+ public void TestResolutionMismatch_record(string ws, object[] actual, string rs)
+ {
+ testResolutionMismatch(ws, mkRecord(actual, Schema.Parse(ws) as RecordSchema), rs);
+ }
+
+ [TestCase("{\"type\":\"enum\",\"name\":\"e\",\"symbols\":[\"s\", \"t\"]}", "s", "int",
+ ExpectedException = typeof(AvroException), Description = "Non-enum schema")]
+ [TestCase("{\"type\":\"enum\",\"name\":\"e\",\"symbols\":[\"s\", \"t\"]}",
+ "s", "{\"type\":\"enum\",\"name\":\"f\",\"symbols\":[\"s\", \"t\"]}",
+ ExpectedException = typeof(AvroException), Description = "Name mismatch")]
+ [TestCase("{\"type\":\"enum\",\"name\":\"e\",\"symbols\":[\"s\", \"t\"]}",
+ "s", "{\"type\":\"enum\",\"name\":\"f\",\"symbols\":[\"t\", \"u\"]}",
+ ExpectedException = typeof(AvroException), Description = "Incompatible symbols")]
+ public void TestResolutionMismatch_enum(string ws, string value, string rs)
+ {
+ testResolutionMismatch(ws, mkEnum(ws, value), rs);
+ }
+
+ [TestCase("{\"type\":\"map\",\"values\":\"int\"}", new object[] { "a", 0 }, "int",
+ ExpectedException = typeof(AvroException), Description = "Non-map schema")]
+ [TestCase("{\"type\":\"map\",\"values\":\"int\"}",
+ new object[] { "a", 0 }, "{\"type\":\"map\",\"values\":\"string\"}",
+ ExpectedException = typeof(AvroException), Description = "Name mismatch")]
+ public void TestResolutionMismatch_map(string ws, object[] value, string rs)
+ {
+ testResolutionMismatch(ws, mkMap(value), rs);
+ }
+
+ [TestCase("{\"type\":\"fixed\",\"name\":\"f\",\"size\":2}", new byte[] { 1, 1 }, "int",
+ ExpectedException = typeof(AvroException), Description = "Non-fixed schema")]
+ [TestCase("{\"type\":\"fixed\",\"name\":\"f\",\"size\":2}",
+ new byte[] { 1, 1 }, "{\"type\":\"fixed\",\"name\":\"g\",\"size\":2}",
+ ExpectedException = typeof(AvroException), Description = "Name mismatch")]
+ [TestCase("{\"type\":\"fixed\",\"name\":\"f\",\"size\":2}",
+ new byte[] { 1, 1 }, "{\"type\":\"fixed\",\"name\":\"f\",\"size\":1}",
+ ExpectedException = typeof(AvroException), Description = "Size mismatch")]
+ public void TestResolutionMismatch_fixed(string ws, byte[] value, string rs)
+ {
+ testResolutionMismatch(ws, mkFixed(ws, value), rs);
+ }
+
+ private static GenericRecord mkRecord(object[] kv, RecordSchema s)
+ {
+ GenericRecord input = new GenericRecord(s);
+ for (int i = 0; i < kv.Length; i += 2)
+ {
+ string fieldName = (string)kv[i];
+ object fieldValue = kv[i + 1];
+ Schema inner = s[fieldName].Schema;
+ if (inner is EnumSchema)
+ {
+ GenericEnum ge = new GenericEnum(inner as EnumSchema, (string)fieldValue);
+ fieldValue = ge;
+ }
+ else if (inner is FixedSchema)
+ {
+ GenericFixed gf = new GenericFixed(inner as FixedSchema);
+ gf.Value = (byte[])fieldValue;
+ fieldValue = gf;
+ }
+ input.Add(fieldName, fieldValue);
+ }
+ return input;
+ }
+
+ private static IDictionary<string, object> mkMap(object[] vv)
+ {
+ IDictionary<string, object> d = new Dictionary<string, object>();
+ for (int j = 0; j < vv.Length; j += 2)
+ {
+ d[(string)vv[j]] = vv[j + 1];
+ }
+ return d;
+ }
+
+ private static object mkEnum(string enumSchema, string value)
+ {
+ return new GenericEnum(Schema.Parse(enumSchema) as EnumSchema, value);
+ }
+
+ private static object mkFixed(string fixedSchema, byte[] value)
+ {
+ return new GenericFixed(Schema.Parse(fixedSchema) as FixedSchema, value);
+ }
+
+ private static S deserialize<S>(Stream ms, Schema ws, Schema rs)
+ {
+ GenericReader<S> r = new GenericReader<S>(ws, rs);
+ Decoder d = new BinaryDecoder(ms);
+ S n = default(S);
+ S output = r.Read(n, d);
+ Assert.AreEqual(ms.Length, ms.Position); // Ensure we have read everything.
+ return output;
+ }
+
+ private static void serialize<T>(string writerSchema, T actual, out Stream ms, out Schema ws)
+ {
+ ms = new MemoryStream();
+ Encoder e = new BinaryEncoder(ms);
+ ws = Schema.Parse(writerSchema);
+ GenericWriter<T> w = new GenericWriter<T>(ws);
+ w.Write(actual, e);
+ ms.Flush();
+ ms.Position = 0;
+ }
+
+ }
+}
Added: avro/trunk/lang/csharp/src/apache/test/IO/BinaryCodecTests.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/test/IO/BinaryCodecTests.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/test/IO/BinaryCodecTests.cs (added)
+++ avro/trunk/lang/csharp/src/apache/test/IO/BinaryCodecTests.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,334 @@
+/**
+ * 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
+ *
+ * http://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 System;
+using System.Collections.Generic;
+using System.Text;
+using NUnit.Framework;
+using System.IO;
+
+using Avro.IO;
+
+namespace Avro.Test
+{
+ using Decoder = Avro.IO.Decoder;
+ using Encoder = Avro.IO.Encoder;
+ delegate T Decode<T>(Decoder d);
+ delegate void Skip<T>(Decoder d);
+ delegate void Encode<T>(Encoder e, T t);
+
+ /// <summary>
+ /// Tests the BinaryEncoder and BinaryDecoder. This is pertty general set of test cases and hence
+ /// can be used for any encoder and its corresponding decoder.
+ /// </summary>
+ [TestFixture]
+ public class BinaryCodecTests
+ {
+
+ /// <summary>
+ /// Writes an avro type T with value t into a stream using the encode method e
+ /// and reads it back using the decode method d and verifies that
+ /// the value read back is the same as the one written in.
+ /// </summary>
+ /// <typeparam name="T">Avro type to test</typeparam>
+ /// <param name="t">Value for the Avro type to test.</param>
+ /// <param name="r">The decode method</param>
+ /// <param name="w">The encode method</param>
+ private void TestRead<T>(T t, Decode<T> r, Encode<T> w, int size)
+ {
+ MemoryStream iostr = new MemoryStream();
+ Encoder e = new BinaryEncoder(iostr);
+ w(e, t);
+ iostr.Flush();
+ Assert.AreEqual(size, iostr.Length);
+ iostr.Position = 0;
+ Decoder d = new BinaryDecoder(iostr);
+ T actual = r(d);
+ Assert.AreEqual(t, actual);
+ Assert.AreEqual(-1, iostr.ReadByte());
+ iostr.Close();
+ }
+
+ /// <summary>
+ /// Writes an avro type T with value t into a stream using the encode method e
+ /// and reads it back using the decode method d and verifies that
+ /// the value read back is the same as the one written in.
+ /// </summary>
+ /// <typeparam name="T">Avro type to test</typeparam>
+ /// <param name="t">Value for the Avro type to test.</param>
+ /// <param name="r">The skip method</param>
+ /// <param name="w">The encode method</param>
+ private void TestSkip<T>(T t, Skip<T> s, Encode<T> w, int size)
+ {
+ MemoryStream iostr = new MemoryStream();
+ Encoder e = new BinaryEncoder(iostr);
+ w(e, t);
+ iostr.Flush();
+ Assert.AreEqual(size, iostr.Length);
+ iostr.Position = 0;
+ Decoder d = new BinaryDecoder(iostr);
+ s(d);
+ Assert.AreEqual(-1, iostr.ReadByte());
+ iostr.Close();
+ }
+
+
+ [TestCase(true)]
+ [TestCase(false)]
+ public void TestBoolean(bool b)
+ {
+ TestRead(b, (Decoder d) => d.ReadBoolean(), (Encoder e, bool t) => e.WriteBoolean(t), 1);
+ TestSkip(b, (Decoder d) => d.SkipBoolean(), (Encoder e, bool t) => e.WriteBoolean(t), 1);
+ }
+
+ [TestCase(0, 1)]
+ [TestCase(1, 1)]
+ [TestCase(63, 1)]
+ [TestCase(64, 2)]
+ [TestCase(8191, 2)]
+ [TestCase(8192, 3)]
+ [TestCase(1048575, 3)]
+ [TestCase(1048576, 4)]
+ [TestCase(134217727, 4)]
+ [TestCase(134217728, 5)]
+ [TestCase(2147483647, 5)]
+ [TestCase(-1, 1)]
+ [TestCase(-64, 1)]
+ [TestCase(-65, 2)]
+ [TestCase(-8192, 2)]
+ [TestCase(-8193, 3)]
+ [TestCase(-1048576, 3)]
+ [TestCase(-1048577, 4)]
+ [TestCase(-134217728, 4)]
+ [TestCase(-134217729, 5)]
+ [TestCase(-2147483648, 5)]
+ public void TestInt(int n, int size)
+ {
+ TestRead(n, (Decoder d) => d.ReadInt(), (Encoder e, int t) => e.WriteInt(t), size);
+ TestSkip(n, (Decoder d) => d.SkipInt(), (Encoder e, int t) => e.WriteInt(t), size);
+ }
+
+ [TestCase(0, 1)]
+ [TestCase(1, 1)]
+ [TestCase(63, 1)]
+ [TestCase(64, 2)]
+ [TestCase(8191, 2)]
+ [TestCase(8192, 3)]
+ [TestCase(1048575, 3)]
+ [TestCase(1048576, 4)]
+ [TestCase(134217727, 4)]
+ [TestCase(134217728, 5)]
+ [TestCase(17179869183L, 5)]
+ [TestCase(17179869184L, 6)]
+ [TestCase(2199023255551L, 6)]
+ [TestCase(2199023255552L, 7)]
+ [TestCase(281474976710655L, 7)]
+ [TestCase(281474976710656L, 8)]
+ [TestCase(36028797018963967L, 8)]
+ [TestCase(36028797018963968L, 9)]
+ [TestCase(4611686018427387903L, 9)]
+ [TestCase(4611686018427387904L, 10)]
+ [TestCase(9223372036854775807L, 10)]
+ [TestCase(-1, 1)]
+ [TestCase(-64, 1)]
+ [TestCase(-65, 2)]
+ [TestCase(-8192, 2)]
+ [TestCase(-8193, 3)]
+ [TestCase(-1048576, 3)]
+ [TestCase(-1048577, 4)]
+ [TestCase(-134217728, 4)]
+ [TestCase(-134217729, 5)]
+ [TestCase(-17179869184L, 5)]
+ [TestCase(-17179869185L, 6)]
+ [TestCase(-2199023255552L, 6)]
+ [TestCase(-2199023255553L, 7)]
+ [TestCase(-281474976710656L, 7)]
+ [TestCase(-281474976710657L, 8)]
+ [TestCase(-36028797018963968L, 8)]
+ [TestCase(-36028797018963969L, 9)]
+ [TestCase(-4611686018427387904L, 9)]
+ [TestCase(-4611686018427387905L, 10)]
+ [TestCase(-9223372036854775808L, 10)]
+ public void TestLong(long n, int size)
+ {
+ TestRead(n, (Decoder d) => d.ReadLong(), (Encoder e, long t) => e.WriteLong(t), size);
+ TestSkip(n, (Decoder d) => d.SkipLong(), (Encoder e, long t) => e.WriteLong(t), size);
+ }
+
+ [TestCase(0.0f)]
+ [TestCase(Single.MaxValue, Description = "Max value")]
+ [TestCase(1.17549435E-38f, Description = "Min 'normal' value")]
+ [TestCase(1.4e-45f, Description = "Min value")]
+ public void TestFloat(float n)
+ {
+ TestRead(n, (Decoder d) => d.ReadFloat(), (Encoder e, float t) => e.WriteFloat(t), 4);
+ TestSkip(n, (Decoder d) => d.SkipFloat(), (Encoder e, float t) => e.WriteFloat(t), 4);
+ }
+
+ [TestCase(0.0)]
+ [TestCase(1.7976931348623157e+308, Description = "Max value")]
+ [TestCase(2.2250738585072014E-308, Description = "Min 'normal' value")]
+ [TestCase(4.9e-324, Description = "Min value")]
+ public void TestDouble(double n)
+ {
+ TestRead(n, (Decoder d) => d.ReadDouble(), (Encoder e, double t) => e.WriteDouble(t), 8);
+ TestSkip(n, (Decoder d) => d.SkipDouble(), (Encoder e, double t) => e.WriteDouble(t), 8);
+ }
+
+
+ [TestCase(0, 1)]
+ [TestCase(5, 1)]
+ [TestCase(63, 1)]
+ [TestCase(64, 2)]
+ [TestCase(8191, 2)]
+ [TestCase(8192, 3)]
+ public void TestBytes(int length, int overhead)
+ {
+ Random r = new Random();
+ byte[] b = new byte[length];
+ r.NextBytes(b);
+ TestRead(b, (Decoder d) => d.ReadBytes(), (Encoder e, byte[] t) => e.WriteBytes(t), overhead + b.Length);
+ TestSkip(b, (Decoder d) => d.SkipBytes(), (Encoder e, byte[] t) => e.WriteBytes(t), overhead + b.Length);
+ }
+
+ [TestCase("", 1)]
+ [TestCase("hello", 1)]
+ [TestCase("1234567890123456789012345678901234567890123456789012345678901234", 2)]
+ public void TestString(string n, int overhead)
+ {
+ TestRead(n, (Decoder d) => d.ReadString(), (Encoder e, string t) => e.WriteString(t), overhead + n.Length);
+ TestSkip(n, (Decoder d) => d.SkipString(), (Encoder e, string t) => e.WriteString(t), overhead + n.Length);
+ }
+
+ [TestCase(0, 1)]
+ [TestCase(1, 1)]
+ [TestCase(64, 2)]
+ public void TestEnum(int n, int size)
+ {
+ TestRead(n, (Decoder d) => d.ReadEnum(), (Encoder e, int t) => e.WriteEnum(t), size);
+ TestSkip(n, (Decoder d) => d.SkipEnum(), (Encoder e, int t) => e.WriteEnum(t), size);
+ }
+
+ [TestCase(1, new int[] { })]
+ [TestCase(3, new int[] { 0 })]
+ [TestCase(4, new int[] { 64 })]
+ public void TestArray(int size, int[] entries)
+ {
+ TestRead(entries, (Decoder d) =>
+ {
+ int[] t = new int[entries.Length];
+ int j = 0;
+ for (long n = d.ReadArrayStart(); n != 0; n = d.ReadArrayNext())
+ {
+ for (int i = 0; i < n; i++) { t[j++] = d.ReadInt(); }
+
+ }
+ return t;
+ },
+ (Encoder e, int[] t) =>
+ {
+ e.WriteArrayStart();
+ e.SetItemCount(t.Length);
+ foreach (int i in t) { e.StartItem(); e.WriteInt(i); } e.WriteArrayEnd();
+ }, size);
+
+ TestSkip(entries, (Decoder d) =>
+ {
+ for (long n = d.ReadArrayStart(); n != 0; n = d.ReadArrayNext())
+ {
+ for (int i = 0; i < n; i++) { d.SkipInt(); }
+
+ }
+ },
+ (Encoder e, int[] t) =>
+ {
+ e.WriteArrayStart();
+ e.SetItemCount(t.Length);
+ foreach (int i in t) { e.StartItem(); e.WriteInt(i); } e.WriteArrayEnd();
+ }, size);
+ }
+
+ [TestCase(1, new string[] { })]
+ [TestCase(6, new string[] { "a", "b" })]
+ [TestCase(9, new string[] { "a", "b", "c", "" })]
+ public void TestMap(int size, string[] entries)
+ {
+ TestRead(entries, (Decoder d) =>
+ {
+ string[] t = new string[entries.Length];
+ int j = 0;
+ for (long n = d.ReadArrayStart(); n != 0; n = d.ReadArrayNext())
+ {
+ for (int i = 0; i < n; i++) { t[j++] = d.ReadString(); t[j++] = d.ReadString(); }
+
+ }
+ return t;
+ },
+ (Encoder e, string[] t) =>
+ {
+ e.WriteArrayStart();
+ e.SetItemCount(t.Length / 2);
+ for (int i = 0; i < t.Length; i += 2)
+ {
+ e.StartItem(); e.WriteString(t[i]); e.WriteString(t[i + 1]);
+ }
+ e.WriteArrayEnd();
+ }, size);
+
+ TestSkip(entries, (Decoder d) =>
+ {
+ for (long n = d.ReadArrayStart(); n != 0; n = d.ReadArrayNext())
+ {
+ for (int i = 0; i < n; i++) { d.SkipString(); d.SkipString(); }
+
+ }
+ },
+ (Encoder e, string[] t) =>
+ {
+ e.WriteArrayStart();
+ e.SetItemCount(t.Length / 2);
+ for (int i = 0; i < t.Length; i += 2)
+ {
+ e.StartItem(); e.WriteString(t[i]); e.WriteString(t[i + 1]);
+ }
+ e.WriteArrayEnd();
+ }, size);
+ }
+
+ [TestCase(0, 1)]
+ [TestCase(1, 1)]
+ [TestCase(64, 2)]
+ public void TestUnionIndex(int n, int size)
+ {
+ TestRead(n, (Decoder d) => d.ReadUnionIndex(), (Encoder e, int t) => e.WriteUnionIndex(t), size);
+ TestSkip(n, (Decoder d) => d.SkipUnionIndex(), (Encoder e, int t) => e.WriteUnionIndex(t), size);
+ }
+
+ [TestCase(0)]
+ [TestCase(1)]
+ [TestCase(64)]
+ public void TestFixed(int size)
+ {
+ byte[] b = new byte[size];
+ new Random().NextBytes(b);
+ TestRead(b, (Decoder d) => { byte[] t = new byte[size]; d.ReadFixed(t); return t; },
+ (Encoder e, byte[] t) => e.WriteFixed(t), size);
+ TestSkip(b, (Decoder d) => d.SkipFixed(size),
+ (Encoder e, byte[] t) => e.WriteFixed(t), size);
+ }
+ }
+}
Added: avro/trunk/lang/csharp/src/apache/test/Properties/AssemblyInfo.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/test/Properties/AssemblyInfo.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/test/Properties/AssemblyInfo.cs (added)
+++ avro/trunk/lang/csharp/src/apache/test/Properties/AssemblyInfo.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,53 @@
+/**
+ * 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
+ *
+ * http://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 System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Avro.test")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache.org")]
+[assembly: AssemblyProduct("Avro.test")]
+[assembly: AssemblyCopyright("Copyright © Apache 2010")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("9c47069f-9d58-4815-bfea-f7dac9a48b05")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("0.9.0.0")]
+[assembly: AssemblyFileVersion("0.9.0.0")]
Added: avro/trunk/lang/csharp/src/apache/test/Protocol/ProtocolTest.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/test/Protocol/ProtocolTest.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/test/Protocol/ProtocolTest.cs (added)
+++ avro/trunk/lang/csharp/src/apache/test/Protocol/ProtocolTest.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,184 @@
+/**
+ * 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
+ *
+ * http://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 System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using NUnit.Framework;
+using Avro;
+
+namespace Avro.Test
+{
+ [TestFixture]
+ public class ProtocolTest
+ {
+ [TestCase(@"{
+ ""protocol"": ""TestProtocol"",
+ ""namespace"": ""com.acme"",
+ ""doc"": ""HelloWorld"",
+
+ ""types"": [
+ {""name"": ""Greeting"", ""type"": ""record"", ""fields"": [
+ {""name"": ""message"", ""type"": ""string""}]},
+ {""name"": ""Curse"", ""type"": ""error"", ""fields"": [
+ {""name"": ""message"", ""type"": ""string""}]},
+ {""name"": ""CurseMore"", ""type"": ""error"", ""fields"": [
+ {""name"": ""message"", ""type"": ""string""}]}
+ ],
+
+ ""messages"": {
+ ""hello"": {
+ ""request"": [{""name"": ""greeting"", ""type"": ""Greeting"" }],
+ ""response"": ""Greeting"",
+ ""errors"": [""Curse"", ""CurseMore""]
+ }
+ }
+}", true)]
+ [TestCase(@"{
+ ""protocol"" : ""MyProtocol"",
+ ""namespace"" : ""com.foo"",
+ ""types"" : [
+ {
+ ""type"" : ""record"",
+ ""name"" : ""A"",
+ ""fields"" : [ { ""name"" : ""f1"", ""type"" : ""long"" } ]
+ },
+ {
+ ""type"" : ""enum"",
+ ""name"" : ""MyEnum"",
+ ""symbols"" : [ ""A"", ""B"", ""C"" ]
+ },
+ {
+ ""type"": ""fixed"",
+ ""size"": 16,
+ ""name"": ""MyFixed""
+ },
+ {
+ ""type"" : ""record"",
+ ""name"" : ""Z"",
+ ""fields"" :
+ [
+ { ""name"" : ""myUInt"", ""type"" : [ ""int"", ""null"" ] },
+ { ""name"" : ""myULong"", ""type"" : [ ""long"", ""null"" ] },
+ { ""name"" : ""myUBool"", ""type"" : [ ""boolean"", ""null"" ] },
+ { ""name"" : ""myUDouble"", ""type"" : [ ""double"", ""null"" ] },
+ { ""name"" : ""myUFloat"", ""type"" : [ ""float"", ""null"" ] },
+ { ""name"" : ""myUBytes"", ""type"" : [ ""bytes"", ""null"" ] },
+ { ""name"" : ""myUString"", ""type"" : [ ""string"", ""null"" ] },
+
+ { ""name"" : ""myInt"", ""type"" : ""int"" },
+ { ""name"" : ""myLong"", ""type"" : ""long"" },
+ { ""name"" : ""myBool"", ""type"" : ""boolean"" },
+ { ""name"" : ""myDouble"", ""type"" : ""double"" },
+ { ""name"" : ""myFloat"", ""type"" : ""float"" },
+ { ""name"" : ""myBytes"", ""type"" : ""bytes"" },
+ { ""name"" : ""myString"", ""type"" : ""string"" },
+ { ""name"" : ""myNull"", ""type"" : ""null"" },
+
+ { ""name"" : ""myFixed"", ""type"" : ""MyFixed"" },
+ { ""name"" : ""myFixed2"", ""type"" : ""MyFixed"" },
+ { ""name"" : ""myA"", ""type"" : ""A"" },
+ { ""name"" : ""myE"", ""type"" : ""MyEnum"" },
+ { ""name"" : ""myArray"", ""type"" : { ""type"" : ""array"", ""items"" : ""bytes"" } },
+ { ""name"" : ""myArray2"", ""type"" : { ""type"" : ""array"", ""items"" : { ""type"" : ""record"", ""name"" : ""newRec"", ""fields"" : [ { ""name"" : ""f1"", ""type"" : ""long""} ] } } },
+ { ""name"" : ""myMap"", ""type"" : { ""type"" : ""map"", ""values"" : ""string"" } },
+ { ""name"" : ""myMap2"", ""type"" : { ""type"" : ""map"", ""values"" : ""newRec"" } },
+ { ""name"" : ""myObject"", ""type"" : [ ""MyEnum"", ""A"", ""null"" ] },
+ { ""name"" : ""next"", ""type"" : [ ""A"", ""null"" ] }
+ ]
+ } ,
+ {
+ ""type"" : ""int""
+ }
+ ]
+}", true)]
+ [TestCase(@"{
+ ""protocol"" : ""MyProtocol"",
+ ""namespace"" : ""com.bar"",
+ ""types"" : [
+ {
+ ""type"" : ""record"",
+ ""name"" : ""A"",
+ ""fields"" :
+ [
+ { ""name"" : ""f1"", ""type"" : ""long"" }
+ ]
+ },
+ {
+ ""type"" : ""enum"",
+ ""name"" : ""MyEnum"",
+ ""symbols"" : [ ""A"", ""B"", ""C"" ]
+ },
+ {
+ ""type"": ""fixed"",
+ ""size"": 16,
+ ""name"": ""MyFixed""
+ },
+ {
+ ""type"" : ""record"",
+ ""name"" : ""Z"",
+ ""fields"" :
+ [
+ { ""name"" : ""myUInt"", ""type"" : [ ""int"", ""null"" ], ""default"" : 1 },
+ { ""name"" : ""myULong"", ""type"" : [ ""long"", ""null"" ], ""default"" : 2 },
+ { ""name"" : ""myUBool"", ""type"" : [ ""boolean"", ""null"" ], ""default"" : true },
+ { ""name"" : ""myUDouble"", ""type"" : [ ""double"", ""null"" ], ""default"" : 3 },
+ { ""name"" : ""myUFloat"", ""type"" : [ ""float"", ""null"" ], ""default"" : 4.5 },
+ { ""name"" : ""myUBytes"", ""type"" : [ ""bytes"", ""null"" ], ""default"" : ""\u00ff"" },
+ { ""name"" : ""myUString"", ""type"" : [ ""string"", ""null"" ], ""default"" : ""foo"" },
+
+ { ""name"" : ""myInt"", ""type"" : ""int"", ""default"" : 10 },
+ { ""name"" : ""myLong"", ""type"" : ""long"", ""default"" : 11 },
+ { ""name"" : ""myBool"", ""type"" : ""boolean"", ""default"" : false },
+ { ""name"" : ""myDouble"", ""type"" : ""double"", ""default"" : 12 },
+ { ""name"" : ""myFloat"", ""type"" : ""float"", ""default"" : 13.14 },
+ { ""name"" : ""myBytes"", ""type"" : ""bytes"", ""default"" : ""\u00ff"" },
+ { ""name"" : ""myString"", ""type"" : ""string"", ""default"" : ""bar"" },
+ { ""name"" : ""myNull"", ""type"" : ""null"", ""default"" : null },
+
+ { ""name"" : ""myFixed"", ""type"" : ""MyFixed"", ""default"" : ""\u00FFFFFFFFFFFFFFFFA"" },
+ { ""name"" : ""myFixed2"", ""type"" : ""MyFixed"", ""default"" : ""\u00FFFFFFFFFFFFFFFFA"" },
+ { ""name"" : ""myA"", ""type"" : ""A"", ""default"" : {""f1"":5} },
+ { ""name"" : ""myE"", ""type"" : ""MyEnum"", ""default"" : ""C"" },
+ { ""name"" : ""myArray"", ""type"" : { ""type"" : ""array"", ""items"" : ""bytes"" }, ""default"" : [ ""a12b"", ""cc50"" ] },
+ { ""name"" : ""myArray2"", ""type"" : { ""type"" : ""array"", ""items"" : { ""type"" : ""record"", ""name"" : ""newRec"", ""fields"" : [ { ""name"" : ""f2"", ""type"" : ""long""} ], ""default"" : {""f2"":5} } }, ""default"" : [ {""f2"":6}, {""f2"":7} ] },
+ { ""name"" : ""myMap"", ""type"" : { ""type"" : ""map"", ""values"" : ""string"" }, ""default"" : {""a"":""A"", ""b"":""B""} },
+ { ""name"" : ""myMap2"", ""type"" : { ""type"" : ""map"", ""values"" : ""newRec"" }, ""default"" : { ""key1"":{""f2"":6}, ""key2"":{""f2"":7} } },
+ { ""name"" : ""myObject"", ""type"" : [ ""MyEnum"", ""A"", ""null"" ], ""default"" : ""A"" },
+ { ""name"" : ""next"", ""type"" : [ ""null"" , ""A"" ], ""default"" : null }
+ ]
+ } ,
+ {
+ ""type"" : ""int""
+ }
+ ]
+}", true)]
+ public static void TestProtocol(string str, bool valid)
+ {
+ Protocol protocol = Protocol.Parse(str);
+ Assert.IsTrue(valid);
+ string json = protocol.ToString();
+
+ Protocol protocol2 = Protocol.Parse(json);
+ string json2 = protocol2.ToString();
+
+ Assert.AreEqual(json,json2);
+ }
+ }
+}
Added: avro/trunk/lang/csharp/src/apache/test/Schema/AliasTest.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/test/Schema/AliasTest.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/test/Schema/AliasTest.cs (added)
+++ avro/trunk/lang/csharp/src/apache/test/Schema/AliasTest.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,239 @@
+/**
+ * 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
+ *
+ * http://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 System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using Avro;
+
+namespace Avro.Test
+{
+ [TestFixture]
+ public class AliasTest
+ {
+ [TestCase(@"{""type"":""record"",""name"":""LongList"", ""namespace"":""com"", ""aliases"":[""c"",""foo.y""],
+ ""fields"":
+ [{""name"":""f1"",""type"":""long"", ""extraprop"":""important"", ""id"":""1029"", ""aliases"":[""a"",""b"",""c""] },
+ {""name"":""f2"",""type"": ""int""}]}",
+ true)]
+ [TestCase(@"{""type"":""record"",""name"":""LongList"", ""aliases"":[""Alias1""],
+ ""fields"":[{""name"":""f1"",""type"":""long"", ""order"":""junk"" },
+ {""name"":""f2"",""type"": ""int""}]}",
+ false)]
+ [TestCase(@"{""type"":""record"",""name"":""LongList"", ""aliases"":[""Alias1""], ""customprop"":""123456"",
+ ""fields"":[{""name"":""f1"",""type"":""long"", ""order"":""ascending"", ""fprop"":""faaa"" },
+ {""name"":""f2"",""type"": ""int""}]}",
+ true)]
+ [TestCase(@"{""type"":""record"",""name"":""LongList"", ""aliases"":[""Alias1""],
+ ""fields"":[{""name"":""f1"",""type"":""long""},
+ {""name"":""f2"",""type"": ""int""}]}",
+ true)]
+ [TestCase(@"{""type"":""record"",""name"":""LongList"", ""aliases"":[""Alias1"",""Alias2""],
+ ""fields"":[{""name"":""f1"",""type"":""long""},
+ {""name"":""f2"",""type"": ""int""}]}",
+ true)]
+ [TestCase(@"{""type"":""record"",""name"":""LongList"", ""aliases"":[""Alias1"",9],
+ ""fields"":[{""name"":""f1"",""type"":""long""},
+ {""name"":""f2"",""type"": ""int""}]}",
+ false)]
+ [TestCase(@"{""type"":""record"",""name"":""LongList"", ""aliases"":[1, 2],
+ ""fields"":[{""name"":""f1"",""type"":""long"", ""default"": ""100""},
+ {""name"":""f2"",""type"": ""int""}]}",
+ false)]
+ [TestCase(@"{""type"":""record"",""name"":""LongList"", ""aliases"": ""wrong alias format"",
+ ""fields"":[{""name"":""value"",""type"":""long"", ""default"": ""100""},
+ {""name"":""next"",""type"":[""LongList"",""null""]}]}",
+ false)]
+ public void TestAliases(string s, bool valid) // also tests properties, default, order
+ {
+ try
+ {
+ Schema sc = Schema.Parse(s);
+ Assert.IsTrue(valid);
+
+ string json = sc.ToString();
+ Schema sc2 = Schema.Parse(json);
+ string json2 = sc2.ToString();
+
+ Assert.IsTrue(json == json2);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ Assert.IsFalse(valid);
+ }
+ }
+
+ // Enum
+ [TestCase(@"{""type"":""enum"",""name"":""Symbols"", ""symbols"" : [ ""A"", ""B"", ""C"" ] }",
+ @"{""type"":""enum"",""name"":""Symbols"", ""symbols"" : [ ""A"", ""B"", ""C"" ] }",
+ true)]
+ [TestCase(@"{""type"":""enum"",""name"":""Symbols"", ""symbols"" : [ ""A"", ""B"", ""C"" ] }",
+ @"{""type"":""enum"",""name"":""NewSymbols"", ""symbols"" : [ ""A"", ""B"", ""C"" ] }",
+ false)]
+ [TestCase(@"{""type"":""enum"",""name"":""Symbols"", ""aliases"" : [""NewSymbols""], ""symbols"" : [ ""A"", ""B"", ""C"" ] }",
+ @"{""type"":""enum"",""name"":""NewSymbols"", ""symbols"" : [ ""A"", ""B"", ""C"" ] }",
+ true)]
+ [TestCase(@"{""type"":""enum"",""name"":""Symbols"", ""aliases"" : [""DiffSymbols"", ""OtherSymbols""], ""symbols"" : [ ""A"", ""B"", ""C"" ] }",
+ @"{""type"":""enum"",""name"":""NewSymbols"", ""symbols"" : [ ""A"", ""B"", ""C"" ] }",
+ false)]
+ public void TestEnumAliasesResolution(string reader, string writer, bool canread)
+ {
+ try
+ {
+ Schema rs = Schema.Parse(reader);
+ Schema ws = Schema.Parse(writer);
+ Assert.IsTrue(rs.CanRead(ws) == canread);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ Assert.IsTrue(false);
+ }
+ }
+
+ // Fixed
+ [TestCase(@"{""type"": ""fixed"", ""name"": ""Fixed"", ""size"": 1}",
+ @"{""type"": ""fixed"", ""name"": ""Fixed"", ""size"": 1}",
+ true)]
+ [TestCase(@"{""type"": ""fixed"", ""name"": ""Fixed"", ""size"": 1}",
+ @"{""type"": ""fixed"", ""name"": ""NewFixed"", ""size"": 1}",
+ false)]
+ [TestCase(@"{""type"": ""fixed"", ""name"": ""Fixed"", ""aliases"" : [""NewFixed""], ""size"": 1}",
+ @"{""type"": ""fixed"", ""name"": ""NewFixed"", ""size"": 1}",
+ true)]
+ [TestCase(@"{""type"": ""fixed"", ""name"": ""Fixed"", ""aliases"" : [""DiffFixed"", ""OtherFixed""], ""size"": 1}",
+ @"{""type"": ""fixed"", ""name"": ""NewFixed"", ""size"": 1}",
+ false)]
+ public void TestFixedAliasesResolution(string reader, string writer, bool canread)
+ {
+ try
+ {
+ Schema rs = Schema.Parse(reader);
+ Schema ws = Schema.Parse(writer);
+ Assert.IsTrue(rs.CanRead(ws) == canread);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ Assert.IsTrue(false);
+ }
+ }
+
+ // Records
+ [TestCase(1,@"{""type"":""record"",""name"":""Rec"",
+ ""fields"":[{""name"":""f1"",""type"":""long"" },
+ {""name"":""f2"",""type"": ""int""}]}",
+ @"{""type"":""record"",""name"":""Rec"",
+ ""fields"":[{""name"":""f1"",""type"":""long"" },
+ {""name"":""f2"",""type"": ""int""}]}",
+ true)]
+ [TestCase(2,@"{""type"":""record"",""name"":""Rec"",
+ ""fields"":[{""name"":""f1"",""type"":""long"" },
+ {""name"":""f2"",""type"": ""int""}]}",
+ @"{""type"":""record"",""name"":""NewRec"",
+ ""fields"":[{""name"":""f1"",""type"":""long"" },
+ {""name"":""f2"",""type"": ""int""}]}",
+ false)]
+ [TestCase(3,@"{""type"":""record"",""name"":""Rec"", ""aliases"":[""NewRec""],
+ ""fields"":[{""name"":""f1"",""type"":""long"" },
+ {""name"":""f2"",""type"": ""int""}]}",
+ @"{""type"":""record"",""name"":""NewRec"",
+ ""fields"":[{""name"":""f1"",""type"":""long"" },
+ {""name"":""f2"",""type"": ""int""}]}",
+ true)]
+ [TestCase(4,@"{""type"":""record"",""name"":""Rec"", ""aliases"":[""OtherRec"",""DiffRec""],
+ ""fields"":[{""name"":""f1"",""type"":""long"" },
+ {""name"":""f2"",""type"": ""int""}]}",
+ @"{""type"":""record"",""name"":""NewRec"",
+ ""fields"":[{""name"":""f1"",""type"":""long"" },
+ {""name"":""f2"",""type"": ""int""}]}",
+ false)]
+ [TestCase(5,@"{""type"":""record"",""name"":""Rec"",
+ ""fields"":[{""name"":""f1"",""type"":""long"" },
+ {""name"":""f3"",""type"": ""int""}]}",
+ @"{""type"":""record"",""name"":""Rec"",
+ ""fields"":[{""name"":""f1"",""type"":""long"" },
+ {""name"":""f2"",""type"": ""int""}]}",
+ false)]
+ [TestCase(6,@"{""type"":""record"",""name"":""Rec"",
+ ""fields"":[{""name"":""f1"",""type"":""long"" },
+ {""name"":""f3"",""type"": ""int"", ""aliases"":[""f2""]}]}",
+ @"{""type"":""record"",""name"":""Rec"",
+ ""fields"":[{""name"":""f1"",""type"":""long"" },
+ {""name"":""f2"",""type"": ""int""}]}",
+ true)]
+ [TestCase(7,@"{""type"":""record"",""name"":""Rec"",
+ ""fields"":[{""name"":""f1"",""type"":""long"" },
+ {""name"":""f3"",""type"": ""int"", ""aliases"":[""f4"",""f5""]}]}",
+ @"{""type"":""record"",""name"":""Rec"",
+ ""fields"":[{""name"":""f1"",""type"":""long"" },
+ {""name"":""f2"",""type"": ""int""}]}",
+ false)]
+ [TestCase(8,@"{""type"":""record"",""name"":""Rec"",
+ ""fields"":[{""name"":""f1"",""type"": {""type"":""enum"", ""name"":""Symbol"", ""symbols"":[""A""] }}]}",
+ @"{""type"":""record"",""name"":""Rec"",
+ ""fields"":[{""name"":""f1"",""type"": {""type"":""enum"", ""name"":""NewSymbol"", ""symbols"":[""A""] }}]}",
+ false)]
+ [TestCase(9,@"{""type"":""record"",""name"":""Rec"",
+ ""fields"":[{""name"":""f1"",""type"": {""type"":""enum"", ""name"":""Symbol"", ""aliases"":[""NewSymbol""], ""symbols"":[""A""] }}]}",
+ @"{""type"":""record"",""name"":""Rec"",
+ ""fields"":[{""name"":""f1"",""type"": {""type"":""enum"", ""name"":""NewSymbol"", ""symbols"":[""A""] }}]}",
+ true)]
+ [TestCase(10,@"{""type"":""record"",""name"":""Rec"",
+ ""fields"":[{""name"":""f1"",""type"": {""type"":""enum"", ""name"":""Symbol"", ""aliases"":[""DiffSymbol""], ""symbols"":[""A""] }}]}",
+ @"{""type"":""record"",""name"":""Rec"",
+ ""fields"":[{""name"":""f1"",""type"": {""type"":""enum"", ""name"":""NewSymbol"", ""symbols"":[""A""] }}]}",
+ false)]
+ [TestCase(11,@"{""type"":""record"",""name"":""Rec"",""aliases"":[""NewRec""],
+ ""fields"":[{""name"":""f2"",""aliases"":[""f1""],""type"": {""type"":""enum"", ""name"":""Symbol"", ""aliases"":[""NewSymbol""], ""symbols"":[""A""] }},
+ {""name"":""f3"",""aliases"":[""f4""],""type"": {""type"":""fixed"", ""name"":""Fixed"", ""aliases"":[""NewFixed""], ""size"": 1 }}
+ ]}",
+ @"{""type"":""record"",""name"":""NewRec"",
+ ""fields"":[{""name"":""f1"",""type"": {""type"":""enum"", ""name"":""NewSymbol"", ""symbols"":[""A""] }},
+ {""name"":""f4"",""type"": {""type"":""fixed"", ""name"":""NewFixed"", ""size"": 1 }}
+ ]}",
+ true)]
+ [TestCase(12,@"{""type"":""record"",""name"":""Rec"",""aliases"":[""NewRec""],
+ ""fields"":[{""name"":""f2"",""aliases"":[""f1""],""type"": {""type"":""enum"", ""name"":""Symbol"", ""aliases"":[""NewSymbol""], ""symbols"":[""A""] }},
+ {""name"":""f3"",""aliases"":[""f4""],""type"": {""type"":""fixed"", ""name"":""Fixed"", ""aliases"":[""NewFixed""], ""size"":1 }}
+ ]}",
+ @"{""type"":""record"",""name"":""NewRec"",
+ ""fields"":[{""name"":""f1"",""type"": {""type"":""enum"", ""name"":""NewSymbol"", ""symbols"":[""A"",""B""] }},
+ {""name"":""f4"",""type"": {""type"":""fixed"", ""name"":""NewFixed"", ""size"":1 }}
+ ]}",
+ true)]
+
+ public void TestRecordAliasesResolution(int testid, string reader, string writer, bool canread)
+ {
+ try
+ {
+ Schema rs = Schema.Parse(reader);
+ Schema ws = Schema.Parse(writer);
+ Assert.IsTrue(rs.CanRead(ws) == canread);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ Assert.IsTrue(false);
+ }
+ }
+
+ }
+}