context: #region License
  // Copyright (c) 2007 James Newton-King
  //
  // 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.
  #endregion
  
  using System;
  using System.Collections.Generic;
  #if !(NET20 || NET35 || PORTABLE) || NETSTANDARD1_3
  using System.Numerics;
  #endif
  using System.Text;
  using Newtonsoft.Json.Converters;
  #if DNXCORE50
  using Xunit;
  using Test = Xunit.FactAttribute;
  using Assert = Newtonsoft.Json.Tests.XUnitAssert;
  #else
  using NUnit.Framework;
  #endif
  using Newtonsoft.Json.Linq;
  using System.IO;
  #if NET20
  using Newtonsoft.Json.Utilities.LinqBridge;
  #else
  using System.Linq;
  using Newtonsoft.Json.Utilities;
  
  #endif
  
  namespace Newtonsoft.Json.Tests.Linq
  {
      [TestFixture]
      public class JTokenTests : TestFixtureBase
      {
          [Test]
          public void DeepEqualsObjectOrder()
          {
              string ob1 = @"{""key1"":""1"",""key2"":""2""}";
              string ob2 = @"{""key2"":""2"",""key1"":""1""}";
  
              JObject j1 = JObject.Parse(ob1);
              JObject j2 = JObject.Parse(ob2);
              Assert.IsTrue(j1.DeepEquals(j2));
          }
  
          [Test]
          public void ReadFrom()
          {
              JObject o = (JObject)JToken.ReadFrom(new JsonTextReader(new StringReader("{'pie':true}")));
              Assert.AreEqual(true, (bool)o["pie"]);
  
              JArray a = (JArray)JToken.ReadFrom(new JsonTextReader(new StringReader("[1,2,3]")));
              Assert.AreEqual(1, (int)a[0]);
              Assert.AreEqual(2, (int)a[1]);
              Assert.AreEqual(3, (int)a[2]);
  
              JsonReader reader = new JsonTextReader(new StringReader("{'pie':true}"));
              reader.Read();
              reader.Read();
  
              JProperty p = (JProperty)JToken.ReadFrom(reader);
              Assert.AreEqual("pie", p.Name);
              Assert.AreEqual(true, (bool)p.Value);
  
              JConstructor c = (JConstructor)JToken.ReadFrom(new JsonTextReader(new StringReader("new Date(1)")));
              Assert.AreEqual("Date", c.Name);
              Assert.IsTrue(JToken.DeepEquals(new JValue(1), c.Values().ElementAt(0)));
  
              JValue v;
  
              v = (JValue)JToken.ReadFrom(new JsonTextReader(new StringReader(@"""stringvalue""")));
              Assert.AreEqual("stringvalue", (string)v);
  
              v = (JValue)JToken.ReadFrom(new JsonTextReader(new StringReader(@"1")));
              Assert.AreEqual(1, (int)v);
  
              v = (JValue)JToken.ReadFrom(new JsonTextReader(new StringReader(@"1.1")));
              Assert.AreEqual(1.1, (double)v);
  
  #if !NET20
              v = (JValue)JToken.ReadFrom(new JsonTextReader(new StringReader(@"""1970-01-01T00:00:00+12:31"""))
              {
                  DateParseHandling = DateParseHandling.DateTimeOffset
              });
              Assert.AreEqual(typeof(DateTimeOffset), v.Value.GetType());
              Assert.AreEqual(new DateTimeOffset(DateTimeUtils.InitialJavaScriptDateTicks, new TimeSpan(12, 31, 0)), v.Value);
  #endif
          }
  
          [Test]
          public void Load()
          {
              JObject o = (JObject)JToken.Load(new JsonTextReader(new StringReader("{'pie':true}")));
              Assert.AreEqual(true, (bool)o["pie"]);
          }
  
          [Test]
          public void Parse()
          {
              JObject o = (JObject)JToken.Parse("{'pie':true}");
              Assert.AreEqual(true, (bool)o["pie"]);
          }
  
          [Test]
          public void Parent()
          {
              JArray v = new JArray(new JConstructor("TestConstructor"), new JValue(new DateTime(2000, 12, 20)));
  
              Assert.AreEqual(null, v.Parent);
  
              JObject o =
                  new JObject(
                      new JProperty("Test1", v),
                      new JProperty("Test2", "Test2Value"),
                      new JProperty("Test3", "Test3Value"),
                      new JProperty("Test4", null)
                      );
  
              Assert.AreEqual(o.Property("Test1"), v.Parent);
  
              JProperty p = new JProperty("NewProperty", v);
  
              // existing value should still have same parent
              Assert.AreEqual(o.Property("Test1"), v.Parent);
  
              // new value should be cloned
              Assert.AreNotSame(p.Value, v);
  
              Assert.AreEqual((DateTime)((JValue)p.Value[1]).Value, (DateTime)((JValue)v[1]).Value);
  
              Assert.AreEqual(v, o["Test1"]);
  
              Assert.AreEqual(null, o.Parent);
              JProperty o1 = new JProperty("O1", o);
              Assert.AreEqual(o, o1.Value);
  
              Assert.AreNotEqual(null, o.Parent);
              JProperty o2 = new JProperty("O2", o);
  
              Assert.AreNotSame(o1.Value, o2.Value);
              Assert.AreEqual(o1.Value.Children().Count(), o2.Value.Children().Count());
              Assert.AreEqual(false, JToken.DeepEquals(o1, o2));
              Assert.AreEqual(true, JToken.DeepEquals(o1.Value, o2.Value));
          }
  
          [Test]
          public void Next()
          {
              JArray a =
                  new JArray(
                      5,
                      6,
                      new JArray(7, 8),
                      new JArray(9, 10)
                      );
  
              JToken next = a[0].Next;
              Assert.AreEqual(6, (int)next);
  
              next = next.Next;
              Assert.IsTrue(JToken.DeepEquals(new JArray(7, 8), next));
  
              next = next.Next;
              Assert.IsTrue(JToken.DeepEquals(new JArray(9, 10), next));
  
              next = next.Next;
              Assert.IsNull(next);
          }
  
          [Test]
          public void Previous()
          {
              JArray a =
                  new JArray(
                      5,
                      6,
                      new JArray(7, 8),
                      new JArray(9, 10)
                      );
  
              JToken previous = a[3].Previous;
              Assert.IsTrue(JToken.DeepEquals(new JArray(7, 8), previous));
  
              previous = previous.Previous;
              Assert.AreEqual(6, (int)previous);
  
              previous = previous.Previous;
              Assert.AreEqual(5, (int)previous);
  
              previous = previous.Previous;
              Assert.IsNull(previous);
          }
  
          [Test]
          public void Children()
          {
              JArray a =
                  new JArray(
                      5,
                      new JArray(1),
                      new JArray(1, 2),
                      new JArray(1, 2, 3)
                      );
  
              Assert.AreEqual(4, a.Count());
              Assert.AreEqual(3, a.Children<JArray>().Count());
          }
  
          [Test]
          public void BeforeAfter()
          {
              JArray a =
                  new JArray(
                      5,
                      new JArray(1, 2, 3),
                      new JArray(1, 2, 3),
                      new JArray(1, 2, 3)
                      );
  
              Assert.AreEqual(5, (int)a[1].Previous);
              Assert.AreEqual(2, a[2].BeforeSelf().Count());
          }
  
          [Test]
          public void Casting()
          {
              Assert.AreEqual(1L, (long)(new JValue(1)));
              Assert.AreEqual(2L, (long)new JArray(1, 2, 3)[1]);
  
              Assert.AreEqual(new DateTime(2000, 12, 20), (DateTime)new JValue(new DateTime(2000, 12, 20)));
  #if !NET20
              Assert.AreEqual(new DateTimeOffset(2000, 12, 20, 0, 0, 0, TimeSpan.Zero), (DateTimeOffset)new JValue(new DateTime(2000, 12, 20, 0, 0, 0, DateTimeKind.Utc)));
              Assert.AreEqual(new DateTimeOffset(2000, 12, 20, 23, 50, 10, TimeSpan.Zero), (DateTimeOffset)new JValue(new DateTimeOffset(2000, 12, 20, 23, 50, 10, TimeSpan.Zero)));
              Assert.AreEqual(null, (DateTimeOffset?)new JValue((DateTimeOffset?)null));
              Assert.AreEqual(null, (DateTimeOffset?)(JValue)null);
  #endif
              Assert.AreEqual(true, (bool)new JValue(true));
              Assert.AreEqual(true, (bool?)new JValue(true));
              Assert.AreEqual(null, (bool?)((JValue)null));
              Assert.AreEqual(null, (bool?)JValue.CreateNull());
              Assert.AreEqual(10, (long)new JValue(10));
              Assert.AreEqual(null, (long?)new JValue((long?)null));
              Assert.AreEqual(null, (long?)(JValue)null);
              Assert.AreEqual(null, (int?)new JValue((int?)null));
              Assert.AreEqual(null, (int?)(JValue)null);
              Assert.AreEqual(null, (DateTime?)new JValue((DateTime?)null));
              Assert.AreEqual(null, (DateTime?)(JValue)null);
              Assert.AreEqual(null, (short?)new JValue((short?)null));
              Assert.AreEqual(null, (short?)(JValue)null);
              Assert.AreEqual(null, (float?)new JValue((float?)null));
              Assert.AreEqual(null, (float?)(JValue)null);
              Assert.AreEqual(null, (double?)new JValue((double?)null));
              Assert.AreEqual(null, (double?)(JValue)null);
              Assert.AreEqual(null, (decimal?)new JValue((decimal?)null));
              Assert.AreEqual(null, (decimal?)(JValue)null);
              Assert.AreEqual(null, (uint?)new JValue((uint?)null));
              Assert.AreEqual(null, (uint?)(JValue)null);
              Assert.AreEqual(null, (sbyte?)new JValue((sbyte?)null));
              Assert.AreEqual(null, (sbyte?)(JValue)null);
              Assert.AreEqual(null, (byte?)new JValue((byte?)null));
              Assert.AreEqual(null, (byte?)(JValue)null);
              Assert.AreEqual(null, (ulong?)new JValue((ulong?)null));
              Assert.AreEqual(null, (ulong?)(JValue)null);
              Assert.AreEqual(null, (uint?)new JValue((uint?)null));
              Assert.AreEqual(null, (uint?)(JValue)null);
              Assert.AreEqual(11.1f, (float)new JValue(11.1));
              Assert.AreEqual(float.MinValue, (float)new JValue(float.MinValue));
              Assert.AreEqual(1.1, (double)new JValue(1.1));
              Assert.AreEqual(uint.MaxValue, (uint)new JValue(uint.MaxValue));
              Assert.AreEqual(ulong.MaxValue, (ulong)new JValue(ulong.MaxValue));
              Assert.AreEqual(ulong.MaxValue, (ulong)new JProperty("Test", new JValue(ulong.MaxValue)));
              Assert.AreEqual(null, (string)new JValue((string)null));
              Assert.AreEqual(5m, (decimal)(new JValue(5L)));
              Assert.AreEqual(5m, (decimal?)(new JValue(5L)));
              Assert.AreEqual(5f, (float)(new JValue(5L)));
              Assert.AreEqual(5f, (float)(new JValue(5m)));
              Assert.AreEqual(5f, (float?)(new JValue(5m)));
              Assert.AreEqual(5, (byte)(new JValue(5)));
              Assert.AreEqual(SByte.MinValue, (sbyte?)(new JValue(SByte.MinValue)));
              Assert.AreEqual(SByte.MinValue, (sbyte)(new JValue(SByte.MinValue)));
  
              Assert.AreEqual(null, (sbyte?)JValue.CreateNull());
  
              Assert.AreEqual("1", (string)(new JValue(1)));
              Assert.AreEqual("1", (string)(new JValue(1.0)));
              Assert.AreEqual("1.0", (string)(new JValue(1.0m)));
              Assert.AreEqual("True", (string)(new JValue(true)));
              Assert.AreEqual(null, (string)(JValue.CreateNull()));
              Assert.AreEqual(null, (string)(JValue)null);
              Assert.AreEqual("12/12/2000 12:12:12", (string)(new JValue(new DateTime(2000, 12, 12, 12, 12, 12, DateTimeKind.Utc))));
  #if !NET20
              Assert.AreEqual("12/12/2000 12:12:12 +00:00", (string)(new JValue(new DateTimeOffset(2000, 12, 12, 12, 12, 12, TimeSpan.Zero))));
  #endif
              Assert.AreEqual(true, (bool)(new JValue(1)));
              Assert.AreEqual(true, (bool)(new JValue(1.0)));
              Assert.AreEqual(true, (bool)(new JValue("true")));
              Assert.AreEqual(true, (bool)(new JValue(true)));
              Assert.AreEqual(true, (bool)(new JValue(2)));
              Assert.AreEqual(false, (bool)(new JValue(0)));
              Assert.AreEqual(1, (int)(new JValue(1)));
              Assert.AreEqual(1, (int)(new JValue(1.0)));
              Assert.AreEqual(1, (int)(new JValue("1")));
              Assert.AreEqual(1, (int)(new JValue(true)));
              Assert.AreEqual(1m, (decimal)(new JValue(1)));
              Assert.AreEqual(1m, (decimal)(new JValue(1.0)));
              Assert.AreEqual(1m, (decimal)(new JValue("1")));
              Assert.AreEqual(1m, (decimal)(new JValue(true)));
              Assert.AreEqual(TimeSpan.FromMinutes(1), (TimeSpan)(new JValue(TimeSpan.FromMinutes(1))));
              Assert.AreEqual("00:01:00", (string)(new JValue(TimeSpan.FromMinutes(1))));
              Assert.AreEqual(TimeSpan.FromMinutes(1), (TimeSpan)(new JValue("00:01:00")));
              Assert.AreEqual("46efe013-b56a-4e83-99e4-4dce7678a5bc", (string)(new JValue(new Guid("46EFE013-B56A-4E83-99E4-4DCE7678A5BC"))));
              Assert.AreEqual("http://www.google.com/", (string)(new JValue(new Uri("http://www.google.com"))));
              Assert.AreEqual(new Guid("46EFE013-B56A-4E83-99E4-4DCE7678A5BC"), (Guid)(new JValue("46EFE013-B56A-4E83-99E4-4DCE7678A5BC")));
              Assert.AreEqual(new Guid("46EFE013-B56A-4E83-99E4-4DCE7678A5BC"), (Guid)(new JValue(new Guid("46EFE013-B56A-4E83-99E4-4DCE7678A5BC"))));
              Assert.AreEqual(new Uri("http://www.google.com"), (Uri)(new JValue("http://www.google.com")));
              Assert.AreEqual(new Uri("http://www.google.com"), (Uri)(new JValue(new Uri("http://www.google.com"))));
              Assert.AreEqual(null, (Uri)(JValue.CreateNull()));
              Assert.AreEqual(Convert.ToBase64String(Encoding.UTF8.GetBytes("hi")), (string)(new JValue(Encoding.UTF8.GetBytes("hi"))));
              CollectionAssert.AreEquivalent((byte[])Encoding.UTF8.GetBytes("hi"), (byte[])(new JValue(Convert.ToBase64String(Encoding.UTF8.GetBytes("hi")))));
              Assert.AreEqual(new Guid("46EFE013-B56A-4E83-99E4-4DCE7678A5BC"), (Guid)(new JValue(new Guid("46EFE013-B56A-4E83-99E4-4DCE7678A5BC").ToByteArray())));
              Assert.AreEqual(new Guid("46EFE013-B56A-4E83-99E4-4DCE7678A5BC"), (Guid?)(new JValue(new Guid("46EFE013-B56A-4E83-99E4-4DCE7678A5BC").ToByteArray())));
  
gt:             Assert.AreEqual((sbyte?)1, (sbyte?)(new JValue((short?)1)));