151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson/*
251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * Copyright (C) 2010 The Android Open Source Project
351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson *
451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * you may not use this file except in compliance with the License.
651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * You may obtain a copy of the License at
751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson *
851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson *
1051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * Unless required by applicable law or agreed to in writing, software
1151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
1251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * See the License for the specific language governing permissions and
1451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson * limitations under the License.
1551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson */
1651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
1751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilsonpackage org.json;
1851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
197365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.util.ArrayList;
207365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.util.Arrays;
217365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.util.HashMap;
227365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.util.Iterator;
237365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.util.List;
247365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.util.Map;
2551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilsonimport junit.framework.TestCase;
2651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
2751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilsonpublic class ParsingTest extends TestCase {
2851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
2951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testParsingNoObjects() {
3051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        try {
3151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            new JSONTokener("").nextValue();
3251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            fail();
3351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        } catch (JSONException e) {
3451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
3551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
3651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
3751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testParsingLiterals() throws JSONException {
3851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(Boolean.TRUE, "true");
3951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(Boolean.FALSE, "false");
4051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(JSONObject.NULL, "null");
4151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(JSONObject.NULL, "NULL");
4251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(Boolean.FALSE, "False");
4351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(Boolean.TRUE, "truE");
4451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
4551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
4651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testParsingQuotedStrings() throws JSONException {
4751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("abc", "\"abc\"");
4851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("123", "\"123\"");
4951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("foo\nbar", "\"foo\\nbar\"");
5051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("foo bar", "\"foo\\u0020bar\"");
5151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("\"{}[]/\\:,=;#", "\"\\\"{}[]/\\\\:,=;#\"");
5251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
5351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
5451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testParsingSingleQuotedStrings() throws JSONException {
5551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("abc", "'abc'");
5651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("123", "'123'");
5751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("foo\nbar", "'foo\\nbar'");
5851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("foo bar", "'foo\\u0020bar'");
5951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("\"{}[]/\\:,=;#", "'\\\"{}[]/\\\\:,=;#'");
6051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
6151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
6251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testParsingUnquotedStrings() throws JSONException {
6351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("abc", "abc");
6451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("123abc", "123abc");
6551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("123e0x", "123e0x");
6651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("123e", "123e");
6751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("123ee21", "123ee21");
6851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("0xFFFFFFFFFFFFFFFFF", "0xFFFFFFFFFFFFFFFFF");
6951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
7051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
7151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    /**
7251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson     * Unfortunately the original implementation attempts to figure out what
7351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson     * Java number type best suits an input value.
7451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson     */
7551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testParsingNumbersThatAreBestRepresentedAsLongs() throws JSONException {
7651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(9223372036854775807L, "9223372036854775807");
7751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(9223372036854775806L, "9223372036854775806");
7851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(-9223372036854775808L, "-9223372036854775808");
7951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(-9223372036854775807L, "-9223372036854775807");
8051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
8151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
8251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testParsingNumbersThatAreBestRepresentedAsIntegers() throws JSONException {
8351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(0, "0");
8451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(5, "5");
8551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(-2147483648, "-2147483648");
8651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(2147483647, "2147483647");
8751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
8851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
8951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testParsingNegativeZero() throws JSONException {
9051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(0, "-0");
9151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
9251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
9351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testParsingIntegersWithAdditionalPrecisionYieldDoubles() throws JSONException {
9451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(1d, "1.00");
9551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(1d, "1.0");
9651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(0d, "0.0");
9751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(-0d, "-0.0");
9851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
9951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
10051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testParsingNumbersThatAreBestRepresentedAsDoubles() throws JSONException {
10151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(9.223372036854776E18, "9223372036854775808");
10251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(-9.223372036854776E18, "-9223372036854775809");
10351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(1.7976931348623157E308, "1.7976931348623157e308");
10451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(2.2250738585072014E-308, "2.2250738585072014E-308");
10551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(4.9E-324, "4.9E-324");
10651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(4.9E-324, "4.9e-324");
10751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
10851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
10951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testParsingOctalNumbers() throws JSONException {
11051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(5, "05");
11151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(8, "010");
11251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(1046, "02026");
11351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
11451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
11551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testParsingHexNumbers() throws JSONException {
11651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(5, "0x5");
11751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(16, "0x10");
11851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(8230, "0x2026");
11951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(180150010, "0xABCDEFA");
12051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(2077093803, "0x7BCDEFAB");
12151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
12251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
12351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testParsingLargeHexValues() throws JSONException {
12451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(Integer.MAX_VALUE, "0x7FFFFFFF");
12551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        String message = "Hex values are parsed as Strings if their signed " +
12651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson                "value is greater than Integer.MAX_VALUE.";
12751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(message, 0x80000000L, "0x80000000");
12851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
12951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
13051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void test64BitHexValues() throws JSONException {
131f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        assertParsed("Large hex longs shouldn't be yield ints or strings",
13251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson                -1L, "0xFFFFFFFFFFFFFFFF");
13351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
13451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
13551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testParsingWithCommentsAndWhitespace() throws JSONException {
13651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("baz", "  // foo bar \n baz");
13719554ec99d57e820a4c9da3bcde93d77b537d515Jesse Wilson        assertParsed("baz", "  // foo bar \r baz");
13819554ec99d57e820a4c9da3bcde93d77b537d515Jesse Wilson        assertParsed("baz", "  // foo bar \r\n baz");
13919554ec99d57e820a4c9da3bcde93d77b537d515Jesse Wilson        assertParsed("baz", "  # foo bar \n baz");
14019554ec99d57e820a4c9da3bcde93d77b537d515Jesse Wilson        assertParsed("baz", "  # foo bar \r baz");
14119554ec99d57e820a4c9da3bcde93d77b537d515Jesse Wilson        assertParsed("baz", "  # foo bar \r\n baz");
14251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(5, "  /* foo bar \n baz */ 5");
14351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(5, "  /* foo bar \n baz */ 5 // quux");
14451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(5, "  5   ");
14551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(5, "  5  \r\n\t ");
14651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(5, "\r\n\t   5 ");
14751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
14851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
14951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testParsingArrays() throws JSONException {
15051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(array(), "[]");
15151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(array(5, 6, true), "[5,6,true]");
15251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(array(5, 6, array()), "[5,6,[]]");
15351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(array(5, 6, 7), "[5;6;7]");
15451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(array(5, 6, 7), "[5  , 6 \t; \r\n 7\n]");
15551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(array(5, 6, 7, null), "[5,6,7,]");
15651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(array(null, null), "[,]");
15751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(array(5, null, null, null, 5), "[5,,,,5]");
15851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(array(null, 5), "[,5]");
15951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(array(null, null, null), "[,,]");
16051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(array(null, null, null, 5), "[,,,5]");
16151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
16251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
16351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testParsingObjects() throws JSONException {
16451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(object("foo", 5), "{\"foo\": 5}");
16551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(object("foo", 5), "{foo: 5}");
16651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(object("foo", 5, "bar", "baz"), "{\"foo\": 5, \"bar\": \"baz\"}");
16751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(object("foo", 5, "bar", "baz"), "{\"foo\": 5; \"bar\": \"baz\"}");
16851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(object("foo", 5, "bar", "baz"), "{\"foo\"= 5; \"bar\"= \"baz\"}");
16951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(object("foo", 5, "bar", "baz"), "{\"foo\"=> 5; \"bar\"=> \"baz\"}");
17051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(object("foo", object(), "bar", array()), "{\"foo\"=> {}; \"bar\"=> []}");
17151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(object("foo", object("foo", array(5, 6))), "{\"foo\": {\"foo\": [5, 6]}}");
17251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed(object("foo", object("foo", array(5, 6))), "{\"foo\":\n\t{\t \"foo\":[5,\r6]}}");
17351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
17451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
17551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testSyntaxProblemUnterminatedObject() {
17651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("{");
17751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("{\"foo\"");
17851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("{\"foo\":");
17951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("{\"foo\":bar");
18051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("{\"foo\":bar,");
18151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("{\"foo\":bar,\"baz\"");
18251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("{\"foo\":bar,\"baz\":");
18351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("{\"foo\":bar,\"baz\":true");
18451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("{\"foo\":bar,\"baz\":true,");
18551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
18651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
18751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testSyntaxProblemEmptyString() {
18851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("");
18951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
19051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
19151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testSyntaxProblemUnterminatedArray() {
19251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("[");
19351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("[,");
19451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("[,,");
19551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("[true");
19651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("[true,");
19751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("[true,,");
19851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
19951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
20051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    public void testSyntaxProblemMalformedObject() {
20151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("{:}");
20251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("{\"key\":}");
20351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("{:true}");
20451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("{\"key\":true:}");
20551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("{null:true}");
20651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("{true:true}");
20751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParseFail("{0xFF:true}");
20851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
20951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
21051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    private void assertParseFail(String malformedJson) {
21151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        try {
21251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            new JSONTokener(malformedJson).nextValue();
21351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            fail("Successfully parsed: \"" + malformedJson + "\"");
21451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        } catch (JSONException e) {
21551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        } catch (StackOverflowError e) {
21651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            fail("Stack overflowed on input: \"" + malformedJson + "\"");
21751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
21851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
21951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
22051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    private JSONArray array(Object... elements) {
22151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return new JSONArray(Arrays.asList(elements));
22251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
22351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
22451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    private JSONObject object(Object... keyValuePairs) throws JSONException {
22551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        JSONObject result = new JSONObject();
22651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        for (int i = 0; i < keyValuePairs.length; i+=2) {
22751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            result.put((String) keyValuePairs[i], keyValuePairs[i+1]);
22851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
22951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        return result;
23051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
23151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
23251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    private void assertParsed(String message, Object expected, String json) throws JSONException {
23351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        Object actual = new JSONTokener(json).nextValue();
23451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        actual = canonicalize(actual);
23551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        expected = canonicalize(expected);
23651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertEquals("For input \"" + json + "\" " + message, expected, actual);
23751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
23851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
23951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    private void assertParsed(Object expected, String json) throws JSONException {
24051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        assertParsed("", expected, json);
24151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
24251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson
24351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    /**
24451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson     * Since they don't implement equals or hashCode properly, this recursively
24551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson     * replaces JSONObjects with an equivalent HashMap, and JSONArrays with the
24651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson     * equivalent ArrayList.
24751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson     */
24851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    private Object canonicalize(Object input) throws JSONException {
24951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        if (input instanceof JSONArray) {
25051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            JSONArray array = (JSONArray) input;
25151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            List<Object> result = new ArrayList<Object>();
25251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            for (int i = 0; i < array.length(); i++) {
25351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson                result.add(canonicalize(array.opt(i)));
25451a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            }
25551a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            return result;
25651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        } else if (input instanceof JSONObject) {
25751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            JSONObject object = (JSONObject) input;
25851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            Map<String, Object> result = new HashMap<String, Object>();
25951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            for (Iterator<?> i = object.keys(); i.hasNext(); ) {
26051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson                String key = (String) i.next();
26151a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson                result.put(key, canonicalize(object.get(key)));
26251a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            }
26351a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            return result;
2643ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes        } else if (input == null || input.equals(JSONObject.NULL)) {
2653ad786880c88955a0e92610d24bb9bbe51b0e14cElliott Hughes            return JSONObject.NULL;
26651a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        } else {
26751a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson            return input;
26851a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson        }
26951a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson    }
27051a095f0bc7aadfcc7e6b3873b97c050c523d102Jesse Wilson}
271