Home | History | Annotate | Download | only in json
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package org.json;
     18 
     19 import java.util.Arrays;
     20 import java.util.Collection;
     21 import java.util.Collections;
     22 import java.util.List;
     23 import junit.framework.TestCase;
     24 
     25 /**
     26  * This black box test was written without inspecting the non-free org.json sourcecode.
     27  */
     28 public class JSONArrayTest extends TestCase {
     29 
     30     public void testEmptyArray() throws JSONException {
     31         JSONArray array = new JSONArray();
     32         assertEquals(0, array.length());
     33         assertEquals("", array.join(" AND "));
     34         try {
     35             array.get(0);
     36             fail();
     37         } catch (JSONException e) {
     38         }
     39         try {
     40             array.getBoolean(0);
     41             fail();
     42         } catch (JSONException e) {
     43         }
     44 
     45         assertEquals("[]", array.toString());
     46         assertEquals("[]", array.toString(4));
     47 
     48         // out of bounds is co-opted with defaulting
     49         assertTrue(array.isNull(0));
     50         assertNull(array.opt(0));
     51         assertFalse(array.optBoolean(0));
     52         assertTrue(array.optBoolean(0, true));
     53 
     54         // bogus (but documented) behaviour: returns null rather than an empty object!
     55         assertNull(array.toJSONObject(new JSONArray()));
     56     }
     57 
     58     public void testEqualsAndHashCode() throws JSONException {
     59         JSONArray a = new JSONArray();
     60         JSONArray b = new JSONArray();
     61         assertTrue(a.equals(b));
     62         assertEquals("equals() not consistent with hashCode()", a.hashCode(), b.hashCode());
     63 
     64         a.put(true);
     65         a.put(false);
     66         b.put(true);
     67         b.put(false);
     68         assertTrue(a.equals(b));
     69         assertEquals(a.hashCode(), b.hashCode());
     70 
     71         b.put(true);
     72         assertFalse(a.equals(b));
     73         assertTrue(a.hashCode() != b.hashCode());
     74     }
     75 
     76     public void testBooleans() throws JSONException {
     77         JSONArray array = new JSONArray();
     78         array.put(true);
     79         array.put(false);
     80         array.put(2, false);
     81         array.put(3, false);
     82         array.put(2, true);
     83         assertEquals("[true,false,true,false]", array.toString());
     84         assertEquals(4, array.length());
     85         assertEquals(Boolean.TRUE, array.get(0));
     86         assertEquals(Boolean.FALSE, array.get(1));
     87         assertEquals(Boolean.TRUE, array.get(2));
     88         assertEquals(Boolean.FALSE, array.get(3));
     89         assertFalse(array.isNull(0));
     90         assertFalse(array.isNull(1));
     91         assertFalse(array.isNull(2));
     92         assertFalse(array.isNull(3));
     93         assertEquals(true, array.optBoolean(0));
     94         assertEquals(false, array.optBoolean(1, true));
     95         assertEquals(true, array.optBoolean(2, false));
     96         assertEquals(false, array.optBoolean(3));
     97         assertEquals("true", array.getString(0));
     98         assertEquals("false", array.getString(1));
     99         assertEquals("true", array.optString(2));
    100         assertEquals("false", array.optString(3, "x"));
    101         assertEquals("[\n     true,\n     false,\n     true,\n     false\n]", array.toString(5));
    102 
    103         JSONArray other = new JSONArray();
    104         other.put(true);
    105         other.put(false);
    106         other.put(true);
    107         other.put(false);
    108         assertTrue(array.equals(other));
    109         other.put(true);
    110         assertFalse(array.equals(other));
    111 
    112         other = new JSONArray();
    113         other.put("true");
    114         other.put("false");
    115         other.put("truE");
    116         other.put("FALSE");
    117         assertFalse(array.equals(other));
    118         assertFalse(other.equals(array));
    119         assertEquals(true, other.getBoolean(0));
    120         assertEquals(false, other.optBoolean(1, true));
    121         assertEquals(true, other.optBoolean(2));
    122         assertEquals(false, other.getBoolean(3));
    123     }
    124 
    125     // http://code.google.com/p/android/issues/detail?id=16411
    126     public void testCoerceStringToBoolean() throws JSONException {
    127         JSONArray array = new JSONArray();
    128         array.put("maybe");
    129         try {
    130             array.getBoolean(0);
    131             fail();
    132         } catch (JSONException expected) {
    133         }
    134         assertEquals(false, array.optBoolean(0));
    135         assertEquals(true, array.optBoolean(0, true));
    136     }
    137 
    138     public void testNulls() throws JSONException {
    139         JSONArray array = new JSONArray();
    140         array.put(3, (Collection) null);
    141         array.put(0, JSONObject.NULL);
    142         assertEquals(4, array.length());
    143         assertEquals("[null,null,null,null]", array.toString());
    144 
    145         // there's 2 ways to represent null; each behaves differently!
    146         assertEquals(JSONObject.NULL, array.get(0));
    147         try {
    148             array.get(1);
    149             fail();
    150         } catch (JSONException e) {
    151         }
    152         try {
    153             array.get(2);
    154             fail();
    155         } catch (JSONException e) {
    156         }
    157         try {
    158             array.get(3);
    159             fail();
    160         } catch (JSONException e) {
    161         }
    162         assertEquals(JSONObject.NULL, array.opt(0));
    163         assertEquals(null, array.opt(1));
    164         assertEquals(null, array.opt(2));
    165         assertEquals(null, array.opt(3));
    166         assertTrue(array.isNull(0));
    167         assertTrue(array.isNull(1));
    168         assertTrue(array.isNull(2));
    169         assertTrue(array.isNull(3));
    170         assertEquals("null", array.optString(0));
    171         assertEquals("", array.optString(1));
    172         assertEquals("", array.optString(2));
    173         assertEquals("", array.optString(3));
    174     }
    175 
    176     /**
    177      * Our behaviour is questioned by this bug:
    178      * http://code.google.com/p/android/issues/detail?id=7257
    179      */
    180     public void testParseNullYieldsJSONObjectNull() throws JSONException {
    181         JSONArray array = new JSONArray("[\"null\",null]");
    182         array.put((Collection) null);
    183         assertEquals("null", array.get(0));
    184         assertEquals(JSONObject.NULL, array.get(1));
    185         try {
    186             array.get(2);
    187             fail();
    188         } catch (JSONException e) {
    189         }
    190         assertEquals("null", array.getString(0));
    191         assertEquals("null", array.getString(1));
    192         try {
    193             array.getString(2);
    194             fail();
    195         } catch (JSONException e) {
    196         }
    197     }
    198 
    199     public void testNumbers() throws JSONException {
    200         JSONArray array = new JSONArray();
    201         array.put(Double.MIN_VALUE);
    202         array.put(9223372036854775806L);
    203         array.put(Double.MAX_VALUE);
    204         array.put(-0d);
    205         assertEquals(4, array.length());
    206 
    207         // toString() and getString(int) return different values for -0d
    208         assertEquals("[4.9E-324,9223372036854775806,1.7976931348623157E308,-0]", array.toString());
    209 
    210         assertEquals(Double.MIN_VALUE, array.get(0));
    211         assertEquals(9223372036854775806L, array.get(1));
    212         assertEquals(Double.MAX_VALUE, array.get(2));
    213         assertEquals(-0d, array.get(3));
    214         assertEquals(Double.MIN_VALUE, array.getDouble(0));
    215         assertEquals(9.223372036854776E18, array.getDouble(1));
    216         assertEquals(Double.MAX_VALUE, array.getDouble(2));
    217         assertEquals(-0d, array.getDouble(3));
    218         assertEquals(0, array.getLong(0));
    219         assertEquals(9223372036854775806L, array.getLong(1));
    220         assertEquals(Long.MAX_VALUE, array.getLong(2));
    221         assertEquals(0, array.getLong(3));
    222         assertEquals(0, array.getInt(0));
    223         assertEquals(-2, array.getInt(1));
    224         assertEquals(Integer.MAX_VALUE, array.getInt(2));
    225         assertEquals(0, array.getInt(3));
    226         assertEquals(Double.MIN_VALUE, array.opt(0));
    227         assertEquals(Double.MIN_VALUE, array.optDouble(0));
    228         assertEquals(0, array.optLong(0, 1L));
    229         assertEquals(0, array.optInt(0, 1));
    230         assertEquals("4.9E-324", array.getString(0));
    231         assertEquals("9223372036854775806", array.getString(1));
    232         assertEquals("1.7976931348623157E308", array.getString(2));
    233         assertEquals("-0.0", array.getString(3));
    234 
    235         JSONArray other = new JSONArray();
    236         other.put(Double.MIN_VALUE);
    237         other.put(9223372036854775806L);
    238         other.put(Double.MAX_VALUE);
    239         other.put(-0d);
    240         assertTrue(array.equals(other));
    241         other.put(0, 0L);
    242         assertFalse(array.equals(other));
    243     }
    244 
    245     public void testStrings() throws JSONException {
    246         JSONArray array = new JSONArray();
    247         array.put("true");
    248         array.put("5.5");
    249         array.put("9223372036854775806");
    250         array.put("null");
    251         array.put("5\"8' tall");
    252         assertEquals(5, array.length());
    253         assertEquals("[\"true\",\"5.5\",\"9223372036854775806\",\"null\",\"5\\\"8' tall\"]",
    254                 array.toString());
    255 
    256         // although the documentation doesn't mention it, join() escapes text and wraps
    257         // strings in quotes
    258         assertEquals("\"true\" \"5.5\" \"9223372036854775806\" \"null\" \"5\\\"8' tall\"",
    259                 array.join(" "));
    260 
    261         assertEquals("true", array.get(0));
    262         assertEquals("null", array.getString(3));
    263         assertEquals("5\"8' tall", array.getString(4));
    264         assertEquals("true", array.opt(0));
    265         assertEquals("5.5", array.optString(1));
    266         assertEquals("9223372036854775806", array.optString(2, null));
    267         assertEquals("null", array.optString(3, "-1"));
    268         assertFalse(array.isNull(0));
    269         assertFalse(array.isNull(3));
    270 
    271         assertEquals(true, array.getBoolean(0));
    272         assertEquals(true, array.optBoolean(0));
    273         assertEquals(true, array.optBoolean(0, false));
    274         assertEquals(0, array.optInt(0));
    275         assertEquals(-2, array.optInt(0, -2));
    276 
    277         assertEquals(5.5d, array.getDouble(1));
    278         assertEquals(5L, array.getLong(1));
    279         assertEquals(5, array.getInt(1));
    280         assertEquals(5, array.optInt(1, 3));
    281 
    282         // The last digit of the string is a 6 but getLong returns a 7. It's probably parsing as a
    283         // double and then converting that to a long. This is consistent with JavaScript.
    284         assertEquals(9223372036854775807L, array.getLong(2));
    285         assertEquals(9.223372036854776E18, array.getDouble(2));
    286         assertEquals(Integer.MAX_VALUE, array.getInt(2));
    287 
    288         assertFalse(array.isNull(3));
    289         try {
    290             array.getDouble(3);
    291             fail();
    292         } catch (JSONException e) {
    293         }
    294         assertEquals(Double.NaN, array.optDouble(3));
    295         assertEquals(-1.0d, array.optDouble(3, -1.0d));
    296     }
    297 
    298     public void testJoin() throws JSONException {
    299         JSONArray array = new JSONArray();
    300         array.put((Collection) null);
    301         assertEquals("null", array.join(" & "));
    302         array.put("\"");
    303         assertEquals("null & \"\\\"\"", array.join(" & "));
    304         array.put(5);
    305         assertEquals("null & \"\\\"\" & 5", array.join(" & "));
    306         array.put(true);
    307         assertEquals("null & \"\\\"\" & 5 & true", array.join(" & "));
    308         array.put(new JSONArray(Arrays.asList(true, false)));
    309         assertEquals("null & \"\\\"\" & 5 & true & [true,false]", array.join(" & "));
    310         array.put(new JSONObject(Collections.singletonMap("x", 6)));
    311         assertEquals("null & \"\\\"\" & 5 & true & [true,false] & {\"x\":6}", array.join(" & "));
    312     }
    313 
    314     public void testJoinWithNull() throws JSONException {
    315         JSONArray array = new JSONArray(Arrays.asList(5, 6));
    316         assertEquals("5null6", array.join(null));
    317     }
    318 
    319     public void testJoinWithSpecialCharacters() throws JSONException {
    320         JSONArray array = new JSONArray(Arrays.asList(5, 6));
    321         assertEquals("5\"6", array.join("\""));
    322     }
    323 
    324     public void testToJSONObject() throws JSONException {
    325         JSONArray keys = new JSONArray();
    326         keys.put("a");
    327         keys.put("b");
    328 
    329         JSONArray values = new JSONArray();
    330         values.put(5.5d);
    331         values.put(false);
    332 
    333         JSONObject object = values.toJSONObject(keys);
    334         assertEquals(5.5d, object.get("a"));
    335         assertEquals(false, object.get("b"));
    336 
    337         keys.put(0, "a");
    338         values.put(0, 11.0d);
    339         assertEquals(5.5d, object.get("a"));
    340     }
    341 
    342     public void testToJSONObjectWithNulls() throws JSONException {
    343         JSONArray keys = new JSONArray();
    344         keys.put("a");
    345         keys.put("b");
    346 
    347         JSONArray values = new JSONArray();
    348         values.put(5.5d);
    349         values.put((Collection) null);
    350 
    351         // null values are stripped!
    352         JSONObject object = values.toJSONObject(keys);
    353         assertEquals(1, object.length());
    354         assertFalse(object.has("b"));
    355         assertEquals("{\"a\":5.5}", object.toString());
    356     }
    357 
    358     public void testToJSONObjectMoreNamesThanValues() throws JSONException {
    359         JSONArray keys = new JSONArray();
    360         keys.put("a");
    361         keys.put("b");
    362         JSONArray values = new JSONArray();
    363         values.put(5.5d);
    364         JSONObject object = values.toJSONObject(keys);
    365         assertEquals(1, object.length());
    366         assertEquals(5.5d, object.get("a"));
    367     }
    368 
    369     public void testToJSONObjectMoreValuesThanNames() throws JSONException {
    370         JSONArray keys = new JSONArray();
    371         keys.put("a");
    372         JSONArray values = new JSONArray();
    373         values.put(5.5d);
    374         values.put(11.0d);
    375         JSONObject object = values.toJSONObject(keys);
    376         assertEquals(1, object.length());
    377         assertEquals(5.5d, object.get("a"));
    378     }
    379 
    380     public void testToJSONObjectNullKey() throws JSONException {
    381         JSONArray keys = new JSONArray();
    382         keys.put(JSONObject.NULL);
    383         JSONArray values = new JSONArray();
    384         values.put(5.5d);
    385         JSONObject object = values.toJSONObject(keys);
    386         assertEquals(1, object.length());
    387         assertEquals(5.5d, object.get("null"));
    388     }
    389 
    390     public void testPutUnsupportedNumbers() throws JSONException {
    391         JSONArray array = new JSONArray();
    392 
    393         try {
    394             array.put(Double.NaN);
    395             fail();
    396         } catch (JSONException e) {
    397         }
    398         try {
    399             array.put(0, Double.NEGATIVE_INFINITY);
    400             fail();
    401         } catch (JSONException e) {
    402         }
    403         try {
    404             array.put(0, Double.POSITIVE_INFINITY);
    405             fail();
    406         } catch (JSONException e) {
    407         }
    408     }
    409 
    410     public void testPutUnsupportedNumbersAsObject() throws JSONException {
    411         JSONArray array = new JSONArray();
    412         array.put(Double.valueOf(Double.NaN));
    413         array.put(Double.valueOf(Double.NEGATIVE_INFINITY));
    414         array.put(Double.valueOf(Double.POSITIVE_INFINITY));
    415         assertEquals(null, array.toString());
    416     }
    417 
    418     /**
    419      * Although JSONArray is usually defensive about which numbers it accepts,
    420      * it doesn't check inputs in its constructor.
    421      */
    422     public void testCreateWithUnsupportedNumbers() throws JSONException {
    423         JSONArray array = new JSONArray(Arrays.asList(5.5, Double.NaN));
    424         assertEquals(2, array.length());
    425         assertEquals(5.5, array.getDouble(0));
    426         assertEquals(Double.NaN, array.getDouble(1));
    427     }
    428 
    429     public void testToStringWithUnsupportedNumbers() throws JSONException {
    430         // when the array contains an unsupported number, toString returns null!
    431         JSONArray array = new JSONArray(Arrays.asList(5.5, Double.NaN));
    432         assertNull(array.toString());
    433     }
    434 
    435     public void testListConstructorCopiesContents() throws JSONException {
    436         List<Object> contents = Arrays.<Object>asList(5);
    437         JSONArray array = new JSONArray(contents);
    438         contents.set(0, 10);
    439         assertEquals(5, array.get(0));
    440     }
    441 
    442     public void testTokenerConstructor() throws JSONException {
    443         JSONArray object = new JSONArray(new JSONTokener("[false]"));
    444         assertEquals(1, object.length());
    445         assertEquals(false, object.get(0));
    446     }
    447 
    448     public void testTokenerConstructorWrongType() throws JSONException {
    449         try {
    450             new JSONArray(new JSONTokener("{\"foo\": false}"));
    451             fail();
    452         } catch (JSONException e) {
    453         }
    454     }
    455 
    456     public void testTokenerConstructorNull() throws JSONException {
    457         try {
    458             new JSONArray((JSONTokener) null);
    459             fail();
    460         } catch (NullPointerException e) {
    461         }
    462     }
    463 
    464     public void testTokenerConstructorParseFail() {
    465         try {
    466             new JSONArray(new JSONTokener("["));
    467             fail();
    468         } catch (JSONException e) {
    469         } catch (StackOverflowError e) {
    470             fail("Stack overflowed on input: \"[\"");
    471         }
    472     }
    473 
    474     public void testStringConstructor() throws JSONException {
    475         JSONArray object = new JSONArray("[false]");
    476         assertEquals(1, object.length());
    477         assertEquals(false, object.get(0));
    478     }
    479 
    480     public void testStringConstructorWrongType() throws JSONException {
    481         try {
    482             new JSONArray("{\"foo\": false}");
    483             fail();
    484         } catch (JSONException e) {
    485         }
    486     }
    487 
    488     public void testStringConstructorNull() throws JSONException {
    489         try {
    490             new JSONArray((String) null);
    491             fail();
    492         } catch (NullPointerException e) {
    493         }
    494     }
    495 
    496     public void testStringConstructorParseFail() {
    497         try {
    498             new JSONArray("[");
    499             fail();
    500         } catch (JSONException e) {
    501         } catch (StackOverflowError e) {
    502             fail("Stack overflowed on input: \"[\"");
    503         }
    504     }
    505 
    506     public void testCreate() throws JSONException {
    507         JSONArray array = new JSONArray(Arrays.asList(5.5, true));
    508         assertEquals(2, array.length());
    509         assertEquals(5.5, array.getDouble(0));
    510         assertEquals(true, array.get(1));
    511         assertEquals("[5.5,true]", array.toString());
    512     }
    513 
    514     public void testAccessOutOfBounds() throws JSONException {
    515         JSONArray array = new JSONArray();
    516         array.put("foo");
    517         assertEquals(null, array.opt(3));
    518         assertEquals(null, array.opt(-3));
    519         assertEquals("", array.optString(3));
    520         assertEquals("", array.optString(-3));
    521         try {
    522             array.get(3);
    523             fail();
    524         } catch (JSONException e) {
    525         }
    526         try {
    527             array.get(-3);
    528             fail();
    529         } catch (JSONException e) {
    530         }
    531         try {
    532             array.getString(3);
    533             fail();
    534         } catch (JSONException e) {
    535         }
    536         try {
    537             array.getString(-3);
    538             fail();
    539         } catch (JSONException e) {
    540         }
    541     }
    542 
    543     public void test_remove() throws Exception {
    544         JSONArray a = new JSONArray();
    545         assertEquals(null, a.remove(-1));
    546         assertEquals(null, a.remove(0));
    547 
    548         a.put("hello");
    549         assertEquals(null, a.remove(-1));
    550         assertEquals(null, a.remove(1));
    551         assertEquals("hello", a.remove(0));
    552         assertEquals(null, a.remove(0));
    553     }
    554 }
    555