2003-07-26 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
[mono.git] / mcs / class / System.XML / Test / System.Xml / XmlTextWriterTests.cs
1 //
2 // System.Xml.XmlTextWriterTests
3 //
4 // Authors:
5 //   Kral Ferch <kral_ferch@hotmail.com>
6 //   Martin Willemoes Hansen <mwh@sysrq.dk>
7 //
8 // (C) 2002 Kral Ferch
9 // (C) 2003 Martin Willemoes Hansen
10 //
11
12 using System;
13 using System.IO;
14 using System.Text;
15 using System.Xml;
16
17 using NUnit.Framework;
18
19 namespace MonoTests.System.Xml
20 {
21         [TestFixture]
22         public class XmlTextWriterTests : Assertion
23         {
24                 StringWriter sw;
25                 XmlTextWriter xtw;
26
27                 [SetUp]
28                 public void GetReady ()
29                 {
30                         sw = new StringWriter ();
31                         xtw = new XmlTextWriter (sw);
32                         xtw.QuoteChar = '\'';
33                 }
34
35                 private string StringWriterText 
36                 {
37                         get { return sw.GetStringBuilder ().ToString (); }
38                 }
39
40                 [Test]
41                 public void AttributeNamespacesNonNamespaceAttributeBefore ()
42                 {
43                         xtw.WriteStartElement ("foo");
44                         xtw.WriteAttributeString("bar", "baz");
45                         xtw.WriteAttributeString ("xmlns", "abc", null, "http://abc.def");
46                         AssertEquals ("<foo bar='baz' xmlns:abc='http://abc.def'", StringWriterText);
47                 }
48
49                 [Test]
50                 public void AttributeNamespacesNonNamespaceAttributeAfter ()
51                 {
52                         xtw.WriteStartElement ("foo");
53
54                         xtw.WriteAttributeString ("xmlns", "abc", null, "http://abc.def");
55                         xtw.WriteAttributeString("bar", "baz");
56                         AssertEquals ("<foo xmlns:abc='http://abc.def' bar='baz'", StringWriterText);
57                 }
58
59                 [Test]
60                 public void AttributeNamespacesThreeParamWithNullInNamespaceParam ()
61                 {
62                         xtw.WriteAttributeString ("xmlns", null, "http://abc.def");
63                         AssertEquals ("xmlns='http://abc.def'", StringWriterText);
64                 }
65
66                 [Test]
67                 public void AttributeNamespacesThreeParamWithTextInNamespaceParam ()
68                 {
69                         try 
70                         {
71                                 xtw.WriteAttributeString ("xmlns", "http://somenamespace.com", "http://abc.def");
72                         } 
73                         catch (ArgumentException) {}
74                 }
75
76                 [Test]
77                 public void AttributeNamespacesWithNullInNamespaceParam ()
78                 {
79                         xtw.WriteAttributeString ("xmlns", "abc", null, "http://abc.def");
80                         AssertEquals ("xmlns:abc='http://abc.def'", StringWriterText);
81                 }
82
83                 [Test]
84                 public void AttributeNamespacesWithTextInNamespaceParam ()
85                 {
86                         try {
87                                 xtw.WriteAttributeString ("xmlns", "abc", "http://somenamespace.com", "http://abc.def");
88                         } catch (ArgumentException) {}
89                 }
90
91                 [Test]
92                 public void AttributeNamespacesXmlnsXmlns ()
93                 {
94                         xtw.WriteStartElement ("foo");
95                         try {
96                                 xtw.WriteAttributeString ("xmlns", "xmlns", null, "http://abc.def");
97                                 // This should not be allowed, even though
98                                 // MS.NET doesn't treat as an error.
99                                 Fail ("any prefix which name starts from \"xml\" must not be allowed.");
100                         }
101                         catch (ArgumentException) {}
102                         xtw.WriteAttributeString ("", "xmlns", null, "http://abc.def");
103                 }
104
105                 [Test]
106                 public void AttributeWriteAttributeString ()
107                 {
108                         xtw.WriteStartElement ("foo");
109
110                         xtw.WriteAttributeString ("foo", "bar");
111                         AssertEquals ("<foo foo='bar'", StringWriterText);
112
113                         xtw.WriteAttributeString ("bar", "");
114                         AssertEquals ("<foo foo='bar' bar=''", StringWriterText);
115
116                         xtw.WriteAttributeString ("baz", null);
117                         AssertEquals ("<foo foo='bar' bar='' baz=''", StringWriterText);
118
119                         xtw.WriteAttributeString ("hoge", "a\nb");
120                         AssertEquals ("<foo foo='bar' bar='' baz='' hoge='a&#xA;b'", StringWriterText);
121
122                         xtw.WriteAttributeString ("fuga", " a\t\r\nb\t");
123                         AssertEquals ("<foo foo='bar' bar='' baz='' hoge='a&#xA;b' fuga=' a\t&#xD;&#xA;b\t'", StringWriterText);
124
125                         try {
126                                 // Why does this pass Microsoft?
127                                 // Anyway, Mono should not allow such code.
128                                 xtw.WriteAttributeString ("", "quux");
129 //                              AssertEquals ("<foo foo='bar' bar='' baz='' ='quux'", StringWriterText);
130                                 Fail ("empty name not allowed.");
131                         } catch (Exception) {
132                         }
133
134                         try {
135                                 // Why does this pass Microsoft?
136                                 // Anyway, Mono should not allow such code.
137                                 xtw.WriteAttributeString (null, "quuux");
138 //                              AssertEquals ("<foo foo='bar' bar='' baz='' ='quux' ='quuux'", StringWriterText);
139                                 Fail ("null name not allowed.");
140                         } catch (Exception) {
141                         }
142                 }
143
144                 [Test]
145                 [ExpectedException (typeof (InvalidOperationException))]
146                 public void AttributeWriteAttributeStringNotInsideOpenStartElement ()
147                 {
148                         xtw.WriteStartElement ("foo");
149                         xtw.WriteString ("bar");
150                         
151                         xtw.WriteAttributeString ("baz", "quux");
152                 }
153
154                 [Test]
155                 public void AttributeWriteAttributeStringWithoutParentElement ()
156                 {
157                         xtw.WriteAttributeString ("foo", "bar");
158                         AssertEquals ("foo='bar'", StringWriterText);
159
160                         xtw.WriteAttributeString ("baz", "quux");
161                         AssertEquals ("foo='bar' baz='quux'", StringWriterText);
162                 }
163
164                 [Test]
165                 public void CDataValid ()
166                 {
167                         xtw.WriteCData ("foo");
168                         AssertEquals ("WriteCData had incorrect output.", "<![CDATA[foo]]>", StringWriterText);
169                 }
170
171                 [Test]
172                 [ExpectedException (typeof (ArgumentException))]
173                 public void CDataInvalid ()
174                 {
175                         xtw.WriteCData("foo]]>bar");
176                 }
177
178                 [Test]
179                 public void CloseOpenElements ()
180                 {
181                         xtw.WriteStartElement("foo");
182                         xtw.WriteStartElement("bar");
183                         xtw.WriteStartElement("baz");
184                         xtw.Close();
185                         AssertEquals ("Close didn't write out end elements properly.", "<foo><bar><baz /></bar></foo>", StringWriterText);
186                 }
187
188                 [Test]
189                 public void CloseWriteAfter ()
190                 {
191                         xtw.WriteElementString ("foo", "bar");
192                         xtw.Close ();
193
194                         // WriteEndElement and WriteStartDocument aren't tested here because
195                         // they will always throw different exceptions besides 'The Writer is closed.'
196                         // and there are already tests for those exceptions.
197
198                         try {
199                                 xtw.WriteCData ("foo");
200                                 Fail ("WriteCData after Close Should have thrown an InvalidOperationException.");
201                         } 
202                         catch (InvalidOperationException) {
203                                 // Don't rely on English message assertion.
204                                 // It is enough to check an exception occurs.
205 //                              AssertEquals ("Exception message is incorrect.", "The Writer is closed.", e.Message);
206                         }
207
208                         try {
209                                 xtw.WriteComment ("foo");
210                                 Fail ("WriteComment after Close Should have thrown an InvalidOperationException.");
211                         } 
212                         catch (InvalidOperationException) {
213 //                              AssertEquals ("Exception message is incorrect.", "The Writer is closed.", e.Message);
214                         }
215
216                         try {
217                                 xtw.WriteProcessingInstruction ("foo", "bar");
218                                 Fail ("WriteProcessingInstruction after Close Should have thrown an InvalidOperationException.");
219                         } 
220                         catch (InvalidOperationException) {
221 //                              AssertEquals ("Exception message is incorrect.", "The Writer is closed.", e.Message);
222                         }
223
224                         try {
225                                 xtw.WriteStartElement ("foo", "bar", "baz");
226                                 Fail ("WriteStartElement after Close Should have thrown an InvalidOperationException.");
227                         } 
228                         catch (InvalidOperationException) {
229 //                              AssertEquals ("Exception message is incorrect.", "The Writer is closed.", e.Message);
230                         }
231
232                         try 
233                         {
234                                 xtw.WriteAttributeString ("foo", "bar");
235                                 Fail ("WriteAttributeString after Close Should have thrown an InvalidOperationException.");
236                         } 
237                         catch (InvalidOperationException) 
238                         {
239 //                              AssertEquals ("Exception message is incorrect.", "The Writer is closed.", e.Message);
240                         }
241
242                         try {
243                                 xtw.WriteString ("foo");
244                                 Fail ("WriteString after Close Should have thrown an InvalidOperationException.");
245                         } 
246                         catch (InvalidOperationException) {
247 //                              AssertEquals ("Exception message is incorrect.", "The Writer is closed.", e.Message);
248                         }
249                 }
250
251                 [Test]
252                 public void CommentValid ()
253                 {
254                         xtw.WriteComment ("foo");
255                         AssertEquals ("WriteComment had incorrect output.", "<!--foo-->", StringWriterText);
256                 }
257
258                 [Test]
259                 public void CommentInvalid ()
260                 {
261                         try {
262                                 xtw.WriteComment("foo-");
263                                 Fail("Should have thrown an ArgumentException.");
264                         } 
265                         catch (ArgumentException) { }
266
267                         try {
268                                 xtw.WriteComment("foo-->bar");
269                                 Fail("Should have thrown an ArgumentException.");
270                         } 
271                         catch (ArgumentException) { }
272                 }
273
274                 [Test]
275                 public void ConstructorsAndBaseStream ()
276                 {
277                         Assert ("BaseStream property returned wrong value.", Object.ReferenceEquals (null, this.xtw.BaseStream));
278
279                         MemoryStream ms;
280                         StreamReader sr;
281                         XmlTextWriter xtw;
282
283                         ms = new MemoryStream ();
284                         xtw = new XmlTextWriter (ms, new UnicodeEncoding ());
285                         xtw.WriteStartDocument ();
286                         xtw.Flush ();
287                         ms.Seek (0, SeekOrigin.Begin);
288                         sr = new StreamReader (ms, Encoding.Unicode);
289                         string expectedXmlDeclaration = "<?xml version=\"1.0\" encoding=\"utf-16\"?>";
290                         string actualXmlDeclaration = sr.ReadToEnd();
291                         AssertEquals (expectedXmlDeclaration, actualXmlDeclaration);
292                         Assert ("BaseStream property returned wrong value.", Object.ReferenceEquals (ms, xtw.BaseStream));
293
294                         ms = new MemoryStream ();
295                         xtw = new XmlTextWriter (ms, new UnicodeEncoding ());
296                         xtw.WriteStartDocument (true);
297                         xtw.Flush ();
298                         ms.Seek (0, SeekOrigin.Begin);
299                         sr = new StreamReader (ms, Encoding.Unicode);
300                         AssertEquals ("<?xml version=\"1.0\" encoding=\"utf-16\" standalone=\"yes\"?>", sr.ReadToEnd ());
301
302                         ms = new MemoryStream ();
303                         xtw = new XmlTextWriter (ms, new UTF8Encoding ());
304                         xtw.WriteStartDocument ();
305                         xtw.Flush ();
306                         ms.Seek (0, SeekOrigin.Begin);
307                         sr = new StreamReader (ms, Encoding.UTF8);
308                         AssertEquals ("<?xml version=\"1.0\" encoding=\"utf-8\"?>", sr.ReadToEnd ());
309
310                         ms = new MemoryStream ();
311                         xtw = new XmlTextWriter (ms, null);
312                         xtw.WriteStartDocument ();
313                         xtw.Flush ();
314                         ms.Seek (0, SeekOrigin.Begin);
315                         sr = new StreamReader (ms, Encoding.UTF8);
316                         AssertEquals ("<?xml version=\"1.0\"?>", sr.ReadToEnd ());
317
318                         ms = new MemoryStream ();
319                         xtw = new XmlTextWriter (ms, null);
320                         xtw.WriteStartDocument (true);
321                         xtw.Flush ();
322                         ms.Seek (0, SeekOrigin.Begin);
323                         sr = new StreamReader (ms, Encoding.UTF8);
324                         AssertEquals ("<?xml version=\"1.0\" standalone=\"yes\"?>", sr.ReadToEnd ());
325                         Assert ("BaseStream property returned wrong value.", Object.ReferenceEquals (ms, xtw.BaseStream));
326                 }
327
328                 [Test]
329                 public void DocumentStart ()
330                 {
331                         xtw.WriteStartDocument ();
332                         AssertEquals ("XmlDeclaration is incorrect.", "<?xml version='1.0' encoding='utf-16'?>", StringWriterText);
333
334                         try 
335                         {
336                                 xtw.WriteStartDocument ();
337                                 Fail("Should have thrown an InvalidOperationException.");
338                         } 
339                         catch (InvalidOperationException) {
340                                 // Don't rely on English message assertion.
341                                 // It is enough to check an exception occurs.
342 //                              AssertEquals ("Exception message is incorrect.",
343 //                                      "WriteStartDocument should be the first call.", e.Message);
344                         }
345
346                         xtw = new XmlTextWriter (sw = new StringWriter ());
347                         xtw.QuoteChar = '\'';
348                         xtw.WriteStartDocument (true);
349                         AssertEquals ("<?xml version='1.0' encoding='utf-16' standalone='yes'?>", StringWriterText);
350
351                         xtw = new XmlTextWriter (sw = new StringWriter ());
352                         xtw.QuoteChar = '\'';
353                         xtw.WriteStartDocument (false);
354                         AssertEquals ("<?xml version='1.0' encoding='utf-16' standalone='no'?>", StringWriterText);
355                 }
356
357                 [Test]
358                 public void ElementEmpty ()
359                 {
360                         xtw.WriteStartElement ("foo");
361                         xtw.WriteEndElement ();
362                         AssertEquals ("Incorrect output.", "<foo />", StringWriterText);
363                 }
364
365                 [Test]
366                 public void ElementWriteElementString ()
367                 {
368                         xtw.WriteElementString ("foo", "bar");
369                         AssertEquals ("WriteElementString has incorrect output.", "<foo>bar</foo>", StringWriterText);
370
371                         xtw.WriteElementString ("baz", "");
372                         AssertEquals ("<foo>bar</foo><baz />", StringWriterText);
373
374                         xtw.WriteElementString ("quux", null);
375                         AssertEquals ("<foo>bar</foo><baz /><quux />", StringWriterText);
376
377                         xtw.WriteElementString ("", "quuux");
378                         AssertEquals ("<foo>bar</foo><baz /><quux /><>quuux</>", StringWriterText);
379
380                         xtw.WriteElementString (null, "quuuux");
381                         AssertEquals ("<foo>bar</foo><baz /><quux /><>quuux</><>quuuux</>", StringWriterText);
382                 }
383
384                 [Test]
385                 public void FormattingTest ()
386                 {
387                         xtw.Formatting = Formatting.Indented;
388                         xtw.WriteStartDocument ();
389                         xtw.WriteStartElement ("foo");
390                         xtw.WriteElementString ("bar", "");
391                         xtw.Close ();
392                         AssertEquals (String.Format ("<?xml version='1.0' encoding='utf-16'?>{0}<foo>{0}  <bar />{0}</foo>", Environment.NewLine), StringWriterText);
393                 }
394
395                 [Test]
396                 public void FormattingInvalidXmlForFun ()
397                 {
398                         xtw.Formatting = Formatting.Indented;
399                         xtw.IndentChar = 'x';
400                         xtw.WriteStartDocument ();
401                         xtw.WriteStartElement ("foo");
402                         xtw.WriteStartElement ("bar");
403                         xtw.WriteElementString ("baz", "");
404                         xtw.Close ();
405                         AssertEquals (String.Format ("<?xml version='1.0' encoding='utf-16'?>{0}<foo>{0}xx<bar>{0}xxxx<baz />{0}xx</bar>{0}</foo>", Environment.NewLine), StringWriterText);
406                 }
407
408                 [Test]
409                 public void FormattingFromRemarks ()
410                 {
411                         // Remarks section of on-line help for XmlTextWriter.Formatting suggests this test.
412                         xtw.Formatting = Formatting.Indented; 
413                         xtw.WriteStartElement ("ol"); 
414                         xtw.WriteStartElement ("li"); 
415                         xtw.WriteString ("The big "); // This means "li" now has a mixed content model. 
416                         xtw.WriteElementString ("b", "E"); 
417                         xtw.WriteElementString ("i", "lephant"); 
418                         xtw.WriteString (" walks slowly."); 
419                         xtw.WriteEndElement (); 
420                         xtw.WriteEndElement ();
421                         AssertEquals (String.Format ("<ol>{0}  <li>The big <b>E</b><i>lephant</i> walks slowly.</li>{0}</ol>", Environment.NewLine), StringWriterText);
422                 }
423
424                 [Test]
425                 public void LookupPrefix ()
426                 {
427                         xtw.WriteStartElement ("root");
428
429                         xtw.WriteStartElement ("one");
430                         xtw.WriteAttributeString ("xmlns", "foo", null, "http://abc.def");
431                         xtw.WriteAttributeString ("xmlns", "bar", null, "http://ghi.jkl");
432                         AssertEquals ("foo", xtw.LookupPrefix ("http://abc.def"));
433                         AssertEquals ("bar", xtw.LookupPrefix ("http://ghi.jkl"));
434                         xtw.WriteEndElement ();
435
436                         xtw.WriteStartElement ("two");
437                         xtw.WriteAttributeString ("xmlns", "baz", null, "http://mno.pqr");
438                         xtw.WriteString("quux");
439                         AssertEquals ("baz", xtw.LookupPrefix ("http://mno.pqr"));
440                         AssertNull (xtw.LookupPrefix ("http://abc.def"));
441                         AssertNull (xtw.LookupPrefix ("http://ghi.jkl"));
442
443                         AssertNull (xtw.LookupPrefix ("http://bogus"));
444                 }
445
446                 [Test]
447                 public void NamespacesAttributesPassingInNamespaces ()
448                 {
449                         xtw.Namespaces = false;
450                         xtw.WriteStartElement ("foo");
451
452                         // These shouldn't throw any exceptions since they don't pass in
453                         // a namespace.
454                         xtw.WriteAttributeString ("bar", "baz");
455                         xtw.WriteAttributeString ("", "a", "", "b");
456                         xtw.WriteAttributeString (null, "c", "", "d");
457                         xtw.WriteAttributeString ("", "e", null, "f");
458                         xtw.WriteAttributeString (null, "g", null, "h");
459
460                         AssertEquals ("<foo bar='baz' a='b' c='d' e='f' g='h'", StringWriterText);
461
462                         // These should throw ArgumentException because they pass in a
463                         // namespace when Namespaces = false.
464                 }
465
466                 [Test]
467                 public void NamespacesElementsPassingInNamespaces ()
468                 {
469                         xtw.Namespaces = false;
470
471                         // These shouldn't throw any exceptions since they don't pass in
472                         // a namespace.
473                         xtw.WriteElementString ("foo", "bar");
474                         xtw.WriteStartElement ("baz");
475                         xtw.WriteStartElement ("quux", "");
476                         xtw.WriteStartElement ("quuux", null);
477                         xtw.WriteStartElement (null, "a", null);
478                         xtw.WriteStartElement (null, "b", "");
479                         xtw.WriteStartElement ("", "c", null);
480                         xtw.WriteStartElement ("", "d", "");
481
482                         AssertEquals ("<foo>bar</foo><baz><quux><quuux><a><b><c><d", StringWriterText);
483
484                         // These should throw ArgumentException because they pass in a
485                         // namespace when Namespaces = false.
486                         try {
487                                 xtw.WriteElementString ("qux", "http://netsack.com/", String.Empty);
488                                 Fail ("Expected an ArgumentException.");
489                         } catch (ArgumentException) {}
490
491                         try {
492                                 xtw.WriteStartElement ("foo", "http://netsack.com/");
493                                 Fail ("Expected an ArgumentException.");
494                         } catch (ArgumentException) {}
495
496                         try {
497                                 xtw.WriteStartElement ("foo", "bar", "http://netsack.com/");
498                                 Fail ("Expected an ArgumentException.");
499                         } catch (ArgumentException) {}
500
501                         try {
502                                 xtw.WriteStartElement ("foo", "bar", null);
503                                 Fail ("Expected an ArgumentException.");
504                         } catch (ArgumentException) {}
505
506                         try {
507                                 xtw.WriteStartElement ("foo", "bar", "");
508                                 Fail ("Expected an ArgumentException.");
509                         } catch (ArgumentException) {}
510
511                         try {
512                                 xtw.WriteStartElement ("foo", "", "");
513                                 Fail ("Expected an ArgumentException.");
514                         } catch (ArgumentException) {}
515                 }
516
517                 [Test]
518                 public void NamespacesNoNamespaceClearsDefaultNamespace ()
519                 {
520                         xtw.WriteStartElement(String.Empty, "foo", "http://netsack.com/");
521                         xtw.WriteStartElement(String.Empty, "bar", String.Empty);
522                         xtw.WriteElementString("baz", String.Empty, String.Empty);
523                         xtw.WriteEndElement();
524                         xtw.WriteEndElement();
525                         AssertEquals ("XmlTextWriter is incorrectly outputting namespaces.",
526                                 "<foo xmlns='http://netsack.com/'><bar xmlns=''><baz /></bar></foo>", StringWriterText);
527                 }
528
529                 [Test]
530                 public void NamespacesPrefix ()
531                 {
532                         xtw.WriteStartElement ("foo", "bar", "http://netsack.com/");
533                         xtw.WriteStartElement ("foo", "baz", "http://netsack.com/");
534                         xtw.WriteElementString ("qux", "http://netsack.com/", String.Empty);
535                         xtw.WriteEndElement ();
536                         xtw.WriteEndElement ();
537                         AssertEquals ("XmlTextWriter is incorrectly outputting prefixes.",
538                                 "<foo:bar xmlns:foo='http://netsack.com/'><foo:baz><foo:qux /></foo:baz></foo:bar>", StringWriterText);
539                 }
540
541                 [Test]
542                 public void NamespacesPrefixWithEmptyAndNullNamespace ()
543                 {
544                         try {
545                                 xtw.WriteStartElement ("foo", "bar", "");
546                                 Fail ("Should have thrown an ArgumentException.");
547                         } catch (ArgumentException) {}
548
549                         try 
550                         {
551                                 xtw.WriteStartElement ("foo", "bar", null);
552                                 Fail ("Should have thrown an ArgumentException.");
553                         } 
554                         catch (ArgumentException) {}
555                 }
556
557                 [Test]
558                 public void NamespacesSettingWhenWriteStateNotStart ()
559                 {
560                         xtw.WriteStartElement ("foo");
561                         try 
562                         {
563                                 xtw.Namespaces = false;
564                                 Fail ("Expected an InvalidOperationException.");
565                         } 
566                         catch (InvalidOperationException) {}
567                         AssertEquals (true, xtw.Namespaces);
568                 }
569
570                 [Test]
571                 public void ProcessingInstructionValid ()
572                 {
573                         xtw.WriteProcessingInstruction("foo", "bar");
574                         AssertEquals ("WriteProcessingInstruction had incorrect output.", "<?foo bar?>", StringWriterText);
575                 }
576
577                 [Test]
578                 public void ProcessingInstructionInvalid ()
579                 {
580                         try 
581                         {
582                                 xtw.WriteProcessingInstruction("fo?>o", "bar");
583                                 Fail("Should have thrown an ArgumentException.");
584                         } 
585                         catch (ArgumentException) { }
586
587                         try 
588                         {
589                                 xtw.WriteProcessingInstruction("foo", "ba?>r");
590                                 Fail("Should have thrown an ArgumentException.");
591                         } 
592                         catch (ArgumentException) { }
593
594                         try 
595                         {
596                                 xtw.WriteProcessingInstruction("", "bar");
597                                 Fail("Should have thrown an ArgumentException.");
598                         } 
599                         catch (ArgumentException) { }
600
601                         try 
602                         {
603                                 xtw.WriteProcessingInstruction(null, "bar");
604                                 Fail("Should have thrown an ArgumentException.");
605                         } 
606                         catch (ArgumentException) { }
607                 }
608
609                 [Test]
610                 public void QuoteCharDoubleQuote ()
611                 {
612                         xtw.QuoteChar = '"';
613
614                         // version, encoding, standalone
615                         xtw.WriteStartDocument (true);
616                         
617                         // namespace declaration
618                         xtw.WriteElementString ("foo", "http://netsack.com", "bar");
619
620                         AssertEquals ("<?xml version=\"1.0\" encoding=\"utf-16\" standalone=\"yes\"?><foo xmlns=\"http://netsack.com\">bar</foo>", StringWriterText);
621
622
623                 }
624
625                 [Test]
626                 [ExpectedException (typeof (ArgumentException))]
627                 public void QuoteCharInvalid ()
628                 {
629                         xtw.QuoteChar = 'x';
630                 }
631
632                 [Test]
633                 public void WriteBase64 ()
634                 {
635                         UTF8Encoding encoding = new UTF8Encoding();
636                         byte[] fooBar = encoding.GetBytes("foobar");
637                         xtw.WriteBase64 (fooBar, 0, 6);
638                         AssertEquals("Zm9vYmFy", StringWriterText);
639
640                         try {
641                                 xtw.WriteBase64 (fooBar, 3, 6);
642                                 Fail ("Expected an Argument Exception to be thrown.");
643                         } catch (ArgumentException) {}
644
645                         try {
646                                 xtw.WriteBase64 (fooBar, -1, 6);
647                                 Fail ("Expected an Argument Exception to be thrown.");
648                         } catch (ArgumentOutOfRangeException) {}
649
650                         try {
651                                 xtw.WriteBase64 (fooBar, 3, -1);
652                                 Fail ("Expected an Argument Exception to be thrown.");
653                         } catch (ArgumentOutOfRangeException) {}
654
655                         try {
656                                 xtw.WriteBase64 (null, 0, 6);
657                                 Fail ("Expected an Argument Exception to be thrown.");
658                         } catch (ArgumentNullException) {}
659                 }
660
661                 [Test]
662                 public void WriteCharEntity ()
663                 {
664                         xtw.WriteCharEntity ('a');
665                         AssertEquals ("&#x61;", StringWriterText);
666
667                         xtw.WriteCharEntity ('A');
668                         AssertEquals ("&#x61;&#x41;", StringWriterText);
669
670                         xtw.WriteCharEntity ('1');
671                         AssertEquals ("&#x61;&#x41;&#x31;", StringWriterText);
672
673                         xtw.WriteCharEntity ('K');
674                         AssertEquals ("&#x61;&#x41;&#x31;&#x4B;", StringWriterText);
675
676                         try {
677                                 xtw.WriteCharEntity ((char)0xd800);
678                         } catch (ArgumentException) {}
679                 }
680
681                 [Test]
682                 [ExpectedException (typeof (InvalidOperationException))]
683                 public void WriteEndAttribute ()
684                 {
685                         xtw.WriteEndAttribute ();
686                 }
687
688                 [Test]
689                 public void WriteEndDocument ()
690                 {
691                         try {
692                                 xtw.WriteEndDocument ();
693                                 Fail ("Expected an ArgumentException.");
694                         } catch (ArgumentException) {}
695
696                         xtw.WriteStartDocument ();
697
698                         try 
699                         {
700                                 xtw.WriteEndDocument ();
701                                 Fail ("Expected an ArgumentException.");
702                         } 
703                         catch (ArgumentException) {}
704
705                         xtw.WriteStartElement ("foo");
706                         xtw.WriteStartAttribute ("bar", null);
707                         AssertEquals ("<?xml version='1.0' encoding='utf-16'?><foo bar='", StringWriterText);
708
709                         xtw.WriteEndDocument ();
710                         AssertEquals ("<?xml version='1.0' encoding='utf-16'?><foo bar='' />", StringWriterText);
711                         AssertEquals (WriteState.Start, xtw.WriteState);
712                 }
713
714                 [Test]
715                 public void WriteEndElement ()
716                 {
717                         try {
718                                 xtw.WriteEndElement ();
719                                 Fail ("Should have thrown an InvalidOperationException.");
720                         } catch (InvalidOperationException) {
721                                 // Don't rely on English message assertion.
722                                 // It is enough to check an exception occurs.
723 //                              AssertEquals ("Exception message is incorrect.", "There was no XML start tag open.", e.Message);
724                         }
725
726                         xtw.WriteStartElement ("foo");
727                         xtw.WriteEndElement ();
728                         AssertEquals ("<foo />", StringWriterText);
729
730                         xtw.WriteStartElement ("bar");
731                         xtw.WriteStartAttribute ("baz", null);
732                         xtw.WriteEndElement ();
733                         AssertEquals ("<foo /><bar baz='' />", StringWriterText);
734                 }
735
736                 [Test]
737                 public void FullEndElement ()
738                 {
739                         xtw.WriteStartElement ("foo");
740                         xtw.WriteFullEndElement ();
741                         AssertEquals ("<foo></foo>", StringWriterText);
742
743                         xtw.WriteStartElement ("bar");
744                         xtw.WriteAttributeString ("foo", "bar");
745                         xtw.WriteFullEndElement ();
746                         AssertEquals ("<foo></foo><bar foo='bar'></bar>", StringWriterText);
747
748                         xtw.WriteStartElement ("baz");
749                         xtw.WriteStartAttribute ("bar", null);
750                         xtw.WriteFullEndElement ();
751                         AssertEquals ("<foo></foo><bar foo='bar'></bar><baz bar=''></baz>", StringWriterText);
752                 }
753
754                 [Test]
755                 public void WriteQualifiedName ()
756                 {
757                         xtw.WriteStartElement (null, "test", null);
758                         xtw.WriteAttributeString ("xmlns", "me", null, "http://localhost/");
759                         xtw.WriteQualifiedName ("bob", "http://localhost/");
760                         xtw.WriteEndElement ();
761
762                         AssertEquals ("<test xmlns:me='http://localhost/'>me:bob</test>", StringWriterText);
763                 }
764
765                 [Test]
766                 public void WriteRaw ()
767                 {
768                         xtw.WriteRaw("&<>\"'");
769                         AssertEquals ("&<>\"'", StringWriterText);
770
771                         xtw.WriteRaw(null);
772                         AssertEquals ("&<>\"'", StringWriterText);
773
774                         xtw.WriteRaw("");
775                         AssertEquals ("&<>\"'", StringWriterText);
776                 }
777
778                 [Test]
779                 public void WriteRawInvalidInAttribute ()
780                 {
781                         xtw.WriteStartElement ("foo");
782                         xtw.WriteStartAttribute ("bar", null);
783                         xtw.WriteRaw ("&<>\"'");
784                         xtw.WriteEndAttribute ();
785                         xtw.WriteEndElement ();
786                         AssertEquals ("<foo bar='&<>\"'' />", StringWriterText);
787                 }
788
789                 [Test]
790                 public void WriteStateTest ()
791                 {
792                         AssertEquals (WriteState.Start, xtw.WriteState);
793                         xtw.WriteStartDocument ();
794                         AssertEquals (WriteState.Prolog, xtw.WriteState);
795                         xtw.WriteStartElement ("root");
796                         AssertEquals (WriteState.Element, xtw.WriteState);
797                         xtw.WriteElementString ("foo", "bar");
798                         AssertEquals (WriteState.Content, xtw.WriteState);
799                         xtw.Close ();
800                         AssertEquals (WriteState.Closed, xtw.WriteState);
801                 }
802
803                 [Test]
804                 public void WriteString ()
805                 {
806                         xtw.WriteStartDocument ();
807                         try {
808                                 xtw.WriteString("foo");
809                         } catch (InvalidOperationException) {}
810
811                         // Testing attribute values
812
813                         xtw.WriteStartElement ("foo");
814                         xtw.WriteAttributeString ("bar", "&<>");
815                         AssertEquals ("<?xml version='1.0' encoding='utf-16'?><foo bar='&amp;&lt;&gt;'", StringWriterText);
816                 }
817
818                 [Test]
819                 public void WriteAttributeStringSingleQuoteChar()
820                 {
821                         // When QuoteChar is single quote then replaces single quotes within attributes
822                         // but not double quotes.
823                         xtw.WriteStartElement ("foo");
824                         xtw.WriteAttributeString ("bar", "\"baz\"");
825                         xtw.WriteAttributeString ("quux", "'baz'");
826                         AssertEquals ("<foo bar='\"baz\"' quux='&apos;baz&apos;'", StringWriterText);
827                 }
828
829                 [Test]
830                 public void WriteAttributeStringDoubleQuoteChar()
831                 {
832                         // When QuoteChar is double quote then replaces double quotes within attributes
833                         // but not single quotes.
834                         xtw.QuoteChar = '"';
835                         xtw.WriteStartElement ("foo");
836                         xtw.WriteAttributeString ("bar", "\"baz\"");
837                         xtw.WriteAttributeString ("quux", "'baz'");
838                         AssertEquals ("<foo bar=\"&quot;baz&quot;\" quux=\"'baz'\"", StringWriterText);
839                 }
840
841                 [Test]
842                 public void WriteStringWithEntities()
843                 {
844                         // Testing element values
845                         xtw.QuoteChar = '\'';
846                         xtw.WriteElementString ("foo", "&<>\"'");
847                         AssertEquals ("<foo>&amp;&lt;&gt;\"'</foo>", StringWriterText);
848                 }
849
850                 [Test]
851                 public void XmlLang ()
852                 {
853                         AssertNull (xtw.XmlLang);
854                         
855                         xtw.WriteStartElement ("foo");
856                         xtw.WriteAttributeString ("xml", "lang", null, "langfoo");
857                         AssertEquals ("langfoo", xtw.XmlLang);
858                         AssertEquals ("<foo xml:lang='langfoo'", StringWriterText);
859
860                         xtw.WriteAttributeString ("boo", "yah");
861                         AssertEquals ("langfoo", xtw.XmlLang);
862                         AssertEquals ("<foo xml:lang='langfoo' boo='yah'", StringWriterText);
863                         
864                         xtw.WriteElementString("bar", "baz");
865                         AssertEquals ("langfoo", xtw.XmlLang);
866                         AssertEquals ("<foo xml:lang='langfoo' boo='yah'><bar>baz</bar>", StringWriterText);
867                         
868                         xtw.WriteString("baz");
869                         AssertEquals ("langfoo", xtw.XmlLang);
870                         AssertEquals ("<foo xml:lang='langfoo' boo='yah'><bar>baz</bar>baz", StringWriterText);
871                         
872                         xtw.WriteStartElement ("quux");
873                         xtw.WriteStartAttribute ("xml", "lang", null);
874                         AssertEquals ("langfoo", xtw.XmlLang);
875                         AssertEquals ("<foo xml:lang='langfoo' boo='yah'><bar>baz</bar>baz<quux xml:lang='", StringWriterText);
876                         
877                         xtw.WriteString("langbar");
878                         AssertEquals ("langfoo", xtw.XmlLang);
879                         AssertEquals ("<foo xml:lang='langfoo' boo='yah'><bar>baz</bar>baz<quux xml:lang='", StringWriterText);
880                         
881                         xtw.WriteEndAttribute ();
882                         AssertEquals ("langbar", xtw.XmlLang);
883                         AssertEquals ("<foo xml:lang='langfoo' boo='yah'><bar>baz</bar>baz<quux xml:lang='langbar'", StringWriterText);
884
885                         // check if xml:lang repeats output even if same as current scope.
886                         xtw.WriteStartElement ("joe");
887                         xtw.WriteAttributeString ("xml", "lang", null, "langbar");
888                         AssertEquals ("<foo xml:lang='langfoo' boo='yah'><bar>baz</bar>baz<quux xml:lang='langbar'><joe xml:lang='langbar'", StringWriterText);
889
890                         
891                         xtw.WriteElementString ("quuux", "squonk");
892                         AssertEquals ("langbar", xtw.XmlLang);
893                         AssertEquals ("<foo xml:lang='langfoo' boo='yah'><bar>baz</bar>baz<quux xml:lang='langbar'><joe xml:lang='langbar'><quuux>squonk</quuux>", StringWriterText);
894
895                         xtw.WriteEndElement ();
896                         xtw.WriteEndElement ();
897                         AssertEquals ("langfoo", xtw.XmlLang);
898                         AssertEquals ("<foo xml:lang='langfoo' boo='yah'><bar>baz</bar>baz<quux xml:lang='langbar'><joe xml:lang='langbar'><quuux>squonk</quuux></joe></quux>", StringWriterText);
899                         
900                         xtw.WriteEndElement ();
901                         AssertNull (xtw.XmlLang);
902                         AssertEquals ("<foo xml:lang='langfoo' boo='yah'><bar>baz</bar>baz<quux xml:lang='langbar'><joe xml:lang='langbar'><quuux>squonk</quuux></joe></quux></foo>", StringWriterText);
903                         
904                         xtw.Close ();
905                         AssertNull (xtw.XmlLang);
906                 }
907
908                 // TODO: test operational aspects
909                 [Test]
910                 public void XmlSpaceTest ()
911                 {
912                         xtw.WriteStartElement ("foo");
913                         AssertEquals (XmlSpace.None, xtw.XmlSpace);
914
915                         xtw.WriteStartElement ("bar");
916                         xtw.WriteAttributeString ("xml", "space", null, "preserve");
917                         AssertEquals (XmlSpace.Preserve, xtw.XmlSpace);
918                         AssertEquals ("<foo><bar xml:space='preserve'", StringWriterText);
919
920                         xtw.WriteStartElement ("baz");
921                         xtw.WriteAttributeString ("xml", "space", null, "preserve");
922                         AssertEquals (XmlSpace.Preserve, xtw.XmlSpace);
923                         AssertEquals ("<foo><bar xml:space='preserve'><baz xml:space='preserve'", StringWriterText);
924
925                         xtw.WriteStartElement ("quux");
926                         xtw.WriteStartAttribute ("xml", "space", null);
927                         AssertEquals (XmlSpace.Preserve, xtw.XmlSpace);
928                         AssertEquals ("<foo><bar xml:space='preserve'><baz xml:space='preserve'><quux xml:space='", StringWriterText);
929
930                         xtw.WriteString ("default");
931                         AssertEquals (XmlSpace.Preserve, xtw.XmlSpace);
932                         AssertEquals ("<foo><bar xml:space='preserve'><baz xml:space='preserve'><quux xml:space='", StringWriterText);
933                         
934                         xtw.WriteEndAttribute ();
935                         AssertEquals (XmlSpace.Default, xtw.XmlSpace);
936                         AssertEquals ("<foo><bar xml:space='preserve'><baz xml:space='preserve'><quux xml:space='default'", StringWriterText);
937
938                         xtw.WriteEndElement ();
939                         AssertEquals (XmlSpace.Preserve, xtw.XmlSpace);
940                         xtw.WriteEndElement ();
941                         AssertEquals (XmlSpace.Preserve, xtw.XmlSpace);
942                         xtw.WriteEndElement ();
943                         AssertEquals (XmlSpace.None, xtw.XmlSpace);
944
945                         xtw.WriteStartElement ("quux");
946                         try {
947                                 xtw.WriteAttributeString ("xml", "space", null, "bubba");
948                         } catch (ArgumentException) {}
949
950                         try {
951                                 xtw.WriteAttributeString ("xml", "space", null, "PRESERVE");
952                         } catch (ArgumentException) {}
953
954                         try {
955                                 xtw.WriteAttributeString ("xml", "space", null, "Preserve");
956                         } catch (ArgumentException) {}
957
958                         try {
959                                 xtw.WriteAttributeString ("xml", "space", null, "Default");
960                         } catch (ArgumentException) {}
961
962                         try {
963                                 xtw.WriteWhitespace ("x");
964                         } catch (ArgumentException) { }
965                 }
966
967                 [Test]
968                 public void XmlSpaceRaw ()
969                 {
970                         xtw.WriteStartElement ("foo");
971                         xtw.WriteStartAttribute ("xml", "space", null);
972                         AssertEquals (XmlSpace.None, xtw.XmlSpace);
973                         AssertEquals ("<foo xml:space='", StringWriterText);
974
975                         xtw.WriteString ("default");
976                         AssertEquals (XmlSpace.None, xtw.XmlSpace);
977                         AssertEquals ("<foo xml:space='", StringWriterText);
978
979                         xtw.WriteEndAttribute ();
980                         AssertEquals (XmlSpace.Default, xtw.XmlSpace);
981                         AssertEquals ("<foo xml:space='default'", StringWriterText);
982                 }
983
984                 [Test]
985                 public void WriteAttributes ()
986                 {
987                         XmlDocument doc = new XmlDocument();
988                         StringWriter sw = new StringWriter();
989                         XmlWriter wr = new XmlTextWriter(sw);
990                         StringBuilder sb = sw.GetStringBuilder();
991                         XmlParserContext ctx = new XmlParserContext(doc.NameTable, new XmlNamespaceManager(doc.NameTable), "", XmlSpace.Default);
992                         XmlTextReader xtr = new XmlTextReader("<?xml version='1.0' encoding='utf-8' standalone='no'?><root a1='A' b2='B' c3='C'><foo><bar /></foo></root>", XmlNodeType.Document, ctx);
993
994                         xtr.Read();     // read XMLDecl
995                         wr.WriteAttributes(xtr, false);
996                         // This method don't always have to take this double-quoted style...
997                         AssertEquals("#WriteAttributes.XmlDecl.1", "version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"", sw.ToString().Trim());
998
999                         sb.Remove(0, sb.Length);        // init
1000                         ctx = new XmlParserContext(doc.NameTable, new XmlNamespaceManager(doc.NameTable), "", XmlSpace.Default);
1001                         xtr = new XmlTextReader("<?xml version='1.0'             standalone='no'?><root a1='A' b2='B' c3='C'><foo><bar /></foo></root>", XmlNodeType.Document, ctx);
1002                         xtr.Read();     // read XMLDecl
1003                         AssertEquals (XmlNodeType.XmlDeclaration, xtr.NodeType);
1004                         sw = new StringWriter ();
1005                         wr = new XmlTextWriter (sw);
1006
1007                         // This block raises an error on MS.NET 1.0.
1008                         wr.WriteAttributes(xtr, false);
1009                         // This method don't always have to take this double-quoted style...
1010                         AssertEquals("#WriteAttributes.XmlDecl.2", "version=\"1.0\" standalone=\"no\"", sw.ToString().Trim());
1011
1012                         sw = new StringWriter ();
1013                         wr = new XmlTextWriter (sw);
1014                         sb.Remove(0, sb.Length);        // init
1015
1016                         xtr.Read();     // read root
1017                         AssertEquals (XmlNodeType.Element, xtr.NodeType);
1018                         wr.WriteStartElement(xtr.LocalName, xtr.NamespaceURI);
1019                         wr.WriteAttributes(xtr, false);
1020                         wr.WriteEndElement();
1021                         wr.Close();
1022                         // This method don't always have to take this double-quoted style...
1023                         AssertEquals("#WriteAttributes.Element", "<root a1=\"A\" b2=\"B\" c3=\"C\" />", sw.ToString().Trim());
1024                 }
1025
1026                 [Test]
1027                 public void WriteWhitespace ()
1028                 {
1029                         xtw.WriteStartElement ("a");
1030                         xtw.WriteWhitespace ("\n\t");
1031                         xtw.WriteStartElement ("b");
1032                         xtw.WriteWhitespace ("\n\t");
1033                         xtw.WriteEndElement ();
1034                         xtw.WriteWhitespace ("\n");
1035                         xtw.WriteEndElement ();
1036                         xtw.WriteWhitespace ("\n");
1037                         xtw.Flush ();
1038                         AssertEquals ("<a>\n\t<b>\n\t</b>\n</a>\n", StringWriterText);
1039                 }
1040
1041                 [Test]
1042                 public void FlushDoesntCloseTag ()
1043                 {
1044                         xtw.WriteStartElement ("foo");
1045                         xtw.WriteAttributeString ("bar", "baz");
1046                         xtw.Flush ();
1047                         AssertEquals ("<foo bar='baz'", StringWriterText);
1048                 }
1049
1050                 [Test]
1051                 public void WriteWhitespaceClosesTag ()
1052                 {
1053                         xtw.WriteStartElement ("foo");
1054                         xtw.WriteAttributeString ("bar", "baz");
1055                         xtw.WriteWhitespace (" ");
1056                         AssertEquals ("<foo bar='baz'> ", StringWriterText);
1057                 }
1058
1059                 [Test]
1060                 public void DontOutputMultipleXmlns ()
1061                 {
1062                         XmlDocument doc = new XmlDocument();\r
1063                         doc.LoadXml("<a xmlns:dt=\"b\" dt:dt=\"c\"/>");\r
1064                         XmlDocument doc2 = new XmlDocument();\r
1065                         doc2.LoadXml(doc.InnerXml);
1066                         AssertEquals ("<a xmlns:dt=\"b\" dt:dt=\"c\" />",
1067                                 doc2.OuterXml);
1068                 }
1069         }
1070 }