[hyena] Add Serializer, and associated tests



commit 3e59c95cc311e865a16d9a69d09597c42d39f43d
Author: Sandy Armstrong <sanfordarmstrong gmail com>
Date:   Thu Feb 18 16:05:07 2010 -0800

    Add Serializer, and associated tests
    
    Signed-off-by: Gabriel Burt <gabriel burt gmail com>

 src/Hyena/Hyena.Json/Serializer.cs               |  146 +++++++++++++++++
 src/Hyena/Hyena.Json/Tests/OldSerializerTests.cs |  101 ++++++++++++
 src/Hyena/Hyena.Json/Tests/SerializerTests.cs    |  188 +++++++++++++++-------
 src/Hyena/Makefile.am                            |    1 +
 4 files changed, 376 insertions(+), 60 deletions(-)
---
diff --git a/src/Hyena/Hyena.Json/Serializer.cs b/src/Hyena/Hyena.Json/Serializer.cs
new file mode 100644
index 0000000..24eb064
--- /dev/null
+++ b/src/Hyena/Hyena.Json/Serializer.cs
@@ -0,0 +1,146 @@
+// Permission is hereby granted, free of charge, to any person obtaining 
+// a copy of this software and associated documentation files (the 
+// "Software"), to deal in the Software without restriction, including 
+// without limitation the rights to use, copy, modify, merge, publish, 
+// distribute, sublicense, and/or sell copies of the Software, and to 
+// permit persons to whom the Software is furnished to do so, subject to 
+// the following conditions: 
+//  
+// The above copyright notice and this permission notice shall be 
+// included in all copies or substantial portions of the Software. 
+//  
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+// 
+// Copyright (c) 2008 Novell, Inc. (http://www.novell.com) 
+// 
+// Authors: 
+//      Sandy Armstrong <sanfordarmstrong gmail com>
+// 
+
+using System;
+using System.IO;
+using System.Text;
+
+namespace Hyena.Json
+{
+    public class Serializer
+    {
+        private const string serializedNull = "null";
+        private const string serializedTrue = "true";
+        private const string serializedFalse = "false";
+
+        private object input;
+
+        public Serializer () { }
+        public Serializer (object input) { SetInput (input); }
+
+        public void SetInput (object input)
+        {
+            this.input = input;
+        }
+
+        // TODO: Support serialize to stream?
+
+        public string Serialize ()
+        {
+            return Serialize (input);
+        }
+        
+        private string SerializeBool (bool val)
+        {
+            return val ? serializedTrue : serializedFalse;
+        }
+
+        private string SerializeInt (int val)
+        {
+            return val.ToString ();
+        }
+
+        private string SerializeDouble (double val)
+        {
+            return val.ToString ();
+        }
+
+        // TODO: exponent stuff
+
+        private string SerializeString (string val)
+        {
+            // TODO: More work, escaping, etc
+            return "\"" +
+                val.Replace ("\\", "\\\\").
+                    Replace ("\"", "\\\"").
+                    Replace ("\b", "\\b").
+                    Replace ("\f", "\\f").
+                    Replace ("\n", "\\n").
+                    Replace ("\r", "\\r").
+                    Replace ("\t", "\\t") +
+                "\"";
+        }
+
+        private string SerializeArray (JsonArray array)
+        {
+            StringBuilder builder = new StringBuilder ("[");
+            for (int i = 0; i < array.Count; i++) {
+                builder.Append (Serialize (array [i]));
+                if (i != (array.Count -1))
+                    builder.Append (",");
+            }
+            builder.Append ("]");
+            return builder.ToString ();
+        }
+
+        private string SerializeObject (JsonObject obj)
+        {
+            StringBuilder builder = new StringBuilder ("{");
+            foreach (var pair in obj) {
+                builder.Append (SerializeString (pair.Key));
+                builder.Append (":");
+                builder.Append (Serialize (pair.Value));
+                builder.Append (",");
+            }
+            // Get rid of trailing comma
+            if (obj.Count > 0)
+                builder.Remove (builder.Length - 1, 1);
+            builder.Append ("}");
+            return builder.ToString ();
+        }
+
+        private string Serialize (object unknownObj)
+        {
+            if (unknownObj == null)
+                return serializedNull;
+            
+            bool? b = unknownObj as bool?;
+            if (b.HasValue)
+                return SerializeBool (b.Value);
+            
+            int? i = unknownObj as int?;
+            if (i.HasValue)
+                return SerializeInt (i.Value);
+
+            double? d = unknownObj as double?;
+            if (d.HasValue)
+                return SerializeDouble (d.Value);
+
+            string s = unknownObj as string;
+            if (s != null)
+                return SerializeString (s);
+
+            JsonObject o = unknownObj as JsonObject;
+            if (o != null)
+                return SerializeObject (o);
+
+            JsonArray a = unknownObj as JsonArray;
+            if (a != null)
+                return SerializeArray (a);
+
+            throw new ArgumentException ("Cannot serialize anything but doubles, integers, strings, JsonObjects, and JsonArrays");
+        }
+    }
+}
diff --git a/src/Hyena/Hyena.Json/Tests/OldSerializerTests.cs b/src/Hyena/Hyena.Json/Tests/OldSerializerTests.cs
new file mode 100644
index 0000000..b427b5b
--- /dev/null
+++ b/src/Hyena/Hyena.Json/Tests/OldSerializerTests.cs
@@ -0,0 +1,101 @@
+//
+// SerializerTests.cs
+//
+// Author:
+//   Gabriel Burt <gabriel burt gmail com>
+//
+// Copyright (c) 2010 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#if ENABLE_TESTS
+
+using System;
+using System.Linq;
+using System.Reflection;
+using NUnit.Framework;
+
+using Hyena.Json;
+using System.Collections;
+
+namespace Hyena.Json.Tests
+{
+    [TestFixture]
+    public class SerializerTests : Hyena.Tests.TestBase
+    {
+        JsonObject obj;
+        const string obj_serialized = "{\n  \"foo\" : bar\n  \"baz\" : 12,2\n}\n";
+        const string array_serialized = "[\n  foo\n  {\n    \"foo\" : bar\n    \"baz\" : 12,2\n  }\n]\n";
+
+        [TestFixtureSetUp]
+        public void Setup ()
+        {
+            obj = new JsonObject ();
+            obj["foo"] = "bar";
+            obj["baz"] = 12.2;
+        }
+
+        [Test]
+        public void Literal ()
+        {
+            Assert.AreEqual (obj_serialized, obj.ToString ());
+        }
+
+        [Test]
+        public void Array ()
+        {
+            var empty = new JsonArray ();
+            Assert.AreEqual ("[ ]\n", empty.ToString ());
+
+            empty.Add (new JsonArray ());
+            Assert.AreEqual ("[\n  [ ]\n]\n", empty.ToString ());
+
+            empty.Add (new JsonObject ());
+            Assert.AreEqual ("[\n  [ ]\n  { }\n]\n", empty.ToString ());
+
+            var a = new JsonArray ();
+            a.Add ("foo");
+            a.Add (obj);
+            Assert.AreEqual (array_serialized, a.ToString ());
+        }
+
+        [Test]
+        public void ExtensionMethods ()
+        {
+            Assert.AreEqual (
+                "[\n  0\n  1\n  2\n  3\n]\n",
+                Enumerable.Range (0, 4).ToJsonString ()
+            );
+
+            Assert.AreEqual (
+                "{\n  \"True\" : [\n    0\n    2\n  ]\n  \"False\" : [\n    1\n    3\n  ]\n}\n",
+                 Enumerable.Range (0, 4).GroupBy<int, bool> (i => i % 2 == 0).ToJsonString ()
+            );
+
+            /*var a = new ArrayList ();
+            a.Add (Enumerable.Range (0, 4).GroupBy<int, bool> (i => i % 2 == 0));
+            Assert.AreEqual (
+                "",
+                a.ToJsonString ()
+            );*/
+        }
+    }
+}
+
+#endif
diff --git a/src/Hyena/Hyena.Json/Tests/SerializerTests.cs b/src/Hyena/Hyena.Json/Tests/SerializerTests.cs
index b427b5b..12dee24 100644
--- a/src/Hyena/Hyena.Json/Tests/SerializerTests.cs
+++ b/src/Hyena/Hyena.Json/Tests/SerializerTests.cs
@@ -1,99 +1,167 @@
 //
 // SerializerTests.cs
 //
-// Author:
-//   Gabriel Burt <gabriel burt gmail com>
+// Authors:
+//   Sandy Armstrong <sanfordarmstrong gmail com>
 //
-// Copyright (c) 2010 Novell, Inc.
+// Copyright (c) 2009 Novell, Inc. (http://www.novell.com)
 //
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
 //
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
 
 #if ENABLE_TESTS
 
 using System;
-using System.Linq;
-using System.Reflection;
-using NUnit.Framework;
 
 using Hyena.Json;
-using System.Collections;
+
+using NUnit.Framework;
 
 namespace Hyena.Json.Tests
 {
     [TestFixture]
     public class SerializerTests : Hyena.Tests.TestBase
     {
-        JsonObject obj;
-        const string obj_serialized = "{\n  \"foo\" : bar\n  \"baz\" : 12,2\n}\n";
-        const string array_serialized = "[\n  foo\n  {\n    \"foo\" : bar\n    \"baz\" : 12,2\n  }\n]\n";
+        [Test]
+        public void SerializeBoolTest ()
+        {
+            Serializer ser = new Serializer (true);
+            Assert.AreEqual ("true", ser.Serialize ());
+            ser.SetInput (false);
+            Assert.AreEqual ("false", ser.Serialize ());
+        }
+
+        [Test]
+        public void SerializeIntTest ()
+        {
+            Serializer ser = new Serializer (12);
+            Assert.AreEqual ("12", ser.Serialize ());
+            ser.SetInput (-658);
+            Assert.AreEqual ("-658", ser.Serialize ());
+            ser.SetInput (0);
+            Assert.AreEqual ("0", ser.Serialize ());
+        }
+
+        [Test]
+        public void SerializeDoubleTest ()
+        {
+            Serializer ser = new Serializer (12.5);
+            Assert.AreEqual ("12.5", ser.Serialize ());
+            ser.SetInput (-658.1);
+            Assert.AreEqual ("-658.1", ser.Serialize ());
+            ser.SetInput (0.0);
+            Assert.AreEqual ("0", ser.Serialize ());
+            ser.SetInput (0.1);
+            Assert.AreEqual ("0.1", ser.Serialize ());
+        }
 
-        [TestFixtureSetUp]
-        public void Setup ()
+        [Test]
+        public void SerializeStringTest ()
         {
-            obj = new JsonObject ();
-            obj["foo"] = "bar";
-            obj["baz"] = 12.2;
+            VerifyString ("The cat\njumped \"over\" the rat! We escape with \\\"",
+                          @"""The cat\njumped \""over\"" the rat! We escape with \\\""""");
         }
 
         [Test]
-        public void Literal ()
+        public void EscapedCharactersTest ()
         {
-            Assert.AreEqual (obj_serialized, obj.ToString ());
+            VerifyString ("\\", @"""\\""");
+            VerifyString ("\b", @"""\b""");
+            VerifyString ("\f", @"""\f""");
+            VerifyString ("\n", @"""\n""");
+            VerifyString ("\r", @"""\r""");
+            VerifyString ("\t", @"""\t""");
+            VerifyString ("\u2022", "\"\u2022\"");
+        }
+
+        private void VerifyString (string original, string expectedSerialized)
+        {
+            Serializer ser = new Serializer (original);
+            string output = ser.Serialize ();
+            Assert.AreEqual (expectedSerialized, output, "Serialized Output");
+            Assert.AreEqual (original, new Deserializer (output).Deserialize (),
+                             "Input should be identical after serialized then deserialized back to string");
         }
 
         [Test]
-        public void Array ()
+        public void SerializeNullTest ()
         {
-            var empty = new JsonArray ();
-            Assert.AreEqual ("[ ]\n", empty.ToString ());
+            Serializer ser = new Serializer (null);
+            Assert.AreEqual ("null", ser.Serialize ());
+        }
 
-            empty.Add (new JsonArray ());
-            Assert.AreEqual ("[\n  [ ]\n]\n", empty.ToString ());
+        [Test]
+        public void SerializeArrayTest ()
+        {
+            JsonArray simpleArray = new JsonArray ();
+            simpleArray.Add (1);
+            simpleArray.Add ("text");
+            simpleArray.Add (0.1);
+            simpleArray.Add ("5");
+            simpleArray.Add (false);
+            simpleArray.Add (null);
 
-            empty.Add (new JsonObject ());
-            Assert.AreEqual ("[\n  [ ]\n  { }\n]\n", empty.ToString ());
+            Serializer ser = new Serializer (simpleArray);
+            Assert.AreEqual ("[1,\"text\",0.1,\"5\",false,null]",
+                             ser.Serialize ());
 
-            var a = new JsonArray ();
-            a.Add ("foo");
-            a.Add (obj);
-            Assert.AreEqual (array_serialized, a.ToString ());
+            JsonArray emptyArray = new JsonArray ();
+            ser.SetInput (emptyArray);
+            Assert.AreEqual ("[]", ser.Serialize ());
         }
 
+        // TODO: Test arrays/objects in each other, various levels deep
+
         [Test]
-        public void ExtensionMethods ()
+        public void SerializeObjectTest ()
+        {
+            JsonObject obj1 = new JsonObject ();
+            obj1 ["intfield"] = 1;
+            obj1 ["text field"] = "text";
+            obj1 ["double-field"] = 0.1;
+            obj1 ["Boolean, Field"] = true;
+            obj1 ["\"Null\"\nfield"] = null;
+
+            Serializer ser = new Serializer (obj1);
+            // Test object equality, since order not guaranteed
+            string output = ser.Serialize ();
+            JsonObject reconstitutedObj1 = (JsonObject) new Deserializer (output).Deserialize ();
+            AssertJsonObjectsEqual (obj1, reconstitutedObj1);
+
+            JsonObject obj2 = new JsonObject ();
+            obj2 ["double-field"] = 0.1;
+            obj2 ["\"Null\"\nfield"] = null;
+            ser.SetInput (obj2);
+            output = ser.Serialize ();
+            Assert.IsTrue ((output == "{\"double-field\":0.1,\"\\\"Null\\\"\\nfield\":null}") ||
+                           (output == "{\"\\\"Null\\\"\\nfield\":null,\"double-field\":0.1}"),
+                           "Serialized output format");
+        }
+
+        private void AssertJsonObjectsEqual (JsonObject expectedObj, JsonObject actualObj)
         {
-            Assert.AreEqual (
-                "[\n  0\n  1\n  2\n  3\n]\n",
-                Enumerable.Range (0, 4).ToJsonString ()
-            );
-
-            Assert.AreEqual (
-                "{\n  \"True\" : [\n    0\n    2\n  ]\n  \"False\" : [\n    1\n    3\n  ]\n}\n",
-                 Enumerable.Range (0, 4).GroupBy<int, bool> (i => i % 2 == 0).ToJsonString ()
-            );
-
-            /*var a = new ArrayList ();
-            a.Add (Enumerable.Range (0, 4).GroupBy<int, bool> (i => i % 2 == 0));
-            Assert.AreEqual (
-                "",
-                a.ToJsonString ()
-            );*/
+            Assert.AreEqual (expectedObj.Count, actualObj.Count, "Field count");
+            foreach (var expectedPair in expectedObj)
+                Assert.AreEqual (expectedPair.Value,
+                                 actualObj [expectedPair.Key],
+                                 expectedPair.Key + " field");
         }
     }
 }
diff --git a/src/Hyena/Makefile.am b/src/Hyena/Makefile.am
index 7079d95..0247803 100644
--- a/src/Hyena/Makefile.am
+++ b/src/Hyena/Makefile.am
@@ -102,6 +102,7 @@ SOURCES =  \
 	Hyena.Metrics/Sample.cs \
 	Hyena.Metrics/Tests/MetricsTests.cs \
 	Hyena.Json/Deserializer.cs \
+	Hyena.Json/Serializer.cs \
 	Hyena.Json/Tests/SerializerTests.cs \
 	Hyena.Json/IJsonCollection.cs \
 	Hyena.Json/Tests/DeserializerTests.cs \



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]