#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; using System.ComponentModel; #if DNXCORE50 using Xunit; using Test = Xunit.FactAttribute; using Assert = Newtonsoft.Json.Tests.XUnitAssert; #else using NUnit.Framework; #endif using Newtonsoft.Json.Linq; #if NET20 using Newtonsoft.Json.Utilities.LinqBridge; #else using System.Linq; #endif namespace Newtonsoft.Json.Tests.Linq { [TestFixture] public class JArrayTests : TestFixtureBase { [Test] public void RemoveSpecificAndRemoveSelf() { JObject o = new JObject { { "results", new JArray(1, 2, 3, 4) } }; JArray a = (JArray)o["results"]; var last = a.Last(); Assert.IsTrue(a.Remove(last)); last = a.Last(); last.Remove(); Assert.AreEqual(2, a.Count); } [Test] public void Clear() { JArray a = new JArray { 1 }; Assert.AreEqual(1, a.Count); a.Clear(); Assert.AreEqual(0, a.Count); } [Test] public void AddToSelf() { JArray a = new JArray(); a.Add(a); Assert.IsFalse(ReferenceEquals(a[0], a)); } [Test] public void Contains() { JValue v = new JValue(1); JArray a = new JArray { v }; Assert.AreEqual(false, a.Contains(new JValue(2))); Assert.AreEqual(false, a.Contains(new JValue(1))); Assert.AreEqual(false, a.Contains(null)); Assert.AreEqual(true, a.Contains(v)); } [Test] public void GenericCollectionCopyTo() { JArray j = new JArray(); j.Add(new JValue(1)); j.Add(new JValue(2)); j.Add(new JValue(3)); Assert.AreEqual(3, j.Count); JToken[] a = new JToken[5]; ((ICollection)j).CopyTo(a, 1); Assert.AreEqual(null, a[0]); Assert.AreEqual(1, (int)a[1]); Assert.AreEqual(2, (int)a[2]); Assert.AreEqual(3, (int)a[3]); Assert.AreEqual(null, a[4]); } [Test] public void GenericCollectionCopyToNullArrayShouldThrow() { JArray j = new JArray(); ExceptionAssert.Throws(() => { ((ICollection)j).CopyTo(null, 0); }, @"Value cannot be null. Parameter name: array"); } [Test] public void GenericCollectionCopyToNegativeArrayIndexShouldThrow() { JArray j = new JArray(); ExceptionAssert.Throws(() => { ((ICollection)j).CopyTo(new JToken[1], -1); }, @"arrayIndex is less than 0. Parameter name: arrayIndex"); } [Test] public void GenericCollectionCopyToArrayIndexEqualGreaterToArrayLengthShouldThrow() { JArray j = new JArray(); ExceptionAssert.Throws(() => { ((ICollection)j).CopyTo(new JToken[1], 1); }, @"arrayIndex is equal to or greater than the length of array."); } [Test] public void GenericCollectionCopyToInsufficientArrayCapacity() { JArray j = new JArray(); j.Add(new JValue(1)); j.Add(new JValue(2)); j.Add(new JValue(3)); ExceptionAssert.Throws(() => { ((ICollection)j).CopyTo(new JToken[3], 1); }, @"The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array."); } [Test] public void Remove() { JValue v = new JValue(1); JArray j = new JArray(); j.Add(v); Assert.AreEqual(1, j.Count); Assert.AreEqual(false, j.Remove(new JValue(1))); Assert.AreEqual(false, j.Remove(null)); Assert.AreEqual(true, j.Remove(v)); Assert.AreEqual(false, j.Remove(v)); Assert.AreEqual(0, j.Count); } [Test] public void IndexOf() { JValue v1 = new JValue(1); JValue v2 = new JValue(1); JValue v3 = new JValue(1); JArray j = new JArray(); j.Add(v1); Assert.AreEqual(0, j.IndexOf(v1)); j.Add(v2); Assert.AreEqual(0, j.IndexOf(v1)); Assert.AreEqual(1, j.IndexOf(v2)); j.AddFirst(v3); Assert.AreEqual(1, j.IndexOf(v1)); Assert.AreEqual(2, j.IndexOf(v2)); Assert.AreEqual(0, j.IndexOf(v3)); v3.Remove(); Assert.AreEqual(0, j.IndexOf(v1)); Assert.AreEqual(1, j.IndexOf(v2)); Assert.AreEqual(-1, j.IndexOf(v3)); } [Test] public void RemoveAt() { JValue v1 = new JValue(1); JValue v2 = new JValue(1); JValue v3 = new JValue(1); JArray j = new JArray(); j.Add(v1); j.Add(v2); j.Add(v3); Assert.AreEqual(true, j.Contains(v1)); j.RemoveAt(0); Assert.AreEqual(false, j.Contains(v1)); Assert.AreEqual(true, j.Contains(v3)); j.RemoveAt(1); Assert.AreEqual(false, j.Contains(v3)); Assert.AreEqual(1, j.Count); } [Test] public void RemoveAtOutOfRangeIndexShouldError() { JArray j = new JArray(); ExceptionAssert.Throws(() => { j.RemoveAt(0); }, @"Index is equal to or greater than Count. Parameter name: index"); } [Test] public void RemoveAtNegativeIndexShouldError() { JArray j = new JArray(); ExceptionAssert.Throws(() => { j.RemoveAt(-1); }, @"Index is less than 0. Parameter name: index"); } [Test] public void Insert() { JValue v1 = new JValue(1); JValue v2 = new JValue(2); JValue v3 = new JValue(3); JValue v4 = new JValue(4); JArray j = new JArray(); j.Add(v1); j.Add(v2); j.Add(v3); j.Insert(1, v4); Assert.AreEqual(0, j.IndexOf(v1)); Assert.AreEqual(1, j.IndexOf(v4)); Assert.AreEqual(2, j.IndexOf(v2)); Assert.AreEqual(3, j.IndexOf(v3)); } [Test] public void AddFirstAddedTokenShouldBeFirst() { JValue v1 = new JValue(1); JValue v2 = new JValue(2); JValue v3 = new JValue(3); JArray j = new JArray(); Assert.AreEqual(null, j.First); Assert.AreEqual(null, j.Last); j.AddFirst(v1); Assert.AreEqual(v1, j.First); Assert.AreEqual(v1, j.Last); j.AddFirst(v2); Assert.AreEqual(v2, j.First); Assert.AreEqual(v1, j.Last); j.AddFirst(v3); Assert.AreEqual(v3, j.First); Assert.AreEqual(v1, j.Last); } [Test] public void InsertShouldInsertAtZeroIndex() { JValue v1 = new JValue(1); JValue v2 = new JValue(2); JArray j = new JArray(); j.Insert(0, v1); Assert.AreEqual(0, j.IndexOf(v1)); j.Insert(0, v2); Assert.AreEqual(1, j.IndexOf(v1)); Assert.AreEqual(0, j.IndexOf(v2)); } [Test] public void InsertNull() { JArray j = new JArray(); j.Insert(0, null); Assert.AreEqual(null, ((JValue)j[0]).Value); } [Test] public void InsertNegativeIndexShouldThrow() { JArray j = new JArray(); ExceptionAssert.Throws(() => { j.Insert(-1, new JValue(1)); }, @"Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index"); } [Test] public void InsertOutOfRangeIndexShouldThrow() { JArray j = new JArray(); ExceptionAssert.Throws(() => { j.Insert(2, new JValue(1)); }, @"Index must be within the bounds of the List. Parameter name: index"); } [Test] public void Item() { JValue v1 = new JValue(1); JValue v2 = new JValue(2); JValue v3 = new JValue(3); JValue v4 = new JValue(4); JArray j = new JArray(); j.Add(v1); j.Add(v2); j.Add(v3); j[1] = v4; Assert.AreEqual(null, v2.Parent); Assert.AreEqual(-1, j.IndexOf(v2)); Assert.AreEqual(j, v4.Parent); Assert.AreEqual(1, j.IndexOf(v4)); } [Test] public void Parse_ShouldThrowOnUnexpectedToken() { string json = @"{""prop"":""value""}"; ExceptionAssert.Throws(() => { JArray.Parse(json); }, "Error reading JArray from JsonReader. Current JsonReader item is not an array: StartObject. Path '', line 1, position 1."); } public class ListItemFields { public string ListItemText { get; set; } public object ListItemValue { get; set; } } [Test] public void ArrayOrder() { string itemZeroText = "Zero text"; IEnumerable t = new List { new ListItemFields { ListItemText = "First", ListItemValue = 1 }, new ListItemFields { ListItemText = "Second", ListItemValue = 2 }, new ListItemFields { ListItemText = "Third", ListItemValue = 3 } }; JObject optionValues = new JObject( new JProperty("options", new JArray( new JObject( new JProperty("text", itemZeroText), new JProperty("value", "0")), from r in t orderby r.ListItemValue select new JObject( new JProperty("text", r.ListItemText), new JProperty("value", r.ListItemValue.ToString()))))); string result = "myOptions = " + optionValues.ToString(); StringAssert.AreEqual(@"myOptions = { ""options"": [ { ""text"": ""Zero text"", ""value"": ""0"" }, { ""text"": ""First"", ""value"": ""1"" }, { ""text"": ""Second"", ""value"": ""2"" }, { ""text"": ""Third"", ""value"": ""3"" } ] }", result); } [Test] public void Iterate() { JArray a = new JArray(1, 2, 3, 4, 5); int i = 1; foreach (JToken token in a) { Assert.AreEqual(i, (int)token); i++; } } #if !(PORTABLE || DNXCORE50 || PORTABLE40) [Test] public void ITypedListGetItemProperties() { JProperty p1 = new JProperty("Test1", 1); JProperty p2 = new JProperty("Test2", "Two"); ITypedList a = new JArray(new JObject(p1, p2)); PropertyDescriptorCollection propertyDescriptors = a.GetItemProperties(null); Assert.IsNotNull(propertyDescriptors); Assert.AreEqual(2, propertyDescriptors.Count); Assert.AreEqual("Test1", propertyDescriptors[0].Name); Assert.AreEqual("Test2", propertyDescriptors[1].Name); } #endif [Test] public void AddArrayToSelf() { JArray a = new JArray(1, 2); a.Add(a); Assert.AreEqual(3, a.Count); Assert.AreEqual(1, (int)a[0]); Assert.AreEqual(2, (int)a[1]); Assert.AreNotSame(a, a[2]); } [Test] public void SetValueWithInvalidIndex() { ExceptionAssert.Throws(() => { JArray a = new JArray(); a["badvalue"] = new JValue(3); }, @"Set JArray values with invalid key value: ""badvalue"". Int32 array index expected."); } [Test] public void SetValue() { object key = 0; JArray a = new JArray((object)null); a[key] = new JValue(3); Assert.AreEqual(3, (int)a[key]); } [Test] public void ReplaceAll() { JArray a = new JArray(new[] { 1, 2, 3 }); Assert.AreEqual(3, a.Count); Assert.AreEqual(1, (int)a[0]); Assert.AreEqual(2, (int)a[1]); Assert.AreEqual(3, (int)a[2]); a.ReplaceAll(1); Assert.AreEqual(1, a.Count); Assert.AreEqual(1, (int)a[0]); } [Test] public void ParseIncomplete() { ExceptionAssert.Throws(() => { JArray.Parse("[1"); }, "Unexpected end of content while loading JArray. Path '[0]', line 1, position 2."); } [Test] public void InsertAddEnd() { JArray array = new JArray(); array.Insert(0, 123); array.Insert(1, 456); Assert.AreEqual(2, array.Count); Assert.AreEqual(123, (int)array[0]); Assert.AreEqual(456, (int)array[1]); } [Test] public void ParseAdditionalContent() { string json = @"[ ""Small"", ""Medium"", ""Large"" ], 987987"; ExceptionAssert.Throws(() => { JArray.Parse(json); }, "Additional text encountered after finished reading JSON content: ,. Path '', line 5, position 1."); } [Test] public void ToListOnEmptyArray() { string json = @"{""decks"":[]}"; JArray decks = (JArray)JObject.Parse(json)["decks"]; IList l = decks.ToList(); Assert.AreEqual(0, l.Count); json = @"{""decks"":[1]}"; decks = (JArray)JObject.Parse(json)["decks"]; l = decks.ToList(); Assert.AreEqual(1, l.Count); } [Test] public void Parse_NoComments() { string json = "[1,2/*comment*/,3]"; JArray a = JArray.Parse(json, new JsonLoadSettings()); Assert.AreEqual(3, a.Count); Assert.AreEqual(1, (int)a[0]); Assert.AreEqual(2, (int)a[1]); Assert.AreEqual(3, (int)a[2]); a = JArray.Parse(json, new JsonLoadSettings { CommentHandling = CommentHandling.Ignore }); Assert.AreEqual(3, a.Count); Assert.AreEqual(1, (int)a[0]); Assert.AreEqual(2, (int)a[1]); Assert.AreEqual(3, (int)a[2]); a = JArray.Parse(json, new JsonLoadSettings { CommentHandling = CommentHandling.Load }); Assert.AreEqual(4, a.Count); Assert.AreEqual(1, (int)a[0]); Assert.AreEqual(2, (int)a[1]); Assert.AreEqual(JTokenType.Comment, a[2].Type); Assert.AreEqual(3, (int)a[3]); } [Test] public void Parse_ExcessiveContentJustComments() { string json = @"[1,2,3]/*comment*/ //Another comment."; JArray a = JArray.Parse(json); Assert.AreEqual(3, a.Count); Assert.AreEqual(1, (int)a[0]); Assert.AreEqual(2, (int)a[1]); Assert.AreEqual(3, (int)a[2]); } [Test] public void Parse_ExcessiveContent() { string json = @"[1,2,3]/*comment*/ //Another comment. []"; ExceptionAssert.Throws(() => JArray.Parse(json), "Additional text encountered after finished reading JSON content: [. Path '', line 3, position 0."); } [Test] public void Parse_LineInfo() { string json = "[1,2,3]"; JArray a = JArray.Parse(json, new JsonLoadSettings()); Assert.AreEqual(true, ((IJsonLineInfo)a).HasLineInfo()); Assert.AreEqual(true, ((IJsonLineInfo)a[0]).HasLineInfo()); Assert.AreEqual(true, ((IJsonLineInfo)a[1]).HasLineInfo()); Assert.AreEqual(true, ((IJsonLineInfo)a[2]).HasLineInfo()); a = JArray.Parse(json, new JsonLoadSettings { LineInfoHandling = LineInfoHandling.Ignore }); Assert.AreEqual(false, ((IJsonLineInfo)a).HasLineInfo()); Assert.AreEqual(false, ((IJsonLineInfo)a[0]).HasLineInfo()); Assert.AreEqual(false, ((IJsonLineInfo)a[1]).HasLineInfo()); Assert.AreEqual(false, ((IJsonLineInfo)a[2]).HasLineInfo()); a = JArray.Parse(json, new JsonLoadSettings { LineInfoHandling = LineInfoHandling.Load }); Assert.AreEqual(true, ((IJsonLineInfo)a).HasLineInfo()); Assert.AreEqual(true, ((IJsonLineInfo)a[0]).HasLineInfo()); Assert.AreEqual(true, ((IJsonLineInfo)a[1]).HasLineInfo()); Assert.AreEqual(true, ((IJsonLineInfo)a[2]).HasLineInfo()); } } }