536cd135cc
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
641 lines
16 KiB
C#
641 lines
16 KiB
C#
//
|
|
// JsonWriterTest.cs
|
|
//
|
|
// Author:
|
|
// Atsushi Enomoto <atsushi@ximian.com>
|
|
//
|
|
// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Runtime.Serialization;
|
|
using System.Runtime.Serialization.Json;
|
|
using System.Xml;
|
|
using NUnit.Framework;
|
|
|
|
namespace MonoTests.System.Runtime.Serialization.Json
|
|
{
|
|
[TestFixture]
|
|
public class JsonWriterTest
|
|
{
|
|
MemoryStream ms;
|
|
XmlDictionaryWriter w;
|
|
|
|
string ResultString {
|
|
get { return Encoding.UTF8.GetString (ms.ToArray ()); }
|
|
}
|
|
|
|
[SetUp]
|
|
public void Setup ()
|
|
{
|
|
ms = new MemoryStream ();
|
|
w = JsonReaderWriterFactory.CreateJsonWriter (ms);
|
|
}
|
|
|
|
/*
|
|
[Test]
|
|
public void Dummy_BitFlagsGenerator ()
|
|
{
|
|
var b = new BitFlagsGenerator (2);
|
|
Assert.IsFalse (b.Load (0), "#a1");
|
|
b.Store (0, false);
|
|
Assert.IsFalse (b.Load (0), "#a2");
|
|
b.Store (0, true);
|
|
Assert.IsTrue (b.Load (0), "#a3");
|
|
Assert.IsFalse (b.Load (1), "#a4");
|
|
b.Store (0, false);
|
|
Assert.IsFalse (b.Load (0), "#a5");
|
|
Assert.IsFalse (b.Load (1), "#a6");
|
|
|
|
Assert.IsFalse (b.Load (1), "#b1");
|
|
b.Store (1, false);
|
|
Assert.IsFalse (b.Load (1), "#b2");
|
|
b.Store (1, true);
|
|
Assert.IsTrue (b.Load (1), "#b3");
|
|
b.Store (1, false);
|
|
Assert.IsFalse (b.Load (1), "#b4");
|
|
|
|
var bytes = new byte [2];
|
|
Assert.IsFalse (BitFlagsGenerator.IsBitSet (bytes, 0), "#c1");
|
|
BitFlagsGenerator.SetBit (bytes, 0);
|
|
Assert.IsTrue (BitFlagsGenerator.IsBitSet (bytes, 0), "#c2");
|
|
Assert.IsFalse (BitFlagsGenerator.IsBitSet (bytes, 1), "#c3");
|
|
BitFlagsGenerator.SetBit (bytes, 0);
|
|
Assert.IsTrue (BitFlagsGenerator.IsBitSet (bytes, 0), "#c4");
|
|
}
|
|
*/
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (ArgumentNullException))]
|
|
public void ConstructorNullStream ()
|
|
{
|
|
JsonReaderWriterFactory.CreateJsonWriter (null);
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (ArgumentNullException))]
|
|
public void ConstructorNullEncoding ()
|
|
{
|
|
JsonReaderWriterFactory.CreateJsonWriter (new MemoryStream (), null);
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (XmlException))]
|
|
public void SimpleElementNotRoot ()
|
|
{
|
|
w.WriteStartElement ("foo");
|
|
}
|
|
|
|
[Test]
|
|
public void SimpleElement ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteEndElement ();
|
|
w.Close ();
|
|
// empty string literal ("")
|
|
Assert.AreEqual ("\"\"", ResultString, "#1");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (XmlException))]
|
|
public void SimpleElement2 ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteStartElement ("foo");
|
|
// type='array' or type='object' is required before writing immediate child of an element.
|
|
}
|
|
|
|
[Test]
|
|
public void SimpleElement3 ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteAttributeString ("type", "object");
|
|
w.WriteStartElement ("e1");
|
|
w.WriteAttributeString ("type", "object");
|
|
w.WriteStartElement ("e1_1");
|
|
w.WriteEndElement (); // treated as a string literal
|
|
w.WriteEndElement ();
|
|
w.WriteStartElement ("e2");
|
|
w.WriteString ("value");
|
|
w.WriteEndElement ();
|
|
w.WriteEndElement ();
|
|
w.Close ();
|
|
string json = "{\"e1\":{\"e1_1\":\"\"},\"e2\":\"value\"}";
|
|
Assert.AreEqual (json, ResultString, "#1");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (ArgumentException))]
|
|
public void AttributeNonType ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
// only "type" attribute is expected.
|
|
w.WriteStartAttribute ("a1");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (XmlException))]
|
|
public void TypeAttributeNonStandard ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteAttributeString ("type", "foo");
|
|
}
|
|
|
|
[Test]
|
|
public void SimpleTypeAttribute ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteAttributeString ("type", "number");
|
|
w.WriteEndElement ();
|
|
w.Close ();
|
|
Assert.AreEqual (String.Empty, ResultString, "#1");
|
|
}
|
|
|
|
[Test]
|
|
public void SimpleTypeAttribute2 ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteAttributeString ("type", "object");
|
|
w.WriteStartElement ("foo");
|
|
w.WriteAttributeString ("type", "number");
|
|
w.WriteString ("1");
|
|
w.WriteEndElement ();
|
|
w.Close ();
|
|
Assert.AreEqual ("{\"foo\":1}", ResultString, "#1");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (XmlException))]
|
|
public void WriteStringForNull ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteStartElement ("foo");
|
|
w.WriteAttributeString ("type", "null");
|
|
w.WriteString ("1");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (XmlException))]
|
|
public void WriteStringForArray ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteAttributeString ("type", "object");
|
|
w.WriteStartElement ("foo");
|
|
w.WriteAttributeString ("type", "array");
|
|
w.WriteString ("1");
|
|
}
|
|
|
|
[Test]
|
|
// uh, no exception?
|
|
public void WriteStringForBoolean ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteAttributeString ("type", "object");
|
|
w.WriteStartElement ("foo");
|
|
w.WriteAttributeString ("type", "boolean");
|
|
w.WriteString ("xyz");
|
|
w.WriteEndElement ();
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (XmlException))]
|
|
public void WriteStringForObject ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteAttributeString ("type", "object");
|
|
w.WriteString ("1");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (XmlException))]
|
|
public void WriteArrayNonItem ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteStartElement ("foo");
|
|
w.WriteAttributeString ("type", "array");
|
|
w.WriteStartElement ("bar");
|
|
}
|
|
|
|
[Test]
|
|
public void WriteArray ()
|
|
{
|
|
w.WriteStartElement ("root"); // name is ignored
|
|
w.WriteAttributeString ("type", "array");
|
|
w.WriteElementString ("item", "v1");
|
|
w.WriteElementString ("item", "v2");
|
|
w.Close ();
|
|
Assert.AreEqual (@"[""v1"",""v2""]", ResultString, "#1");
|
|
}
|
|
|
|
[Test]
|
|
public void WriteArrayInObject ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteAttributeString ("type", "object");
|
|
w.WriteStartElement ("foo");
|
|
w.WriteAttributeString ("type", "array");
|
|
w.WriteElementString ("item", "v1");
|
|
w.WriteElementString ("item", "v2");
|
|
w.Close ();
|
|
Assert.AreEqual (@"{""foo"":[""v1"",""v2""]}", ResultString, "#1");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (ArgumentException))]
|
|
public void WriteStartElementNonEmptyNS ()
|
|
{
|
|
// namespaces are not allowed
|
|
w.WriteStartElement (String.Empty, "x", "urn:foo");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (ArgumentException))]
|
|
public void WriteStartElementNonEmptyPrefix ()
|
|
{
|
|
// prefixes are not allowed
|
|
w.WriteStartElement ("p", "x", "urn:foo");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (XmlException))]
|
|
public void WriteStartElementMultiTopLevel ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteEndElement ();
|
|
// hmm...
|
|
Assert.AreEqual (WriteState.Content, w.WriteState, "#1");
|
|
// writing of multiple root elements is not supported
|
|
w.WriteStartElement ("root2");
|
|
w.Close ();
|
|
Assert.AreEqual (String.Empty, ResultString, "#2");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (ArgumentException))]
|
|
public void WriteStartAttributeNonEmptyNS ()
|
|
{
|
|
// namespaces are not allowed
|
|
w.WriteStartElement ("root");
|
|
// well, empty prefix for a global attribute would be
|
|
// replaced anyways ...
|
|
w.WriteStartAttribute (String.Empty, "x", "urn:foo");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (ArgumentException))]
|
|
public void WriteStartAttributeInXmlNamespace ()
|
|
{
|
|
// even "xml" namespace is not allowed (anyways only "type" is allowed ...)
|
|
w.WriteStartElement ("root");
|
|
w.WriteStartAttribute ("xml", "lang", "http://www.w3.org/XML/1998/namespace");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (ArgumentNullException))]
|
|
public void LookupPrefixNull ()
|
|
{
|
|
w.LookupPrefix (null);
|
|
}
|
|
|
|
[Test]
|
|
public void LookupPrefix ()
|
|
{
|
|
// since namespaces are not allowed, it mostly makes no sense...
|
|
Assert.AreEqual (String.Empty, w.LookupPrefix (String.Empty), "#1");
|
|
Assert.IsNull (w.LookupPrefix ("urn:nonexistent"), "#2");
|
|
Assert.AreEqual ("xml", w.LookupPrefix ("http://www.w3.org/XML/1998/namespace"), "#3");
|
|
Assert.AreEqual ("xmlns", w.LookupPrefix ("http://www.w3.org/2000/xmlns/"), "#4");
|
|
}
|
|
|
|
[Test]
|
|
public void WriteStartDocument ()
|
|
{
|
|
Assert.AreEqual (WriteState.Start, w.WriteState, "#1");
|
|
w.WriteStartDocument ();
|
|
Assert.AreEqual (WriteState.Start, w.WriteState, "#2");
|
|
w.WriteStartDocument (true);
|
|
Assert.AreEqual (WriteState.Start, w.WriteState, "#3");
|
|
// So, it does nothing
|
|
}
|
|
|
|
[Test]
|
|
public void WriteEndDocument ()
|
|
{
|
|
w.WriteEndDocument (); // so, it is completely wrong, but ignored.
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (NotSupportedException))]
|
|
public void WriteDocType ()
|
|
{
|
|
w.WriteDocType (null, null, null, null);
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (NotSupportedException))]
|
|
public void WriteComment ()
|
|
{
|
|
w.WriteComment ("test");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (NotSupportedException))]
|
|
public void WriteEntityRef ()
|
|
{
|
|
w.WriteEntityRef ("ent");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (ArgumentException))]
|
|
public void WriteProcessingInstruction ()
|
|
{
|
|
// since this method accepts case-insensitive "XML",
|
|
// it throws ArgumentException.
|
|
w.WriteProcessingInstruction ("T", "D");
|
|
}
|
|
|
|
[Test]
|
|
public void WriteProcessingInstructionXML ()
|
|
{
|
|
// You might not know, but in some cases, things like
|
|
// XmlWriter.WriteNode() is implemented to invoke
|
|
// this method for writing XML declaration. This
|
|
// check is (seems) case-insensitive.
|
|
w.WriteProcessingInstruction ("XML", "foobar");
|
|
// In this case, the data is simply ignored (as
|
|
// WriteStartDocument() is).
|
|
}
|
|
|
|
[Test]
|
|
public void WriteRaw ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteRaw ("sample");
|
|
w.WriteRaw (new char [] {'0', '1', '2', '3'}, 1, 2);
|
|
w.Close ();
|
|
Assert.AreEqual ("\"sample12\"", ResultString);
|
|
}
|
|
|
|
[Test]
|
|
public void WriteCData ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteCData ("]]>"); // this behavior is incompatible with ordinal XmlWriters.
|
|
w.Close ();
|
|
Assert.AreEqual ("\"]]>\"", ResultString);
|
|
}
|
|
|
|
[Test]
|
|
public void WriteCharEntity ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteCharEntity ('>');
|
|
w.Close ();
|
|
Assert.AreEqual ("\">\"", ResultString);
|
|
}
|
|
|
|
[Test]
|
|
public void WriteWhitespace ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteWhitespace ("\t \n\r");
|
|
w.Close ();
|
|
Assert.AreEqual (@"""\t \n\r""", ResultString);
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (ArgumentException))]
|
|
public void WriteWhitespaceNonWhitespace ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteWhitespace ("TEST");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (InvalidOperationException))]
|
|
public void WriteStringTopLevel ()
|
|
{
|
|
w.WriteString ("test");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (XmlException))]
|
|
public void WriteStartAttributeTopLevel ()
|
|
{
|
|
w.WriteStartAttribute ("test");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (InvalidOperationException))]
|
|
public void WriteStartDocumentAtClosed ()
|
|
{
|
|
w.Close ();
|
|
w.WriteStartDocument ();
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (InvalidOperationException))]
|
|
public void WriteStartElementAtClosed ()
|
|
{
|
|
w.Close ();
|
|
w.WriteStartElement ("foo");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (InvalidOperationException))]
|
|
public void WriteProcessingInstructionAtClosed ()
|
|
{
|
|
w.Close ();
|
|
w.WriteProcessingInstruction ("xml", "version='1.0'");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (XmlException))]
|
|
public void WriteMixedContent ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteString ("TEST");
|
|
w.WriteStartElement ("mixed"); // is not allowed.
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (XmlException))]
|
|
public void WriteStartElementInvalidTopLevelName ()
|
|
{
|
|
w.WriteStartElement ("anyname");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (ArgumentNullException))]
|
|
public void WriteStartElementNullName ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteAttributeString ("type", "object");
|
|
w.WriteStartElement (null);
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (ArgumentException))]
|
|
public void WriteStartElementEmptyName ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteAttributeString ("type", "object");
|
|
w.WriteStartElement (String.Empty);
|
|
// It is regarded as invalid name in JSON. However,
|
|
// I don't think there is such limitation in JSON specification.
|
|
}
|
|
|
|
[Test]
|
|
public void WriteStartElementWithRuntimeTypeName ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteAttributeString ("type", "object");
|
|
w.WriteAttributeString ("__type", "FooType:#FooNamespace");
|
|
w.Close ();
|
|
Assert.AreEqual (@"{""__type"":""FooType:#FooNamespace""}", ResultString);
|
|
}
|
|
|
|
[Test]
|
|
public void WriteStartElementWeirdName ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteAttributeString ("type", "object");
|
|
w.WriteStartElement ("!!!");
|
|
w.Close ();
|
|
Assert.AreEqual (@"{""!!!"":""""}", ResultString);
|
|
}
|
|
|
|
[Test]
|
|
public void WriteRootAsObject ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteStartAttribute ("type");
|
|
w.WriteString ("object");
|
|
w.WriteEndAttribute ();
|
|
w.Close ();
|
|
Assert.AreEqual ("{}", ResultString);
|
|
}
|
|
|
|
[Test]
|
|
public void WriteRootAsArray ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteStartAttribute ("type");
|
|
w.WriteString ("array");
|
|
w.WriteEndAttribute ();
|
|
w.Close ();
|
|
Assert.AreEqual ("[]", ResultString);
|
|
}
|
|
|
|
[Test]
|
|
public void WriteRootAsLiteral ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.Close ();
|
|
Assert.AreEqual ("\"\"", ResultString);
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (XmlException))]
|
|
public void WriteEndElementOnAttribute ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteStartAttribute ("type");
|
|
w.WriteString ("array");
|
|
w.WriteEndElement ();
|
|
}
|
|
|
|
[Test]
|
|
public void WriteAttributeAsSeparateStrings ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteStartAttribute ("type");
|
|
w.WriteString ("arr");
|
|
w.WriteString ("ay");
|
|
w.WriteEndAttribute ();
|
|
w.Close ();
|
|
Assert.AreEqual ("[]", ResultString);
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (XmlException))]
|
|
public void WriteStartAttributeInAttributeMode ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteStartAttribute ("type");
|
|
w.WriteStartAttribute ("type");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (XmlException))]
|
|
public void WriteStartAttributeInContentMode ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteString ("TEST");
|
|
w.WriteStartAttribute ("type");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (XmlException))]
|
|
public void WriteStartElementInAttributeMode ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteStartAttribute ("type");
|
|
w.WriteStartElement ("child");
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException (typeof (XmlException))]
|
|
public void CloseAtAtributeState ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteStartAttribute ("type");
|
|
w.WriteString ("array");
|
|
// It calls WriteEndElement() without calling
|
|
// WriteEndAttribute().
|
|
w.Close ();
|
|
}
|
|
|
|
[Test]
|
|
public void WriteSlashEscaped ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteString ("/my date/");
|
|
w.WriteEndElement ();
|
|
w.Close ();
|
|
Assert.AreEqual ("\"\\/my date\\/\"", ResultString);
|
|
}
|
|
|
|
[Test]
|
|
public void WriteNullType ()
|
|
{
|
|
w.WriteStartElement ("root");
|
|
w.WriteAttributeString ("type", "object");
|
|
w.WriteStartElement ("foo");
|
|
w.WriteAttributeString ("type", "null");
|
|
w.Close ();
|
|
Assert.AreEqual ("{\"foo\":null}", ResultString);
|
|
}
|
|
}
|
|
}
|