context: //
  // JsonReaderTest.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.Globalization;
  using System.IO;
  using System.Runtime.Serialization.Json;
  using System.Text;
  using System.Threading;
  using System.Xml;
  using NUnit.Framework;
  
  namespace MonoTests.System.Runtime.Serialization.Json
  {
  	[TestFixture]
  	public class JsonReaderTest
  	{
  		XmlDictionaryReader reader;
  
  		Stream GetInput (string s)
  		{
  			return new MemoryStream (Encoding.ASCII.GetBytes (s));
  		}
  
  		XmlDictionaryReader CreateReader (string s)
  		{
  			return JsonReaderWriterFactory.CreateJsonReader (GetInput (s), new XmlDictionaryReaderQuotas ());
  		}
  
  		void AssertNode (int depth, string localName, XmlNodeType nodeType, string value, string type, XmlDictionaryReader reader, string label)
  		{
  			Assert.AreEqual (localName, reader.LocalName, label + ".LocalName");
  			Assert.AreEqual (nodeType, reader.NodeType, label + ".NodeType");
  			Assert.AreEqual (value, reader.Value, label + ".Value");
  			Assert.AreEqual (type, reader.GetAttribute ("type"), label + ".GetAttribute('type')");
  		}
  
  		// Constructors
  
  		[Test]
  		[ExpectedException (typeof (ArgumentNullException))]
  		public void ConstructorNullBytes ()
  		{
  			JsonReaderWriterFactory.CreateJsonReader ((byte []) null, new XmlDictionaryReaderQuotas ());
  		}
  
  		[Test]
  		[ExpectedException (typeof (ArgumentNullException))]
  		public void ConstructorNullStream ()
  		{
  			JsonReaderWriterFactory.CreateJsonReader ((Stream) null, new XmlDictionaryReaderQuotas ());
  		}
  
  		[Test]
  		[ExpectedException (typeof (ArgumentNullException))]
  		public void ConstructorNullReaderQuotas ()
  		{
  			JsonReaderWriterFactory.CreateJsonReader (GetInput ("{}"), null);
  		}
  
  		[Test]
  		public void ConstructorNullEncodingAndReaderClose ()
  		{
  			JsonReaderWriterFactory.CreateJsonReader (GetInput ("{}"), null, new XmlDictionaryReaderQuotas (), null);
  		}
  
  		// Close()
  
  		[Test]
  		public void CloseTwice ()
  		{
  			reader = CreateReader ("{}");
  			reader.Close ();
  			reader.Close ();
  		}
  
  		[Test]
  		// hmm... [ExpectedException (typeof (InvalidOperationException))]
  		public void CloseAndRead ()
  		{
  			reader = CreateReader ("{}");
  			reader.Close ();
  			reader.Read ();
  		}
  
  		[Test]
  		// hmm... [ExpectedException (typeof (InvalidOperationException))]
  		public void CloseAndMoveToFirstAttribute ()
  		{
  			reader = CreateReader ("{}");
  			reader.Close ();
  			reader.MoveToFirstAttribute ();
  		}
  
  		// Read() several top-level types
  
  		[Test]
  		public void ReadStateEmpty ()
  		{
  			reader = CreateReader ("");
  			Assert.AreEqual (ReadState.Initial, reader.ReadState, "#1");
  			reader.Read ();
  			Assert.AreEqual (ReadState.EndOfFile, reader.ReadState, "#2");
  			reader.Close ();
  			Assert.AreEqual (ReadState.Closed, reader.ReadState, "#3");
  		}
  
  		[Test]
  		public void ReadStateEmpty2 ()
  		{
  			reader = CreateReader ("  ");
  			Assert.AreEqual (ReadState.Initial, reader.ReadState, "#1");
  			reader.Read ();
  			Assert.AreEqual (ReadState.EndOfFile, reader.ReadState, "#2");
  			reader.Close ();
  			Assert.AreEqual (ReadState.Closed, reader.ReadState, "#3");
  		}
  
  		[Test]
  		public void ReadStateObject ()
  		{
  			reader = CreateReader ("{}");
  			Assert.AreEqual (ReadState.Initial, reader.ReadState, "#1");
  			reader.Read (); // element
  			Assert.AreEqual (ReadState.Interactive, reader.ReadState, "#2");
  			reader.Read (); // endelement
  			Assert.AreEqual (ReadState.Interactive, reader.ReadState, "#3");
  			reader.Read (); // endoffile
  			Assert.AreEqual (ReadState.EndOfFile, reader.ReadState, "#4");
  			reader.Close ();
  			Assert.AreEqual (ReadState.Closed, reader.ReadState, "#5");
  		}
  
  		[Test]
  		public void ReadStateArray ()
  		{
  			reader = CreateReader ("[]");
  			Assert.AreEqual (ReadState.Initial, reader.ReadState, "#1");
  			reader.Read (); // element
  			Assert.AreEqual (ReadState.Interactive, reader.ReadState, "#2");
  			reader.Read (); // endelement
  			Assert.AreEqual (ReadState.Interactive, reader.ReadState, "#3");
  			reader.Read (); // endoffile
  			Assert.AreEqual (ReadState.EndOfFile, reader.ReadState, "#4");
  			reader.Close ();
  			Assert.AreEqual (ReadState.Closed, reader.ReadState, "#5");
  		}
  
  		[Test]
  		public void ReadNumber ()
  		{
  			reader = CreateReader ("1234");
  			Assert.AreEqual (ReadState.Initial, reader.ReadState, "#1");
  			reader.Read (); // dummy root element
  			Assert.AreEqual (ReadState.Interactive, reader.ReadState, "#2");
  			Assert.AreEqual (XmlNodeType.Element, reader.NodeType, "#2-1");
  			Assert.AreEqual ("root", reader.LocalName, "#2-2");
  			reader.Read (); // content (number)
  			Assert.AreEqual (ReadState.Interactive, reader.ReadState, "#3");
  			Assert.AreEqual (XmlNodeType.Text, reader.NodeType, "#3-1");
  			Assert.AreEqual ("1234", reader.Value, "#3-2");
  			reader.Read (); // endelement
  			Assert.AreEqual (ReadState.Interactive, reader.ReadState, "#4");
  			Assert.AreEqual (XmlNodeType.EndElement, reader.NodeType, "#4-1");
  			reader.Read (); // endoffile
  			Assert.AreEqual (ReadState.EndOfFile, reader.ReadState, "#5");
  			reader.Close ();
  			Assert.AreEqual (ReadState.Closed, reader.ReadState, "#6");
  		}
  
  		[Test]
  		public void ReadBool ()
  		{
  			reader = CreateReader ("true");
  			Assert.AreEqual (ReadState.Initial, reader.ReadState, "#1");
  			reader.Read (); // dummy root element
  			Assert.AreEqual (ReadState.Interactive, reader.ReadState, "#2");
  			Assert.AreEqual (XmlNodeType.Element, reader.NodeType, "#2-1");
  			Assert.AreEqual ("root", reader.LocalName, "#2-2");
  			Assert.AreEqual ("boolean", reader.GetAttribute ("type"), "#2-3");
  			reader.Read (); // content (boolean)
  			Assert.AreEqual (ReadState.Interactive, reader.ReadState, "#3");
  			Assert.AreEqual (XmlNodeType.Text, reader.NodeType, "#3-1");
  			Assert.AreEqual ("true", reader.Value, "#3-2");
  			reader.Read (); // endelement
  			Assert.AreEqual (ReadState.Interactive, reader.ReadState, "#4");
  			Assert.AreEqual (XmlNodeType.EndElement, reader.NodeType, "#4-1");
  			reader.Read (); // endoffile
  			Assert.AreEqual (ReadState.EndOfFile, reader.ReadState, "#5");
  			reader.Close ();
  			Assert.AreEqual (ReadState.Closed, reader.ReadState, "#6");
  		}
  
  		[Test]
  		public void ReadNull ()
  		{
  			reader = CreateReader ("null");
  			Assert.AreEqual (ReadState.Initial, reader.ReadState, "#1");
  			reader.Read (); // dummy root element
  			Assert.AreEqual (ReadState.Interactive, reader.ReadState, "#2");
  			Assert.AreEqual (XmlNodeType.Element, reader.NodeType, "#2-1");
  			Assert.AreEqual ("root", reader.LocalName, "#2-2");
  			// When it is null, the value is never given and the reader is skipped to the end element.
  			reader.Read (); // endlement
  			Assert.AreEqual (ReadState.Interactive, reader.ReadState, "#3");
  			Assert.AreEqual (XmlNodeType.EndElement, reader.NodeType, "#3-1");
  			reader.Read (); // endoffile
  			Assert.AreEqual (ReadState.EndOfFile, reader.ReadState, "#4");
  			reader.Close ();
  			Assert.AreEqual (ReadState.Closed, reader.ReadState, "#4");
  		}
  
  		[Test]
  		public void ReadString ()
  		{
  			reader = CreateReader ("\"true\"");
  			Assert.AreEqual (ReadState.Initial, reader.ReadState, "#1");
  			reader.Read (); // dummy root element
  			Assert.AreEqual (ReadState.Interactive, reader.ReadState, "#2");
  			Assert.AreEqual (XmlNodeType.Element, reader.NodeType, "#2-1");
  			Assert.AreEqual ("root", reader.LocalName, "#2-2");
  			Assert.AreEqual ("string", reader.GetAttribute ("type"), "#2-3");
  			reader.Read (); // content (number)
  			Assert.AreEqual (ReadState.Interactive, reader.ReadState, "#3");
  			Assert.AreEqual (XmlNodeType.Text, reader.NodeType, "#3-1");
  			Assert.AreEqual ("true", reader.Value, "#3-2");
  			reader.Read (); // endelement
  			Assert.AreEqual (ReadState.Interactive, reader.ReadState, "#4");
  			Assert.AreEqual (XmlNodeType.EndElement, reader.NodeType, "#4-1");
  			reader.Read (); // endoffile
  			Assert.AreEqual (ReadState.EndOfFile, reader.ReadState, "#5");
  			reader.Close ();
  			Assert.AreEqual (ReadState.Closed, reader.ReadState, "#6");
  		}
  
  		// MoveToAttribute() / MoveToElement()
  
  		[Test]
  		public void MoveToAttributeObject ()
  		{
  			reader = CreateReader ("{}");
  			Assert.IsFalse (reader.MoveToFirstAttribute (), "#1");
  			reader.Read (); // element
  			Assert.IsTrue (reader.MoveToFirstAttribute (), "#2");
  			Assert.AreEqual ("type", reader.LocalName, "#3");
  			Assert.AreEqual ("object", reader.Value, "#4");
  			Assert.IsTrue (reader.ReadAttributeValue (), "#5");
  			Assert.AreEqual ("object", reader.Value, "#6");
  			Assert.IsFalse (reader.MoveToNextAttribute (), "#7");
  			Assert.IsTrue (reader.MoveToFirstAttribute (), "#8");
  			Assert.IsFalse (reader.MoveToNextAttribute (), "#9");
  		}
  
  		[Test]
  		public void MoveToElementObject ()
  		{
  			reader = CreateReader ("{}");
  			reader.Read (); // element
  			Assert.IsTrue (reader.MoveToFirstAttribute (), "#1");
  			Assert.IsTrue (reader.MoveToElement (), "#1-1");
  
  			Assert.IsTrue (reader.MoveToFirstAttribute (), "#2");
  			Assert.IsTrue (reader.ReadAttributeValue (), "#2-1");
  			Assert.IsTrue (reader.MoveToElement (), "#2-2");
  
  			Assert.IsTrue (reader.MoveToFirstAttribute (), "#3");
  			Assert.IsFalse (reader.MoveToNextAttribute (), "#3-1");
  			Assert.IsTrue (reader.MoveToElement (), "#3-2");
  		}
  
  		[Test]
  		public void MoveToAttributeArray ()
  		{
  			reader = CreateReader ("[]");
  			Assert.IsFalse (reader.MoveToFirstAttribute (), "#1");
  			reader.Read (); // element
  			Assert.IsTrue (reader.MoveToFirstAttribute (), "#2");
  			Assert.AreEqual ("type", reader.LocalName, "#3");
  			Assert.AreEqual ("array", reader.Value, "#4");
  			Assert.IsTrue (reader.ReadAttributeValue (), "#5");
  			Assert.AreEqual ("array", reader.Value, "#6");
  			Assert.IsFalse (reader.MoveToNextAttribute (), "#7");
  			Assert.IsTrue (reader.MoveToFirstAttribute (), "#8");
  			Assert.IsFalse (reader.MoveToNextAttribute (), "#9");
  		}
  
  		[Test]
  		public void MoveToElementArray ()
  		{
  			reader = CreateReader ("[]");
  			reader.Read (); // element
  			Assert.IsTrue (reader.MoveToFirstAttribute (), "#1");
  			Assert.IsTrue (reader.MoveToElement (), "#1-1");
  
  			Assert.IsTrue (reader.MoveToFirstAttribute (), "#2");
  			Assert.IsTrue (reader.ReadAttributeValue (), "#2-1");
  			Assert.IsTrue (reader.MoveToElement (), "#2-2");
  
  			Assert.IsTrue (reader.MoveToFirstAttribute (), "#3");
  			Assert.IsFalse (reader.MoveToNextAttribute (), "#3-1");
  			Assert.IsTrue (reader.MoveToElement (), "#3-2");
  		}
  
  		[Test]
  		public void MoveToAttributeSimpleDummyRoot ()
  		{
  			reader = CreateReader ("1234");
  			Assert.IsFalse (reader.MoveToFirstAttribute (), "#1");
  			reader.Read (); // element
  			Assert.IsTrue (reader.MoveToFirstAttribute (), "#2");
  			Assert.AreEqual ("type", reader.LocalName, "#3");
  			Assert.AreEqual ("number", reader.Value, "#4");
  			Assert.IsTrue (reader.ReadAttributeValue (), "#5");
  			Assert.AreEqual ("number", reader.Value, "#6");
  			Assert.IsFalse (reader.MoveToNextAttribute (), "#7");
  			Assert.IsTrue (reader.MoveToFirstAttribute (), "#8");
  			Assert.IsFalse (reader.MoveToNextAttribute (), "#9");
  		}
  
  		[Test]
  		public void MoveToElementSimpleDummyRoot ()
  		{
  			reader = CreateReader ("1234");
  			reader.Read (); // element
  			Assert.IsTrue (reader.MoveToFirstAttribute (), "#1");
  			Assert.IsTrue (reader.MoveToElement (), "#1-1");
  
  			Assert.IsTrue (reader.MoveToFirstAttribute (), "#2");
  			Assert.IsTrue (reader.ReadAttributeValue (), "#2-1");
  			Assert.IsTrue (reader.MoveToElement (), "#2-2");
  
  			Assert.IsTrue (reader.MoveToFirstAttribute (), "#3");
  			Assert.IsFalse (reader.MoveToNextAttribute (), "#3-1");
  			Assert.IsTrue (reader.MoveToElement (), "#3-2");
  		}
  
  		// Read() arrays and objects
  
  		[Test]
  		public void ReadArrayContent ()
  		{
  			reader = CreateReader ("[123, \"123\", true, \"true\"]");
  
  			// number value
  			reader.Read (); // element
  			AssertNode (0, "root", XmlNodeType.Element, String.Empty, "array", reader, "#1");
  
  			reader.Read (); // 123 - element
  			Assert.AreEqual ("number", reader.GetAttribute ("type"), "#2-0");
  			AssertNode (1, "item", XmlNodeType.Element, String.Empty, "number", reader, "#2");
  			reader.Read (); // 123 - text
  			AssertNode (2, String.Empty, XmlNodeType.Text, "123", null, reader, "#3");
  			reader.Read (); // 123 - endelement
  			AssertNode (1, "item", XmlNodeType.EndElement, String.Empty, null, reader, "#4");
  
  			// string value #1
  
gt: 			reader.Read (); // "123" - element