Merge pull request #2200 from xmcclure/image-audit-oops
[mono.git] / mcs / class / System.Runtime.Serialization / Test / System.Runtime.Serialization.Json / JsonWriterTest.cs
1 //
2 // JsonWriterTest.cs
3 //
4 // Author:
5 //      Atsushi Enomoto  <atsushi@ximian.com>
6 //
7 // Copyright (C) 2007 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 using System;
29 using System.IO;
30 using System.Text;
31 using System.Runtime.Serialization;
32 using System.Runtime.Serialization.Json;
33 using System.Xml;
34 using NUnit.Framework;
35
36 namespace MonoTests.System.Runtime.Serialization.Json
37 {
38         [TestFixture]
39         public class JsonWriterTest
40         {
41                 MemoryStream ms;
42                 XmlDictionaryWriter w;
43
44                 string ResultString {
45                         get { return Encoding.UTF8.GetString (ms.ToArray ()); }
46                 }
47
48                 [SetUp]
49                 public void Setup ()
50                 {
51                         ms = new MemoryStream ();
52                         w = JsonReaderWriterFactory.CreateJsonWriter (ms);
53                 }
54
55                 /*
56                 [Test]
57                 public void Dummy_BitFlagsGenerator ()
58                 {
59                         var b = new BitFlagsGenerator (2);
60                         Assert.IsFalse (b.Load (0), "#a1");
61                         b.Store (0, false);
62                         Assert.IsFalse (b.Load (0), "#a2");
63                         b.Store (0, true);
64                         Assert.IsTrue (b.Load (0), "#a3");
65                         Assert.IsFalse (b.Load (1), "#a4");
66                         b.Store (0, false);
67                         Assert.IsFalse (b.Load (0), "#a5");
68                         Assert.IsFalse (b.Load (1), "#a6");
69
70                         Assert.IsFalse (b.Load (1), "#b1");
71                         b.Store (1, false);
72                         Assert.IsFalse (b.Load (1), "#b2");
73                         b.Store (1, true);
74                         Assert.IsTrue (b.Load (1), "#b3");
75                         b.Store (1, false);
76                         Assert.IsFalse (b.Load (1), "#b4");
77
78                         var bytes = new byte [2];
79                         Assert.IsFalse (BitFlagsGenerator.IsBitSet (bytes, 0), "#c1");
80                         BitFlagsGenerator.SetBit (bytes, 0);
81                         Assert.IsTrue (BitFlagsGenerator.IsBitSet (bytes, 0), "#c2");
82                         Assert.IsFalse (BitFlagsGenerator.IsBitSet (bytes, 1), "#c3");
83                         BitFlagsGenerator.SetBit (bytes, 0);
84                         Assert.IsTrue (BitFlagsGenerator.IsBitSet (bytes, 0), "#c4");
85                 }
86                 */
87
88                 [Test]
89                 [ExpectedException (typeof (ArgumentNullException))]
90                 public void ConstructorNullStream ()
91                 {
92                         JsonReaderWriterFactory.CreateJsonWriter (null);
93                 }
94
95                 [Test]
96                 [ExpectedException (typeof (ArgumentNullException))]
97                 public void ConstructorNullEncoding ()
98                 {
99                         JsonReaderWriterFactory.CreateJsonWriter (new MemoryStream (), null);
100                 }
101
102                 [Test]
103                 [ExpectedException (typeof (XmlException))]
104                 public void SimpleElementNotRoot ()
105                 {
106                         w.WriteStartElement ("foo");
107                 }
108
109                 [Test]
110                 public void SimpleElement ()
111                 {
112                         w.WriteStartElement ("root");
113                         w.WriteEndElement ();
114                         w.Close ();
115                         // empty string literal ("")
116                         Assert.AreEqual ("\"\"", ResultString, "#1");
117                 }
118
119                 [Test]
120                 [ExpectedException (typeof (XmlException))]
121                 public void SimpleElement2 ()
122                 {
123                         w.WriteStartElement ("root");
124                         w.WriteStartElement ("foo");
125                         // type='array' or type='object' is required before writing immediate child of an element.
126                 }
127
128                 [Test]
129                 public void SimpleElement3 ()
130                 {
131                         w.WriteStartElement ("root");
132                         w.WriteAttributeString ("type", "object");
133                         w.WriteStartElement ("e1");
134                         w.WriteAttributeString ("type", "object");
135                         w.WriteStartElement ("e1_1");
136                         w.WriteEndElement (); // treated as a string literal
137                         w.WriteEndElement ();
138                         w.WriteStartElement ("e2");
139                         w.WriteString ("value");
140                         w.WriteEndElement ();
141                         w.WriteEndElement ();
142                         w.Close ();
143                         string json = "{\"e1\":{\"e1_1\":\"\"},\"e2\":\"value\"}";
144                         Assert.AreEqual (json, ResultString, "#1");
145                 }
146
147                 [Test]
148                 [ExpectedException (typeof (ArgumentException))]
149                 public void AttributeNonType ()
150                 {
151                         w.WriteStartElement ("root");
152                         // only "type" attribute is expected.
153                         w.WriteStartAttribute ("a1");
154                 }
155
156                 [Test]
157                 [ExpectedException (typeof (XmlException))]
158                 public void TypeAttributeNonStandard ()
159                 {
160                         w.WriteStartElement ("root");
161                         w.WriteAttributeString ("type", "foo");
162                 }
163
164                 [Test]
165                 public void SimpleTypeAttribute ()
166                 {
167                         w.WriteStartElement ("root");
168                         w.WriteAttributeString ("type", "number");
169                         w.WriteEndElement ();
170                         w.Close ();
171                         Assert.AreEqual (String.Empty, ResultString, "#1");
172                 }
173
174                 [Test]
175                 public void SimpleTypeAttribute2 ()
176                 {
177                         w.WriteStartElement ("root");
178                         w.WriteAttributeString ("type", "object");
179                         w.WriteStartElement ("foo");
180                         w.WriteAttributeString ("type", "number");
181                         w.WriteString ("1");
182                         w.WriteEndElement ();
183                         w.Close ();
184                         Assert.AreEqual ("{\"foo\":1}", ResultString, "#1");
185                 }
186
187                 [Test]
188                 [ExpectedException (typeof (XmlException))]
189                 public void WriteStringForNull ()
190                 {
191                         w.WriteStartElement ("root");
192                         w.WriteStartElement ("foo");
193                         w.WriteAttributeString ("type", "null");
194                         w.WriteString ("1");
195                 }
196
197                 [Test]
198                 [ExpectedException (typeof (XmlException))]
199                 public void WriteStringForArray ()
200                 {
201                         w.WriteStartElement ("root");
202                         w.WriteAttributeString ("type", "object");
203                         w.WriteStartElement ("foo");
204                         w.WriteAttributeString ("type", "array");
205                         w.WriteString ("1");
206                 }
207
208                 [Test]
209                 // uh, no exception?
210                 public void WriteStringForBoolean ()
211                 {
212                         w.WriteStartElement ("root");
213                         w.WriteAttributeString ("type", "object");
214                         w.WriteStartElement ("foo");
215                         w.WriteAttributeString ("type", "boolean");
216                         w.WriteString ("xyz");
217                         w.WriteEndElement ();
218                 }
219
220                 [Test]
221                 [ExpectedException (typeof (XmlException))]
222                 public void WriteStringForObject ()
223                 {
224                         w.WriteStartElement ("root");
225                         w.WriteAttributeString ("type", "object");
226                         w.WriteString ("1");
227                 }
228
229                 [Test]
230                 [ExpectedException (typeof (XmlException))]
231                 public void WriteArrayNonItem ()
232                 {
233                         w.WriteStartElement ("root");
234                         w.WriteStartElement ("foo");
235                         w.WriteAttributeString ("type", "array");
236                         w.WriteStartElement ("bar");
237                 }
238
239                 [Test]
240                 public void WriteArray ()
241                 {
242                         w.WriteStartElement ("root"); // name is ignored
243                         w.WriteAttributeString ("type", "array");
244                         w.WriteElementString ("item", "v1");
245                         w.WriteElementString ("item", "v2");
246                         w.Close ();
247                         Assert.AreEqual (@"[""v1"",""v2""]", ResultString, "#1");
248                 }
249
250                 [Test]
251                 public void WriteArrayInObject ()
252                 {
253                         w.WriteStartElement ("root");
254                         w.WriteAttributeString ("type", "object");
255                         w.WriteStartElement ("foo");
256                         w.WriteAttributeString ("type", "array");
257                         w.WriteElementString ("item", "v1");
258                         w.WriteElementString ("item", "v2");
259                         w.Close ();
260                         Assert.AreEqual (@"{""foo"":[""v1"",""v2""]}", ResultString, "#1");
261                 }
262
263                 [Test]
264                 [ExpectedException (typeof (ArgumentException))]
265                 public void WriteStartElementNonEmptyNS ()
266                 {
267                         // namespaces are not allowed
268                         w.WriteStartElement (String.Empty, "x", "urn:foo");
269                 }
270
271                 [Test]
272                 [ExpectedException (typeof (ArgumentException))]
273                 public void WriteStartElementNonEmptyPrefix ()
274                 {
275                         // prefixes are not allowed
276                         w.WriteStartElement ("p", "x", "urn:foo");
277                 }
278
279                 [Test]
280                 [ExpectedException (typeof (XmlException))]
281                 public void WriteStartElementMultiTopLevel ()
282                 {
283                         w.WriteStartElement ("root");
284                         w.WriteEndElement ();
285                         // hmm...
286                         Assert.AreEqual (WriteState.Content, w.WriteState, "#1");
287                         // writing of multiple root elements is not supported
288                         w.WriteStartElement ("root2");
289                         w.Close ();
290                         Assert.AreEqual (String.Empty, ResultString, "#2");
291                 }
292
293                 [Test]
294                 [ExpectedException (typeof (ArgumentException))]
295                 public void WriteStartAttributeNonEmptyNS ()
296                 {
297                         // namespaces are not allowed
298                         w.WriteStartElement ("root");
299                         // well, empty prefix for a global attribute would be
300                         // replaced anyways ...
301                         w.WriteStartAttribute (String.Empty, "x", "urn:foo");
302                 }
303
304                 [Test]
305                 [ExpectedException (typeof (ArgumentException))]
306                 public void WriteStartAttributeInXmlNamespace ()
307                 {
308                         // even "xml" namespace is not allowed (anyways only "type" is allowed ...)
309                         w.WriteStartElement ("root");
310                         w.WriteStartAttribute ("xml", "lang", "http://www.w3.org/XML/1998/namespace");
311                 }
312
313                 [Test]
314                 [ExpectedException (typeof (ArgumentNullException))]
315                 public void LookupPrefixNull ()
316                 {
317                         w.LookupPrefix (null);
318                 }
319
320                 [Test]
321                 public void LookupPrefix ()
322                 {
323                         // since namespaces are not allowed, it mostly makes no sense...
324                         Assert.AreEqual (String.Empty, w.LookupPrefix (String.Empty), "#1");
325                         Assert.IsNull (w.LookupPrefix ("urn:nonexistent"), "#2");
326                         Assert.AreEqual ("xml", w.LookupPrefix ("http://www.w3.org/XML/1998/namespace"), "#3");
327                         Assert.AreEqual ("xmlns", w.LookupPrefix ("http://www.w3.org/2000/xmlns/"), "#4");
328                 }
329
330                 [Test]
331                 public void WriteStartDocument ()
332                 {
333                         Assert.AreEqual (WriteState.Start, w.WriteState, "#1");
334                         w.WriteStartDocument ();
335                         Assert.AreEqual (WriteState.Start, w.WriteState, "#2");
336                         w.WriteStartDocument (true);
337                         Assert.AreEqual (WriteState.Start, w.WriteState, "#3");
338                         // So, it does nothing
339                 }
340
341                 [Test]
342                 public void WriteEndDocument ()
343                 {
344                         w.WriteEndDocument (); // so, it is completely wrong, but ignored.
345                 }
346
347                 [Test]
348                 [ExpectedException (typeof (NotSupportedException))]
349                 public void WriteDocType ()
350                 {
351                         w.WriteDocType (null, null, null, null);
352                 }
353
354                 [Test]
355                 [ExpectedException (typeof (NotSupportedException))]
356                 public void WriteComment ()
357                 {
358                         w.WriteComment ("test");
359                 }
360
361                 [Test]
362                 [ExpectedException (typeof (NotSupportedException))]
363                 public void WriteEntityRef ()
364                 {
365                         w.WriteEntityRef ("ent");
366                 }
367
368                 [Test]
369                 [ExpectedException (typeof (ArgumentException))]
370                 public void WriteProcessingInstruction ()
371                 {
372                         // since this method accepts case-insensitive "XML",
373                         // it throws ArgumentException.
374                         w.WriteProcessingInstruction ("T", "D");
375                 }
376
377                 [Test]
378                 public void WriteProcessingInstructionXML ()
379                 {
380                         // You might not know, but in some cases, things like
381                         // XmlWriter.WriteNode() is implemented to invoke
382                         // this method for writing XML declaration. This
383                         // check is (seems) case-insensitive.
384                         w.WriteProcessingInstruction ("XML", "foobar");
385                         // In this case, the data is simply ignored (as
386                         // WriteStartDocument() is).
387                 }
388
389                 [Test]
390                 public void WriteRaw ()
391                 {
392                         w.WriteStartElement ("root");
393                         w.WriteRaw ("sample");
394                         w.WriteRaw (new char [] {'0', '1', '2', '3'}, 1, 2);
395                         w.Close ();
396                         Assert.AreEqual ("\"sample12\"", ResultString);
397                 }
398
399                 [Test]
400                 public void WriteCData ()
401                 {
402                         w.WriteStartElement ("root");
403                         w.WriteCData ("]]>"); // this behavior is incompatible with ordinal XmlWriters.
404                         w.Close ();
405                         Assert.AreEqual ("\"]]>\"", ResultString);
406                 }
407
408                 [Test]
409                 public void WriteCharEntity ()
410                 {
411                         w.WriteStartElement ("root");
412                         w.WriteCharEntity ('>');
413                         w.Close ();
414                         Assert.AreEqual ("\">\"", ResultString);
415                 }
416
417                 [Test]
418                 public void WriteWhitespace ()
419                 {
420                         w.WriteStartElement ("root");
421                         w.WriteWhitespace ("\t  \n\r");
422                         w.Close ();
423                         Assert.AreEqual (@"""\u0009  \u000a\u000d""", ResultString);
424                 }
425
426                 [Test]
427                 [ExpectedException (typeof (ArgumentException))]
428                 public void WriteWhitespaceNonWhitespace ()
429                 {
430                         w.WriteStartElement ("root");
431                         w.WriteWhitespace ("TEST");
432                 }
433
434                 [Test]
435                 [ExpectedException (typeof (InvalidOperationException))]
436                 public void WriteStringTopLevel ()
437                 {
438                         w.WriteString ("test");
439                 }
440
441                 [Test]
442                 [ExpectedException (typeof (XmlException))]
443                 public void WriteStartAttributeTopLevel ()
444                 {
445                         w.WriteStartAttribute ("test");
446                 }
447
448                 [Test]
449                 [ExpectedException (typeof (InvalidOperationException))]
450                 public void WriteStartDocumentAtClosed ()
451                 {
452                         w.Close ();
453                         w.WriteStartDocument ();
454                 }
455
456                 [Test]
457                 [ExpectedException (typeof (InvalidOperationException))]
458                 public void WriteStartElementAtClosed ()
459                 {
460                         w.Close ();
461                         w.WriteStartElement ("foo");
462                 }
463
464                 [Test]
465                 [ExpectedException (typeof (InvalidOperationException))]
466                 public void WriteProcessingInstructionAtClosed ()
467                 {
468                         w.Close ();
469                         w.WriteProcessingInstruction ("xml", "version='1.0'");
470                 }
471
472                 [Test]
473                 [ExpectedException (typeof (XmlException))]
474                 public void WriteMixedContent ()
475                 {
476                         w.WriteStartElement ("root");
477                         w.WriteString ("TEST");
478                         w.WriteStartElement ("mixed"); // is not allowed.
479                 }
480
481                 [Test]
482                 [ExpectedException (typeof (XmlException))]
483                 public void WriteStartElementInvalidTopLevelName ()
484                 {
485                         w.WriteStartElement ("anyname");
486                 }
487
488                 [Test]
489                 [ExpectedException (typeof (ArgumentNullException))]
490                 public void WriteStartElementNullName ()
491                 {
492                         w.WriteStartElement ("root");
493                         w.WriteAttributeString ("type", "object");
494                         w.WriteStartElement (null);
495                 }
496
497                 [Test]
498                 [ExpectedException (typeof (ArgumentException))]
499                 public void WriteStartElementEmptyName ()
500                 {
501                         w.WriteStartElement ("root");
502                         w.WriteAttributeString ("type", "object");
503                         w.WriteStartElement (String.Empty);
504                         // It is regarded as invalid name in JSON. However,
505                         // I don't think there is such limitation in JSON specification.
506                 }
507
508                 [Test]
509                 public void WriteStartElementWithRuntimeTypeName ()
510                 {
511                         w.WriteStartElement ("root");
512                         w.WriteAttributeString ("type", "object");
513                         w.WriteAttributeString ("__type", "FooType:#FooNamespace");
514                         w.Close ();
515                         Assert.AreEqual (@"{""__type"":""FooType:#FooNamespace""}", ResultString);
516                 }
517
518                 [Test]
519                 public void WriteStartElementWeirdName ()
520                 {
521                         w.WriteStartElement ("root");
522                         w.WriteAttributeString ("type", "object");
523                         w.WriteStartElement ("!!!");
524                         w.Close ();
525                         Assert.AreEqual (@"{""!!!"":""""}", ResultString);
526                 }
527
528                 [Test]
529                 public void WriteRootAsObject ()
530                 {
531                         w.WriteStartElement ("root");
532                         w.WriteStartAttribute ("type");
533                         w.WriteString ("object");
534                         w.WriteEndAttribute ();
535                         w.Close ();
536                         Assert.AreEqual ("{}", ResultString);
537                 }
538
539                 [Test]
540                 public void WriteRootAsArray ()
541                 {
542                         w.WriteStartElement ("root");
543                         w.WriteStartAttribute ("type");
544                         w.WriteString ("array");
545                         w.WriteEndAttribute ();
546                         w.Close ();
547                         Assert.AreEqual ("[]", ResultString);
548                 }
549
550                 [Test]
551                 public void WriteRootAsLiteral ()
552                 {
553                         w.WriteStartElement ("root");
554                         w.Close ();
555                         Assert.AreEqual ("\"\"", ResultString);
556                 }
557
558                 [Test]
559                 [ExpectedException (typeof (XmlException))]
560                 public void WriteEndElementOnAttribute ()
561                 {
562                         w.WriteStartElement ("root");
563                         w.WriteStartAttribute ("type");
564                         w.WriteString ("array");
565                         w.WriteEndElement ();
566                 }
567
568                 [Test]
569                 public void WriteAttributeAsSeparateStrings ()
570                 {
571                         w.WriteStartElement ("root");
572                         w.WriteStartAttribute ("type");
573                         w.WriteString ("arr");
574                         w.WriteString ("ay");
575                         w.WriteEndAttribute ();
576                         w.Close ();
577                         Assert.AreEqual ("[]", ResultString);
578                 }
579
580                 [Test]
581                 [ExpectedException (typeof (XmlException))]
582                 public void WriteStartAttributeInAttributeMode ()
583                 {
584                         w.WriteStartElement ("root");
585                         w.WriteStartAttribute ("type");
586                         w.WriteStartAttribute ("type");
587                 }
588
589                 [Test]
590                 [ExpectedException (typeof (XmlException))]
591                 public void WriteStartAttributeInContentMode ()
592                 {
593                         w.WriteStartElement ("root");
594                         w.WriteString ("TEST");
595                         w.WriteStartAttribute ("type");
596                 }
597
598                 [Test]
599                 [ExpectedException (typeof (XmlException))]
600                 public void WriteStartElementInAttributeMode ()
601                 {
602                         w.WriteStartElement ("root");
603                         w.WriteStartAttribute ("type");
604                         w.WriteStartElement ("child");
605                 }
606
607                 [Test]
608                 [ExpectedException (typeof (XmlException))]
609                 public void CloseAtAtributeState ()
610                 {
611                         w.WriteStartElement ("root");
612                         w.WriteStartAttribute ("type");
613                         w.WriteString ("array");
614                         // It calls WriteEndElement() without calling
615                         // WriteEndAttribute().
616                         w.Close ();
617                 }
618
619                 [Test]
620                 public void WriteSlashEscaped ()
621                 {
622                         w.WriteStartElement ("root");
623                         w.WriteString ("/my date/");
624                         w.WriteEndElement ();
625                         w.Close ();
626                         Assert.AreEqual ("\"\\/my date\\/\"", ResultString);
627                 }
628
629                 [Test]
630                 public void WriteNullType ()
631                 {
632                         w.WriteStartElement ("root");
633                         w.WriteAttributeString ("type", "object");
634                         w.WriteStartElement ("foo");
635                         w.WriteAttributeString ("type", "null");
636                         w.Close ();
637                         Assert.AreEqual ("{\"foo\":null}", ResultString);
638                 }
639         }
640 }