// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Runtime.Serialization.Json; using Xunit; namespace System.Json { public class JsonArrayTest { [Fact] public void JsonArrayConstructorParamsTest() { JsonArray target; target = new JsonArray(); Assert.Equal(0, target.Count); target = new JsonArray(null); Assert.Equal(0, target.Count); List items = new List { AnyInstance.AnyJsonValue1, AnyInstance.AnyJsonValue2 }; target = new JsonArray(items.ToArray()); ValidateJsonArrayItems(target, items); target = new JsonArray(items[0], items[1]); ValidateJsonArrayItems(target, items); // Invalide tests items.Add(AnyInstance.DefaultJsonValue); ExceptionHelper.Throws(() => new JsonArray(items.ToArray())); ExceptionHelper.Throws(() => new JsonArray(items[0], items[1], items[2])); } [Fact] public void JsonArrayConstructorEnumTest() { List items = new List { AnyInstance.AnyJsonValue1, AnyInstance.AnyJsonValue2, AnyInstance.AnyJsonValue3 }; JsonArray target; target = new JsonArray(items); ValidateJsonArrayItems(target, items); ExceptionHelper.Throws(() => new JsonArray((IEnumerable)null)); items.Add(AnyInstance.DefaultJsonValue); ExceptionHelper.Throws(() => new JsonArray(items)); } [Fact] public void AddTest() { JsonArray target = new JsonArray(); JsonValue item = AnyInstance.AnyJsonValue1; Assert.False(target.Contains(item)); target.Add(item); Assert.Equal(1, target.Count); Assert.Equal(item, target[0]); Assert.True(target.Contains(item)); ExceptionHelper.Throws(() => target.Add(AnyInstance.DefaultJsonValue)); } [Fact] public void AddRangeEnumTest() { List items = new List { AnyInstance.AnyJsonValue1, AnyInstance.AnyJsonValue2 }; JsonArray target = new JsonArray(); target.AddRange(items); ValidateJsonArrayItems(target, items); ExceptionHelper.Throws(() => new JsonArray().AddRange((IEnumerable)null)); items.Add(AnyInstance.DefaultJsonValue); ExceptionHelper.Throws(() => new JsonArray().AddRange(items)); } [Fact] public void AddRangeParamsTest() { List items = new List { AnyInstance.AnyJsonValue1, AnyInstance.AnyJsonValue2, AnyInstance.AnyJsonValue3 }; JsonArray target; target = new JsonArray(); target.AddRange(items[0], items[1], items[2]); ValidateJsonArrayItems(target, items); target = new JsonArray(); target.AddRange(items.ToArray()); ValidateJsonArrayItems(target, items); target.AddRange(); ValidateJsonArrayItems(target, items); items.Add(AnyInstance.DefaultJsonValue); ExceptionHelper.Throws(() => new JsonArray().AddRange(items[items.Count - 1])); ExceptionHelper.Throws(() => new JsonArray().AddRange(items)); } [Fact] public void ClearTest() { JsonArray target = new JsonArray(AnyInstance.AnyJsonValue1, AnyInstance.AnyJsonValue2); Assert.Equal(2, target.Count); target.Clear(); Assert.Equal(0, target.Count); } [Fact] public void ContainsTest() { JsonValue item1 = AnyInstance.AnyJsonValue1; JsonValue item2 = AnyInstance.AnyJsonValue2; JsonArray target = new JsonArray(item1); Assert.True(target.Contains(item1)); Assert.False(target.Contains(item2)); target.Add(item2); Assert.True(target.Contains(item1)); Assert.True(target.Contains(item2)); target.Remove(item1); Assert.False(target.Contains(item1)); Assert.True(target.Contains(item2)); } [Fact] public void ReadAsComplexTypeTest() { JsonArray target = new JsonArray(AnyInstance.AnyInt, AnyInstance.AnyInt + 1, AnyInstance.AnyInt + 2); int[] intArray1 = (int[])target.ReadAsType(typeof(int[])); int[] intArray2 = target.ReadAsType(); Assert.Equal(((JsonArray)target).Count, intArray1.Length); Assert.Equal(((JsonArray)target).Count, intArray2.Length); for (int i = 0; i < intArray1.Length; i++) { Assert.Equal(AnyInstance.AnyInt + i, intArray1[i]); Assert.Equal(AnyInstance.AnyInt + i, intArray2[i]); } } [Fact] public void CopyToTest() { JsonValue item1 = AnyInstance.AnyJsonValue1; JsonValue item2 = AnyInstance.AnyJsonValue2; JsonArray target = new JsonArray(item1, item2); JsonValue[] array = new JsonValue[target.Count + 1]; target.CopyTo(array, 0); Assert.Equal(item1, array[0]); Assert.Equal(item2, array[1]); target.CopyTo(array, 1); Assert.Equal(item1, array[1]); Assert.Equal(item2, array[2]); ExceptionHelper.Throws(() => target.CopyTo(null, 0)); ExceptionHelper.Throws(() => target.CopyTo(array, -1)); ExceptionHelper.Throws(() => target.CopyTo(array, array.Length - target.Count + 1)); } [Fact] public void IndexOfTest() { JsonValue item1 = AnyInstance.AnyJsonValue1; JsonValue item2 = AnyInstance.AnyJsonValue2; JsonValue item3 = AnyInstance.AnyJsonValue3; JsonArray target = new JsonArray(item1, item2); Assert.Equal(0, target.IndexOf(item1)); Assert.Equal(1, target.IndexOf(item2)); Assert.Equal(-1, target.IndexOf(item3)); } [Fact] public void InsertTest() { JsonValue item1 = AnyInstance.AnyJsonValue1; JsonValue item2 = AnyInstance.AnyJsonValue2; JsonValue item3 = AnyInstance.AnyJsonValue3; JsonArray target = new JsonArray(item1); Assert.Equal(1, target.Count); target.Insert(0, item2); Assert.Equal(2, target.Count); Assert.Equal(item2, target[0]); Assert.Equal(item1, target[1]); target.Insert(1, item3); Assert.Equal(3, target.Count); Assert.Equal(item2, target[0]); Assert.Equal(item3, target[1]); Assert.Equal(item1, target[2]); target.Insert(target.Count, item2); Assert.Equal(4, target.Count); Assert.Equal(item2, target[0]); Assert.Equal(item3, target[1]); Assert.Equal(item1, target[2]); Assert.Equal(item2, target[3]); ExceptionHelper.Throws(() => target.Insert(-1, item3)); ExceptionHelper.Throws(() => target.Insert(target.Count + 1, item1)); ExceptionHelper.Throws(() => target.Insert(0, AnyInstance.DefaultJsonValue)); } [Fact] public void RemoveTest() { JsonValue item1 = AnyInstance.AnyJsonValue1; JsonValue item2 = AnyInstance.AnyJsonValue2; JsonValue item3 = AnyInstance.AnyJsonValue3; JsonArray target = new JsonArray(item1, item2, item3); Assert.True(target.Remove(item2)); Assert.Equal(2, target.Count); Assert.Equal(item1, target[0]); Assert.Equal(item3, target[1]); Assert.False(target.Remove(item2)); Assert.Equal(2, target.Count); } [Fact] public void RemoveAtTest() { JsonValue item1 = AnyInstance.AnyJsonValue1; JsonValue item2 = AnyInstance.AnyJsonValue2; JsonValue item3 = AnyInstance.AnyJsonValue3; JsonArray target = new JsonArray(item1, item2, item3); target.RemoveAt(1); Assert.Equal(2, target.Count); Assert.Equal(item1, target[0]); Assert.Equal(item3, target[1]); ExceptionHelper.Throws(() => target.RemoveAt(-1)); ExceptionHelper.Throws(() => target.RemoveAt(target.Count)); } [Fact] public void ToStringTest() { JsonArray target; JsonValue item1 = AnyInstance.AnyJsonValue1; JsonValue item2 = null; JsonValue item3 = AnyInstance.AnyJsonValue2; target = new JsonArray(item1, item2, item3); string expected = String.Format(CultureInfo.InvariantCulture, "[{0},null,{1}]", item1.ToString(), item3.ToString()); Assert.Equal(expected, target.ToString()); string json = "[\r\n \"hello\",\r\n null,\r\n [\r\n 1,\r\n 2,\r\n 3\r\n ]\r\n]"; target = JsonValue.Parse(json) as JsonArray; Assert.Equal(json.Replace("\r\n", "").Replace(" ", ""), target.ToString()); } [Fact] public void GetEnumeratorTest() { JsonValue item1 = AnyInstance.AnyJsonValue1; JsonValue item2 = AnyInstance.AnyJsonValue2; IEnumerable target = new JsonArray(item1, item2); IEnumerator enumerator = target.GetEnumerator(); Assert.True(enumerator.MoveNext()); Assert.Equal(item1, enumerator.Current); Assert.True(enumerator.MoveNext()); Assert.Equal(item2, enumerator.Current); Assert.False(enumerator.MoveNext()); } [Fact] public void GetEnumeratorTest1() { JsonValue item1 = AnyInstance.AnyJsonValue1; JsonValue item2 = AnyInstance.AnyJsonValue2; IEnumerable target = new JsonArray(item1, item2); IEnumerator enumerator = target.GetEnumerator(); Assert.True(enumerator.MoveNext()); Assert.Equal(item1, enumerator.Current); Assert.True(enumerator.MoveNext()); Assert.Equal(item2, enumerator.Current); Assert.False(enumerator.MoveNext()); } [Fact] public void CountTest() { JsonValue item1 = AnyInstance.AnyJsonValue1; JsonValue item2 = AnyInstance.AnyJsonValue2; JsonArray target = new JsonArray(); Assert.Equal(0, target.Count); target.Add(item1); Assert.Equal(1, target.Count); target.Add(item2); Assert.Equal(2, target.Count); target.Remove(item1); Assert.Equal(1, target.Count); } [Fact] public void IsReadOnlyTest() { JsonArray target = AnyInstance.AnyJsonArray; Assert.False(target.IsReadOnly); } [Fact] public void ItemTest() { JsonValue item1 = AnyInstance.AnyJsonValue1; JsonValue item2 = AnyInstance.AnyJsonValue2; JsonArray target = new JsonArray(item1); Assert.Equal(item1, target[0]); target[0] = item2; Assert.Equal(item2, target[0]); Assert.Equal(item2, target[(short)0]); Assert.Equal(item2, target[(ushort)0]); Assert.Equal(item2, target[(byte)0]); Assert.Equal(item2, target[(sbyte)0]); Assert.Equal(item2, target[(char)0]); ExceptionHelper.Throws(delegate { var i = target[-1]; }); ExceptionHelper.Throws(delegate { var i = target[target.Count]; }); ExceptionHelper.Throws(delegate { target[-1] = AnyInstance.AnyJsonValue1; }); ExceptionHelper.Throws(delegate { target[target.Count] = AnyInstance.AnyJsonValue2; }); ExceptionHelper.Throws(delegate { target[0] = AnyInstance.DefaultJsonValue; }); } [Fact] public void ChangingEventsTest() { JsonArray ja = new JsonArray(AnyInstance.AnyInt, AnyInstance.AnyBool, null); TestEvents( ja, arr => arr.Add(1), new List> { new Tuple(true, ja, new JsonValueChangeEventArgs(1, JsonValueChange.Add, 3)), new Tuple(false, ja, new JsonValueChangeEventArgs(1, JsonValueChange.Add, 3)), }); TestEvents( ja, arr => arr.AddRange(AnyInstance.AnyString, AnyInstance.AnyDouble), new List> { new Tuple(true, ja, new JsonValueChangeEventArgs(AnyInstance.AnyString, JsonValueChange.Add, 4)), new Tuple(true, ja, new JsonValueChangeEventArgs(AnyInstance.AnyDouble, JsonValueChange.Add, 5)), new Tuple(false, ja, new JsonValueChangeEventArgs(AnyInstance.AnyString, JsonValueChange.Add, 4)), new Tuple(false, ja, new JsonValueChangeEventArgs(AnyInstance.AnyDouble, JsonValueChange.Add, 5)), }); TestEvents( ja, arr => arr[1] = 2, new List> { new Tuple(true, ja, new JsonValueChangeEventArgs(2, JsonValueChange.Replace, 1)), new Tuple(false, ja, new JsonValueChangeEventArgs(AnyInstance.AnyBool, JsonValueChange.Replace, 1)), }); ja = new JsonArray { 1, 2, 3 }; TestEvents( ja, arr => arr.Insert(1, "new value"), new List> { new Tuple(true, ja, new JsonValueChangeEventArgs("new value", JsonValueChange.Add, 1)), new Tuple(false, ja, new JsonValueChangeEventArgs("new value", JsonValueChange.Add, 1)), }); TestEvents( ja, arr => arr.RemoveAt(1), new List> { new Tuple(true, ja, new JsonValueChangeEventArgs("new value", JsonValueChange.Remove, 1)), new Tuple(false, ja, new JsonValueChangeEventArgs("new value", JsonValueChange.Remove, 1)), }); TestEvents( ja, arr => arr.Clear(), new List> { new Tuple(true, ja, new JsonValueChangeEventArgs(null, JsonValueChange.Clear, 0)), new Tuple(false, ja, new JsonValueChangeEventArgs(null, JsonValueChange.Clear, 0)), }); ja = new JsonArray(1, 2, 3); TestEvents( ja, arr => arr.Remove(new JsonPrimitive("Not there")), new List>()); JsonValue elementInArray = ja[1]; TestEvents( ja, arr => arr.Remove(elementInArray), new List> { new Tuple(true, ja, new JsonValueChangeEventArgs(elementInArray, JsonValueChange.Remove, 1)), new Tuple(false, ja, new JsonValueChangeEventArgs(elementInArray, JsonValueChange.Remove, 1)), }); } [Fact] public void NestedChangingEventTest() { JsonArray target = new JsonArray { new JsonArray { 1, 2 }, new JsonArray { 3, 4 } }; JsonArray child = target[1] as JsonArray; TestEvents( target, arr => ((JsonArray)arr[1]).Add(5), new List>()); target = new JsonArray(); child = new JsonArray(1, 2); TestEvents( target, arr => { arr.Add(child); ((JsonArray)arr[0]).Add(5); }, new List> { new Tuple(true, target, new JsonValueChangeEventArgs(child, JsonValueChange.Add, 0)), new Tuple(false, target, new JsonValueChangeEventArgs(child, JsonValueChange.Add, 0)), }); } [Fact] public void MultipleListenersTest() { for (int changingListeners = 0; changingListeners <= 2; changingListeners++) { for (int changedListeners = 0; changedListeners <= 2; changedListeners++) { MultipleListenersTestHelper( () => new JsonArray(1, 2), delegate(JsonArray arr) { arr[1] = "hello"; arr.RemoveAt(0); arr.Add("world"); arr.Clear(); }, new List { new JsonValueChangeEventArgs("hello", JsonValueChange.Replace, 1), new JsonValueChangeEventArgs(1, JsonValueChange.Remove, 0), new JsonValueChangeEventArgs("world", JsonValueChange.Add, 1), new JsonValueChangeEventArgs(null, JsonValueChange.Clear, 0), }, new List { new JsonValueChangeEventArgs(2, JsonValueChange.Replace, 1), new JsonValueChangeEventArgs(1, JsonValueChange.Remove, 0), new JsonValueChangeEventArgs("world", JsonValueChange.Add, 1), new JsonValueChangeEventArgs(null, JsonValueChange.Clear, 0), }, changingListeners, changedListeners); } } } [Fact] public void JsonTypeTest() { JsonArray target = AnyInstance.AnyJsonArray; Assert.Equal(JsonType.Array, target.JsonType); } internal static void TestEvents(JsonValueType target, Action actionToTriggerEvent, List> expectedEvents) where JsonValueType : JsonValue { List> actualEvents = new List>(); EventHandler changingHandler = delegate(object sender, JsonValueChangeEventArgs e) { actualEvents.Add(new Tuple(true, sender as JsonValue, e)); }; EventHandler changedHandler = delegate(object sender, JsonValueChangeEventArgs e) { actualEvents.Add(new Tuple(false, sender as JsonValue, e)); }; target.Changing += new EventHandler(changingHandler); target.Changed += new EventHandler(changedHandler); actionToTriggerEvent(target); target.Changing -= new EventHandler(changingHandler); target.Changed -= new EventHandler(changedHandler); ValidateExpectedEvents(expectedEvents, actualEvents); } private static void TestEvents(JsonArray array, Action actionToTriggerEvent, List> expectedEvents) { TestEvents(array, actionToTriggerEvent, expectedEvents); } private static void ValidateExpectedEvents(List> expectedEvents, List> actualEvents) { Assert.Equal(expectedEvents.Count, actualEvents.Count); for (int i = 0; i < expectedEvents.Count; i++) { bool expectedIsChanging = expectedEvents[i].Item1; bool actualIsChanging = expectedEvents[i].Item1; Assert.Equal(expectedIsChanging, actualIsChanging); JsonValue expectedSender = expectedEvents[i].Item2; JsonValue actualSender = actualEvents[i].Item2; Assert.Same(expectedSender, actualSender); JsonValueChangeEventArgs expectedEventArgs = expectedEvents[i].Item3; JsonValueChangeEventArgs actualEventArgs = actualEvents[i].Item3; Assert.Equal(expectedEventArgs.Change, actualEventArgs.Change); Assert.Equal(expectedEventArgs.Index, actualEventArgs.Index); Assert.Equal(expectedEventArgs.Key, actualEventArgs.Key); string expectedChild = expectedEventArgs.Child == null ? "null" : expectedEventArgs.Child.ToString(); string actualChild = actualEventArgs.Child == null ? "null" : actualEventArgs.Child.ToString(); Assert.Equal(expectedChild, actualChild); } } internal static void MultipleListenersTestHelper( Func createTarget, Action actionToTriggerEvents, List expectedChangingEventArgs, List expectedChangedEventArgs, int changingListeners, int changedListeners) where JsonValueType : JsonValue { Console.WriteLine("Testing events on a {0} for {1} changING listeners and {2} changED listeners", typeof(JsonValueType).Name, changingListeners, changedListeners); JsonValueType target = createTarget(); List>[] actualChangingEvents = new List>[changingListeners]; List>[] actualChangedEvents = new List>[changedListeners]; List> expectedChangingEvents = new List>( expectedChangingEventArgs.Select((args) => new Tuple(true, target, args))); List> expectedChangedEvents = new List>( expectedChangedEventArgs.Select((args) => new Tuple(false, target, args))); for (int i = 0; i < changingListeners; i++) { actualChangingEvents[i] = new List>(); int index = i; target.Changing += delegate(object sender, JsonValueChangeEventArgs e) { actualChangingEvents[index].Add(new Tuple(true, sender as JsonValue, e)); }; } for (int i = 0; i < changedListeners; i++) { actualChangedEvents[i] = new List>(); int index = i; target.Changed += delegate(object sender, JsonValueChangeEventArgs e) { actualChangedEvents[index].Add(new Tuple(false, sender as JsonValue, e)); }; } actionToTriggerEvents(target); for (int i = 0; i < changingListeners; i++) { Console.WriteLine("Validating Changing events for listener {0}", i); ValidateExpectedEvents(expectedChangingEvents, actualChangingEvents[i]); } for (int i = 0; i < changedListeners; i++) { Console.WriteLine("Validating Changed events for listener {0}", i); ValidateExpectedEvents(expectedChangedEvents, actualChangedEvents[i]); } } private static void ValidateJsonArrayItems(JsonArray jsonArray, IEnumerable expectedItems) { List expected = new List(expectedItems); Assert.Equal(expected.Count, jsonArray.Count); for (int i = 0; i < expected.Count; i++) { Assert.Equal(expected[i], jsonArray[i]); } } } }