[gxml/jgs: 5/7] test/jgs: add old json-glib style serialization into its own directory



commit ddeff4217abb9ca6c77120426f50afa69e07e7cb
Author: Richard Schwarting <aquarichy gmail com>
Date:   Mon Apr 14 22:11:49 2014 -0400

    test/jgs: add old json-glib style serialization into its own directory

 test/jgs/SerializableTest.vala  |  290 ++++++++++++++++++
 test/jgs/SerializationTest.vala |  621 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 911 insertions(+), 0 deletions(-)
---
diff --git a/test/jgs/SerializableTest.vala b/test/jgs/SerializableTest.vala
new file mode 100644
index 0000000..be3edaf
--- /dev/null
+++ b/test/jgs/SerializableTest.vala
@@ -0,0 +1,290 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+using GXml;
+using Gee;
+
+/**
+ * Test cases:
+ *   field, property
+ *   primitive, complex, collection, object
+ *   visibility
+ *
+ * *. simple field: int, string, double, bool
+ * *. simple property: int, string, double
+ * *. collection property: glist, ghashtable,
+ * *. gee collection property: list, set, hashtable
+ * *. complex: simple object, complex object, enum, struct etc.
+ *
+ * TODO: How do we want to handle the case of A having B and C as properties, and B and C both have D as a 
property? if we serialize and then deserialize, we'll end up with D1 and D2 separate; we might want to have 
some memory identifier to tell if we've already deserialised something and then we can just pioint to that.
+ *
+ */
+
+/*
+  Test overriding nothing (rely on defaults)
+   Test overriding {de,}serialize_property
+   Test overriding list_properties/find_property
+   Test overriding {set,get}_property
+*/
+
+public class SerializableTomato : GLib.Object, GXml.Serializable {
+       public int weight;
+       private int age { get; set; }
+       public int height { get; set; }
+       public string description { get; set; }
+
+       public SerializableTomato (int weight, int age, int height, string description) {
+               this.weight = weight;
+               this.age = age;
+               this.height = height;
+               this.description = description;
+       }
+
+       public string to_string () {
+               return "SerializableTomato {weight:%d, age:%d, height:%d, description:%s}".printf (weight, 
age, height, description);
+       }
+
+       public static bool equals (SerializableTomato a, SerializableTomato b) {
+               bool same = (a.weight == b.weight &&
+                            a.age == b.age &&
+                            a.height == b.height &&
+                            a.description == b.description);
+
+               return same;
+       }
+}
+
+public class SerializableCapsicum : GLib.Object, GXml.Serializable {
+       public int weight;
+       private int age { get; set; }
+       public int height { get; set; }
+       public unowned GLib.List<int> ratings { get; set; }
+
+       public string to_string () {
+               string str = "SerializableCapsicum {weight:%d, age:%d, height:%d, ratings:".printf (weight, 
age, height);
+               foreach (int rating in ratings) {
+                       str += "%d ".printf (rating);
+               }
+               str += "}";
+               return str;
+       }
+
+       public SerializableCapsicum (int weight, int age, int height, GLib.List<int> ratings) {
+               this.weight = weight;
+               this.age = age;
+               this.height = height;
+               this.ratings = ratings;
+       }
+
+       /* TODO: do we really need GLib.Value? or should we modify the object directly?
+          Want an example using GBoxed too
+          Perhaps these shouldn't be object methods, perhaps they should be static?
+          Can't have static methods in an interface :(, right? */
+       public bool deserialize_property (string property_name, /* out GLib.Value value, */
+                                         GLib.ParamSpec spec, GXml.Node property_node)  {
+               GLib.Value outvalue = GLib.Value (typeof (int));
+
+               switch (property_name) {
+               case "ratings":
+                       this.ratings = new GLib.List<int> ();
+                       foreach (GXml.Node rating in property_node.child_nodes) {
+                               int64.try_parse (((GXml.Element)rating).content, out outvalue);
+                               this.ratings.append ((int)outvalue.get_int64 ());
+                       }
+                       return true;
+               case "height":
+                       int64.try_parse (((GXml.Element)property_node).content, out outvalue);
+                       this.height = (int)outvalue.get_int64 () - 1;
+                       return true;
+               default:
+                       Test.message ("Wasn't expecting the SerializableCapsicum property '%s'", 
property_name);
+                       assert_not_reached ();
+               }
+
+               return false;
+       }
+       public GXml.Node? serialize_property (string property_name, /*GLib.Value value,*/ GLib.ParamSpec 
spec, GXml.Document doc) {
+               GXml.Element c_prop;
+               GXml.Element rating;
+
+               switch (property_name) {
+               case "ratings":
+                       GXml.DocumentFragment frag = doc.create_document_fragment ();
+                       foreach (int rating_int in ratings) {
+                               rating = doc.create_element ("rating");
+                               rating.content = "%d".printf (rating_int);
+                               frag.append_child (rating);
+                       }
+                       return frag;
+               case "height":
+                       return doc.create_text_node ("%d".printf (height + 1));
+               default:
+                       Test.message ("Wasn't expecting the SerializableCapsicum property '%s'", 
property_name);
+                       assert_not_reached ();
+               }
+
+               // returning null does a normal serialization
+               return null;
+       }
+}
+
+
+public class SerializableBanana : GLib.Object, GXml.Serializable {
+       private int private_field;
+       public int public_field;
+       private int private_property { get; set; }
+       public int public_property { get; set; }
+
+       public SerializableBanana (int private_field, int public_field, int private_property, int 
public_property) {
+               this.private_field = private_field;
+               this.public_field = public_field;
+               this.private_property = private_property;
+               this.public_property = public_property;
+
+       }
+
+       public string to_string () {
+               return "SerializableBanana {private_field:%d, public_field:%d, private_property:%d, 
public_property:%d}".printf  (this.private_field, this.public_field, this.private_property, 
this.public_property);
+       }
+
+       public static bool equals (SerializableBanana a, SerializableBanana b) {
+               return (a.private_field == b.private_field &&
+                       a.public_field == b.public_field &&
+                       a.private_property == b.private_property &&
+                       a.public_property == b.public_property);
+       }
+
+       private ParamSpec[] properties = null;
+       public unowned GLib.ParamSpec[] list_properties () {
+               // TODO: so, if someone implements list_properties, but they don't create there array until 
called, that could be inefficient if they don't cache.  If they create it at construction, then serialising 
and deserialising will lose it?   offer guidance
+               if (this.properties == null) {
+                       properties = new ParamSpec[4];
+                       int i = 0;
+                       foreach (string name in new string[] { "private-field", "public-field", 
"private-property", "public-property" }) {
+                               properties[i] = new ParamSpecInt (name, name, name, int.MIN, int.MAX, 0, 
ParamFlags.READABLE); // TODO: offer guidance for these fields, esp. ParamFlags
+                               i++;
+                               // TODO: does serialisation use anything other than ParamSpec.name?
+                       }
+               }
+               return this.properties;
+       }
+
+       private GLib.ParamSpec prop;
+       public unowned GLib.ParamSpec? find_property (string property_name) {
+               GLib.ParamSpec[] properties = this.list_properties ();
+               foreach (ParamSpec prop in properties) {
+                       if (prop.name == property_name) {
+                               this.prop = prop;
+                               return this.prop;
+                       }
+               }
+               return null;
+       }
+
+       public void get_property (GLib.ParamSpec spec, ref GLib.Value str_value) {
+               Value value = Value (typeof (int));
+
+               switch (spec.name) {
+               case "private-field":
+                       value.set_int (this.private_field);
+                       break;
+               case "public-field":
+                       value.set_int (this.public_field);
+                       break;
+               case "private-property":
+                       value.set_int (this.private_property);
+                       break;
+               case "public-property":
+                       value.set_int (this.public_property);
+                       break;
+               default:
+                       ((GLib.Object)this).get_property (spec.name, ref str_value);
+                       return;
+               }
+
+               value.transform (ref str_value);
+               return;
+       }
+
+       public void set_property (GLib.ParamSpec spec, GLib.Value value) {
+               switch (spec.name) {
+               case "private-field":
+                       this.private_field = value.get_int ();
+                       break;
+               case "public-field":
+                       this.public_field = value.get_int ();
+                       break;
+               case "private-property":
+                       this.private_property = value.get_int ();
+                       break;
+               case "public-property":
+                       this.public_property = value.get_int ();
+                       break;
+               default:
+                       ((GLib.Object)this).set_property (spec.name, value);
+                       return;
+               }
+       }
+}
+
+class SerializableTest : GXmlTest {
+       public static void add_tests () {
+               Test.add_func ("/gxml/serializable/interface_defaults", () => {
+                               SerializableTomato tomato = new SerializableTomato (0, 0, 12, "cats");
+
+                               SerializationTest.test_serialization_deserialization (tomato, 
"interface_defaults", (GLib.EqualFunc)SerializableTomato.equals, 
(SerializationTest.StringifyFunc)SerializableTomato.to_string);
+                       });
+               Test.add_func ("/gxml/serializable/interface_override_serialization_on_list", () => {
+                               GXml.Document doc;
+                               SerializableCapsicum capsicum;
+                               SerializableCapsicum capsicum_new;
+                               string expectation;
+                               Regex regex;
+                               GLib.List<int> ratings;
+
+                               // Clear cache to avoid collisions with other tests
+                               Serialization.clear_cache ();
+
+                               ratings = new GLib.List<int> ();
+                               ratings.append (8);
+                               ratings.append (13);
+                               ratings.append (21);
+
+                               capsicum = new SerializableCapsicum (2, 3, 5, ratings);
+                               try {
+                                       doc = Serialization.serialize_object (capsicum);
+                               } catch (GXml.SerializationError e) {
+                                       Test.message ("%s", e.message);
+                                       assert_not_reached ();
+                               }
+
+                               expectation = "<\\?xml version=\"1.0\"\\?>\n<Object 
otype=\"SerializableCapsicum\" oid=\"0x[0-9a-f]+\"><Property ptype=\"gint\" 
pname=\"height\">6</Property><Property ptype=\"gpointer\" 
pname=\"ratings\"><rating>8</rating><rating>13</rating><rating>21</rating></Property></Object>";
+
+                               try {
+                                       regex = new Regex (expectation);
+                                       if (! regex.match (doc.to_string ())) {
+                                               Test.message ("Did not serialize as expected.  Got [%s] but 
expected [%s]", doc.to_string (), expectation);
+                                               assert_not_reached ();
+                                       }
+
+                                       try {
+                                               capsicum_new = 
(SerializableCapsicum)Serialization.deserialize_object (doc);
+                                       } catch (GXml.SerializationError e) {
+                                               Test.message ("%s", e.message);
+                                               assert_not_reached ();
+                                       }
+                                       if (capsicum_new.height != 5 || ratings.length () != 3 || 
ratings.nth_data (0) != 8 || ratings.nth_data (2) != 21) {
+                                               Test.message ("Did not deserialize as expected.  Got [%s] but 
expected height and ratings from [%s]", capsicum_new.to_string (), capsicum.to_string ());
+                                               assert_not_reached ();
+                                       }
+                               } catch (RegexError e) {
+                                       Test.message ("Regular expression [%s] for test failed: %s",
+                                                     expectation, e.message);
+                                       assert_not_reached ();
+                               }
+                       });
+               Test.add_func ("/gxml/serializable/interface_override_properties_view", () => {
+                               SerializableBanana banana = new SerializableBanana (17, 19, 23, 29);
+
+                               SerializationTest.test_serialization_deserialization (banana, 
"interface_override_properties", (GLib.EqualFunc)SerializableBanana.equals, 
(SerializationTest.StringifyFunc)SerializableBanana.to_string);
+                       });
+       }
+}
diff --git a/test/jgs/SerializationTest.vala b/test/jgs/SerializationTest.vala
new file mode 100644
index 0000000..da4accc
--- /dev/null
+++ b/test/jgs/SerializationTest.vala
@@ -0,0 +1,621 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+using GXml;
+using Gee;
+
+/**
+ * Test cases:
+ *   field, property
+ *   primitive, complex, collection, object
+ *   visibility
+ *
+ * *. simple field: int, string, double, bool
+ * *. simple property: int, string, double
+ * *. collection property: glist, ghashtable,
+ * *. gee collection property: list, set, hashtable
+ * *. complex: simple object, complex object, enum, struct etc.
+ *
+ * TODO: How do we want to handle the case of A having B and C as properties, and B and C both have D as a 
property? if we serialize and then deserialize, we'll end up with D1 and D2 separate; we might want to have 
some memory identifier to tell if we've already deserialised something and then we can just pioint to that.
+ *
+ */
+
+/*
+  Test overriding nothing (rely on defaults)
+   Test overriding {de,}serialize_property
+   Test overriding list_properties/find_property
+   Test overriding {set,get}_property
+*/
+
+// TODO: if I don't subclass GLib.Object, a Vala class's object can't be serialised?
+public class Fruit : GLib.Object {
+       string colour;
+       int weight;
+       public string name;
+       public int age {
+               get { return weight; }
+               set { weight = 3 * value; }
+       }
+       public string to_string () {
+               return "Fruit: colour[%s] weight[%d] name[%s] age[%d]".printf(this.colour, this.weight, 
this.name, this.age);
+       }
+
+       public void set_all (string colour, int weight, string name, int age) {
+               this.colour = colour;
+               this.weight = weight; // weight will never matter as age will always overwrite
+               this.name = name;
+               this.age = age;
+       }
+       public bool test (string colour, int weight, string name, int age) {
+               return (this.colour == colour &&
+                       this.weight == weight &&
+                       this.name == name &&
+                       this.age == age);
+       }
+}
+
+public class SimpleFields : GLib.Object {
+       public int public_int;
+       public double public_double;
+       public string public_string;
+       public bool public_bool;
+       private int private_int;
+
+       // TODO: want something like reflection to automate this :D
+       public string to_string () {
+               return "SimpleFields: public_int[%d] public_double[%f] public_string[%s] public_bool[%s] 
private_int[%d]".printf (public_int, public_double, public_string, public_bool.to_string (), private_int);
+       }
+
+       public SimpleFields (int public_int, double public_double,
+                            string public_string, bool public_bool, int private_int) {
+               this.public_int = public_int;
+               this.public_double = public_double;
+               this.public_string = public_string;
+               this.public_bool = public_bool;
+               this.private_int = private_int;
+       }
+
+       public static bool equals (SimpleFields a, SimpleFields b) {
+               return (a.public_double == b.public_double &&
+                       a.public_string == b.public_string &&
+                       a.public_bool == b.public_bool &&
+                       a.private_int == b.private_int);
+       }
+}
+
+public class SimpleProperties : GLib.Object {
+       public int public_int { get; set; }
+       public double public_double { get; set; }
+       public string public_string { get; set; }
+       public bool public_bool { get; set; }
+       private int private_int { get; set; }
+
+       public string to_string () {
+               return "SimpleFields: public_int[%d] public_double[%f] public_string[%s] public_bool[%s] 
private_int[%d]".printf (public_int, public_double, public_string, public_bool.to_string (), private_int);
+       }
+
+       public SimpleProperties (int public_int, double public_double, string public_string, bool 
public_bool, int private_int) {
+               this.public_int = public_int;
+               this.public_double = public_double;
+               this.public_string = public_string;
+               this.public_bool = public_bool;
+               this.private_int = private_int;
+       }
+
+       public static bool equals (SimpleProperties a, SimpleProperties b) {
+               return (a.public_int == b.public_int &&
+                       a.public_double == b.public_double &&
+                       a.public_string == b.public_string &&
+                       a.public_bool == b.public_bool &&
+                       a.private_int == b.private_int);
+       }
+}
+
+public class CollectionProperties : GLib.Object {
+       public unowned GLib.List list { get; set; } // Need to test these with C code too
+       public GLib.HashTable table { get; set; }
+
+       public string to_string () {
+               return "CollectionProperties: list[length:%u] table[size:%u]".printf (list.length (), 
table.size ());
+               // TODO: consider stringifying elements
+       }
+
+       public CollectionProperties (GLib.List list, GLib.HashTable table) {
+               this.list = list;
+               this.table = table;
+       }
+
+       public static bool equals (CollectionProperties a, CollectionProperties b) {
+               return false; // TODO: need to figure out how i want to compare these
+       }
+}
+
+public class GeeCollectionProperties : GLib.Object {
+       public Gee.List list { get; set; }
+       public Gee.HashSet hash_set { get; set; }
+       public Gee.Set geeset { get; set; }
+       public Gee.HashMap map { get; set; }
+       public Gee.Collection collection { get; set; }
+
+       public string to_string () {
+               return "GeeCollectionProperties: list[size:%d] hash_st[size:%d] geeset[size:%d] map[size:%d] 
collection[size:%d]".printf (list.size, hash_set.size, geeset.size, map.size, collection.size);
+               // TODO: consider stringifying elements
+       }
+
+       public GeeCollectionProperties (Gee.List list, Gee.HashSet hash_set, Gee.Set geeset, Gee.HashMap map, 
Gee.Collection collection) {
+               this.list = list;
+               this.hash_set = hash_set;
+               this.geeset = geeset;
+               this.map = map;
+               this.collection = collection;
+       }
+
+       public static bool equals (GeeCollectionProperties a, GeeCollectionProperties b) {
+               return false; // TODO: how do I want to compare these
+       }
+}
+
+public class ComplexSimpleProperties : GLib.Object {
+       public SimpleProperties simple { get; set; }
+
+       public string to_string () {
+               return "ComplexSimpleProperties: simple[%s]".printf (simple.to_string ());
+       }
+
+       public ComplexSimpleProperties (SimpleProperties simple) {
+               this.simple = simple;
+       }
+
+       public static bool equals (ComplexSimpleProperties a, ComplexSimpleProperties b) {
+               return SimpleProperties.equals (a.simple, b.simple);
+       }
+}
+
+public class ComplexDuplicateProperties : GLib.Object {
+       public SimpleProperties a { get; set; }
+       public SimpleProperties b { get; set; }
+
+       public string to_string () {
+               return "ComplexDuplicateProperties: a[%s] b[%s]".printf (a.to_string (), b.to_string ());
+       }
+
+       public ComplexDuplicateProperties (SimpleProperties simple) {
+               this.a = simple;
+               this.b = simple;
+       }
+
+       public static bool equals (ComplexDuplicateProperties cdp_a, ComplexDuplicateProperties cdp_b) {
+               return (SimpleProperties.equals (cdp_a.a, cdp_b.a) &&
+                       SimpleProperties.equals (cdp_a.b, cdp_b.b));
+       }
+}
+
+public class ComplexComplexProperties : GLib.Object {
+       public ComplexSimpleProperties complex_simple { get; set; }
+
+       public string to_string () {
+               return "ComplexComplexProperties: complex_simple[%s]".printf (complex_simple.to_string ());
+       }
+
+       public ComplexComplexProperties (ComplexSimpleProperties complex_simple) {
+               this.complex_simple = complex_simple;
+       }
+
+       public static bool equals (ComplexComplexProperties a, ComplexComplexProperties b) {
+               return ComplexSimpleProperties.equals (a.complex_simple, b.complex_simple);
+       }
+}
+
+public enum EnumProperty {
+       ONE = 11,
+       TWO,
+       THREE;
+}
+
+public class EnumProperties : GLib.Object {
+       public EnumProperty enum_property { get; set; default = EnumProperty.ONE; } // if you don't use 
get;set; it's readonly
+
+       public string to_string () {
+               return "%d".printf (enum_property);
+       }
+
+       public EnumProperties (EnumProperty enum_property) {
+               this.enum_property = enum_property;
+       }
+
+       public static bool equals (EnumProperties a, EnumProperties b) {
+               return (a.enum_property == b.enum_property);
+       }
+}
+
+public class RecursiveProperty : GLib.Object {
+       public RecursiveProperty recursive_property { get; set; }
+       public string addr { get; set; }
+
+       public string to_string () {
+               return "{addr:%s,recursive_property:{addr:%s,recursive_property:{addr:%s,...}}}".printf 
(addr, recursive_property.addr, recursive_property.recursive_property.addr);
+               //return "this:%p{recursive_property:%p{recursive_property:%p{...}}}".printf (this, 
this.recursive_property, this.recursive_property.recursive_property);
+       }
+
+       public RecursiveProperty () {
+               this.recursive_property = this;
+               this.addr = "%p".printf (this);
+       }
+
+       public static bool equals (RecursiveProperty a, RecursiveProperty b) {
+               return (a.to_string () == b.to_string ());
+       }
+}
+
+
+/* **********************  TEST BEGINS *******************************/
+
+class SerializationTest : GXmlTest {
+       public delegate string StringifyFunc (GLib.Object object);
+
+       public static GLib.Object test_serialization_deserialization (GLib.Object object, string name, 
EqualFunc equals, StringifyFunc stringify) {
+               string xml_filename;
+               GXml.Node node;
+               GXml.Document doc;
+               GLib.Object object_new = null;
+
+               // make sure we have a fresh cache without collisions from previous tests
+               Serialization.clear_cache ();
+
+               xml_filename = "_serialization_test_" + name + ".xml";
+
+               try {
+                       node = Serialization.serialize_object (object);
+
+                       // TODO: assert that node is right
+                       node.owner_document.save_to_path (xml_filename);
+                       // TODO: assert that saved file is right
+                       doc = new GXml.Document.from_path (xml_filename);
+                       // TODO: assert that loaded file is right; do document compare with original
+
+                       object_new = Serialization.deserialize_object (doc);
+
+                       if (! equals (object, object_new)) {
+                               Test.message ("Expected [%s] but got [%s]",
+                                             stringify (object), stringify (object_new));
+                               assert_not_reached ();
+                       }
+               } catch (GLib.Error e) {
+                       Test.message ("%s", e.message);
+                       assert_not_reached ();
+               }
+
+               return object_new;
+       }
+
+       public static void add_tests () {
+               bool auto_fields = GLib.Test.thorough (); /* This enables future-looking tests that should be 
failing right now */
+
+               Test.add_func ("/gxml/serialization/xml_serialize", () => {
+                               Fruit fruit;
+                               GXml.Node fruit_xml;
+                               string expectation;
+                               Regex regex;
+
+                               // Clear cache to avoid collisions with other tests
+                               Serialization.clear_cache ();
+
+                               /* TODO: This test should change once we can serialise fields
+                                  and private properties */
+                               expectation = "<\\?xml version=\"1.0\"\\?>\n<Object otype=\"Fruit\" 
oid=\"0x[0-9a-f]+\"><Property( pname=\"age\"| ptype=\"gint\")+>9</Property></Object>";
+
+                               fruit = new Fruit ();
+                               fruit.name = "fish";
+                               fruit.age = 3;
+
+                               try {
+                                       fruit_xml = Serialization.serialize_object (fruit);
+
+                                       regex = new Regex (expectation);
+                                       if (! regex.match (fruit_xml.to_string ())) {
+                                               // TODO: how does Test.message work? Nothing ever seems to 
show up in the test report!
+                                               Test.message ("Expected [%s] but found [%s]",
+                                                             expectation, fruit_xml.to_string ());
+                                               assert_not_reached ();
+                                       }
+                               } catch (RegexError e) {
+                                       Test.message ("Regular expression [%s] for test failed: %s",
+                                                     expectation, e.message);
+                                       assert_not_reached ();
+                               } catch (GXml.SerializationError e) {
+                                       Test.message ("%s", e.message);
+                                       assert_not_reached ();
+                               }
+
+                       });
+               Test.add_func ("/gxml/serialization/xml_deserialize", () => {
+                               Document doc;
+                               Fruit fruit;
+
+                               try {
+                                       doc = new Document.from_string ("<Object otype='Fruit'><Property 
pname='age' ptype='gint'>3</Property></Object>");
+                                       fruit = (Fruit)Serialization.deserialize_object (doc);
+
+                                       // we expect 9 because Fruit triples it in the setter
+                                       if (fruit.age != 9) {
+                                               Test.message ("Expected fruit.age [%d] but found [%d]", 9, 
fruit.age);
+                                               assert_not_reached (); // TODO: check weight?
+                                       }
+                               } catch (GLib.Error e) {
+                                       Test.message ("%s", e.message);
+                                       assert_not_reached ();
+                               }
+                       });
+               Test.add_func ("/gxml/serialization/xml_deserialize_no_type", () => {
+                               Document doc;
+                               Fruit fruit;
+
+                               /* Right now we can infer the type from a property's name, but fields we 
might need to specify */
+                               try {
+                                       doc = new Document.from_string ("<Object otype='Fruit'><Property 
pname='age'>3</Property></Object>");
+                                       fruit = (Fruit)Serialization.deserialize_object (doc);
+                               } catch (GLib.Error e) {
+                                       Test.message ("%s", e.message);
+                                       assert_not_reached ();
+                               }
+                       });
+               Test.add_func ("/gxml/serialization/xml_deserialize_bad_property_name", () => {
+                               Document doc;
+
+                               try {
+                                       doc = new Document.from_string ("<Object otype='Fruit'><Property 
name='badname'>3</Property></Object>");
+                                       Serialization.deserialize_object (doc);
+                                       Test.message ("Expected SerializationError.UNKNOWN_PROPERTY to be 
thrown for property 'badname' in object 'Fruit' :(  Did not happen.");
+                                       assert_not_reached ();
+                               } catch (GXml.SerializationError.UNKNOWN_PROPERTY e) {
+                                       // Pass
+                               } catch (GLib.Error e) {
+                                       Test.message ("%s", e.message);
+                                       assert_not_reached ();
+                               }
+                       });
+               Test.add_func ("/gxml/serialization/xml_deserialize_bad_object_type", () => {
+                               Document doc;
+
+                               try {
+                                       doc = new Document.from_string ("<Object otype='BadType'></Object>");
+                                       Serialization.deserialize_object (doc);
+                                       assert_not_reached ();
+                               } catch (GXml.SerializationError.UNKNOWN_TYPE e) {
+                                       // Pass
+                               } catch (GLib.Error e) {
+                                       Test.message ("%s", e.message);
+                                       assert_not_reached ();
+                               }
+                       });
+               Test.add_func ("/gxml/serialization/xml_deserialize_bad_property_type", () => {
+                               Document doc;
+                               Fruit fruit;
+
+                               // Clear cache to avoid collisions with other tests
+                               Serialization.clear_cache ();
+
+                               try {
+                                       doc = new Document.from_string ("<Object otype='Fruit'><Property 
pname='age' ptype='badtype'>blue</Property></Object>");
+                                       fruit = (Fruit)Serialization.deserialize_object (doc);
+                                       assert_not_reached ();
+                               } catch (GXml.SerializationError.UNSUPPORTED_TYPE e) {
+                                       // Pass
+                               } catch (GLib.Error e) {
+                                       Test.message ("%s", e.message);
+                                       assert_not_reached ();
+                               }
+                       });
+               Test.add_func ("/gxml/serialization/simple_properties", () => {
+                               SimpleProperties obj = new SimpleProperties (3, 4.2, "catfish", true, 0); // 
set private arg just to 0
+                               test_serialization_deserialization (obj, "simple_properties", 
(GLib.EqualFunc)SimpleProperties.equals, (StringifyFunc)SimpleProperties.to_string);
+                       });
+               Test.add_func ("/gxml/serialization/complex_simple_properties", () => {
+                               SimpleProperties simple_properties;
+                               ComplexSimpleProperties obj;
+
+                               simple_properties = new SimpleProperties (3, 4.2, "catfish", true, 0);
+                               obj = new ComplexSimpleProperties (simple_properties);
+
+                               test_serialization_deserialization (obj, "complex_simple_properties", 
(GLib.EqualFunc)ComplexSimpleProperties.equals, (StringifyFunc)ComplexSimpleProperties.to_string);
+                       });
+               Test.add_func ("/gxml/serialization/complex_duplicate_properties", () => {
+                               /* This tests the case where the same object is referenced multiple
+                                  times during serialisation; we want to deserialise it to just
+                                  one object, rather than creating a new object for each reference. */
+
+                               SimpleProperties simple_properties;
+                               ComplexDuplicateProperties obj;
+                               ComplexDuplicateProperties restored;
+                               GXml.Document xml;
+
+                               // Clear cache to avoid collisions with other tests
+                               Serialization.clear_cache ();
+
+                               simple_properties = new SimpleProperties (3, 4.2, "catfish", true, 0);
+                               obj = new ComplexDuplicateProperties (simple_properties);
+
+                               try {
+                                       xml = Serialization.serialize_object (obj);
+
+                                       restored = 
(ComplexDuplicateProperties)Serialization.deserialize_object (xml);
+                               } catch (GXml.SerializationError e) {
+                                       Test.message ("%s", e.message);
+                                       assert_not_reached ();
+                               }
+
+                               if (restored.a != restored.b) {
+                                       Test.message ("Properties a (%p) and b (%p) should reference the same 
object but do not", restored.a, restored.b);
+                                       assert_not_reached ();
+                               }
+                       });
+               Test.add_func ("/gxml/serialization/complex_complex_properties", () => {
+                               ComplexComplexProperties obj;
+                               SimpleProperties simple_properties;
+                               ComplexSimpleProperties complex_simple_properties;
+
+                               simple_properties = new SimpleProperties (3, 4.2, "catfish", true, 0);
+                               complex_simple_properties = new ComplexSimpleProperties (simple_properties);
+                               obj = new ComplexComplexProperties (complex_simple_properties);
+
+                               test_serialization_deserialization (obj, "complex_complex_properties", 
(GLib.EqualFunc)ComplexComplexProperties.equals, (StringifyFunc)ComplexComplexProperties.to_string);
+                       });
+               Test.add_func ("/gxml/serialization/enum_properties", () => {
+                               EnumProperties obj = new EnumProperties (EnumProperty.THREE);
+                               test_serialization_deserialization (obj, "enum_properties", 
(GLib.EqualFunc)EnumProperties.equals, (StringifyFunc)EnumProperties.to_string);
+                       });
+               Test.add_func ("/gxml/serialization/recursion", () => {
+                               RecursiveProperty obj = new RecursiveProperty ();
+
+                               test_serialization_deserialization (obj, "recursion", 
(GLib.EqualFunc)RecursiveProperty.equals, (StringifyFunc)RecursiveProperty.to_string);
+                       });
+
+
+               // TODO: more to do, for structs and stuff and things that interfaces
+               if (auto_fields) {
+                       /* This doesn't really belong here, but auto_fields should really change to 
future_tests,
+                          as automatically serializing fields and GeeCollections are both currently not 
supported. */
+                       Test.add_func ("/gxml/serialization/gee_collection_tree_set", () => {
+                                       Gee.TreeSet<string> s = new Gee.TreeSet<string> ();
+
+                                       s.add ("stars");
+                                       s.add ("Sterne");
+                                       s.add ("etoile");
+
+                                       test_serialization_deserialization (s, "gee_collection_tree_set",
+                                                                           (ao, bo) => { // equals
+                                                                                   Gee.TreeSet<string> a = 
(Gee.TreeSet<string>)ao;
+                                                                                   Gee.TreeSet<string> b = 
(Gee.TreeSet<string>)bo;
+
+                                                                                   return 
(((Gee.Collection)a).contains_all (b) && ((Gee.Collection)b).contains_all (a));
+                                                                           },
+                                                                           (obj) => { // to_string
+                                                                                   Gee.TreeSet<string> 
tree_set = (Gee.TreeSet<string>)obj;
+
+                                                                                   string str = "{ ";
+                                                                                   foreach (string item in 
tree_set) {
+                                                                                           str += "[" + item 
+ "] ";
+                                                                                   }
+                                                                                   str += "}";
+                                                                                   return str;
+                                                                           });
+                               });
+
+                       Test.message ("WARNING: thorough tests are expected to fail, as they test " +
+                                     "feature not yet implemented, pertaining to automatic handling " +
+                                     "of fields and private properties.  You can achieve the same " +
+                                     "effect as these features, though, by making a class implement " +
+                                     "GXmlSerializable and overriding its view of its properties " +
+                                     "for GXmlSerialization.");
+
+                       Test.add_func ("/gxml/serialization/collection_properties", () => {
+                                       // TODO: want a test with more complex data than strings
+
+                                       CollectionProperties obj;
+                                       GLib.List<string> list;
+                                       GLib.HashTable<string,string> table;
+
+                                       list = new GLib.List<string> ();
+                                       list.append ("a");
+                                       list.append ("b");
+                                       list.append ("c");
+
+                                       table = new GLib.HashTable<string,string> (GLib.str_hash, 
GLib.str_equal);
+                                       table.set ("aa", "AA");
+                                       table.set ("bb", "BB");
+                                       table.set ("cc", "CC");
+
+                                       obj = new CollectionProperties (list, table);
+
+                                       test_serialization_deserialization (obj, "collection_properties", 
(GLib.EqualFunc)CollectionProperties.equals, (StringifyFunc)CollectionProperties.to_string);
+                               });
+                       Test.add_func ("/gxml/serialization/gee_collection_properties", () => {
+                                       GeeCollectionProperties obj;
+
+                                       Gee.List<string> list = new Gee.ArrayList<string> ();
+                                       Gee.HashSet<string> hashset = new Gee.HashSet<string> ();
+                                       Gee.Set<string> tset = new Gee.TreeSet<string> ();
+                                       Gee.HashMap<string,string> map = new Gee.HashMap<string,string> ();
+                                       Gee.Collection<string> col = new Gee.LinkedList<string> ();
+
+                                       foreach (string str in new string[] { "a", "b", "c" }) {
+                                               list.add (str);
+                                               hashset.add (str);
+                                               tset.add (str);
+                                               map.set (str + str, str + str + str);
+                                               col.add (str);
+                                       }
+
+                                       obj = new GeeCollectionProperties (list, hashset, tset, map, col);
+                                       test_serialization_deserialization (obj, "gee_collection_properties", 
(GLib.EqualFunc)GeeCollectionProperties.equals, (StringifyFunc)GeeCollectionProperties.to_string);
+                               });
+
+                       Test.add_func ("/gxml/serialization/xml_automatically_serialize_fields", () => {
+                                       /* NOTE: We expect this one to fail right now */
+
+                                       Fruit fruit;
+                                       GXml.Node fruit_xml;
+                                       string expectation;
+                                       Regex regex;
+
+                                       // Clear cache to avoid collisions with other tests
+                                       Serialization.clear_cache ();
+
+                                       expectation = "<Object otype=\"Fruit\" oid=\"0x[0-9a-f]+\"><Property 
pname=\"colour\">blue</Property><Property pname=\"weight\">9</Property><Property 
pname=\"name\">fish</Property><Property pname=\"age\" ptype=\"gint\">3</Property></Object>";
+                                       // weight expected to be 9 because age sets it *3
+
+                                       fruit = new Fruit ();
+                                       fruit.set_all ("blue", 11, "fish", 3);
+
+                                       try {
+                                               fruit_xml = Serialization.serialize_object (fruit);
+
+                                               regex = new Regex (expectation);
+                                               if (! regex.match (fruit_xml.to_string ())) {
+                                                       Test.message ("Expected [%s] but found [%s]",
+                                                                     expectation, fruit_xml.to_string ());
+                                                       assert_not_reached ();
+                                               }
+                                       } catch (RegexError e) {
+                                               Test.message ("Regular expression [%s] for test failed: %s",
+                                                             expectation, e.message);
+                                               assert_not_reached ();
+                                       } catch (GXml.SerializationError e) {
+                                               Test.message ("%s", e.message);
+                                               assert_not_reached ();
+                                       }
+                               });
+                       Test.add_func ("/gxml/serialization/xml_deserialize_fields", () => {
+                                       /* TODO: expecting this one to fail right now,
+                                          because we probably still don't support fields,
+                                          just properties. */
+                                       Document doc;
+                                       Fruit fruit;
+
+                                       // Clear cache to avoid collisions with other tests
+                                       Serialization.clear_cache ();
+
+                                       try {
+                                               doc = new Document.from_string ("<Object 
otype='Fruit'><Property pname='colour' ptype='gchararray'>blue</Property><Property pname='weight' 
ptype='gint'>11</Property><Property pname='name' ptype='gchararray'>fish</Property><Property pname='age' 
ptype='gint'>3</Property></Object>");
+                                               fruit = (Fruit)Serialization.deserialize_object (doc);
+
+                                               if (! fruit.test ("blue", 11, "fish", 3)) {
+                                                       Test.message ("Expected [\"%s\", %d, \"%s\", %d] but 
found [%s]", "blue", 11, "fish", 3, fruit.to_string ());
+                                                       assert_not_reached (); // Note that age sets weight 
normally
+                                               }
+                                       } catch (GXml.SerializationError e) {
+                                               Test.message ("%s", e.message);
+                                               assert_not_reached ();
+                                       }
+                               });
+                       Test.add_func ("/gxml/serialization/simple_fields", () => {
+                                       SimpleFields obj = new SimpleFields (3, 4.5, "cat", true, 6);
+                                       test_serialization_deserialization (obj, "simple_fields", 
(GLib.EqualFunc)SimpleFields.equals, (StringifyFunc)SimpleFields.to_string);
+                               });
+                       Test.add_func ("/gxml/serialization/simple_properties_private", () => {
+                                       SimpleProperties obj = new SimpleProperties (3, 4.2, "catfish", true, 
9);  // 5th arg is private
+                                       test_serialization_deserialization (obj, "simple_properties", 
(GLib.EqualFunc)SimpleProperties.equals, (StringifyFunc)SimpleProperties.to_string);
+                               });
+               }
+               /*** WARNING: above block is CONDITIONAL ***/
+
+       }
+}


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