5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2007 Novell, Inc (http://www.novell.com)
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
31 using System.Runtime.Serialization;
32 using System.Runtime.Serialization.Json;
34 using NUnit.Framework;
36 namespace MonoTests.System.Runtime.Serialization.Json
39 public class JsonWriterTest
42 XmlDictionaryWriter w;
45 get { return Encoding.UTF8.GetString (ms.ToArray ()); }
51 ms = new MemoryStream ();
52 w = JsonReaderWriterFactory.CreateJsonWriter (ms);
57 public void Dummy_BitFlagsGenerator ()
59 var b = new BitFlagsGenerator (2);
60 Assert.IsFalse (b.Load (0), "#a1");
62 Assert.IsFalse (b.Load (0), "#a2");
64 Assert.IsTrue (b.Load (0), "#a3");
65 Assert.IsFalse (b.Load (1), "#a4");
67 Assert.IsFalse (b.Load (0), "#a5");
68 Assert.IsFalse (b.Load (1), "#a6");
70 Assert.IsFalse (b.Load (1), "#b1");
72 Assert.IsFalse (b.Load (1), "#b2");
74 Assert.IsTrue (b.Load (1), "#b3");
76 Assert.IsFalse (b.Load (1), "#b4");
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");
89 [ExpectedException (typeof (ArgumentNullException))]
90 public void ConstructorNullStream ()
92 JsonReaderWriterFactory.CreateJsonWriter (null);
96 [ExpectedException (typeof (ArgumentNullException))]
97 public void ConstructorNullEncoding ()
99 JsonReaderWriterFactory.CreateJsonWriter (new MemoryStream (), null);
103 [ExpectedException (typeof (XmlException))]
104 public void SimpleElementNotRoot ()
106 w.WriteStartElement ("foo");
110 public void SimpleElement ()
112 w.WriteStartElement ("root");
113 w.WriteEndElement ();
115 // empty string literal ("")
116 Assert.AreEqual ("\"\"", ResultString, "#1");
120 [ExpectedException (typeof (XmlException))]
121 public void SimpleElement2 ()
123 w.WriteStartElement ("root");
124 w.WriteStartElement ("foo");
125 // type='array' or type='object' is required before writing immediate child of an element.
129 public void SimpleElement3 ()
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 ();
143 string json = "{\"e1\":{\"e1_1\":\"\"},\"e2\":\"value\"}";
144 Assert.AreEqual (json, ResultString, "#1");
148 [ExpectedException (typeof (ArgumentException))]
149 public void AttributeNonType ()
151 w.WriteStartElement ("root");
152 // only "type" attribute is expected.
153 w.WriteStartAttribute ("a1");
157 [ExpectedException (typeof (XmlException))]
158 public void TypeAttributeNonStandard ()
160 w.WriteStartElement ("root");
161 w.WriteAttributeString ("type", "foo");
165 public void SimpleTypeAttribute ()
167 w.WriteStartElement ("root");
168 w.WriteAttributeString ("type", "number");
169 w.WriteEndElement ();
171 Assert.AreEqual (String.Empty, ResultString, "#1");
175 public void SimpleTypeAttribute2 ()
177 w.WriteStartElement ("root");
178 w.WriteAttributeString ("type", "object");
179 w.WriteStartElement ("foo");
180 w.WriteAttributeString ("type", "number");
182 w.WriteEndElement ();
184 Assert.AreEqual ("{\"foo\":1}", ResultString, "#1");
188 [ExpectedException (typeof (XmlException))]
189 public void WriteStringForNull ()
191 w.WriteStartElement ("root");
192 w.WriteStartElement ("foo");
193 w.WriteAttributeString ("type", "null");
198 [ExpectedException (typeof (XmlException))]
199 public void WriteStringForArray ()
201 w.WriteStartElement ("root");
202 w.WriteAttributeString ("type", "object");
203 w.WriteStartElement ("foo");
204 w.WriteAttributeString ("type", "array");
210 public void WriteStringForBoolean ()
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 ();
221 [ExpectedException (typeof (XmlException))]
222 public void WriteStringForObject ()
224 w.WriteStartElement ("root");
225 w.WriteAttributeString ("type", "object");
230 [ExpectedException (typeof (XmlException))]
231 public void WriteArrayNonItem ()
233 w.WriteStartElement ("root");
234 w.WriteStartElement ("foo");
235 w.WriteAttributeString ("type", "array");
236 w.WriteStartElement ("bar");
240 public void WriteArray ()
242 w.WriteStartElement ("root"); // name is ignored
243 w.WriteAttributeString ("type", "array");
244 w.WriteElementString ("item", "v1");
245 w.WriteElementString ("item", "v2");
247 Assert.AreEqual (@"[""v1"",""v2""]", ResultString, "#1");
251 public void WriteArrayInObject ()
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");
260 Assert.AreEqual (@"{""foo"":[""v1"",""v2""]}", ResultString, "#1");
264 [ExpectedException (typeof (ArgumentException))]
265 public void WriteStartElementNonEmptyNS ()
267 // namespaces are not allowed
268 w.WriteStartElement (String.Empty, "x", "urn:foo");
272 [ExpectedException (typeof (ArgumentException))]
273 public void WriteStartElementNonEmptyPrefix ()
275 // prefixes are not allowed
276 w.WriteStartElement ("p", "x", "urn:foo");
280 [ExpectedException (typeof (XmlException))]
281 public void WriteStartElementMultiTopLevel ()
283 w.WriteStartElement ("root");
284 w.WriteEndElement ();
286 Assert.AreEqual (WriteState.Content, w.WriteState, "#1");
287 // writing of multiple root elements is not supported
288 w.WriteStartElement ("root2");
290 Assert.AreEqual (String.Empty, ResultString, "#2");
294 [ExpectedException (typeof (ArgumentException))]
295 public void WriteStartAttributeNonEmptyNS ()
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");
305 [ExpectedException (typeof (ArgumentException))]
306 public void WriteStartAttributeInXmlNamespace ()
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");
314 [ExpectedException (typeof (ArgumentNullException))]
315 public void LookupPrefixNull ()
317 w.LookupPrefix (null);
321 public void LookupPrefix ()
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");
331 public void WriteStartDocument ()
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
342 public void WriteEndDocument ()
344 w.WriteEndDocument (); // so, it is completely wrong, but ignored.
348 [ExpectedException (typeof (NotSupportedException))]
349 public void WriteDocType ()
351 w.WriteDocType (null, null, null, null);
355 [ExpectedException (typeof (NotSupportedException))]
356 public void WriteComment ()
358 w.WriteComment ("test");
362 [ExpectedException (typeof (NotSupportedException))]
363 public void WriteEntityRef ()
365 w.WriteEntityRef ("ent");
369 [ExpectedException (typeof (ArgumentException))]
370 public void WriteProcessingInstruction ()
372 // since this method accepts case-insensitive "XML",
373 // it throws ArgumentException.
374 w.WriteProcessingInstruction ("T", "D");
378 public void WriteProcessingInstructionXML ()
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).
390 public void WriteRaw ()
392 w.WriteStartElement ("root");
393 w.WriteRaw ("sample");
394 w.WriteRaw (new char [] {'0', '1', '2', '3'}, 1, 2);
396 Assert.AreEqual ("\"sample12\"", ResultString);
400 public void WriteCData ()
402 w.WriteStartElement ("root");
403 w.WriteCData ("]]>"); // this behavior is incompatible with ordinal XmlWriters.
405 Assert.AreEqual ("\"]]>\"", ResultString);
409 public void WriteCharEntity ()
411 w.WriteStartElement ("root");
412 w.WriteCharEntity ('>');
414 Assert.AreEqual ("\">\"", ResultString);
418 public void WriteWhitespace ()
420 w.WriteStartElement ("root");
421 w.WriteWhitespace ("\t \n\r");
423 Assert.AreEqual (@"""\u0009 \u000a\u000d""", ResultString);
427 [ExpectedException (typeof (ArgumentException))]
428 public void WriteWhitespaceNonWhitespace ()
430 w.WriteStartElement ("root");
431 w.WriteWhitespace ("TEST");
435 [ExpectedException (typeof (InvalidOperationException))]
436 public void WriteStringTopLevel ()
438 w.WriteString ("test");
442 [ExpectedException (typeof (XmlException))]
443 public void WriteStartAttributeTopLevel ()
445 w.WriteStartAttribute ("test");
449 [ExpectedException (typeof (InvalidOperationException))]
450 public void WriteStartDocumentAtClosed ()
453 w.WriteStartDocument ();
457 [ExpectedException (typeof (InvalidOperationException))]
458 public void WriteStartElementAtClosed ()
461 w.WriteStartElement ("foo");
465 [ExpectedException (typeof (InvalidOperationException))]
466 public void WriteProcessingInstructionAtClosed ()
469 w.WriteProcessingInstruction ("xml", "version='1.0'");
473 [ExpectedException (typeof (XmlException))]
474 public void WriteMixedContent ()
476 w.WriteStartElement ("root");
477 w.WriteString ("TEST");
478 w.WriteStartElement ("mixed"); // is not allowed.
482 [ExpectedException (typeof (XmlException))]
483 public void WriteStartElementInvalidTopLevelName ()
485 w.WriteStartElement ("anyname");
489 [ExpectedException (typeof (ArgumentNullException))]
490 public void WriteStartElementNullName ()
492 w.WriteStartElement ("root");
493 w.WriteAttributeString ("type", "object");
494 w.WriteStartElement (null);
498 [ExpectedException (typeof (ArgumentException))]
499 public void WriteStartElementEmptyName ()
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.
509 public void WriteStartElementWithRuntimeTypeName ()
511 w.WriteStartElement ("root");
512 w.WriteAttributeString ("type", "object");
513 w.WriteAttributeString ("__type", "FooType:#FooNamespace");
515 Assert.AreEqual (@"{""__type"":""FooType:#FooNamespace""}", ResultString);
519 public void WriteStartElementWeirdName ()
521 w.WriteStartElement ("root");
522 w.WriteAttributeString ("type", "object");
523 w.WriteStartElement ("!!!");
525 Assert.AreEqual (@"{""!!!"":""""}", ResultString);
529 public void WriteRootAsObject ()
531 w.WriteStartElement ("root");
532 w.WriteStartAttribute ("type");
533 w.WriteString ("object");
534 w.WriteEndAttribute ();
536 Assert.AreEqual ("{}", ResultString);
540 public void WriteRootAsArray ()
542 w.WriteStartElement ("root");
543 w.WriteStartAttribute ("type");
544 w.WriteString ("array");
545 w.WriteEndAttribute ();
547 Assert.AreEqual ("[]", ResultString);
551 public void WriteRootAsLiteral ()
553 w.WriteStartElement ("root");
555 Assert.AreEqual ("\"\"", ResultString);
559 [ExpectedException (typeof (XmlException))]
560 public void WriteEndElementOnAttribute ()
562 w.WriteStartElement ("root");
563 w.WriteStartAttribute ("type");
564 w.WriteString ("array");
565 w.WriteEndElement ();
569 public void WriteAttributeAsSeparateStrings ()
571 w.WriteStartElement ("root");
572 w.WriteStartAttribute ("type");
573 w.WriteString ("arr");
574 w.WriteString ("ay");
575 w.WriteEndAttribute ();
577 Assert.AreEqual ("[]", ResultString);
581 [ExpectedException (typeof (XmlException))]
582 public void WriteStartAttributeInAttributeMode ()
584 w.WriteStartElement ("root");
585 w.WriteStartAttribute ("type");
586 w.WriteStartAttribute ("type");
590 [ExpectedException (typeof (XmlException))]
591 public void WriteStartAttributeInContentMode ()
593 w.WriteStartElement ("root");
594 w.WriteString ("TEST");
595 w.WriteStartAttribute ("type");
599 [ExpectedException (typeof (XmlException))]
600 public void WriteStartElementInAttributeMode ()
602 w.WriteStartElement ("root");
603 w.WriteStartAttribute ("type");
604 w.WriteStartElement ("child");
608 [ExpectedException (typeof (XmlException))]
609 public void CloseAtAtributeState ()
611 w.WriteStartElement ("root");
612 w.WriteStartAttribute ("type");
613 w.WriteString ("array");
614 // It calls WriteEndElement() without calling
615 // WriteEndAttribute().
620 public void WriteSlashEscaped ()
622 w.WriteStartElement ("root");
623 w.WriteString ("/my date/");
624 w.WriteEndElement ();
626 Assert.AreEqual ("\"\\/my date\\/\"", ResultString);
630 public void WriteNullType ()
632 w.WriteStartElement ("root");
633 w.WriteAttributeString ("type", "object");
634 w.WriteStartElement ("foo");
635 w.WriteAttributeString ("type", "null");
637 Assert.AreEqual ("{\"foo\":null}", ResultString);