Files

651 lines
19 KiB
C#

#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<JToken>)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<ArgumentNullException>(() => { ((ICollection<JToken>)j).CopyTo(null, 0); },
@"Value cannot be null.
Parameter name: array",
"Value cannot be null. (Parameter 'array')");
}
[Test]
public void GenericCollectionCopyToNegativeArrayIndexShouldThrow()
{
JArray j = new JArray();
ExceptionAssert.Throws<ArgumentOutOfRangeException>(() => { ((ICollection<JToken>)j).CopyTo(new JToken[1], -1); },
@"arrayIndex is less than 0.
Parameter name: arrayIndex",
"arrayIndex is less than 0. (Parameter 'arrayIndex')");
}
[Test]
public void GenericCollectionCopyToArrayIndexEqualGreaterToArrayLengthShouldThrow()
{
JArray j = new JArray();
ExceptionAssert.Throws<ArgumentException>(() => { ((ICollection<JToken>)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<ArgumentException>(() => { ((ICollection<JToken>)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<ArgumentOutOfRangeException>(
() => { j.RemoveAt(0); },
@"Index is equal to or greater than Count.
Parameter name: index",
"Index is equal to or greater than Count. (Parameter 'index')");
}
[Test]
public void RemoveAtNegativeIndexShouldError()
{
JArray j = new JArray();
ExceptionAssert.Throws<ArgumentOutOfRangeException>(
() => { j.RemoveAt(-1); },
@"Index is less than 0.
Parameter name: index",
"Index is less than 0. (Parameter '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<ArgumentOutOfRangeException>(
() => { 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",
"Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')");
}
[Test]
public void InsertOutOfRangeIndexShouldThrow()
{
JArray j = new JArray();
ExceptionAssert.Throws<ArgumentOutOfRangeException>(
() => { j.Insert(2, new JValue(1)); },
@"Index must be within the bounds of the List.
Parameter name: index",
"Index must be within the bounds of the List. (Parameter '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<JsonReaderException>(() => { 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<ListItemFields> t = new List<ListItemFields>
{
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) || NETSTANDARD2_0 || NET6_0_OR_GREATER
[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<ArgumentException>(() =>
{
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<JsonReaderException>(() => { 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<JsonReaderException>(() => { 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<JToken> 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<JsonReaderException>(() => 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());
}
}
}