2 // ComplexDataStructure.cs
5 // Lluis Sanchez Gual (lluis@ximian.com)
7 // (C) 2004 Novell, Inc.
13 using System.Xml.Schema;
14 using System.Xml.Serialization;
15 using System.Collections;
16 using System.ComponentModel;
17 using NUnit.Framework;
19 namespace MonoTests.System.XmlSerialization
22 public class ComplexDataStructure
25 [NUnit.Framework.Category("NotDotNet")] // FDBK50639
26 public void WriteLiteral ()
28 Test data = BuildTestObject ();
30 XmlSerializer ss = new XmlSerializer (GetLiteralTypeMapping ());
31 XmlSerializerNamespaces nams = new XmlSerializerNamespaces ();
32 StringWriter sw = new StringWriter();
33 ss.Serialize (sw,data,nams);
34 string serialized = sw.ToString ();
35 serialized = XmlSerializerTests.Infoset (serialized);
37 StreamReader sr = new StreamReader ("Test/XmlFiles/literal-data.xml");
38 string expected = sr.ReadToEnd ();
41 expected = XmlSerializerTests.Infoset (expected);
42 Assert.AreEqual (expected, serialized);
46 [NUnit.Framework.Category ("NotDotNet")] // MS.NET results in compilation error (probably it generates bogus source.)
47 public void ReadLiteral ()
49 XmlSerializer ss = new XmlSerializer (GetLiteralTypeMapping ());
50 XmlSerializerNamespaces nams = new XmlSerializerNamespaces ();
52 StreamReader sr = new StreamReader ("Test/XmlFiles/literal-data.xml");
53 Test data = (Test) ss.Deserialize (sr);
56 CheckObjectContent (BuildTestObject(), data);
59 XmlTypeMapping GetLiteralTypeMapping ()
61 XmlRootAttribute root = new XmlRootAttribute("rootroot");
62 Type[] types = new Type[] {typeof(UknTestPart), typeof(AnotherTestPart), typeof(DblStringContainer) };
63 XmlReflectionImporter ri = new XmlReflectionImporter ();
64 foreach (Type t in types) ri.IncludeType (t);
65 return ri.ImportTypeMapping (typeof(Test), root);
68 XmlTypeMapping GetEncodedTypeMapping ()
70 SoapReflectionImporter sri = new SoapReflectionImporter ();
71 sri.IncludeType (typeof(UknTestPart));
72 sri.IncludeType (typeof(AnotherTestPart));
73 sri.IncludeType (typeof(DblStringContainer));
74 return sri.ImportTypeMapping (typeof(Test));
77 Test BuildTestObject ()
79 XmlDocument doc = new XmlDocument();
81 Test t = new UknTestPart();
86 t.parts = new TestPart[3];
87 t.parts[0] = new TestPart();
88 t.parts[0].name = "un";
89 t.parts[0].bval = true;
90 t.parts[1] = new TestPart();
91 t.parts[1].name = "dos";
92 t.parts[1].bval = false;
93 t.parts[2] = t.parts[0];
95 t.strings = new string[] { "un", "dos", null, "tres" };
96 t.ushorts = new ushort[] { 1,2,3 };
98 t.ta.extraTextNodes = new XmlNode[] { doc.CreateTextNode ("AA"), doc.CreateTextNode ("BB") };
100 t.tam2 = new TA[][][]
102 new TA[][] { new TA[] {new TA(), new TA()}, new TA[] {new TA(), new TA()}},
103 new TA[][] { new TA[] {new TB(), new TA()}, new TA[] {new TB(), new TA()}},
104 new TA[][] { new TA[] {new TA(), new TB()}, new TA[] {new TA(), new TA()}}
108 t.flatParts = t.parts;
110 t.flatParts2 = new TA[] {new TA(), new TB(), null, new TB()};
112 t.anot = new AnotherTestPart ();
113 ((AnotherTestPart)t.anot).lo = 1234567890;
118 XmlElement e1 = doc.CreateElement ("explicitElement");
119 XmlElement e2 = doc.CreateElement ("subElement");
120 e2.SetAttribute ("unAtrib","val");
121 doc.AppendChild (e1);
126 t.someElems = new XmlNode[3];
128 t.someElems[1] = null;
131 t.extraElems = new XmlElement[1];
132 t.extraElems[0] = doc.CreateElement ("extra1");
133 t.extraElems[0].SetAttribute ("val","1");
135 t.extraElems23 = new XmlElement[2];
136 t.extraElems23[0] = doc.CreateElement ("extra2");
137 t.extraElems23[0].SetAttribute ("val","2");
138 t.extraElems23[1] = doc.CreateElement ("extra3");
139 t.extraElems23[1].SetAttribute ("val","3");
141 t.extraElemsRest = doc.CreateElement ("extra4");
142 t.extraElemsRest.SetAttribute ("val","4");
144 t.uktester = new UnknownAttributeTester();
145 t.uktester.aa = "hihi";
147 t.uktester.extraAtts = new XmlAttribute[3];
148 t.uktester.extraAtts[0] = doc.CreateAttribute ("extraAtt1");
149 t.uktester.extraAtts[0].Value = "val1";
150 t.uktester.extraAtts[1] = doc.CreateAttribute ("extraAtt2");
151 t.uktester.extraAtts[1].Value = "val2";
152 t.uktester.extraAtts[2] = doc.CreateAttribute ("extraAtt3");
153 t.uktester.extraAtts[2].Value = "val3";
156 t.ob4 = (float)54321.12;
159 t.opArray = new option[] { option.CC, option.BB, option.AA };
163 t.byteArray = new byte[] { 11,33,55,222 };
164 t.byteByteArray = new byte[][] { t.byteArray, t.byteArray };
166 t.ttList = new ArrayList();
167 t.ttList.Add ("two");
168 t.ttList.Add ("strings");
169 // t.extraText = "Additional text";
171 t.RoList = new ArrayList ();
172 t.RoList.Add (t.parts[0]);
173 t.RoList.Add (t.parts[1]);
175 /* t.struc = new OneStruct();
177 t.struc.cc = "this is a struct";
179 t.multiList = new ArrayList[2];
180 t.multiList[0] = new ArrayList ();
181 t.multiList[0].Add (22);
182 t.multiList[0].Add (33);
183 t.multiList[1] = new ArrayList ();
184 t.multiList[1].Add (888);
185 t.multiList[1].Add (999);
187 // XmlSerializer does not deserialize default values explicitly.
188 //t.defElem = "theDefValue";
189 //t.defAttr = "theDefValue";
191 t.special = new CustomHashtable ();
192 t.special.Add ("one","1");
193 t.special.Add ("two","2");
194 t.special.Add ("three","3");
196 t.attqname = new XmlQualifiedName ("thename","thenamespace");
198 DblStringContainer dbc = new DblStringContainer ();
199 dbc.doublestring = new string [][] { null, new string[] {"hello"} };
200 AnotherTestPart at = new AnotherTestPart ();
204 DblStringContainerAnm dbca = new DblStringContainerAnm ();
206 t.dbscontainer = dbca;
211 void CheckObjectContent (Test exp, Test t)
213 Assert.AreEqual (exp.a, t.a, "t.a");
214 Assert.AreEqual (exp.b, t.b, "t.b");
215 Assert.AreEqual (exp.bbis, t.bbis, "t.bbis");
216 Assert.AreEqual (exp.c, t.c, "t.c");
218 Assert.IsNotNull (t.parts, "t.parts");
219 CheckParts ("t.parts", exp.parts, t.parts);
221 TestPart.AssertEquals ("t.part", exp.part, t.part);
223 AssertionHelper.AssertEqualsArray ("t.strings", exp.strings, t.strings);
224 AssertionHelper.AssertEqualsArray ("t.ushorts", exp.ushorts, t.ushorts);
226 TA.AssertEquals ("t.ta", exp.ta, t.ta);
228 Assert.IsNotNull (t.tam2, "t.tam2");
229 CheckTaArray ("t.tam2", exp.tam2, t.tam2);
231 Assert.IsNotNull (t.tam3, "t.tam3");
232 CheckTaArray ("t.tam3", exp.tam3, t.tam3);
234 Assert.IsNotNull (t.flatParts, "t.flatParts");
235 CheckParts ("t.flatParts", exp.flatParts, t.flatParts);
237 // Null element is ignored
238 Assert.IsNotNull (t.flatParts2, "t.flatParts2");
239 Assert.AreEqual (3, t.flatParts2.Length, "t.flatParts2.Length");
240 TA.AssertEquals ("t.flatParts2 0", exp.flatParts2[0], t.flatParts2[0]);
241 TA.AssertEquals ("t.flatParts2 1", exp.flatParts2[1], t.flatParts2[1]);
242 TA.AssertEquals ("t.flatParts2 2", exp.flatParts2[3], t.flatParts2[2]);
244 Assert.IsNotNull (t.anot, "t.anot");
245 Assert.AreEqual (((AnotherTestPart)exp.anot).lo, ((AnotherTestPart)t.anot).lo, "t.anot.lo");
247 TestPart.AssertEquals ("t.ob", exp.ob as TestPart, t.ob as TestPart);
248 TestPart.AssertEquals ("t.ob2", exp.ob2 as TestPart, t.ob2 as TestPart);
250 AssertionHelper.AssertEqualsXml ("t.oneElem", exp.oneElem, t.oneElem);
251 AssertionHelper.AssertEqualsXml ("t.oneElem2", exp.oneElem2, t.oneElem2);
253 // One of the elements was null and it is ignored
254 Assert.IsNotNull (t.someElems, "t.someElems");
255 Assert.AreEqual (2, t.someElems.Length, "t.someElems.Length");
256 AssertionHelper.AssertEqualsXml ("t.someElems[0]", exp.someElems[0], t.someElems[0]);
257 AssertionHelper.AssertEqualsXml ("t.someElems[1]", exp.someElems[2], t.someElems[1]);
259 Assert.IsNotNull (t.extraElems, "t.extraElems");
260 Assert.AreEqual (exp.extraElems.Length, t.extraElems.Length, "t.extraElems.Length");
261 for (int n=0; n<exp.extraElems.Length; n++)
262 AssertionHelper.AssertEqualsXml ("t.extraElems[" + n + "]", exp.extraElems[n], t.extraElems[n]);
264 Assert.IsNotNull (t.extraElems23, "t.extraElems23");
265 Assert.AreEqual (exp.extraElems23.Length, t.extraElems23.Length, "t.extraElems23.Length");
266 for (int n=0; n<t.extraElems23.Length; n++)
267 AssertionHelper.AssertEqualsXml ("t.extraElems23[" + n + "]", exp.extraElems23[n], t.extraElems23[n]);
269 AssertionHelper.AssertEqualsXml ("t.extraElemsRest", exp.extraElemsRest, t.extraElemsRest);
271 UnknownAttributeTester.AssertEquals ("t.uktester", exp.uktester, t.uktester);
273 Assert.AreEqual (exp.ob3, t.ob3, "t.ob3");
274 Assert.AreEqual (exp.ob4, t.ob4, "t.ob4");
275 Assert.AreEqual (exp.op1, t.op1, "t.op1");
277 AssertionHelper.AssertEqualsArray ("t.opArray", exp.opArray, t.opArray);
279 Assert.AreEqual (exp.ukOpt, t.ukOpt, "t.ukOpt");
280 Assert.AreEqual (exp.opAtt, t.opAtt, "t.opAtt");
282 AssertionHelper.AssertEqualsArray ("t.byteArray", exp.byteArray, t.byteArray);
283 AssertionHelper.AssertEqualsArray ("t.byteByteArray", exp.byteByteArray, t.byteByteArray);
285 Assert.IsNotNull (t.ttList, "t.ttList");
286 AssertionHelper.AssertEqualsArray ("t.ttList", exp.ttList.ToArray(), t.ttList.ToArray());
288 Assert.IsNotNull (t.RoList, "t.RoList");
289 Assert.AreEqual (exp.RoList.Count, t.RoList.Count, "t.RoList.Count");
290 for (int n=0; n<exp.RoList.Count; n++)
291 TestPart.AssertEquals ("t.RoList " + n, (TestPart)exp.RoList[n], (TestPart)t.RoList[n]);
293 Assert.AreEqual (exp.struc.aa, t.struc.aa, "t.struc.aa");
294 Assert.AreSame (exp.struc.cc, t.struc.cc, "t.struc.cc");
296 Assert.IsNotNull (t.multiList, "t.multiList");
297 Assert.AreEqual (exp.multiList.Length, t.multiList.Length, "t.multiList.Count");
298 for (int n=0; n<exp.multiList.Length; n++)
299 AssertionHelper.AssertEqualsArray ("t.multiList " + n, exp.multiList[n].ToArray(), t.multiList[n].ToArray());
301 Assert.AreEqual (exp.defElem, t.defElem, "t.defElem");
302 Assert.AreEqual (exp.defAttr, t.defAttr, "t.defAttr");
304 CustomHashtable.AssertEquals ("t.special", exp.special, t.special);
306 Assert.AreEqual (exp.attqname, t.attqname, "t.attqname");
308 Assert.IsNotNull (t.dbscontainer, "t.dbscontainer");
309 DblStringContainer tdbca = t.dbscontainer.at as DblStringContainer;
310 DblStringContainer expdbca = exp.dbscontainer.at as DblStringContainer;
311 Assert.IsNotNull (tdbca, "t.dbscontainer.at");
313 Assert.IsNotNull (tdbca, "t.dbscontainer.dbca");
314 AssertionHelper.AssertEqualsArray ("t.dbscontainer.at.doublestring", expdbca.doublestring, tdbca.doublestring);
316 AnotherTestPart tat = tdbca.at as AnotherTestPart;
317 AnotherTestPart expat = expdbca.at as AnotherTestPart;
318 Assert.IsNotNull (tat, "t.dbscontainer.dbca.at");
319 Assert.AreEqual (expat.lo, tat.lo, "t.dbscontainer.dbca.at.lo");
322 void CheckParts (string id, TestPart[] exp, TestPart[] parts)
324 AssertionHelper.AssertType (id, exp, parts);
325 Assert.AreEqual (exp.Length, parts.Length, id + " Len");
326 for (int n=0; n<exp.Length; n++)
327 TestPart.AssertEquals (id + "[" + n + "]", exp[n], parts[n]);
330 void CheckTaArray (string id, TA[][][] exp, TA[][][] arr)
332 AssertionHelper.AssertType (id, exp, arr);
333 Assert.AreEqual (exp.Length, arr.Length, id + " Len");
334 for (int n=0; n<exp.Length; n++)
337 TA[][] expar = exp[n];
339 AssertionHelper.AssertType (id, expar, tar);
340 Assert.AreEqual (expar.Length, tar.Length);
342 for (int m=0; m<expar.Length; m++)
345 TA[] expar2 = expar[m];
347 AssertionHelper.AssertType (id, expar2, tar2);
348 Assert.AreEqual (expar2.Length, tar2.Length, id);
350 for (int i=0; i<expar2.Length; i++)
351 TA.AssertEquals (id + "[" + n + "][" + m + "][" + i + "]", expar2[i], tar2[i]);
357 public class AssertionHelper
359 public static bool AssertType (string id, object exp, object ob)
362 Assert.IsNull (ob, id);
366 Assert.IsNotNull (ob, id);
367 Assert.AreEqual (exp.GetType(), ob.GetType(), id + " type");
372 public static void AssertEqualsXml (string id, XmlNode exp, XmlNode ob)
374 if (!AssertType (id, exp, ob)) return;
375 Assert.AreEqual (XmlSerializerTests.Infoset (exp), XmlSerializerTests.Infoset (ob), id);
378 public static void AssertEqualsArray (string id, Array exp, Array ob)
380 if (!AssertType (id, exp, ob)) return;
381 Assert.AreEqual (exp.GetLength(0), ob.GetLength(0), id + " Length");
382 for (int n=0; n<exp.GetLength(0); n++) {
383 object it = exp.GetValue(n);
385 AssertEqualsArray (id + "[" + n + "]", it as Array, ob.GetValue(n) as Array);
387 Assert.AreEqual (it, ob.GetValue(n), id + "[" + n + "]");
392 [XmlType(TypeName="")]
393 [XmlRoot(ElementName="aaaaaa",Namespace="")]
394 [XmlInclude(typeof(UknTestPart))]
395 [SoapInclude(typeof(UknTestPart))]
398 // public option op;elem.SchemaTypeName
401 [SoapElement(ElementName="suba")]
402 [XmlElement(ElementName="suba",Namespace="kk")]
409 [XmlAttribute (Namespace="attribns")]
412 [XmlElement(Namespace="oo")]
413 public TestPart part;
417 public TestPart[] parts;
419 [SoapElement(ElementName="multita")]
420 [XmlArray(ElementName="multita")]
421 // [XmlArrayItem(ElementName="itema",NestingLevel=1)]
422 [XmlArrayItem(ElementName="itema",Type=typeof(TA),NestingLevel=1)]
423 [XmlArrayItem(ElementName="itemb",Type=typeof(TB),NestingLevel=1)]
424 public TA[][] tam = new TA[][] { new TA[] {new TA(), new TB()}, new TA[] {new TA(), new TA()}};
426 // [SoapElement(ElementName="multita2")]
428 [XmlArray(ElementName="multita2")]
429 [XmlArrayItem(ElementName="data1",NestingLevel=0)]
431 [XmlArrayItem(ElementName="data2",NestingLevel=1,Namespace="da2")]
432 [XmlArrayItem(ElementName="data3a",Type=typeof(TA),NestingLevel=2,Namespace="da3")]
433 [XmlArrayItem(ElementName="data3b",Type=typeof(TB),NestingLevel=2,Namespace="da3")]
434 public TA[][][] tam2;
437 public TA[][][] tam3;
439 [SoapElement(IsNullable=true)]
440 [XmlElement(IsNullable=true)]
441 public string mayBeNull;
443 public string[] strings;
445 [XmlArray(Namespace="arrayNamespace")]
446 public ushort[] ushorts;
449 public TestPart[] flatParts;
451 [SoapElement (ElementName="flatTAs")]
452 [XmlElement (ElementName="flatTAs")]
453 public TA[] flatParts2;
457 [XmlElement (Namespace="uimp")]
464 public XmlElement oneElem;
467 [XmlElement (ElementName="unElement", Namespace="elemns")]
468 public XmlElement oneElem2;
471 [XmlElement (ElementName="unsElements", Namespace="elemns")]
472 public XmlNode[] someElems;
475 [XmlAnyElement ("extra1")]
476 public XmlElement[] extraElems;
479 [XmlAnyElement ("extra2")]
480 [XmlAnyElement ("extra3")]
481 [XmlAnyElement ("extra3","nnn")]
482 public XmlElement[] extraElems23;
486 public XmlElement extraElemsRest;
488 public UnknownAttributeTester uktester;
491 public option[] opArray;
499 public byte[] byteArray;
501 public byte[][] byteByteArray;
503 [XmlElement(Type=typeof(string))]
504 [XmlElement(ElementName="kk",Type=typeof(int))]
505 public object[] tt = new object[] { "aa",22 };
507 public ArrayList ttList;
510 public ArrayList RoList
512 get { return roList; }
513 set { roList = value; }
518 public ArrayList[] multiList;
522 public OneStruct struc;
524 [DefaultValue("theDefValue")]
525 public string defElem;
528 [DefaultValue("theDefValue")]
529 public string defAttr;
531 [XmlText (Type=typeof(string))]
532 [XmlElement (Type=typeof(int))]
533 public object[] xmltext = new object[] {"aa",33,"bb",776};
536 public CustomHashtable special;
539 public XmlQualifiedName attqname;
542 public DateTime[] arrayAttribute;
544 [XmlArray (Namespace="mm")]
545 public string[][] dummyStringArray = new string[][] {null,null};
547 [XmlElement (Namespace="mm")]
548 public DblStringContainerAnm dbscontainer;
551 public class DblStringContainerAnm
556 [XmlType(Namespace="mm")]
557 public class DblStringContainer
559 [XmlArrayItem (NestingLevel=1, IsNullable=true)]
560 public string [][] doublestring;
564 [SoapType(TypeName="TC")]
565 [XmlType(TypeName="TC")]
566 [XmlInclude(typeof(TB))]
567 [SoapInclude(typeof(TB))]
574 public XmlNode[] extraTextNodes;
576 public static void AssertEquals (string id, TA expected, TA ob)
578 if (!AssertionHelper.AssertType (id, expected, ob)) return;
579 Assert.AreEqual (expected.xx, ob.xx, id + " xx");
580 // TODO: extraTextNodes
588 public static void AssertEquals (string id, TB expected, TB ob)
590 if (!AssertionHelper.AssertType (id, expected, ob)) return;
591 Assert.AreEqual (expected.yy, ob.yy, id + " yy");
592 TA.AssertEquals (id + " base", expected, ob);
596 public class UnknownAttributeTester
605 public XmlAttribute[] extraAtts;
607 // [XmlText(Type=typeof(XmlNode))]
608 // public XmlNode extraText;
610 public static void AssertEquals (string id, UnknownAttributeTester exp, UnknownAttributeTester ob)
612 if (!AssertionHelper.AssertType (id, exp, ob)) return;
613 Assert.AreEqual (exp.aa, ob.aa, id + " aa");
615 if (!AssertionHelper.AssertType (id + " extraAtts", exp.extraAtts, ob.extraAtts)) return;
618 for (int n=0; n<ob.extraAtts.Length; n++)
620 XmlAttribute at = ob.extraAtts [n];
621 if (at.NamespaceURI == "http://www.w3.org/2000/xmlns/") continue;
622 Assert.IsTrue (p < exp.extraAtts.Length, id + " extraAtts length");
623 AssertionHelper.AssertEqualsXml (id + ".extraAtts " + n, exp.extraAtts [p], ob.extraAtts[n]);
629 [SoapType(TypeName="UnTestPart", Namespace="mm")]
630 [XmlType(TypeName="UnTestPart", Namespace="mm")]
631 public class TestPart
636 public static void AssertEquals (string id, TestPart expected, TestPart ob)
638 if (!AssertionHelper.AssertType (id, expected, ob)) return;
639 Assert.AreEqual (expected.name, ob.name, id + " name");
640 Assert.AreEqual (expected.bval, ob.bval, id + " bval");
644 [SoapType(Namespace="mm")]
645 [XmlType(Namespace="mm")]
646 public class AnotherTestPart
652 public class UknTestPart : Test
654 [XmlElement(IsNullable=true)]
659 public struct OneStruct
665 // [XmlType(Namespace="enum_namespace")]
669 [SoapEnum(Name="xmlBB")]
670 [XmlEnum(Name="xmlBB")]
676 public class CustomHashtable : IXmlSerializable
678 Hashtable data = new Hashtable ();
680 public void Add (string key, string value)
682 data.Add (key, value);
685 public static void AssertEquals (string id, CustomHashtable exp, CustomHashtable ob)
687 if (!AssertionHelper.AssertType (id, exp, ob)) return;
688 if (!AssertionHelper.AssertType (id, exp.data, ob.data)) return;
690 Assert.AreEqual (exp.data.Count, ob.data.Count, id + " data Count");
692 foreach (DictionaryEntry entry in exp.data)
693 Assert.AreEqual (entry.Value, ob.data[entry.Key]);
696 public void ReadXml (XmlReader reader)
698 // Read the element enclosing the object
699 reader.ReadStartElement();
700 reader.MoveToContent ();
702 // Reads the "data" element
703 reader.ReadStartElement();
704 reader.MoveToContent ();
705 while (reader.NodeType != XmlNodeType.EndElement)
707 if (reader.NodeType == XmlNodeType.Element)
709 string key = reader.LocalName;
710 data [key] = reader.ReadElementString ();
714 reader.MoveToContent ();
717 reader.ReadEndElement ();
720 public void WriteXml (XmlWriter writer)
722 writer.WriteStartElement ("data");
723 foreach (DictionaryEntry entry in data)
725 writer.WriteElementString ((string)entry.Key, (string)entry.Value);
727 writer.WriteEndElement ();
730 public XmlSchema GetSchema ()
732 XmlSchema s = new XmlSchema ();
733 s.TargetNamespace = "http://www.go-mono.org/schemas";
735 XmlSchemaElement e = new XmlSchemaElement ();
738 XmlSchemaComplexType cs = new XmlSchemaComplexType ();
739 XmlSchemaSequence seq = new XmlSchemaSequence ();
740 XmlSchemaAny any = new XmlSchemaAny ();
742 any.MaxOccurs = decimal.MaxValue;