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/05/30 11:01:34 UTC

svn commit: r1129077 - in /avro/branches/branch-1.5: ./ lang/csharp/src/apache/main/Protocol/ lang/csharp/src/apache/main/Schema/ lang/csharp/src/apache/test/Protocol/

Author: cutting
Date: Mon May 30 09:01:33 2011
New Revision: 1129077

URL: http://svn.apache.org/viewvc?rev=1129077&view=rev
Log:
Merge -c 1129071 from trunk to 1.5 branch.  Fixes: AVRO-826.

Modified:
    avro/branches/branch-1.5/   (props changed)
    avro/branches/branch-1.5/CHANGES.txt
    avro/branches/branch-1.5/lang/csharp/src/apache/main/Protocol/Message.cs
    avro/branches/branch-1.5/lang/csharp/src/apache/main/Protocol/Protocol.cs
    avro/branches/branch-1.5/lang/csharp/src/apache/main/Schema/RecordSchema.cs
    avro/branches/branch-1.5/lang/csharp/src/apache/test/Protocol/ProtocolTest.cs

Propchange: avro/branches/branch-1.5/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon May 30 09:01:33 2011
@@ -1 +1 @@
-/avro/trunk:1075938,1075993,1078917,1079055,1079060,1079063,1083246,1085921,1086727,1086730,1086866,1087076,1087129,1087136,1087439-1087440,1087463,1087472,1087792,1089128,1089131,1089550,1094812,1095206-1095208,1095493,1095529,1095548,1095550,1096798,1097916,1097927,1097968,1097974,1102332,1102335,1124127,1124971,1129053
+/avro/trunk:1075938,1075993,1078917,1079055,1079060,1079063,1083246,1085921,1086727,1086730,1086866,1087076,1087129,1087136,1087439-1087440,1087463,1087472,1087792,1089128,1089131,1089550,1094812,1095206-1095208,1095493,1095529,1095548,1095550,1096798,1097916,1097927,1097968,1097974,1102332,1102335,1124127,1124971,1129053,1129071

Modified: avro/branches/branch-1.5/CHANGES.txt
URL: http://svn.apache.org/viewvc/avro/branches/branch-1.5/CHANGES.txt?rev=1129077&r1=1129076&r2=1129077&view=diff
==============================================================================
--- avro/branches/branch-1.5/CHANGES.txt (original)
+++ avro/branches/branch-1.5/CHANGES.txt Mon May 30 09:01:33 2011
@@ -14,6 +14,9 @@ Avro 1.5.2 (unreleased)
     while writing data to a file and then continue writing to that
     file.  (scottcarey & cutting)
 
+    AVRO-826. C#: Add MD5 and hashcode functions to Protocol.
+    (Dona Alvarez via cutting)
+
   BUG FIXES
 
     AVRO-818. C: Fix data file corruption bug in C library (dcreager)

Modified: avro/branches/branch-1.5/lang/csharp/src/apache/main/Protocol/Message.cs
URL: http://svn.apache.org/viewvc/avro/branches/branch-1.5/lang/csharp/src/apache/main/Protocol/Message.cs?rev=1129077&r1=1129076&r2=1129077&view=diff
==============================================================================
--- avro/branches/branch-1.5/lang/csharp/src/apache/main/Protocol/Message.cs (original)
+++ avro/branches/branch-1.5/lang/csharp/src/apache/main/Protocol/Message.cs Mon May 30 09:01:33 2011
@@ -141,5 +141,45 @@ namespace Avro
 
             writer.WriteEndObject();
         }
+
+        /// <summary>
+        /// Tests equality of this Message object with the passed object
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <returns></returns>
+        public override bool Equals(Object obj) 
+        {
+          if (obj == this) return true;
+          if (!(obj is Message)) return false;
+
+          Message that = obj as Message;
+          return this.Name.Equals(that.Name) && 
+                 this.Request.Equals(that.Request) &&
+                 areEqual(this.Response, that.Response) && 
+                 areEqual(this.Error, that.Error);
+        }
+
+        /// <summary>
+        /// Returns the hash code of this Message object
+        /// </summary>
+        /// <returns></returns>
+        public override int GetHashCode() 
+        {
+            return Name.GetHashCode() +
+                   Request.GetHashCode() +
+                  (Response == null ? 0 : Response.GetHashCode()) +
+                  (Error == null ? 0 : Error.GetHashCode());
+        }
+
+        /// <summary>
+        /// Tests equality of two objects taking null values into account 
+        /// </summary>
+        /// <param name="o1"></param>
+        /// <param name="o2"></param>
+        /// <returns></returns>
+        protected static bool areEqual(object o1, object o2)
+        {
+            return o1 == null ? o2 == null : o1.Equals(o2);
+        }
     }
 }

Modified: avro/branches/branch-1.5/lang/csharp/src/apache/main/Protocol/Protocol.cs
URL: http://svn.apache.org/viewvc/avro/branches/branch-1.5/lang/csharp/src/apache/main/Protocol/Protocol.cs?rev=1129077&r1=1129076&r2=1129077&view=diff
==============================================================================
--- avro/branches/branch-1.5/lang/csharp/src/apache/main/Protocol/Protocol.cs (original)
+++ avro/branches/branch-1.5/lang/csharp/src/apache/main/Protocol/Protocol.cs Mon May 30 09:01:33 2011
@@ -51,6 +51,24 @@ namespace Avro
         /// </summary>
         public IDictionary<string,Message> Messages { get; set; }
 
+        private byte[] md5;
+        public byte[] MD5
+        {
+            get 
+            {
+                try
+                {
+                    if (md5 == null)
+                        md5 = System.Security.Cryptography.MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(ToString()));
+                }
+                catch (Exception ex)
+                {
+                    throw new AvroRuntimeException("MD5 get exception", ex);
+                }
+                return md5; 
+            }
+        }
+
         /// <summary>
         /// Constructor for Protocol class
         /// </summary>
@@ -187,5 +205,90 @@ namespace Avro
             writer.WriteEndObject();
             writer.WriteEndObject();
         }
+
+        /// <summary>
+        /// Tests equality of this protocol object with the passed object
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <returns></returns>
+        public override bool Equals(object obj)
+        {
+            if (obj == this) return true;
+            if (!(obj is Protocol)) return false;
+
+            Protocol that = obj as Protocol;
+
+            return this.Name.Equals(that.Name) && this.Namespace.Equals(that.Namespace) && 
+                    TypesEquals(that.Types) && MessagesEquals(that.Messages);
+        }
+
+        /// <summary>
+        /// Test equality of this protocols Types list with the passed Types list.
+        /// Order of schemas does not matter, as long as all types in this protocol
+        /// are also defined in the passed protocol
+        /// </summary>
+        /// <param name="that"></param>
+        /// <returns></returns>
+        private bool TypesEquals(IList<Schema> that)
+        {
+            if (Types.Count != that.Count) return false;
+            foreach (Schema schema in Types)
+                if (!that.Contains(schema)) return false;
+            return true;
+        }
+
+        /// <summary>
+        /// Test equality of this protocols Message map with the passed Message map
+        /// Order of messages does not matter, as long as all messages in this protocol
+        /// are also defined in the passed protocol
+        /// </summary>
+        /// <param name="that"></param>
+        /// <returns></returns>
+        private bool MessagesEquals(IDictionary<string, Message> that)
+        {
+            if (Messages.Count != that.Count) return false;
+            foreach (KeyValuePair<string, Message> pair in Messages) 
+            { 
+                if (!that.ContainsKey(pair.Key))
+                    return false;
+                if (!pair.Value.Equals(that[pair.Key]))
+                    return false; 
+            } 
+            return true;
+        }
+
+        /// <summary>
+        /// Returns the hash code of this protocol object
+        /// </summary>
+        /// <returns></returns>
+        public override int GetHashCode()
+        {
+            return Name.GetHashCode() + Namespace.GetHashCode() +
+                   GetTypesHashCode() + GetMessagesHashCode();
+        }
+
+        /// <summary>
+        /// Returns the hash code of the Types list
+        /// </summary>
+        /// <returns></returns>
+        private int GetTypesHashCode()
+        {
+            int hash = Types.Count;
+            foreach (Schema schema in Types)
+                hash += schema.GetHashCode();
+            return hash;
+        }
+
+        /// <summary>
+        /// Returns the hash code of the Messages map
+        /// </summary>
+        /// <returns></returns>
+        private int GetMessagesHashCode()
+        {
+            int hash = Messages.Count;
+            foreach (KeyValuePair<string, Message> pair in Messages)
+                hash += (pair.Key.GetHashCode() + pair.Value.GetHashCode());
+            return hash;
+        }
     }
 }

Modified: avro/branches/branch-1.5/lang/csharp/src/apache/main/Schema/RecordSchema.cs
URL: http://svn.apache.org/viewvc/avro/branches/branch-1.5/lang/csharp/src/apache/main/Schema/RecordSchema.cs?rev=1129077&r1=1129076&r2=1129077&view=diff
==============================================================================
--- avro/branches/branch-1.5/lang/csharp/src/apache/main/Schema/RecordSchema.cs (original)
+++ avro/branches/branch-1.5/lang/csharp/src/apache/main/Schema/RecordSchema.cs Mon May 30 09:01:33 2011
@@ -249,13 +249,13 @@ namespace Avro
         /// <returns></returns>
         public override int GetHashCode()
         {
-            return protect(() =>
+            return protect(() => 0, () =>
             {
                 int result = SchemaName.GetHashCode();
                 foreach (Field f in Fields) result += 29 * f.GetHashCode();
                 result += getHashCode(Props);
                 return result;
-            }, () => 0, this);
+            }, this);
         }
 
         /// <summary>

Modified: avro/branches/branch-1.5/lang/csharp/src/apache/test/Protocol/ProtocolTest.cs
URL: http://svn.apache.org/viewvc/avro/branches/branch-1.5/lang/csharp/src/apache/test/Protocol/ProtocolTest.cs?rev=1129077&r1=1129076&r2=1129077&view=diff
==============================================================================
--- avro/branches/branch-1.5/lang/csharp/src/apache/test/Protocol/ProtocolTest.cs (original)
+++ avro/branches/branch-1.5/lang/csharp/src/apache/test/Protocol/ProtocolTest.cs Mon May 30 09:01:33 2011
@@ -180,5 +180,266 @@ namespace Avro.Test
 
             Assert.AreEqual(json,json2);
         }
+
+        // Protocols match
+        [TestCase(
+@"{
+  ""protocol"": ""TestProtocol"",
+  ""namespace"": ""com.acme"",
+
+  ""types"": [
+    {""name"": ""Greeting"", ""type"": ""record"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]},
+    {""name"": ""Curse"", ""type"": ""error"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]}
+  ],
+
+  ""messages"": {
+    ""hello"": {
+      ""request"": [{""name"": ""greeting"", ""type"": ""Greeting"" }],
+      ""response"": ""Greeting"",
+      ""errors"": [""Curse""]
+    }
+  }
+}", 
+@"{
+  ""protocol"": ""TestProtocol"",
+  ""namespace"": ""com.acme"",
+
+  ""types"": [
+    {""name"": ""Greeting"", ""type"": ""record"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]},
+    {""name"": ""Curse"", ""type"": ""error"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]}
+  ],
+
+  ""messages"": {
+    ""hello"": {
+      ""request"": [{""name"": ""greeting"", ""type"": ""Greeting"" }],
+      ""response"": ""Greeting"",
+      ""errors"": [""Curse""]
+    }
+  }
+}",
+  true,true)]
+        // Protocols match, order of schemas in 'types' are different
+        [TestCase(
+@"{
+  ""protocol"": ""TestProtocol"",
+  ""namespace"": ""com.acme"",
+
+  ""types"": [
+    {""name"": ""Curse"", ""type"": ""error"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]},
+    {""name"": ""Greeting"", ""type"": ""record"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]}
+  ],
+
+  ""messages"": {
+    ""hello"": {
+      ""request"": [{""name"": ""greeting"", ""type"": ""Greeting"" }],
+      ""response"": ""Greeting"",
+      ""errors"": [""Curse""]
+    }
+  }
+}",
+@"{
+  ""protocol"": ""TestProtocol"",
+  ""namespace"": ""com.acme"",
+
+  ""types"": [
+    {""name"": ""Greeting"", ""type"": ""record"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]},
+    {""name"": ""Curse"", ""type"": ""error"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]}
+  ],
+
+  ""messages"": {
+    ""hello"": {
+      ""request"": [{""name"": ""greeting"", ""type"": ""Greeting"" }],
+      ""response"": ""Greeting"",
+      ""errors"": [""Curse""]
+    }
+  }
+}",
+  false,true)]
+        // Name of protocol is different
+        [TestCase(
+@"{
+  ""protocol"": ""TestProtocol1"",
+  ""namespace"": ""com.acme"",
+
+  ""types"": [
+    {""name"": ""Greeting"", ""type"": ""record"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]},
+    {""name"": ""Curse"", ""type"": ""error"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]}
+  ],
+
+  ""messages"": {
+    ""hello"": {
+      ""request"": [{""name"": ""greeting"", ""type"": ""Greeting"" }],
+      ""response"": ""Greeting"",
+      ""errors"": [""Curse""]
+    }
+  }
+}",
+@"{
+  ""protocol"": ""TestProtocol"",
+  ""namespace"": ""com.acme"",
+
+  ""types"": [
+    {""name"": ""Greeting"", ""type"": ""record"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]},
+    {""name"": ""Curse"", ""type"": ""error"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]}
+  ],
+
+  ""messages"": {
+    ""hello"": {
+      ""request"": [{""name"": ""greeting"", ""type"": ""Greeting"" }],
+      ""response"": ""Greeting"",
+      ""errors"": [""Curse""]
+    }
+  }
+}",
+  false,false)]
+        // Name of a message request is different: 'hi'
+        [TestCase(
+@"{
+  ""protocol"": ""TestProtocol"",
+  ""namespace"": ""com.acme"",
+
+  ""types"": [
+    {""name"": ""Greeting"", ""type"": ""record"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]},
+    {""name"": ""Curse"", ""type"": ""error"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]}
+  ],
+
+  ""messages"": {
+    ""hello"": {
+      ""request"": [{""name"": ""greeting"", ""type"": ""Greeting"" }],
+      ""response"": ""Greeting"",
+      ""errors"": [""Curse""]
+    }
+  }
+}",
+@"{
+  ""protocol"": ""TestProtocol"",
+  ""namespace"": ""com.acme"",
+
+  ""types"": [
+    {""name"": ""Greeting"", ""type"": ""record"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]},
+    {""name"": ""Curse"", ""type"": ""error"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]}
+  ],
+
+  ""messages"": {
+    ""hi"": {
+      ""request"": [{""name"": ""greeting"", ""type"": ""Greeting"" }],
+      ""response"": ""Greeting"",
+      ""errors"": [""Curse""]
+    }
+  }
+}",
+  false,false)]
+        // Name of a type is different : Curse1
+        [TestCase(
+@"{
+  ""protocol"": ""TestProtocol"",
+  ""namespace"": ""com.acme"",
+
+  ""types"": [
+    {""name"": ""Greeting"", ""type"": ""record"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]},
+    {""name"": ""Curse1"", ""type"": ""error"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]}
+  ],
+
+  ""messages"": {
+    ""hello"": {
+      ""request"": [{""name"": ""greeting"", ""type"": ""Greeting"" }],
+      ""response"": ""Greeting"",
+      ""errors"": [""Curse1""]
+    }
+  }
+}",
+@"{
+  ""protocol"": ""TestProtocol"",
+  ""namespace"": ""com.acme"",
+
+  ""types"": [
+    {""name"": ""Greeting"", ""type"": ""record"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]},
+    {""name"": ""Curse"", ""type"": ""error"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]}
+  ],
+
+  ""messages"": {
+    ""hi"": {
+      ""request"": [{""name"": ""greeting"", ""type"": ""Greeting"" }],
+      ""response"": ""Greeting"",
+      ""errors"": [""Curse""]
+    }
+  }
+}",
+  false,false)]
+        // Name of a record field is different: 'mymessage'
+        [TestCase(
+@"{
+  ""protocol"": ""TestProtocol"",
+  ""namespace"": ""com.acme"",
+
+  ""types"": [
+    {""name"": ""Greeting"", ""type"": ""record"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]},
+    {""name"": ""Curse"", ""type"": ""error"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]}
+  ],
+
+  ""messages"": {
+    ""hello"": {
+      ""request"": [{""name"": ""greeting"", ""type"": ""Greeting"" }],
+      ""response"": ""Greeting"",
+      ""errors"": [""Curse""]
+    }
+  }
+}",
+@"{
+  ""protocol"": ""TestProtocol"",
+  ""namespace"": ""com.acme"",
+
+  ""types"": [
+    {""name"": ""Greeting"", ""type"": ""record"", ""fields"": [
+      {""name"": ""message"", ""type"": ""string""}]},
+    {""name"": ""Curse"", ""type"": ""error"", ""fields"": [
+      {""name"": ""mymessage"", ""type"": ""string""}]}
+  ],
+
+  ""messages"": {
+    ""hi"": {
+      ""request"": [{""name"": ""greeting"", ""type"": ""Greeting"" }],
+      ""response"": ""Greeting"",
+      ""errors"": [""Curse""]
+    }
+  }
+}",
+  false,false)]
+        public static void TestProtocolHash(string str1, string str2, bool md5_equal, bool hash_equal)
+        {
+            Protocol protocol1 = Protocol.Parse(str1);
+            Protocol protocol2 = Protocol.Parse(str2);
+
+            byte[] md51 = protocol1.MD5;
+            byte[] md52 = protocol2.MD5;
+
+            int hash1 = protocol1.GetHashCode();
+            int hash2 = protocol2.GetHashCode();
+
+            Assert.AreEqual(md5_equal, md51.SequenceEqual(md52));
+            Assert.AreEqual(hash_equal, hash1 == hash2);
+        }
     }
 }