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);
+            }
+        }
+
+    }
+}