// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Json;
using System.Net.Http.Internal;
using System.Text;
using Newtonsoft.Json.Linq;
using Xunit;
using Xunit.Extensions;
namespace System.Net.Http.Formatting
{
public class FormUrlEncodedJsonFromUriQueryTests
{
#region Tests
[Theory,
InlineData("abc", "{\"abc\":\"\"}"),
InlineData("%2eabc%2e", "{\".abc.\":\"\"}"),
InlineData("", "{}"),
InlineData("a=1", "{\"a\":\"1\"}")]
public void SimpleStringsTest(string encoded, string expectedResult)
{
ValidateFormUrlEncoded(encoded, expectedResult);
}
[Theory,
InlineData("a=2", "{\"a\":\"2\"}"),
InlineData("b=true", "{\"b\":\"true\"}"),
InlineData("c=hello", "{\"c\":\"hello\"}"),
InlineData("d=", "{\"d\":\"\"}"),
InlineData("e=null", "{\"e\":\"null\"}")]
public void SimpleObjectsTest(string encoded, string expectedResult)
{
ValidateFormUrlEncoded(encoded, expectedResult);
}
[Fact]
public void LegacyArraysTest()
{
ValidateFormUrlEncoded("a=1&a=hello&a=333", "{\"a\":[\"1\",\"hello\",\"333\"]}");
// Only valid in shallow serialization
ParseInvalidFormUrlEncoded("a[z]=2&a[z]=3");
}
[Theory,
InlineData("a[]=1&a[]=hello&a[]=333", "{\"a\":[\"1\",\"hello\",\"333\"]}"),
InlineData("a[b][]=1&a[b][]=hello&a[b][]=333", "{\"a\":{\"b\":[\"1\",\"hello\",\"333\"]}}"),
InlineData("a[]=", "{\"a\":[\"\"]}"),
InlineData("a%5B%5D=2", @"{""a"":[""2""]}"),
InlineData("a[x][0]=1&a[x][]=2", @"{""a"":{""x"":[""1"",""2""]}}")]
public void ArraysTest(string encoded, string expectedResult)
{
ValidateFormUrlEncoded(encoded, expectedResult);
}
[Theory,
InlineData("a[0][]=1&a[0][]=hello&a[1][]=333", "{\"a\":[[\"1\",\"hello\"],[\"333\"]]}"),
InlineData("a[b][0][]=1&a[b][1][]=hello&a[b][1][]=333", "{\"a\":{\"b\":[[\"1\"],[\"hello\",\"333\"]]}}"),
InlineData("a[0][0][0][]=1", "{\"a\":[[[[\"1\"]]]]}")]
public void MultidimensionalArraysTest(string encoded, string expectedResult)
{
ValidateFormUrlEncoded(encoded, expectedResult);
}
[Theory,
InlineData("a[0][]=hello&a[2][]=333", "{\"a\":{\"0\":[\"hello\"],\"2\":[\"333\"]}}"),
InlineData("a[0]=hello", "{\"a\":[\"hello\"]}"),
InlineData("a[1][]=hello", "{\"a\":{\"1\":[\"hello\"]}}"),
InlineData("a[1][0]=hello", "{\"a\":{\"1\":[\"hello\"]}}")]
public void SparseArraysTest(string encoded, string expectedResult)
{
ValidateFormUrlEncoded(encoded, expectedResult);
}
[Theory,
InlineData("b[]=2&b[1][c]=d", "{\"b\":[\"2\",{\"c\":\"d\"}]}")]
public void ArraysWithMixedMembers(string encoded, string expectedResult)
{
ValidateFormUrlEncoded(encoded, expectedResult);
}
[Theory,
InlineData("=3", "{\"\":\"3\"}"),
InlineData("a=1&=3", "{\"a\":\"1\",\"\":\"3\"}"),
InlineData("=3&b=2", "{\"\":\"3\",\"b\":\"2\"}")]
public void EmptyKeyTest(string encoded, string expectedResult)
{
ValidateFormUrlEncoded(encoded, expectedResult);
}
[Theory,
InlineData("a[b]=1&a=2"),
InlineData("a[b]=1&a[b][]=2"),
InlineData("a[x][]=1&a[x][0]=2"),
InlineData("a=2&a[b]=1"),
InlineData("[]=1"),
InlineData("a[][]=0"),
InlineData("a[][x]=0"),
InlineData("a&a[b]=1")]
public void InvalidObjectGraphsTest(string encoded)
{
ParseInvalidFormUrlEncoded(encoded);
}
[Theory,
InlineData("a[b=2"),
InlineData("a[[b]=2"),
InlineData("a[b]]=2")]
public void InvalidFormUrlEncodingTest(string encoded)
{
ParseInvalidFormUrlEncoded(encoded);
}
///
/// Tests for parsing form-urlencoded data originated from JS primitives.
///
[Theory,
InlineData("abc", @"{""abc"":""""}"),
InlineData("123", @"{""123"":""""}"),
InlineData("true", @"{""true"":""""}"),
InlineData("", "{}"),
InlineData("%2fabc%2f", @"{""/abc/"":""""}")]
public void TestJValue(string encoded, string expectedResult)
{
ValidateFormUrlEncoded(encoded, expectedResult);
}
///
/// Negative tests for parsing form-urlencoded data originated from JS primitives.
///
[Theory,
InlineData("a[b]=1&a=2"),
InlineData("a=2&a[b]=1"),
InlineData("[]=1")]
public void TestJValueNegative(string encoded)
{
ParseInvalidFormUrlEncoded(encoded);
}
///
/// Tests for parsing form-urlencoded data originated from JS objects.
///
[Theory,
InlineData("a=NaN", @"{""a"":""NaN""}"),
InlineData("a=false", @"{""a"":""false""}"),
InlineData("a=foo", @"{""a"":""foo""}"),
InlineData("1=1", "{\"1\":\"1\"}")]
public void TestObjects(string encoded, string expectedResult)
{
ValidateFormUrlEncoded(encoded, expectedResult);
}
///
/// Tests for parsing form-urlencoded data originated from JS arrays.
///
[Theory,
InlineData("a[]=2", @"{""a"":[""2""]}"),
InlineData("a[]=", @"{""a"":[""""]}"),
InlineData("a[0][0][]=1", @"{""a"":[[[""1""]]]}"),
InlineData("z[]=9&z[]=true&z[]=undefined&z[]=", @"{""z"":[""9"",""true"",""undefined"",""""]}"),
InlineData("z[]=9&z[]=true&z[]=undefined&z[]=null", @"{""z"":[""9"",""true"",""undefined"",""null""]}"),
InlineData("z[0][]=9&z[0][]=true&z[1][]=undefined&z[1][]=null", @"{""z"":[[""9"",""true""],[""undefined"",""null""]]}"),
InlineData("a[0][x]=2", @"{""a"":[{""x"":""2""}]}"),
InlineData("a%5B%5D=2", @"{""a"":[""2""]}"),
InlineData("a%5B%5D=", @"{""a"":[""""]}"),
InlineData("z%5B%5D=9&z%5B%5D=true&z%5B%5D=undefined&z%5B%5D=", @"{""z"":[""9"",""true"",""undefined"",""""]}"),
InlineData("z%5B%5D=9&z%5B%5D=true&z%5B%5D=undefined&z%5B%5D=null", @"{""z"":[""9"",""true"",""undefined"",""null""]}"),
InlineData("z%5B0%5D%5B%5D=9&z%5B0%5D%5B%5D=true&z%5B1%5D%5B%5D=undefined&z%5B1%5D%5B%5D=null", @"{""z"":[[""9"",""true""],[""undefined"",""null""]]}")]
public void TestArray(string encoded, string expectedResult)
{
ValidateFormUrlEncoded(encoded, expectedResult);
}
///
/// Tests for parsing form-urlencoded data originated from JS arrays, using the jQuery 1.3 format (no []'s).
///
[Theory,
InlineData("z=9&z=true&z=undefined&z=", @"{""z"":[""9"",""true"",""undefined"",""""]}"),
InlineData("z=9&z=true&z=undefined&z=null", @"{""z"":[""9"",""true"",""undefined"",""null""]}"),
InlineData("z=9&z=true&z=undefined&z=null&a=hello", @"{""z"":[""9"",""true"",""undefined"",""null""],""a"":""hello""}")]
public void TestArrayCompat(string encoded, string expectedResult)
{
ValidateFormUrlEncoded(encoded, expectedResult);
}
///
/// Negative tests for parsing form-urlencoded data originated from JS arrays.
///
[Theory,
InlineData("a[z]=2&a[z]=3")]
public void TestArrayCompatNegative(string encoded)
{
ParseInvalidFormUrlEncoded(encoded);
}
///
/// Tests for form-urlencoded data originated from sparse JS arrays.
///
[Theory,
InlineData("a[2]=hello", @"{""a"":{""2"":""hello""}}"),
InlineData("a[x][0]=2", @"{""a"":{""x"":[""2""]}}"),
InlineData("a[x][1]=2", @"{""a"":{""x"":{""1"":""2""}}}"),
InlineData("a[x][0]=0&a[x][1]=1", @"{""a"":{""x"":[""0"",""1""]}}"),
InlineData("a[0][0][0]=hello&a[1][0][0][0][]=hello", @"{""a"":[[[""hello""]],[[[[""hello""]]]]]}"),
InlineData("a[0][0][0]=hello&a[1][0][0][0]=hello", @"{""a"":[[[""hello""]],[[[""hello""]]]]}"),
InlineData("a[1][0][]=1", @"{""a"":{""1"":[[""1""]]}}"),
InlineData("a[1][1][]=1", @"{""a"":{""1"":{""1"":[""1""]}}}"),
InlineData("a[1][1][0]=1", @"{""a"":{""1"":{""1"":[""1""]}}}"),
InlineData("a[0][]=2&a[0][]=3&a[2][]=1", "{\"a\":{\"0\":[\"2\",\"3\"],\"2\":[\"1\"]}}"),
InlineData("a[x][]=1&a[x][1]=2", @"{""a"":{""x"":[""1"",""2""]}}"),
InlineData("a[x][0]=1&a[x][]=2", @"{""a"":{""x"":[""1"",""2""]}}")]
public void TestArraySparse(string encoded, string expectedResult)
{
ValidateFormUrlEncoded(encoded, expectedResult);
}
///
/// Negative tests for parsing form-urlencoded arrays.
///
[Theory,
InlineData("a[x]=2&a[x][]=3"),
InlineData("a[]=1&a[0][]=2"),
InlineData("a[]=1&a[0][0][]=2"),
InlineData("a[x][]=1&a[x][0]=2"),
InlineData("a[][]=0"),
InlineData("a[][x]=0")]
public void TestArrayIndexNegative(string encoded)
{
ParseInvalidFormUrlEncoded(encoded);
}
public static IEnumerable