Support x:Arguments in XamlObjectWriter.
[mono.git] / mcs / class / System.Xaml / Test / System.Xaml / XamlObjectWriterTest.cs
1 //
2 // Copyright (C) 2010 Novell Inc. http://novell.com
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //
23 using System;
24 using System.Collections;
25 using System.Collections.Generic;
26 using System.ComponentModel;
27 using System.IO;
28 using System.Linq;
29 using System.Reflection;
30 using System.Windows.Markup;
31 using System.Xaml;
32 using System.Xaml.Schema;
33 using System.Xml;
34 using NUnit.Framework;
35
36 using CategoryAttribute = NUnit.Framework.CategoryAttribute;
37
38 namespace MonoTests.System.Xaml
39 {
40         [TestFixture]
41         public class XamlObjectWriterTest
42         {
43                 PropertyInfo str_len = typeof (string).GetProperty ("Length");
44                 XamlSchemaContext sctx = new XamlSchemaContext (null, null);
45                 XamlType xt, xt2, xt3, xt4;
46                 XamlMember xm, xm2, xm3;
47
48                 public XamlObjectWriterTest ()
49                 {
50                         xt = new XamlType (typeof (string), sctx);
51                         xt2 = new XamlType (typeof (List<int>), sctx);
52                         xt3 = new XamlType (typeof (TestClass1), sctx);
53                         xt4 = new XamlType (typeof (Foo), sctx);
54                         xm = new XamlMember (str_len, sctx);
55                         xm2 = new XamlMember (typeof (TestClass1).GetProperty ("TestProp1"), sctx);
56                         xm3 = new XamlMember (typeof (TestClass1).GetProperty ("TestProp2"), sctx);
57                 }
58                 
59                 public class TestClass1
60                 {
61                         public TestClass1 ()
62                         {
63                                 TestProp3 = "foobar";
64                         }
65                         public string TestProp1 { get; set; }
66                         // nested.
67                         public TestClass1 TestProp2 { get; set; }
68                         public string TestProp3 { get; set; }
69                         public int TestProp4 { get; set; }
70                 }
71
72                 public class Foo : List<int>
73                 {
74                         public Foo ()
75                         {
76                                 Bar = new List<string> ();
77                         }
78                         public List<string> Bar { get; private set; }
79                         public List<string> Baz { get; set; }
80                         public string Ext { get; set; }
81                 }
82                 
83                 [Test]
84                 [ExpectedException (typeof (ArgumentNullException))]
85                 public void SchemaContextNull ()
86                 {
87                         new XamlObjectWriter (null);
88                 }
89
90                 [Test]
91                 public void SettingsNull ()
92                 {
93                         // allowed.
94                         var w = new XamlObjectWriter (sctx, null);
95                         Assert.AreEqual (sctx, w.SchemaContext, "#1");
96                 }
97
98                 [Test]
99                 [ExpectedException (typeof (XamlObjectWriterException))]
100                 public void InitWriteEndMember ()
101                 {
102                         new XamlObjectWriter (sctx, null).WriteEndMember ();
103                 }
104
105                 [Test]
106                 [ExpectedException (typeof (XamlObjectWriterException))]
107                 public void InitWriteEndObject ()
108                 {
109                         new XamlObjectWriter (sctx, null).WriteEndObject ();
110                 }
111
112                 [Test]
113                 [ExpectedException (typeof (XamlObjectWriterException))]
114                 public void InitWriteGetObject ()
115                 {
116                         new XamlObjectWriter (sctx, null).WriteGetObject ();
117                 }
118
119                 [Test]
120                 [ExpectedException (typeof (XamlObjectWriterException))]
121                 public void InitWriteValue ()
122                 {
123                         new XamlObjectWriter (sctx, null).WriteValue ("foo");
124                 }
125
126                 [Test]
127                 [ExpectedException (typeof (XamlObjectWriterException))]
128                 public void InitWriteStartMember ()
129                 {
130                         new XamlObjectWriter (sctx, null).WriteStartMember (new XamlMember (str_len, sctx));
131                 }
132
133                 [Test]
134                 public void InitWriteNamespace ()
135                 {
136                         var xw = new XamlObjectWriter (sctx, null);
137                         xw.WriteNamespace (new NamespaceDeclaration ("urn:foo", "x")); // ignored.
138                         xw.Close ();
139                         Assert.IsNull (xw.Result, "#1");
140                 }
141
142                 [Test]
143                 [ExpectedException (typeof (ArgumentNullException))]
144                 public void WriteNamespaceNull ()
145                 {
146                         new XamlObjectWriter (sctx, null).WriteNamespace (null);
147                 }
148
149                 [Test]
150                 public void InitWriteStartObject ()
151                 {
152                         var xw = new XamlObjectWriter (sctx, null);
153                         xw.WriteStartObject (new XamlType (typeof (int), sctx));
154                         xw.Close ();
155                         Assert.AreEqual (0, xw.Result, "#1");
156                 }
157
158                 [Test]
159                 [ExpectedException (typeof (XamlObjectWriterException))]
160                 public void GetObjectAfterStartObject ()
161                 {
162                         var xw = new XamlObjectWriter (sctx, null);
163                         xw.WriteStartObject (xt3);
164                         xw.WriteGetObject ();
165                 }
166
167                 [Test]
168                 //[ExpectedException (typeof (XamlObjectWriterException))]
169                 public void WriteStartObjectAfterTopLevel ()
170                 {
171                         var xw = new XamlObjectWriter (sctx, null);
172                         xw.WriteStartObject (xt3);
173                         xw.WriteEndObject ();
174                         // writing another root is <del>not</del> allowed.
175                         xw.WriteStartObject (xt3);
176                 }
177
178                 [Test]
179                 [ExpectedException (typeof (XamlObjectWriterException))]
180                 public void WriteEndObjectExcess ()
181                 {
182                         var xw = new XamlObjectWriter (sctx, null);
183                         xw.WriteStartObject (xt3);
184                         xw.WriteEndObject ();
185                         xw.WriteEndObject ();
186                 }
187
188                 [Test]
189                 [ExpectedException (typeof (XamlObjectWriterException))]
190                 public void StartObjectWriteEndMember ()
191                 {
192                         var xw = new XamlObjectWriter (sctx, null);
193                         xw.WriteStartObject (xt3);
194                         xw.WriteEndMember ();
195                 }
196
197                 [Test]
198                 public void WriteObjectAndMember ()
199                 {
200                         var xw = new XamlObjectWriter (sctx, null);
201                         xw.WriteStartObject (xt3);
202                         xw.WriteStartMember (xm2);
203                         xw.WriteValue ("foo");
204                         xw.WriteEndMember ();
205                         xw.Close ();
206                 }
207
208                 [Test]
209                 public void StartMemberWriteEndMember ()
210                 {
211                         var xw = new XamlObjectWriter (sctx, null);
212                         xw.WriteStartObject (xt3);
213                         xw.WriteStartMember (xm3);
214                         xw.WriteEndMember (); // unlike XamlXmlWriter, it is not treated as an error...
215                         xw.Close ();
216                 }
217
218                 [Test]
219                 [ExpectedException (typeof (XamlObjectWriterException))]
220                 public void StartMemberWriteStartMember ()
221                 {
222                         var xw = new XamlObjectWriter (sctx, null);
223                         xw.WriteStartObject (xt3);
224                         xw.WriteStartMember (xm3);
225                         xw.WriteStartMember (xm3);
226                 }
227
228                 [Test]
229                 public void WriteObjectInsideMember ()
230                 {
231                         var xw = new XamlObjectWriter (sctx, null);
232                         xw.WriteStartObject (xt3);
233                         xw.WriteStartMember (xm3);
234                         xw.WriteStartObject (xt3);
235                         xw.WriteEndObject ();
236                         xw.WriteEndMember ();
237                         xw.Close ();
238                 }
239
240                 [Test]
241                 [ExpectedException (typeof (XamlDuplicateMemberException))]
242                 public void ValueAfterObject ()
243                 {
244                         var xw = new XamlObjectWriter (sctx, null);
245                         xw.WriteStartObject (xt3);
246                         xw.WriteStartMember (xm3);
247                         xw.WriteStartObject (xt3);
248                         xw.WriteEndObject ();
249                         // passes here, but ...
250                         xw.WriteValue ("foo");
251                         // rejected here, unlike XamlXmlWriter.
252                         //
253                         // Basically, assume that no content could be written 
254                         // for an object member within XamlObjectWriter.
255                         xw.WriteEndMember ();
256                 }
257
258                 [Test]
259                 [ExpectedException (typeof (XamlDuplicateMemberException))]
260                 public void ValueAfterObject2 ()
261                 {
262                         var xw = new XamlObjectWriter (sctx, null);
263                         xw.WriteStartObject (xt3);
264                         xw.WriteStartMember (xm3);
265                         xw.WriteStartObject (xt3);
266                         xw.WriteEndObject ();
267                         // passes here, but should be rejected later.
268                         xw.WriteValue ("foo");
269
270                         xw.WriteEndMember (); // Though this raises an error.
271                 }
272
273                 [Test]
274                 [ExpectedException (typeof (XamlDuplicateMemberException))]
275                 public void DuplicateAssignment ()
276                 {
277                         var xw = new XamlObjectWriter (sctx, null);
278                         xw.WriteStartObject (xt3);
279                         xw.WriteStartMember (xm3);
280                         xw.WriteStartObject (xt3);
281                         xw.WriteEndObject ();
282                         xw.WriteValue ("foo"); // causes duplicate assignment.
283                         xw.WriteEndMember ();
284                 }
285
286                 [Test]
287                 [ExpectedException (typeof (XamlDuplicateMemberException))]
288                 [Category ("NotWorking")]
289                 public void DuplicateAssignment2 ()
290                 {
291                         var xw = new XamlObjectWriter (sctx, null);
292                         xw.WriteStartObject (xt3);
293                         xw.WriteStartMember (xm3);
294                         xw.WriteStartObject (xt3);
295                         xw.WriteEndObject ();
296                         xw.WriteEndMember ();
297                         xw.WriteStartMember (xm3);
298                 }
299
300                 [Test]
301                 //[ExpectedException (typeof (ArgumentException))] // oh? XamlXmlWriter raises this.
302                 [Category ("NotWorking")] // so, it's not worthy of passing.
303                 public void WriteValueTypeMismatch ()
304                 {
305                         var xw = new XamlObjectWriter (sctx, null);
306                         xw.WriteStartObject (xt);
307                         xw.WriteStartMember (XamlLanguage.Initialization);
308                         xw.WriteValue (new TestClass1 ());
309                         xw.WriteEndMember ();
310                         xw.Close ();
311                         Assert.IsNotNull (xw.Result, "#1");
312                         Assert.AreEqual (typeof (TestClass1), xw.Result.GetType (), "#2");
313                 }
314
315                 [Test]
316                 [ExpectedException (typeof (XamlObjectWriterException))] // it fails to convert type and set property value.
317                 public void WriteValueTypeMismatch2 ()
318                 {
319                         var xw = new XamlObjectWriter (sctx, null);
320                         xw.WriteStartObject (xt3);
321                         xw.WriteStartMember (xm3);
322                         xw.WriteValue ("foo");
323                         xw.WriteEndMember ();
324                 }
325
326                 [Test]
327                 public void WriteValueTypeOK ()
328                 {
329                         var xw = new XamlObjectWriter (sctx, null);
330                         xw.WriteStartObject (xt);
331                         xw.WriteStartMember (XamlLanguage.Initialization);
332                         xw.WriteValue ("foo");
333                         xw.WriteEndMember ();
334                         xw.Close ();
335                         Assert.AreEqual ("foo", xw.Result, "#1");
336                 }
337
338                 [Test]
339                 // This behavior is different from XamlXmlWriter. Compare to XamlXmlWriterTest.WriteValueList().
340                 public void WriteValueList ()
341                 {
342                         var xw = new XamlObjectWriter (sctx, null);
343                         xw.WriteStartObject (new XamlType (typeof (List<string>), sctx));
344                         xw.WriteStartMember (XamlLanguage.Items);
345                         xw.WriteValue ("foo");
346                         xw.WriteValue ("bar");
347                         xw.WriteEndMember ();
348                         xw.Close ();
349                         var l = xw.Result as List<string>;
350                         Assert.IsNotNull (l, "#1");
351                         Assert.AreEqual ("foo", l [0], "#2");
352                         Assert.AreEqual ("bar", l [1], "#3");
353                 }
354
355                 // I believe .NET XamlObjectWriter.Dispose() is hack and should
356                 // be fixed to exactly determine which of End (member or object)
357                 // to call that results in this ExpectedException.
358                 // Surprisingly, PositionalParameters is allowed to be closed
359                 // without EndMember. So it smells that .NET is hacky.
360                 // We should disable this test and introduce better code (which
361                 // is already in XamlWriterInternalBase).
362                 [Test]
363                 [ExpectedException (typeof (XamlObjectWriterException))]
364                 [Ignore ("See the comment in XamlObjectWriterTest.cs")]
365                 public void CloseWithoutEndMember ()
366                 {
367                         var xw = new XamlObjectWriter (sctx, null);
368                         xw.WriteStartObject (xt);
369                         xw.WriteStartMember (XamlLanguage.Initialization);
370                         xw.WriteValue ("foo");
371                         xw.Close ();
372                 }
373
374                 [Test]
375                 [ExpectedException (typeof (XamlObjectWriterException))]
376                 public void WriteValueAfterValue ()
377                 {
378                         var xw = new XamlObjectWriter (sctx, null);
379                         xw.WriteStartObject (xt);
380                         xw.WriteValue ("foo");
381                         xw.WriteValue ("bar");
382                 }
383
384                 [Test]
385                 [ExpectedException (typeof (XamlObjectWriterException))]
386                 public void WriteValueAfterNullValue ()
387                 {
388                         var xw = new XamlObjectWriter (sctx, null);
389                         xw.WriteStartObject (xt);
390                         xw.WriteValue (null);
391                         xw.WriteValue ("bar");
392                 }
393
394                 [ExpectedException (typeof (XamlObjectWriterException))]
395                 public void StartMemberWriteEndObject ()
396                 {
397                         var xw = new XamlObjectWriter (sctx, null);
398                         xw.WriteStartObject (xt3);
399                         xw.WriteStartMember (xm3);
400                         xw.WriteEndObject ();
401                 }
402
403                 [Test]
404                 public void WriteNamespace ()
405                 {
406                         var xw = new XamlObjectWriter (sctx, null);
407                         xw.WriteNamespace (new NamespaceDeclaration (XamlLanguage.Xaml2006Namespace, "x"));
408                         xw.WriteNamespace (new NamespaceDeclaration ("urn:foo", "y"));
409                         xw.WriteStartObject (xt3);
410                         xw.WriteEndObject ();
411                         xw.Close ();
412                         var ret = xw.Result;
413                         Assert.IsTrue (ret is TestClass1, "#1");
414                 }
415
416                 [Test]
417                 [ExpectedException (typeof (XamlObjectWriterException))]
418                 public void StartObjectStartObject ()
419                 {
420                         var xw = new XamlObjectWriter (sctx, null);
421                         xw.WriteStartObject (xt3);
422                         xw.WriteStartObject (xt3);
423                 }
424
425                 [Test]
426                 [ExpectedException (typeof (XamlObjectWriterException))]
427                 public void StartObjectValue ()
428                 {
429                         var xw = new XamlObjectWriter (sctx, null);
430                         xw.WriteStartObject (xt3);
431                         xw.WriteValue ("foo");
432                 }
433
434                 [Test]
435                 [ExpectedException (typeof (XamlDuplicateMemberException))] // duplicate member assignment
436                 public void ObjectContainsObjectAndObject ()
437                 {
438                         var xw = new XamlObjectWriter (sctx, null);
439                         xw.WriteStartObject (xt3);
440                         xw.WriteStartMember (xm3);
441                         xw.WriteStartObject (xt3);
442                         xw.WriteEndObject ();
443                         xw.WriteStartObject (xt3);
444                         xw.WriteEndObject (); // the exception happens *here*
445                         // FIXME: so, WriteEndMember() should not be required, but we fail here. Practically this difference should not matter.
446                         xw.WriteEndMember (); // of xm3
447                 }
448
449                 [Test]
450                 [ExpectedException (typeof (XamlDuplicateMemberException))] // duplicate member assignment
451                 public void ObjectContainsObjectAndValue ()
452                 {
453                         var xw = new XamlObjectWriter (sctx, null);
454                         xw.WriteStartObject (xt3);
455                         xw.WriteStartMember (xm3);
456                         xw.WriteStartObject (xt3);
457                         xw.WriteEndObject ();
458                         xw.WriteValue ("foo"); // but this is allowed ...
459
460                         xw.WriteEndMember (); // Though this raises an error.
461                 }
462
463                 [Test]
464                 [ExpectedException (typeof (XamlDuplicateMemberException))] // duplicate member assignment
465                 public void ObjectContainsObjectAndValue2 ()
466                 {
467                         var xw = new XamlObjectWriter (sctx, null);
468                         xw.WriteStartObject (xt3);
469                         xw.WriteStartMember (xm3);
470                         xw.WriteStartObject (xt3);
471                         xw.WriteEndObject ();
472                         xw.WriteValue ("foo");
473                         xw.WriteEndMember (); // ... until here.
474                 }
475
476                 [Test]
477                 [ExpectedException (typeof (XamlObjectWriterException))] // unlike XamlXmlWriter (IOE)
478                 public void EndObjectAfterNamespace ()
479                 {
480                         var xw = new XamlObjectWriter (sctx, null);
481                         xw.WriteStartObject (xt3);
482                         xw.WriteNamespace (new NamespaceDeclaration ("urn:foo", "y"));
483                         xw.WriteEndObject ();
484                 }
485
486                 [Test]
487                 [ExpectedException (typeof (XamlObjectWriterException))] // ... unlike XamlXmlWriter (throws IOE)
488                 public void WriteValueAfterNamespace ()
489                 {
490                         var xw = new XamlObjectWriter (sctx, null);
491                         xw.WriteStartObject (xt);
492                         xw.WriteStartMember (XamlLanguage.Initialization);
493                         xw.WriteNamespace (new NamespaceDeclaration ("urn:foo", "y"));
494                         xw.WriteValue ("foo");
495                 }
496
497                 [Test]
498                 [ExpectedException (typeof (XamlObjectWriterException))] // ... unlike XamlXmlWriter (allowed)
499                 public void ValueThenStartObject ()
500                 {
501                         var xw = new XamlObjectWriter (sctx, null);
502                         xw.WriteStartObject (xt3);
503                         xw.WriteStartMember (xm2);
504                         xw.WriteValue ("foo");
505                         xw.WriteStartObject (xt3);
506                         xw.Close ();
507                 }
508
509                 [Test]
510                 [ExpectedException (typeof (XamlObjectWriterException))] // ... unlike XamlXmlWriter (allowed, as it allows StartObject after Value)
511                 public void ValueThenNamespace ()
512                 {
513                         var xw = new XamlObjectWriter (sctx, null);
514                         xw.WriteStartObject (xt3);
515                         xw.WriteStartMember (xm2);
516                         xw.WriteValue ("foo");
517                         xw.WriteNamespace (new NamespaceDeclaration ("y", "urn:foo")); // this does not raise an error (since it might start another object)
518                 }
519
520                 [Test]
521                 [ExpectedException (typeof (XamlObjectWriterException))] // strange, this does *not* result in IOE...
522                 public void ValueThenNamespaceThenEndMember ()
523                 {
524                         var xw = new XamlObjectWriter (sctx, null);
525                         xw.WriteStartObject (xt3);
526                         xw.WriteStartMember (xm2);
527                         xw.WriteValue ("foo");
528                         xw.WriteNamespace (new NamespaceDeclaration ("y", "urn:foo"));
529                         xw.WriteEndMember ();
530                 }
531
532                 [Test]
533                 [ExpectedException (typeof (XamlObjectWriterException))] // This is also very different, requires exactly opposite namespace output manner to XamlXmlWriter (namespace first, object follows).
534                 public void StartMemberAfterNamespace ()
535                 {
536                         var xw = new XamlObjectWriter (sctx, null);
537                         xw.WriteStartObject (xt3);
538                         xw.WriteNamespace (new NamespaceDeclaration ("urn:foo", "y"));
539                 }
540
541                 [Test]
542                 [Category ("NotWorking")]
543                 public void StartMemberBeforeNamespace ()
544                 {
545                         var xw = new XamlObjectWriter (sctx, null);
546                         xw.WriteStartObject (xt3);
547                         xw.WriteStartMember (xm2); // note that it should be done *after* WriteNamespace in XamlXmlWriter. SO inconsistent.
548                         xw.WriteNamespace (new NamespaceDeclaration ("urn:foo", "y"));
549                         xw.WriteEndMember ();
550                         xw.Close ();
551                 }
552
553                 [Test]
554                 [ExpectedException (typeof (XamlObjectWriterException))]
555                 public void StartMemberBeforeNamespace2 ()
556                 {
557                         var xw = new XamlObjectWriter (sctx, null);
558                         xw.WriteStartObject (xt3);
559                         xw.WriteStartMember (xm2);
560                         xw.WriteNamespace (new NamespaceDeclaration ("urn:foo", "y"));
561                         // and here, NamespaceDeclaration is written as if it 
562                         // were another value object( unlike XamlXmlWriter)
563                         // and rejects further value.
564                         xw.WriteValue ("foo");
565                 }
566
567                 [Test]
568                 [ExpectedException (typeof (XamlObjectWriterException))]
569                 public void EndMemberThenStartObject ()
570                 {
571                         var xw = new XamlObjectWriter (sctx, null);
572                         xw.WriteStartObject (xt3);
573                         xw.WriteStartMember (xm2);
574                         xw.WriteValue ("foo");
575                         xw.WriteEndMember ();
576                         xw.WriteStartObject (xt3);
577                 }
578
579                 // The semantics on WriteGetObject() is VERY different from XamlXmlWriter.
580
581                 [Test]
582                 [ExpectedException (typeof (XamlObjectWriterException))]
583                 public void GetObjectOnNullValue ()
584                 {
585                         var xw = new XamlObjectWriter (sctx, null);
586                         xw.WriteStartObject (xt3);
587                         xw.WriteStartMember (xm2);
588                         xw.WriteGetObject ();
589                 }
590
591                 [Test]
592                 [ExpectedException (typeof (XamlObjectWriterException))]
593                 public void GetObjectOnNullValue2 ()
594                 {
595                         var xw = new XamlObjectWriter (sctx, null);
596                         xw.WriteStartObject (xt4);
597                         xw.WriteStartMember (new XamlMember (typeof (Foo).GetProperty ("Baz"), sctx)); // unlike Bar, Baz is not initialized.
598                         xw.WriteGetObject (); // fails, because it is null.
599                 }
600
601                 [Test]
602                 [Category ("NotWorking")]
603                 public void GetObjectOnIntValue ()
604                 {
605                         var xw = new XamlObjectWriter (sctx, null);
606                         xw.WriteStartObject (xt3);
607                         xw.WriteStartMember (xt3.GetMember ("TestProp4")); // int
608                         xw.WriteGetObject (); // passes!!! WTF
609                         xw.WriteEndObject ();
610                 }
611
612                 [Test]
613                 // String is not treated as a collection on XamlXmlWriter, while this XamlObjectWriter does.
614                 public void GetObjectOnNonNullString ()
615                 {
616                         var xw = new XamlObjectWriter (sctx, null);
617                         xw.WriteStartObject (xt3);
618                         Assert.IsNull (xw.Result, "#1");
619                         xw.WriteStartMember (xt3.GetMember ("TestProp3"));
620                         xw.WriteGetObject ();
621                         Assert.IsNull (xw.Result, "#2");
622                 }
623
624                 [Test]
625                 public void GetObjectOnCollection ()
626                 {
627                         var xw = new XamlObjectWriter (sctx, null);
628                         xw.WriteStartObject (xt4);
629                         xw.WriteStartMember (new XamlMember (typeof (Foo).GetProperty ("Bar"), sctx));
630                         xw.WriteGetObject ();
631                         xw.Close ();
632                 }
633
634                 [Test]
635                 [ExpectedException (typeof (XamlObjectWriterException))]
636                 public void ValueAfterGetObject ()
637                 {
638                         var xw = new XamlObjectWriter (sctx, null);
639                         xw.WriteStartObject (xt4);
640                         xw.WriteStartMember (new XamlMember (typeof (Foo).GetProperty ("Bar"), sctx));
641                         xw.WriteGetObject ();
642                         xw.WriteValue ("foo");
643                 }
644
645                 [Test]
646                 [ExpectedException (typeof (XamlObjectWriterException))]
647                 public void StartObjectAfterGetObject ()
648                 {
649                         var xw = new XamlObjectWriter (sctx, null);
650                         xw.WriteStartObject (xt4);
651                         xw.WriteStartMember (new XamlMember (typeof (Foo).GetProperty ("Bar"), sctx));
652                         xw.WriteGetObject ();
653                         xw.WriteStartObject (xt);
654                 }
655
656                 [Test]
657                 [ExpectedException (typeof (XamlObjectWriterException))]
658                 public void EndMemberAfterGetObject ()
659                 {
660                         var xw = new XamlObjectWriter (sctx, null);
661                         xw.WriteStartObject (xt4);
662                         xw.WriteStartMember (new XamlMember (typeof (Foo).GetProperty ("Bar"), sctx));
663                         xw.WriteGetObject ();
664                         xw.WriteEndMember (); // ...!?
665                 }
666
667                 [Test]
668                 public void StartMemberAfterGetObject ()
669                 {
670                         var xw = new XamlObjectWriter (sctx, null);
671                         xw.WriteStartObject (xt4);
672                         var xmm = xt4.GetMember ("Bar");
673                         xw.WriteStartMember (xmm); // <List.Bar>
674                         xw.WriteGetObject (); // shifts current member to List<T>.
675                         xw.WriteStartMember (xmm.Type.GetMember ("Capacity"));
676                         xw.WriteValue (5);
677                         xw.WriteEndMember ();
678                         /*
679                         xw.WriteEndObject (); // got object
680                         xw.WriteEndMember (); // Bar
681                         xw.WriteEndObject (); // started object
682                         */
683                         xw.Close ();
684                 }
685
686                 [Test]
687                 public void EndObjectAfterGetObject ()
688                 {
689                         var xw = new XamlObjectWriter (sctx, null);
690                         xw.WriteStartObject (xt4);
691                         xw.WriteStartMember (new XamlMember (typeof (Foo).GetProperty ("Bar"), sctx));
692                         xw.WriteGetObject ();
693                         xw.WriteEndObject ();
694                 }
695
696                 // extra use case based tests.
697
698                 [Test]
699                 public void WriteEx_Type_WriteString ()
700                 {
701                         var ow = new XamlObjectWriter (sctx);
702                         ow.WriteNamespace (new NamespaceDeclaration (XamlLanguage.Xaml2006Namespace, "x"
703                         ));
704                         ow.WriteStartObject (XamlLanguage.Type);
705                         ow.WriteStartMember (XamlLanguage.PositionalParameters);
706                         ow.WriteValue ("x:Int32");
707                         ow.Close ();
708                         Assert.AreEqual (typeof (int), ow.Result, "#1");
709                 }
710
711                 [Test]
712                 public void WriteEx_Type_WriteType ()
713                 {
714                         var ow = new XamlObjectWriter (sctx);
715                         ow.WriteNamespace (new NamespaceDeclaration (XamlLanguage.Xaml2006Namespace, "x"
716                         ));
717                         ow.WriteStartObject (XamlLanguage.Type);
718                         ow.WriteStartMember (XamlLanguage.PositionalParameters);
719                         ow.WriteValue (typeof (int));
720                         ow.Close ();
721                         Assert.AreEqual (typeof (int), ow.Result, "#1");
722                 }
723                 
724                 // common use case based tests (to other readers/writers).
725
726                 XamlReader GetReader (string filename)
727                 {
728                         return new XamlXmlReader (XmlReader.Create (Path.Combine ("Test/XmlFiles", filename), new XmlReaderSettings () { CloseInput =true }));
729                 }
730
731                 [Test]
732                 public void Write_String ()
733                 {
734                         using (var xr = GetReader ("String.xml")) {
735                                 var des = XamlServices.Load (xr);
736                                 Assert.AreEqual ("foo", des, "#1");
737                         }
738                 }
739
740                 [Test]
741                 public void Write_Int32 ()
742                 {
743                         using (var xr = GetReader ("Int32.xml")) {
744                                 var des = XamlServices.Load (xr);
745                                 Assert.AreEqual (5, des, "#1");
746                         }
747                 }
748
749                 [Test]
750                 public void Write_DateTime ()
751                 {
752                         using (var xr = GetReader ("DateTime.xml")) {
753                                 var des = XamlServices.Load (xr);
754                                 Assert.AreEqual (new DateTime (2010, 4, 14), des, "#1");
755                         }
756                 }
757
758                 [Test]
759                 public void Write_TimeSpan ()
760                 {
761                         using (var xr = GetReader ("TimeSpan.xml")) {
762                                 var des = XamlServices.Load (xr);
763                                 Assert.AreEqual (TimeSpan.FromMinutes (7), des, "#1");
764                         }
765                 }
766
767                 [Test]
768                 public void Write_Uri ()
769                 {
770                         using (var xr = GetReader ("Uri.xml")) {
771                                 var des = XamlServices.Load (xr);
772                                 Assert.AreEqual (new Uri ("urn:foo"), des, "#1");
773                         }
774                 }
775
776                 [Test]
777                 public void Write_Null ()
778                 {
779                         using (var xr = GetReader ("NullExtension.xml")) {
780                                 var des = XamlServices.Load (xr);
781                                 Assert.IsNull (des, "#1");
782                         }
783                 }
784
785                 [Test]
786                 public void Write_Type ()
787                 {
788                         using (var xr = GetReader ("Type.xml")) {
789                                 var des = XamlServices.Load (xr);
790                                 Assert.AreEqual (typeof (int), des, "#1");
791                         }
792                 }
793
794                 [Test]
795                 public void Write_Type2 ()
796                 {
797                         var obj = typeof (MonoTests.System.Xaml.TestClass1);
798                         using (var xr = GetReader ("Type2.xml")) {
799                                 var des = XamlServices.Load (xr);
800                                 Assert.AreEqual (obj, des, "#1");
801                         }
802                 }
803
804                 [Test]
805                 public void Write_Guid ()
806                 {
807                         var obj = Guid.Parse ("9c3345ec-8922-4662-8e8d-a4e41f47cf09");
808                         using (var xr = GetReader ("Guid.xml")) {
809                                 var des = XamlServices.Load (xr);
810                                 Assert.AreEqual (obj, des, "#1");
811                         }
812                 }
813
814                 [Test]
815                 [ExpectedException (typeof (XamlObjectWriterException))] // cannot resolve the StaticExtension value.
816                 [Category ("NotWorking")]
817                 public void Write_StaticExtension ()
818                 {
819                         var obj = new StaticExtension ("FooBar");
820                         using (var xr = GetReader ("StaticExtension.xml")) {
821                                 var des = XamlServices.Load (xr);
822                                 Assert.AreEqual (obj, des, "#1");
823                         }
824                 }
825
826                 [Test]
827                 [Ignore ("Not sure why MemberType is NOT serialized. Needs investigation")]
828                 public void Write_StaticExtension2 ()
829                 {
830                         var obj = new StaticExtension ("FooBar"); //incorrect
831                         using (var xr = GetReader ("StaticExtension2.xml")) {
832                                 var des = XamlServices.Load (xr);
833                                 Assert.AreEqual (obj, des, "#1");
834                         }
835                 }
836
837                 [Test]
838                 public void Write_Reference ()
839                 {
840                         using (var xr = GetReader ("Reference.xml")) {
841                                 var des = XamlServices.Load (xr);
842                                 // .NET does not return Reference.
843                                 // Its ProvideValue() returns MS.Internal.Xaml.Context.NameFixupToken,
844                                 // which is assumed (by name) to resolve to the referenced object.
845                                 Assert.IsNotNull (des, "#1");
846                                 //Assert.AreEqual (new Reference ("FooBar"), des, "#1");
847                         }
848                 }
849
850                 [Test]
851                 public void Write_ArrayInt32 ()
852                 {
853                         var obj = new int [] {4, -5, 0, 255, int.MaxValue};
854                         using (var xr = GetReader ("Array_Int32.xml")) {
855                                 var des = XamlServices.Load (xr);
856                                 Assert.AreEqual (obj, des, "#1");
857                         }
858                 }
859
860                 [Test]
861                 public void Write_ListInt32 ()
862                 {
863                         var obj = new int [] {5, -3, int.MaxValue, 0}.ToList ();
864                         using (var xr = GetReader ("List_Int32.xml")) {
865                                 var des = (List<int>) XamlServices.Load (xr);
866                                 Assert.AreEqual (obj.ToArray (), des.ToArray (), "#1");
867                         }
868                 }
869
870                 [Test]
871                 public void Write_ListInt32_2 ()
872                 {
873                         var obj = new List<int> (new int [0]) { Capacity = 0 }; // set explicit capacity for trivial implementation difference
874                         using (var xr = GetReader ("List_Int32_2.xml")) {
875                                 var des = (List<int>) XamlServices.Load (xr);
876                                 Assert.AreEqual (obj.ToArray (), des.ToArray (), "#1");
877                         }
878                 }
879
880                 [Test]
881                 public void Write_ListType ()
882                 {
883                         var obj = new List<Type> (new Type [] {typeof (int), typeof (Dictionary<Type, XamlType>)}) { Capacity = 2 };
884                         using (var xr = GetReader ("List_Type.xml")) {
885                                 var des = XamlServices.Load (xr);
886                                 Assert.AreEqual (obj, des, "#1");
887                         }
888                 }
889
890                 [Test]
891                 [Category ("NotWorking")]
892                 public void Write_DictionaryInt32String ()
893                 {
894                         var dic = new Dictionary<int,string> ();
895                         dic.Add (0, "foo");
896                         dic.Add (5, "bar");
897                         dic.Add (-2, "baz");
898                         using (var xr = GetReader ("Dictionary_Int32_String.xml")) {
899                                 var des = XamlServices.Load (xr);
900                                 Assert.AreEqual (dic, des, "#1");
901                         }
902                 }
903
904                 [Test]
905                 [Category ("NotWorking")]
906                 public void Write_DictionaryStringType ()
907                 {
908                         var dic = new Dictionary<string,Type> ();
909                         dic.Add ("t1", typeof (int));
910                         dic.Add ("t2", typeof (int []));
911                         dic.Add ("t3", typeof (int?));
912                         dic.Add ("t4", typeof (List<int>));
913                         dic.Add ("t5", typeof (Dictionary<int,DateTime>));
914                         dic.Add ("t6", typeof (List<KeyValuePair<int,DateTime>>));
915                         using (var xr = GetReader ("Dictionary_String_Type.xml")) {
916                                 var des = XamlServices.Load (xr);
917                                 Assert.AreEqual (dic, des, "#1");
918                         }
919                 }
920
921                 [Test]
922                 [Ignore ("Needs to get successfully deserialized. Currently we can't")]
923                 public void Write_PositionalParameters1Wrapper ()
924                 {
925                         // Unlike the above case, this has the wrapper object and hence PositionalParametersClass1 can be written as an attribute (markup extension)
926                         var obj = new PositionalParametersWrapper ("foo", 5);
927                         using (var xr = GetReader ("PositionalParametersWrapper.xml")) {
928                                 var des = XamlServices.Load (xr);
929                                 Assert.AreEqual (obj, des, "#1");
930                         }
931                 }
932                 
933                 [Test]
934                 public void Write_ArgumentAttributed ()
935                 {
936                         //var obj = new ArgumentAttributed ("foo", "bar");
937                         using (var xr = GetReader ("ArgumentAttributed.xml")) {
938                                 var des = (ArgumentAttributed) XamlServices.Load (xr);
939                                 Assert.AreEqual ("foo", des.Arg1, "#1");
940                                 Assert.AreEqual ("bar", des.Arg2, "#2");
941                         }
942                 }
943
944                 [Test]
945                 public void Write_ArrayExtension2 ()
946                 {
947                         //var obj = new ArrayExtension (typeof (int));
948                         using (var xr = GetReader ("ArrayExtension2.xml")) {
949                                 var des = XamlServices.Load (xr);
950                                 // The resulting object is not ArrayExtension.
951                                 Assert.AreEqual (new int [0], des, "#1");
952                         }
953                 }
954
955                 [Test]
956                 public void Write_ArrayList ()
957                 {
958                         var obj = new ArrayList (new int [] {5, -3, 0});
959                         using (var xr = GetReader ("ArrayList.xml")) {
960                                 var des = XamlServices.Load (xr);
961                                 Assert.AreEqual (obj, des, "#1");
962                         }
963                 }
964
965                 [Test]
966                 [Ignore ("Needs to get successfully deserialized. Currently we can't")]
967                 public void ComplexPositionalParameterWrapper ()
968                 {
969                         //var obj = new ComplexPositionalParameterWrapper () { Param = new ComplexPositionalParameterClass (new ComplexPositionalParameterValue () { Foo = "foo" })};
970                         using (var xr = GetReader ("ComplexPositionalParameterWrapper.xml")) {
971                                 var des = (ComplexPositionalParameterWrapper) XamlServices.Load (xr);
972                                 Assert.IsNotNull (des.Param, "#1");
973                                 Assert.AreEqual ("foo", des.Param.Value, "#2");
974                         }
975                 }
976
977                 [Test]
978                 public void Write_ListWrapper ()
979                 {
980                         var obj = new ListWrapper (new List<int> (new int [] {5, -3, 0}) { Capacity = 3}); // set explicit capacity for trivial implementation difference
981                         using (var xr = GetReader ("ListWrapper.xml")) {
982                                 var des = (ListWrapper) XamlServices.Load (xr);
983                                 Assert.IsNotNull (des, "#1");
984                                 Assert.IsNotNull (des.Items, "#2");
985                                 Assert.AreEqual (obj.Items.ToArray (), des.Items.ToArray (), "#3");
986                         }
987                 }
988
989                 [Test]
990                 public void Write_ListWrapper2 ()
991                 {
992                         var obj = new ListWrapper2 (new List<int> (new int [] {5, -3, 0}) { Capacity = 3}); // set explicit capacity for trivial implementation difference
993                         using (var xr = GetReader ("ListWrapper2.xml")) {
994                                 var des = (ListWrapper2) XamlServices.Load (xr);
995                                 Assert.IsNotNull (des, "#1");
996                                 Assert.IsNotNull (des.Items, "#2");
997                                 Assert.AreEqual (obj.Items.ToArray (), des.Items.ToArray (), "#3");
998                         }
999                 }
1000
1001                 [Test]
1002                 public void Write_MyArrayExtension ()
1003                 {
1004                         //var obj = new MyArrayExtension (new int [] {5, -3, 0});
1005                         using (var xr = GetReader ("MyArrayExtension.xml")) {
1006                                 var des = XamlServices.Load (xr);
1007                                 // ProvideValue() returns an array
1008                                 Assert.AreEqual (new int [] {5, -3, 0}, des, "#1");
1009                         }
1010                 }
1011
1012                 [Test]
1013                 public void Write_MyArrayExtensionA ()
1014                 {
1015                         //var obj = new MyArrayExtensionA (new int [] {5, -3, 0});
1016                         using (var xr = GetReader ("MyArrayExtensionA.xml")) {
1017                                 var des = XamlServices.Load (xr);
1018                                 // ProvideValue() returns an array
1019                                 Assert.AreEqual (new int [] {5, -3, 0}, des, "#1");
1020                         }
1021                 }
1022
1023                 [Test]
1024                 public void Write_MyExtension ()
1025                 {
1026                         //var obj = new MyExtension () { Foo = typeof (int), Bar = "v2", Baz = "v7"};
1027                         using (var xr = GetReader ("MyExtension.xml")) {
1028                                 var des = XamlServices.Load (xr);
1029                                 // ProvideValue() returns this.
1030                                 Assert.AreEqual ("provided_value", des, "#1");
1031                         }
1032                 }
1033
1034                 [Test]
1035                 [ExpectedException (typeof (InvalidCastException))] // unable to cast string to MarkupExtension
1036                 [Category ("NotWorking")]
1037                 public void Write_MyExtension2 ()
1038                 {
1039                         //var obj = new MyExtension2 () { Foo = typeof (int), Bar = "v2"};
1040                         using (var xr = GetReader ("MyExtension2.xml")) {
1041                                 XamlServices.Load (xr);
1042                         }
1043                 }
1044
1045                 [Test]
1046                 public void Write_MyExtension3 ()
1047                 {
1048                         //var obj = new MyExtension3 () { Foo = typeof (int), Bar = "v2"};
1049                         using (var xr = GetReader ("MyExtension3.xml")) {
1050                                 var des = XamlServices.Load (xr);
1051                                 // StringConverter is used and the resulting value comes from ToString().
1052                                 Assert.AreEqual ("MonoTests.System.Xaml.MyExtension3", des, "#1");
1053                         }
1054                 }
1055
1056                 [Test]
1057                 [ExpectedException (typeof (XamlObjectWriterException))] // wrong TypeConverter input (input string for DateTimeConverter invalid)
1058                 public void Write_MyExtension4 ()
1059                 {
1060                         var obj = new MyExtension4 () { Foo = typeof (int), Bar = "v2"};
1061                         using (var xr = GetReader ("MyExtension4.xml")) {
1062                                 var des = XamlServices.Load (xr);
1063                                 Assert.AreEqual (obj, des, "#1");
1064                         }
1065                 }
1066
1067                 [Test]
1068                 public void Write_MyExtension6 ()
1069                 {
1070                         //var obj = new MyExtension6 ("foo");
1071                         using (var xr = GetReader ("MyExtension6.xml")) {
1072                                 var des = XamlServices.Load (xr);
1073                                 // ProvideValue() returns this.
1074                                 Assert.AreEqual ("foo", des, "#1");
1075                         }
1076                 }
1077                 
1078                 [Test]
1079                 public void Write_PropertyDefinition ()
1080                 {
1081                         //var obj = new PropertyDefinition () { Modifier = "protected", Name = "foo", Type = XamlLanguage.String };
1082                         using (var xr = GetReader ("PropertyDefinition.xml")) {
1083                                 var des = (PropertyDefinition) XamlServices.Load (xr);
1084                                 Assert.AreEqual ("protected", des.Modifier, "#1");
1085                                 Assert.AreEqual ("foo", des.Name, "#2");
1086                                 Assert.AreEqual (XamlLanguage.String, des.Type, "#3");
1087                         }
1088                 }
1089         }
1090 }