Merge pull request #347 from JamesB7/master
[mono.git] / mcs / class / System.Xaml / Test / System.Xaml / XamlXmlWriterTest.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 NUnit.Framework;
34
35 using CategoryAttribute = NUnit.Framework.CategoryAttribute;
36
37 namespace MonoTests.System.Xaml
38 {
39         [TestFixture]
40         public class XamlXmlWriterTest
41         {
42                 PropertyInfo str_len = typeof (string).GetProperty ("Length");
43                 XamlSchemaContext sctx = new XamlSchemaContext (null, null);
44                 XamlType xt, xt2;
45                 XamlMember xm;
46
47                 public XamlXmlWriterTest ()
48                 {
49                         xt = new XamlType (typeof (string), sctx);
50                         xt2 = new XamlType (typeof (List<int>), sctx);
51                         xm = new XamlMember (str_len, sctx);
52                 }
53
54                 public class Foo : List<int>
55                 {
56                         public List<string> Bar { get; set; }
57                 }
58                 
59                 [Test]
60                 [ExpectedException (typeof (ArgumentNullException))]
61                 public void SchemaContextNull ()
62                 {
63                         new XamlXmlWriter (new MemoryStream (), null);
64                 }
65
66                 [Test]
67                 public void SettingsNull ()
68                 {
69                         // allowed.
70                         var w = new XamlXmlWriter (new MemoryStream (), sctx, null);
71                         Assert.AreEqual (sctx, w.SchemaContext, "#1");
72                         Assert.IsNotNull (w.Settings, "#2");
73                 }
74
75                 [Test]
76                 [ExpectedException (typeof (XamlXmlWriterException))]
77                 public void InitWriteEndMember ()
78                 {
79                         new XamlXmlWriter (new MemoryStream (), sctx, null).WriteEndMember ();
80                 }
81
82                 [Test]
83                 [ExpectedException (typeof (XamlXmlWriterException))]
84                 public void InitWriteEndObject ()
85                 {
86                         new XamlXmlWriter (new MemoryStream (), sctx, null).WriteEndObject ();
87                 }
88
89                 [Test]
90                 [ExpectedException (typeof (XamlXmlWriterException))]
91                 public void InitWriteGetObject ()
92                 {
93                         new XamlXmlWriter (new MemoryStream (), sctx, null).WriteGetObject ();
94                 }
95
96                 [Test]
97                 [ExpectedException (typeof (XamlXmlWriterException))]
98                 public void InitWriteValue ()
99                 {
100                         new XamlXmlWriter (new StringWriter (), sctx, null).WriteValue ("foo");
101                 }
102
103                 [Test]
104                 [ExpectedException (typeof (XamlXmlWriterException))]
105                 public void InitWriteStartMember ()
106                 {
107                         new XamlXmlWriter (new StringWriter (), sctx, null).WriteStartMember (new XamlMember (str_len, sctx));
108                 }
109
110                 [Test]
111                 public void InitWriteNamespace ()
112                 {
113                         var sw = new StringWriter ();
114                         var xw = new XamlXmlWriter (sw, sctx, null);
115                         xw.WriteNamespace (new NamespaceDeclaration ("urn:foo", "x")); // ignored.
116                         xw.Close ();
117                         Assert.AreEqual ("", sw.ToString (), "#1");
118                 }
119
120                 [Test]
121                 [ExpectedException (typeof (ArgumentNullException))]
122                 public void WriteNamespaceNull ()
123                 {
124                         new XamlXmlWriter (new StringWriter (), sctx, null).WriteNamespace (null);
125                 }
126
127                 [Test]
128                 public void InitWriteStartObject ()
129                 {
130                         string xml = @"<?xml version='1.0' encoding='utf-16'?><Int32 xmlns='http://schemas.microsoft.com/winfx/2006/xaml' />";
131                         var sw = new StringWriter ();
132                         var xw = new XamlXmlWriter (sw, sctx, null);
133                         xw.WriteStartObject (new XamlType (typeof (int), sctx));
134                         xw.Close ();
135                         Assert.AreEqual (xml, sw.ToString ().Replace ('"', '\''), "#1");
136                 }
137
138                 [Test]
139                 [ExpectedException (typeof (XamlXmlWriterException))]
140                 public void GetObjectAfterStartObject ()
141                 {
142                         var sw = new StringWriter ();
143                         var xw = new XamlXmlWriter (sw, sctx, null);
144                         xw.WriteStartObject (xt);
145                         xw.WriteGetObject ();
146                 }
147
148                 [Test]
149                 [ExpectedException (typeof (XamlXmlWriterException))]
150                 public void WriteStartObjectAfterTopLevel ()
151                 {
152                         var sw = new StringWriter ();
153                         var xw = new XamlXmlWriter (sw, sctx, null);
154                         xw.WriteStartObject (xt);
155                         xw.WriteEndObject ();
156                         // writing another root is not allowed.
157                         xw.WriteStartObject (xt);
158                 }
159
160                 [Test]
161                 [ExpectedException (typeof (XamlXmlWriterException))]
162                 public void WriteEndObjectExcess ()
163                 {
164                         var sw = new StringWriter ();
165                         var xw = new XamlXmlWriter (sw, sctx, null);
166                         xw.WriteStartObject (xt);
167                         xw.WriteEndObject ();
168                         xw.WriteEndObject ();
169                 }
170
171                 [Test]
172                 [ExpectedException (typeof (XamlXmlWriterException))]
173                 public void StartObjectWriteEndMember ()
174                 {
175                         var sw = new StringWriter ();
176                         var xw = new XamlXmlWriter (sw, sctx, null);
177                         xw.WriteStartObject (xt);
178                         xw.WriteEndMember ();
179                 }
180
181                 [Test]
182                 public void WriteObjectAndMember ()
183                 {
184                         string xml = @"<?xml version='1.0' encoding='utf-16'?><String Length='foo' xmlns='http://schemas.microsoft.com/winfx/2006/xaml' />";
185                         var sw = new StringWriter ();
186                         var xw = new XamlXmlWriter (sw, sctx, null);
187                         xw.WriteStartObject (xt);
188                         xw.WriteStartMember (xm);
189                         xw.WriteValue ("foo");
190                         xw.WriteEndMember ();
191                         xw.Close ();
192                         Assert.AreEqual (xml, sw.ToString ().Replace ('"', '\''), "#1");
193                 }
194
195                 [Test]
196                 [ExpectedException (typeof (XamlXmlWriterException))]
197                 public void StartMemberWriteEndMember ()
198                 {
199                         var sw = new StringWriter ();
200                         var xw = new XamlXmlWriter (sw, sctx, null);
201                         xw.WriteStartObject (xt);
202                         xw.WriteStartMember (xm);
203                         xw.WriteEndMember (); // wow, really?
204                 }
205
206                 [Test]
207                 [ExpectedException (typeof (XamlXmlWriterException))]
208                 public void StartMemberWriteStartMember ()
209                 {
210                         var sw = new StringWriter ();
211                         var xw = new XamlXmlWriter (sw, sctx, null);
212                         xw.WriteStartObject (xt);
213                         xw.WriteStartMember (xm);
214                         xw.WriteStartMember (xm);
215                 }
216
217                 [Test]
218                 public void WriteObjectInsideMember ()
219                 {
220                         string xml = @"<?xml version='1.0' encoding='utf-16'?><String xmlns='http://schemas.microsoft.com/winfx/2006/xaml'><String.Length><String /></String.Length></String>";
221                         var sw = new StringWriter ();
222                         var xw = new XamlXmlWriter (sw, sctx, null);
223                         xw.WriteStartObject (xt);
224                         xw.WriteStartMember (xm);
225                         xw.WriteStartObject (xt);
226                         xw.WriteEndObject ();
227                         xw.WriteEndMember ();
228                         xw.Close ();
229                         Assert.AreEqual (xml, sw.ToString ().Replace ('"', '\''), "#1");
230                 }
231
232                 [Test]
233                 public void ValueAfterObject ()
234                 {
235                         string xml = @"<?xml version='1.0' encoding='utf-16'?><String xmlns='http://schemas.microsoft.com/winfx/2006/xaml'><String.Length><String />foo</String.Length></String>";
236                         var sw = new StringWriter ();
237                         var xw = new XamlXmlWriter (sw, sctx, null);
238                         xw.WriteStartObject (xt);
239                         xw.WriteStartMember (xm);
240                         xw.WriteStartObject (xt);
241                         xw.WriteEndObject ();
242                         // allowed.
243                         xw.WriteValue ("foo");
244                         xw.WriteEndMember ();
245                         xw.Close ();
246                         Assert.AreEqual (xml, sw.ToString ().Replace ('"', '\''), "#1");
247                 }
248
249                 [Test]
250                 [Category ("NotWorking")] // This is an abnormal operation and I cannot completely care about such operations.
251                 public void ValueAfterObject2 ()
252                 {
253                         string xml = @"<?xml version='1.0' encoding='utf-16'?><String xmlns='http://schemas.microsoft.com/winfx/2006/xaml'><String.Length>foo<String />foo</String.Length></String>";
254                         var sw = new StringWriter ();
255                         var xw = new XamlXmlWriter (sw, sctx, null);
256                         xw.WriteStartObject (xt);
257                         xw.WriteStartMember (xm);
258                         xw.WriteValue ("foo");
259                         xw.WriteStartObject (xt);
260                         xw.WriteEndObject ();
261                         // allowed.
262                         xw.WriteValue ("foo");
263                         xw.WriteEndMember ();
264                         xw.Close ();
265                         Assert.AreEqual (xml, sw.ToString ().Replace ('"', '\''), "#1");
266                 }
267
268                 [Test]
269                 public void ValueAfterObject3 ()
270                 {
271                         string xml = @"<?xml version='1.0' encoding='utf-16'?><String xmlns='http://schemas.microsoft.com/winfx/2006/xaml'><String.Length><String />foo<String />foo</String.Length></String>";
272                         var sw = new StringWriter ();
273                         var xw = new XamlXmlWriter (sw, sctx, null);
274                         xw.WriteStartObject (xt);
275                         xw.WriteStartMember (xm);
276                         xw.WriteStartObject (xt);
277                         xw.WriteEndObject ();
278                         xw.WriteValue ("foo");
279                         xw.WriteStartObject (xt);
280                         xw.WriteEndObject ();
281                         xw.WriteValue ("foo");
282                         xw.WriteEndMember ();
283                         xw.Close ();
284                         Assert.AreEqual (xml, sw.ToString ().Replace ('"', '\''), "#1");
285                 }
286
287                 [Test]
288                 [ExpectedException (typeof (ArgumentException))]
289                 public void WriteValueTypeNonString ()
290                 {
291                         var sw = new StringWriter ();
292                         var xw = new XamlXmlWriter (sw, sctx, null);
293                         xw.WriteStartObject (xt);
294                         xw.WriteStartMember (xm);
295                         xw.WriteValue (5); // even the type matches the member type, writing non-string value is rejected.
296                 }
297
298                 [Test]
299                 [ExpectedException (typeof (XamlXmlWriterException))]
300                 public void WriteValueAfterValue ()
301                 {
302                         var sw = new StringWriter ();
303                         var xw = new XamlXmlWriter (sw, sctx, null);
304                         xw.WriteStartObject (xt);
305                         xw.WriteValue ("foo");
306                         xw.WriteValue ("bar");
307                 }
308
309                 [Test]
310                 [ExpectedException (typeof (XamlXmlWriterException))]
311                 public void WriteValueAfterNullValue ()
312                 {
313                         var sw = new StringWriter ();
314                         var xw = new XamlXmlWriter (sw, sctx, null);
315                         xw.WriteStartObject (xt);
316                         xw.WriteValue (null);
317                         xw.WriteValue ("bar");
318                 }
319
320                 [Test]
321                 [ExpectedException (typeof (XamlXmlWriterException))]
322                 public void WriteValueList ()
323                 {
324                         var sw = new StringWriter ();
325                         var xw = new XamlXmlWriter (sw, sctx, null);
326                         xw.WriteStartObject (new XamlType (typeof (List<string>), sctx));
327                         xw.WriteStartMember (XamlLanguage.Items);
328                         xw.WriteValue ("foo");
329                         xw.WriteValue ("bar");
330                 }
331
332                 [ExpectedException (typeof (XamlXmlWriterException))]
333                 public void StartMemberWriteEndObject ()
334                 {
335                         var sw = new StringWriter ();
336                         var xw = new XamlXmlWriter (sw, sctx, null);
337                         xw.WriteStartObject (xt);
338                         xw.WriteStartMember (xm);
339                         xw.WriteEndObject ();
340                 }
341
342                 [Test]
343                 public void WriteNamespace ()
344                 {
345                         string xml = @"<?xml version='1.0' encoding='utf-16'?><x:String xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:y='urn:foo' />";
346                         var sw = new StringWriter ();
347                         var xw = new XamlXmlWriter (sw, sctx, null);
348                         xw.WriteNamespace (new NamespaceDeclaration (XamlLanguage.Xaml2006Namespace, "x"));
349                         xw.WriteNamespace (new NamespaceDeclaration ("urn:foo", "y"));
350                         xw.WriteStartObject (xt);
351                         xw.WriteEndObject ();
352                         xw.Close ();
353                         Assert.AreEqual (xml, sw.ToString ().Replace ('"', '\''), "#1");
354                 }
355
356                 [Test]
357                 [ExpectedException (typeof (XamlXmlWriterException))]
358                 public void StartObjectStartObject ()
359                 {
360                         var sw = new StringWriter ();
361                         var xw = new XamlXmlWriter (sw, sctx, null);
362                         xw.WriteStartObject (xt);
363                         xw.WriteStartObject (xt);
364                 }
365
366                 [Test]
367                 [ExpectedException (typeof (XamlXmlWriterException))]
368                 public void StartObjectValue ()
369                 {
370                         var sw = new StringWriter ();
371                         var xw = new XamlXmlWriter (sw, sctx, null);
372                         xw.WriteStartObject (xt);
373                         xw.WriteValue ("foo");
374                 }
375
376                 [Test]
377                 public void ObjectThenNamespaceThenObjectThenObject ()
378                 {
379                         string xml = @"<?xml version='1.0' encoding='utf-16'?><String xmlns='http://schemas.microsoft.com/winfx/2006/xaml'><String.Length><String /><String /></String.Length></String>";
380                         var sw = new StringWriter ();
381                         var xw = new XamlXmlWriter (sw, sctx, null);
382                         xw.WriteStartObject (xt); // <String>
383                         xw.WriteStartMember (xm); // <String.Length>
384                         xw.WriteStartObject (xt); // <String />
385                         xw.WriteEndObject ();
386                         xw.WriteStartObject (xt); // <String />
387                         xw.WriteEndObject ();
388                         xw.Close ();
389                         Assert.AreEqual (xml, sw.ToString ().Replace ('"', '\''), "#1");
390                 }
391
392                 // This doesn't result in XamlXmlWriterException. Instead,
393                 // IOE is thrown. WriteValueAfterNamespace() too.
394                 // It is probably because namespaces are verified independently
395                 // from state transition (and borks when the next write is not
396                 // appropriate).
397                 [Test]
398                 [ExpectedException (typeof (InvalidOperationException))]
399                 public void EndObjectAfterNamespace ()
400                 {
401                         var sw = new StringWriter ();
402                         var xw = new XamlXmlWriter (sw, sctx, null);
403                         xw.WriteStartObject (xt);
404                         xw.WriteNamespace (new NamespaceDeclaration ("urn:foo", "y"));
405                         xw.WriteEndObject ();
406                 }
407
408                 [Test]
409                 [ExpectedException (typeof (InvalidOperationException))] // ... shouldn't it be XamlXmlWriterException?
410                 public void WriteValueAfterNamespace ()
411                 {
412                         var sw = new StringWriter ();
413                         var xw = new XamlXmlWriter (sw, sctx, null);
414                         xw.WriteStartObject (xt);
415                         xw.WriteStartMember (XamlLanguage.Initialization);
416                         xw.WriteNamespace (new NamespaceDeclaration ("urn:foo", "y"));
417                         xw.WriteValue ("foo");
418                 }
419
420                 [Test]
421                 [Category ("NotWorking")]
422                 public void ValueThenStartObject ()
423                 {
424                         string xml = @"<?xml version='1.0' encoding='utf-16'?><String xmlns='http://schemas.microsoft.com/winfx/2006/xaml'><String.Length>foo<String /></String.Length></String>";
425                         var sw = new StringWriter ();
426                         var xw = new XamlXmlWriter (sw, sctx, null);
427                         xw.WriteStartObject (xt);
428                         xw.WriteStartMember (xm);
429                         xw.WriteValue ("foo");
430                         xw.WriteStartObject (xt); // looks like it is ignored. It is weird input anyways.
431                         xw.Close ();
432                         Assert.AreEqual (xml, sw.ToString ().Replace ('"', '\''), "#1");
433                 }
434
435                 [Test]
436                 public void ValueThenNamespace ()
437                 {
438                         var sw = new StringWriter ();
439                         var xw = new XamlXmlWriter (sw, sctx, null);
440                         xw.WriteStartObject (xt);
441                         xw.WriteStartMember (xm);
442                         xw.WriteValue ("foo");
443                         xw.WriteNamespace (new NamespaceDeclaration ("y", "urn:foo")); // this does not raise an error (since it might start another object)
444                 }
445
446                 [Test]
447                 [ExpectedException (typeof (XamlXmlWriterException))] // strange, this does *not* result in IOE...
448                 public void ValueThenNamespaceThenEndMember ()
449                 {
450                         var sw = new StringWriter ();
451                         var xw = new XamlXmlWriter (sw, sctx, null);
452                         xw.WriteStartObject (xt);
453                         xw.WriteStartMember (xm);
454                         xw.WriteValue ("foo");
455                         xw.WriteNamespace (new NamespaceDeclaration ("y", "urn:foo"));
456                         xw.WriteEndMember ();
457                 }
458
459                 [Test]
460                 public void StartMemberAfterNamespace ()
461                 {
462                         // This test shows:
463                         // 1) StartMember after NamespaceDeclaration is valid
464                         // 2) Member is written as an element (not attribute)
465                         //    if there is a NamespaceDeclaration in the middle.
466                         string xml = @"<?xml version='1.0' encoding='utf-16'?><String xmlns='http://schemas.microsoft.com/winfx/2006/xaml'><String.Length xmlns:y='urn:foo'>foo</String.Length></String>";
467                         var sw = new StringWriter ();
468                         var xw = new XamlXmlWriter (sw, sctx, null);
469                         xw.WriteStartObject (xt);
470                         xw.WriteNamespace (new NamespaceDeclaration ("urn:foo", "y"));
471                         xw.WriteStartMember (xm);
472                         xw.WriteValue ("foo");
473                         xw.Close ();
474                         Assert.AreEqual (xml, sw.ToString ().Replace ('"', '\''), "#1");
475                 }
476
477                 [Test]
478                 [ExpectedException (typeof (XamlXmlWriterException))]
479                 public void EndMemberThenStartObject ()
480                 {
481                         var sw = new StringWriter ();
482                         var xw = new XamlXmlWriter (sw, sctx, null);
483                         xw.WriteStartObject (xt);
484                         xw.WriteStartMember (xm);
485                         xw.WriteValue ("foo");
486                         xw.WriteEndMember ();
487                         xw.WriteStartObject (xt);
488                 }
489
490                 [Test]
491                 [ExpectedException (typeof (InvalidOperationException))]
492                 public void GetObjectOnNonCollection ()
493                 {
494                         var sw = new StringWriter ();
495                         var xw = new XamlXmlWriter (sw, sctx, null);
496                         xw.WriteStartObject (xt);
497                         xw.WriteStartMember (xm);
498                         xw.WriteGetObject ();
499                 }
500
501                 [Test]
502                 [ExpectedException (typeof (InvalidOperationException))]
503                 public void GetObjectOnNonCollection2 ()
504                 {
505                         var sw = new StringWriter ();
506                         var xw = new XamlXmlWriter (sw, sctx, null);
507                         xw.WriteStartObject (xt);
508                         xw.WriteStartMember (new XamlMember (typeof (string).GetProperty ("Length"), sctx)); // Length is of type int, which is not a collection
509                         xw.WriteGetObject ();
510                 }
511
512                 [Test]
513                 public void GetObjectOnCollection ()
514                 {
515                         string xml = @"<?xml version='1.0' encoding='utf-16'?><List xmlns='clr-namespace:System.Collections.Generic;assembly=mscorlib'><x:TypeArguments xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>x:Int32</x:TypeArguments><List.Bar /></List>";
516                         var sw = new StringWriter ();
517                         var xw = new XamlXmlWriter (sw, sctx, null);
518                         xw.WriteStartObject (xt2);
519                         xw.WriteStartMember (new XamlMember (typeof (Foo).GetProperty ("Bar"), sctx));
520                         xw.WriteGetObject ();
521                         xw.Close ();
522                         // FIXME: enable it once we got generic type output fixed.
523                         //Assert.AreEqual (xml, sw.ToString ().Replace ('"', '\''), "#1");
524                 }
525
526                 [Test]
527                 [ExpectedException (typeof (XamlXmlWriterException))]
528                 public void ValueAfterGetObject ()
529                 {
530                         var sw = new StringWriter ();
531                         var xw = new XamlXmlWriter (sw, sctx, null);
532                         xw.WriteStartObject (xt2);
533                         xw.WriteStartMember (new XamlMember (typeof (Foo).GetProperty ("Bar"), sctx));
534                         xw.WriteGetObject ();
535                         xw.WriteValue ("foo");
536                 }
537
538                 [Test]
539                 [ExpectedException (typeof (XamlXmlWriterException))]
540                 public void StartObjectAfterGetObject ()
541                 {
542                         var sw = new StringWriter ();
543                         var xw = new XamlXmlWriter (sw, sctx, null);
544                         xw.WriteStartObject (xt2);
545                         xw.WriteStartMember (new XamlMember (typeof (Foo).GetProperty ("Bar"), sctx));
546                         xw.WriteGetObject ();
547                         xw.WriteStartObject (xt);
548                 }
549
550                 [Test]
551                 [ExpectedException (typeof (XamlXmlWriterException))]
552                 public void EndMemberAfterGetObject ()
553                 {
554                         var sw = new StringWriter ();
555                         var xw = new XamlXmlWriter (sw, sctx, null);
556                         xw.WriteStartObject (xt2);
557                         xw.WriteStartMember (new XamlMember (typeof (Foo).GetProperty ("Bar"), sctx));
558                         xw.WriteGetObject ();
559                         xw.WriteEndMember (); // ...!?
560                 }
561
562                 [Test]
563                 public void StartMemberAfterGetObject ()
564                 {
565                         string xml = @"<?xml version='1.0' encoding='utf-16'?><List xmlns='clr-namespace:System.Collections.Generic;assembly=mscorlib'><x:TypeArguments xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>x:Int32</x:TypeArguments><List.Bar><List.Length /></List.Bar></List>";
566                         var sw = new StringWriter ();
567                         var xw = new XamlXmlWriter (sw, sctx, null);
568                         xw.WriteStartObject (xt2); // <List
569                         xw.WriteStartMember (new XamlMember (typeof (Foo).GetProperty ("Bar"), sctx)); // <List.Bar>
570                         xw.WriteGetObject ();
571                         xw.WriteStartMember (xm); // <List.Length /> . Note that the corresponding member is String.Length(!)
572                         xw.Close ();
573                         // FIXME: enable it once we got generic type output fixed.
574                         //Assert.AreEqual (xml, sw.ToString ().Replace ('"', '\''), "#1");
575                 }
576
577                 [Test]
578                 public void EndObjectAfterGetObject ()
579                 {
580                         var sw = new StringWriter ();
581                         var xw = new XamlXmlWriter (sw, sctx, null);
582                         xw.WriteStartObject (xt2);
583                         xw.WriteStartMember (new XamlMember (typeof (Foo).GetProperty ("Bar"), sctx));
584                         xw.WriteGetObject ();
585                         xw.WriteEndObject ();
586                 }
587
588                 [Test]
589                 public void WriteNode ()
590                 {
591                         string xml = @"<?xml version='1.0' encoding='utf-16'?><x:String xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>foo</x:String>";
592                         var r = new XamlObjectReader ("foo", sctx);
593                         var sw = new StringWriter ();
594                         var w = new XamlXmlWriter (sw, sctx, null);
595                         while (r.Read ())
596                                 w.WriteNode (r);
597                         w.Close ();
598                         Assert.AreEqual (xml, sw.ToString ().Replace ('"', '\''), "#1");
599                 }
600
601                 [Test]
602                 public void WriteNode2 ()
603                 {
604                         var r = new XamlObjectReader ("foo", sctx);
605                         var w = new XamlObjectWriter (sctx, null);
606                         while (r.Read ())
607                                 w.WriteNode (r);
608                         w.Close ();
609                         Assert.AreEqual ("foo", w.Result, "#1");
610                 }
611
612                 [Test]
613                 public void ConstructorArguments ()
614                 {
615                         string xml = String.Format (@"<?xml version='1.0' encoding='utf-16'?><ArgumentAttributed xmlns='clr-namespace:MonoTests.System.Xaml;assembly={0}' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'><x:Arguments><x:String>xxx</x:String><x:String>yyy</x:String></x:Arguments></ArgumentAttributed>",  GetType ().Assembly.GetName ().Name);
616                         Assert.IsFalse (sctx.FullyQualifyAssemblyNamesInClrNamespaces, "premise0");
617                         var r = new XamlObjectReader (new ArgumentAttributed ("xxx", "yyy"), sctx);
618                         var sw = new StringWriter ();
619                         var w = new XamlXmlWriter (sw, sctx, null);
620                         XamlServices.Transform (r, w);
621                         Assert.AreEqual (xml, sw.ToString ().Replace ('"', '\''), "#1");
622                 }
623
624                 [Test]
625                 public void WriteValueAsString ()
626                 {
627                         var sw = new StringWriter ();
628                         var xw = new XamlXmlWriter (sw, sctx, null);
629                         var xt = sctx.GetXamlType (typeof (TestXmlWriterClass1));
630                         xw.WriteStartObject (xt);
631                         xw.WriteStartMember (xt.GetMember ("Foo"));
632                         xw.WriteValue ("50");
633                         xw.Close ();
634                         string xml = String.Format (@"<?xml version='1.0' encoding='utf-16'?><TestXmlWriterClass1 xmlns='clr-namespace:MonoTests.System.Xaml;assembly={0}' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'></TestXmlWriterClass1>",  GetType ().Assembly.GetName ().Name);
635                 }
636
637                 string ReadXml (string name)
638                 {
639 #if NET_4_5
640                         string ver = "net_4_5";
641 #else
642                         string ver = "net_4_0";
643 #endif
644                         return File.ReadAllText ("Test/XmlFiles/" + name).Trim ().Replace (">\n", ">\r\n").Replace ("net_4_0", ver);
645                 }
646
647                 [Test]
648                 public void Write_String ()
649                 {
650                         Assert.AreEqual (ReadXml ("String.xml"), XamlServices.Save ("foo"), "#1");
651                 }
652
653                 [Test]
654                 public void Write_Int32 ()
655                 {
656                         Assert.AreEqual (ReadXml ("Int32.xml"), XamlServices.Save (5), "#1");
657                 }
658
659                 [Test]
660                 public void Write_DateTime ()
661                 {
662                         Assert.AreEqual (ReadXml ("DateTime.xml"), XamlServices.Save (new DateTime (2010, 4, 14)), "#1");
663                 }
664
665                 [Test]
666                 public void Write_TimeSpan ()
667                 {
668                         Assert.AreEqual (ReadXml ("TimeSpan.xml"), XamlServices.Save (TimeSpan.FromMinutes (7)), "#1");
669                 }
670
671                 [Test]
672                 public void Write_Uri ()
673                 {
674                         Assert.AreEqual (ReadXml ("Uri.xml"), XamlServices.Save (new Uri ("urn:foo")), "#1");
675                 }
676
677                 [Test]
678                 public void Write_Null ()
679                 {
680                         Assert.AreEqual (ReadXml ("NullExtension.xml"), XamlServices.Save (null), "#1");
681                 }
682
683                 [Test]
684                 public void Write_NullExtension ()
685                 {
686                         Assert.AreEqual (ReadXml ("NullExtension.xml"), XamlServices.Save (new NullExtension ()), "#1");
687                 }
688
689                 [Test]
690                 public void Write_Type ()
691                 {
692                         Assert.AreEqual (ReadXml ("Type.xml").Trim (), XamlServices.Save (typeof (int)), "#1");
693                 }
694
695                 [Test]
696                 public void Write_Type2 ()
697                 {
698                         Assert.AreEqual (ReadXml ("Type2.xml").Trim (), XamlServices.Save (typeof (TestClass1)), "#1");
699                 }
700
701                 [Test]
702                 public void Write_Guid ()
703                 {
704                         Assert.AreEqual (ReadXml ("Guid.xml").Trim (), XamlServices.Save (Guid.Parse ("9c3345ec-8922-4662-8e8d-a4e41f47cf09")), "#1");
705                 }
706
707                 [Test]
708                 public void Write_StaticExtension ()
709                 {
710                         Assert.AreEqual (ReadXml ("StaticExtension.xml").Trim (), XamlServices.Save (new StaticExtension ("FooBar")), "#1");
711                 }
712
713                 [Test]
714                 public void Write_StaticExtension2 ()
715                 {
716                         Assert.AreEqual (ReadXml ("StaticExtension.xml").Trim (), XamlServices.Save (new StaticExtension () { Member = "FooBar"}), "#1");
717                 }
718
719                 [Test]
720                 public void Write_Reference ()
721                 {
722                         Assert.AreEqual (ReadXml ("Reference.xml").Trim (), XamlServices.Save (new Reference ("FooBar")), "#1");
723                 }
724
725                 [Test]
726                 public void Write_ArrayInt32 ()
727                 {
728                         Assert.AreEqual (ReadXml ("Array_Int32.xml").Trim (), XamlServices.Save (new int [] {4, -5, 0, 255, int.MaxValue}), "#1");
729                 }
730
731                 [Test]
732                 public void Write_ListInt32 ()
733                 {
734                         Assert.AreEqual (ReadXml ("List_Int32.xml").Trim (), XamlServices.Save (new int [] {5, -3, int.MaxValue, 0}.ToList ()), "#1");
735                 }
736
737                 [Test]
738                 public void Write_ListInt32_2 ()
739                 {
740                         var obj = new List<int> (new int [0]) { Capacity = 0 }; // set explicit capacity for trivial implementation difference
741                         Assert.AreEqual (ReadXml ("List_Int32_2.xml").Trim (), XamlServices.Save (obj), "#1");
742                 }
743
744                 [Test]
745                 public void Write_ListType ()
746                 {
747                         var obj = new List<Type> (new Type [] {typeof (int), typeof (Dictionary<Type, XamlType>)}) { Capacity = 2 };
748                         Assert.AreEqual (ReadXml ("List_Type.xml").Trim (), XamlServices.Save (obj), "#1");
749                 }
750
751                 [Test]
752                 public void Write_ListArray ()
753                 {
754                         var obj = new List<Array> (new Array [] { new int [] { 1,2,3}, new string [] { "foo", "bar", "baz" }}) { Capacity = 2 };
755                         Assert.AreEqual (ReadXml ("List_Array.xml").Trim (), XamlServices.Save (obj), "#1");
756                 }
757
758                 [Test]
759                 public void Write_DictionaryInt32String ()
760                 {
761                         var dic = new Dictionary<int,string> ();
762                         dic.Add (0, "foo");
763                         dic.Add (5, "bar");
764                         dic.Add (-2, "baz");
765                         Assert.AreEqual (ReadXml ("Dictionary_Int32_String.xml").Trim (), XamlServices.Save (dic), "#1");
766                 }
767
768                 [Test]
769                 public void Write_DictionaryStringType ()
770                 {
771                         var dic = new Dictionary<string,Type> ();
772                         dic.Add ("t1", typeof (int));
773                         dic.Add ("t2", typeof (int []));
774                         dic.Add ("t3", typeof (int?));
775                         dic.Add ("t4", typeof (List<int>));
776                         dic.Add ("t5", typeof (Dictionary<int,DateTime>));
777                         dic.Add ("t6", typeof (List<KeyValuePair<int,DateTime>>));
778                         Assert.AreEqual (ReadXml ("Dictionary_String_Type.xml").Trim (), XamlServices.Save (dic), "#1");
779                 }
780
781                 [Test]
782                 [ExpectedException (typeof (XamlXmlWriterException))]
783                 public void Write_PositionalParameters1 ()
784                 {
785                         // PositionalParameters can only be written when the 
786                         // instance is NOT the root object.
787                         //
788                         // A single positional parameter can be written as an 
789                         // attribute, but there are two in PositionalParameters1.
790                         //
791                         // A default constructor could be used to not use
792                         // PositionalParameters, but there isn't in this type.
793                         var obj = new PositionalParametersClass1 ("foo", 5);
794                         XamlServices.Save (obj);
795                 }
796
797                 [Test]
798                 public void Write_PositionalParameters1Wrapper ()
799                 {
800                         // Unlike the above case, this has the wrapper object and hence PositionalParametersClass1 can be written as an attribute (markup extension)
801                         var obj = new PositionalParametersWrapper ("foo", 5);
802                         Assert.AreEqual (ReadXml ("PositionalParametersWrapper.xml").Trim (), XamlServices.Save (obj), "#1");
803                 }
804                 
805                 [Test]
806                 public void Write_ArgumentAttributed ()
807                 {
808                         var obj = new ArgumentAttributed ("foo", "bar");
809                         Assert.AreEqual (ReadXml ("ArgumentAttributed.xml").Trim (), XamlServices.Save (obj), "#1");
810                 }
811
812                 [Test]
813                 public void Write_ArrayExtension2 ()
814                 {
815                         var obj = new ArrayExtension (typeof (int));
816                         Assert.AreEqual (ReadXml ("ArrayExtension2.xml").Trim (), XamlServices.Save (obj), "#1");
817                 }
818
819                 [Test]
820                 public void Write_ArrayList ()
821                 {
822                         var obj = new ArrayList (new int [] {5, -3, 0});
823                         Assert.AreEqual (ReadXml ("ArrayList.xml").Trim (), XamlServices.Save (obj), "#1");
824                 }
825
826                 [Test]
827                 public void ComplexPositionalParameterWrapper ()
828                 {
829                         var obj = new ComplexPositionalParameterWrapper () { Param = new ComplexPositionalParameterClass (new ComplexPositionalParameterValue () { Foo = "foo" })};
830                         Assert.AreEqual (ReadXml ("ComplexPositionalParameterWrapper.xml").Trim (), XamlServices.Save (obj), "#1");
831                 }
832
833                 [Test]
834                 public void Write_ListWrapper ()
835                 {
836                         var obj = new ListWrapper (new List<int> (new int [] {5, -3, 0}) { Capacity = 3}); // set explicit capacity for trivial implementation difference
837                         Assert.AreEqual (ReadXml ("ListWrapper.xml").Trim (), XamlServices.Save (obj), "#1");
838                 }
839
840                 [Test]
841                 public void Write_ListWrapper2 ()
842                 {
843                         var obj = new ListWrapper2 (new List<int> (new int [] {5, -3, 0}) { Capacity = 3}); // set explicit capacity for trivial implementation difference
844                         Assert.AreEqual (ReadXml ("ListWrapper2.xml").Trim (), XamlServices.Save (obj), "#1");
845                 }
846
847                 [Test]
848                 public void Write_MyArrayExtension ()
849                 {
850                         var obj = new MyArrayExtension (new int [] {5, -3, 0});
851                         Assert.AreEqual (ReadXml ("MyArrayExtension.xml").Trim (), XamlServices.Save (obj), "#1");
852                 }
853
854                 [Test]
855                 public void Write_MyArrayExtensionA ()
856                 {
857                         var obj = new MyArrayExtensionA (new int [] {5, -3, 0});
858                         Assert.AreEqual (ReadXml ("MyArrayExtensionA.xml").Trim (), XamlServices.Save (obj), "#1");
859                 }
860
861                 [Test]
862                 public void Write_MyExtension ()
863                 {
864                         var obj = new MyExtension () { Foo = typeof (int), Bar = "v2", Baz = "v7"};
865                         Assert.AreEqual (ReadXml ("MyExtension.xml").Trim (), XamlServices.Save (obj), "#1");
866                 }
867
868                 [Test]
869                 public void Write_MyExtension2 ()
870                 {
871                         var obj = new MyExtension2 () { Foo = typeof (int), Bar = "v2"};
872                         Assert.AreEqual (ReadXml ("MyExtension2.xml").Trim (), XamlServices.Save (obj), "#1");
873                 }
874
875                 [Test]
876                 public void Write_MyExtension3 ()
877                 {
878                         var obj = new MyExtension3 () { Foo = typeof (int), Bar = "v2"};
879                         Assert.AreEqual (ReadXml ("MyExtension3.xml").Trim (), XamlServices.Save (obj), "#1");
880                 }
881
882                 [Test]
883                 public void Write_MyExtension4 ()
884                 {
885                         var obj = new MyExtension4 () { Foo = typeof (int), Bar = "v2"};
886                         Assert.AreEqual (ReadXml ("MyExtension4.xml").Trim (), XamlServices.Save (obj), "#1");
887                 }
888
889                 [Test]
890                 public void Write_MyExtension6 ()
891                 {
892                         var obj = new MyExtension6 ("foo");
893                         Assert.AreEqual (ReadXml ("MyExtension6.xml").Trim (), XamlServices.Save (obj), "#1");
894                 }
895                 
896                 [Test]
897                 public void Write_PropertyDefinition ()
898                 {
899                         var obj = new PropertyDefinition () { Modifier = "protected", Name = "foo", Type = XamlLanguage.String };
900                         Assert.AreEqual (ReadXml ("PropertyDefinition.xml").Trim (), XamlServices.Save (obj), "#1");
901                 }
902                 
903                 [Test]
904                 public void Write_StaticExtensionWrapper ()
905                 {
906                         var obj = new StaticExtensionWrapper () { Param = new StaticExtension ("StaticExtensionWrapper.Foo") };
907                         Assert.AreEqual (ReadXml ("StaticExtensionWrapper.xml").Trim (), XamlServices.Save (obj), "#1");
908                 }
909
910                 [Test]
911                 public void Write_TypeExtensionWrapper ()
912                 {
913                         var obj = new TypeExtensionWrapper () { Param = new TypeExtension ("Foo") };
914                         Assert.AreEqual (ReadXml ("TypeExtensionWrapper.xml").Trim (), XamlServices.Save (obj), "#1");
915                 }
916
917                 [Test]
918                 public void Write_NamedItems ()
919                 {
920                         // foo
921                         // - bar
922                         // -- foo
923                         // - baz
924                         var obj = new NamedItem ("foo");
925                         var obj2 = new NamedItem ("bar");
926                         obj.References.Add (obj2);
927                         obj.References.Add (new NamedItem ("baz"));
928                         obj2.References.Add (obj);
929
930                         Assert.AreEqual (ReadXml ("NamedItems.xml").Trim (), XamlServices.Save (obj), "#1");
931                 }
932
933                 [Test]
934                 public void Write_NamedItems2 ()
935                 {
936                         // i1
937                         // - i2
938                         // -- i3
939                         // - i4
940                         // -- i3
941                         var obj = new NamedItem2 ("i1");
942                         var obj2 = new NamedItem2 ("i2");
943                         var obj3 = new NamedItem2 ("i3");
944                         var obj4 = new NamedItem2 ("i4");
945                         obj.References.Add (obj2);
946                         obj.References.Add (obj4);
947                         obj2.References.Add (obj3);
948                         obj4.References.Add (obj3);
949
950                         Assert.AreEqual (ReadXml ("NamedItems2.xml").Trim (), XamlServices.Save (obj), "#1");
951                 }
952
953                 [Test]
954                 public void Write_XmlSerializableWrapper ()
955                 {
956                         var obj = new XmlSerializableWrapper (new XmlSerializable ("<root/>"));
957                         Assert.AreEqual (ReadXml ("XmlSerializableWrapper.xml").Trim (), XamlServices.Save (obj), "#1");
958                 }
959
960                 [Test]
961                 public void Write_XmlSerializable ()
962                 {
963                         var obj = new XmlSerializable ("<root/>");
964                         Assert.AreEqual (ReadXml ("XmlSerializable.xml").Trim (), XamlServices.Save (obj), "#1");
965                 }
966
967                 [Test]
968                 public void Write_ListXmlSerializable ()
969                 {
970                         var obj = new List<XmlSerializable> ();
971                         obj.Add (new XmlSerializable ("<root/>"));
972                         Assert.AreEqual (ReadXml ("List_XmlSerializable.xml").Trim (), XamlServices.Save (obj), "#1");
973                 }
974
975                 [Test]
976                 public void Write_AttachedProperty ()
977                 {
978                         var obj = new AttachedWrapper ();
979                         Attachable.SetFoo (obj, "x");
980                         Attachable.SetFoo (obj.Value, "y");
981                         try {
982                                 Assert.AreEqual (ReadXml ("AttachedProperty.xml").Trim (), XamlServices.Save (obj), "#1");
983                         } finally {
984                                 Attachable.SetFoo (obj, null);
985                                 Attachable.SetFoo (obj.Value, null);
986                         }
987                 }
988
989                 [Test]
990                 [Category ("NotWorking")] // cosmetic attribute order difference
991                 public void Write_AbstractWrapper ()
992                 {
993                         var obj = new AbstractContainer () { Value2 = new DerivedObject () { Foo = "x" } };
994                         Assert.AreEqual (ReadXml ("AbstractContainer.xml").Trim (), XamlServices.Save (obj), "#1");
995                 }
996
997                 [Test]
998                 public void Write_ReadOnlyPropertyContainer ()
999                 {
1000                         var obj = new ReadOnlyPropertyContainer () { Foo = "x" };
1001                         Assert.AreEqual (ReadXml ("ReadOnlyPropertyContainer.xml").Trim (), XamlServices.Save (obj), "#1");
1002                         
1003                         var sw = new StringWriter ();
1004                         var xw = new XamlXmlWriter (sw, new XamlSchemaContext ());
1005                         var xt = xw.SchemaContext.GetXamlType (obj.GetType ());
1006                         xw.WriteStartObject (xt);
1007                         xw.WriteStartMember (xt.GetMember ("Bar"));
1008                         xw.WriteValue ("x");
1009                         xw.WriteEndMember ();
1010                         xw.WriteEndObject ();
1011                         xw.Close ();
1012                         Assert.IsTrue (sw.ToString ().IndexOf ("Bar") > 0, "#2"); // it is not rejected by XamlXmlWriter. But XamlServices does not write it.
1013                 }
1014
1015                 [Test]
1016                 public void Write_TypeConverterOnListMember ()
1017                 {
1018                         var obj = new SecondTest.TypeOtherAssembly ();
1019                         obj.Values.AddRange (new uint? [] {1, 2, 3});
1020                         Assert.AreEqual (ReadXml ("TypeConverterOnListMember.xml").Trim (), XamlServices.Save (obj), "#1");
1021                 }
1022
1023                 [Test]
1024                 public void Write_EnumContainer ()
1025                 {
1026                         var obj = new EnumContainer () { EnumProperty = EnumValueType.Two };
1027                         Assert.AreEqual (ReadXml ("EnumContainer.xml").Trim (), XamlServices.Save (obj), "#1");
1028                 }
1029
1030                 [Test]
1031                 public void Write_CollectionContentProperty ()
1032                 {
1033                         var obj = new CollectionContentProperty ();
1034                         for (int i = 0; i < 4; i++)
1035                                 obj.ListOfItems.Add (new SimpleClass ());
1036                         Assert.AreEqual (ReadXml ("CollectionContentProperty.xml").Trim (), XamlServices.Save (obj), "#1");
1037                 }
1038
1039                 [Test]
1040                 public void Write_CollectionContentPropertyX ()
1041                 {
1042                         var obj = new CollectionContentPropertyX ();
1043                         var l = new List<object> ();
1044                         obj.ListOfItems.Add (l);
1045                         for (int i = 0; i < 4; i++)
1046                                 l.Add (new SimpleClass ());
1047                         Assert.AreEqual (ReadXml ("CollectionContentPropertyX.xml").Trim (), XamlServices.Save (obj), "#1");
1048                 }
1049
1050                 [Test]
1051                 [Category ("NotWorking")] // TestProperty is written as element so far.
1052                 public void Write_AmbientPropertyContainer ()
1053                 {
1054                         var obj = new SecondTest.ResourcesDict ();
1055                         var t1 = new SecondTest.TestObject ();
1056                         obj.Add ("TestDictItem", t1);
1057                         var t2 = new SecondTest.TestObject ();
1058                         t2.TestProperty = t1;
1059                         obj.Add ("okay", t2);
1060                         Assert.AreEqual (ReadXml ("AmbientPropertyContainer.xml").Trim (), XamlServices.Save (obj), "#1");
1061                 }
1062
1063                 [Test]
1064                 public void Write_NullableContainer ()
1065                 {
1066                         var obj = new NullableContainer () { TestProp = 5 };
1067                         Assert.AreEqual (ReadXml ("NullableContainer.xml").Trim (), XamlServices.Save (obj), "#1");
1068                 }
1069         }
1070
1071         public class TestXmlWriterClass1
1072         {
1073                 public int Foo { get; set; }
1074         }
1075 }