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 libcore.org.json;
     18 
     19 import java.math.BigDecimal;
     20 import java.math.BigInteger;
     21 import java.util.ArrayList;
     22 import java.util.Arrays;
     23 import java.util.Collection;
     24 import java.util.Collections;
     25 import java.util.HashMap;
     26 import java.util.HashSet;
     27 import java.util.Iterator;
     28 import java.util.Map;
     29 import java.util.NoSuchElementException;
     30 import java.util.Objects;
     31 import java.util.Set;
     32 import java.util.TreeMap;
     33 import junit.framework.TestCase;
     34 
     35 import org.json.JSONArray;
     36 import org.json.JSONException;
     37 import org.json.JSONObject;
     38 import org.json.JSONTokener;
     39 
     40 /**
     41  * This black box test was written without inspecting the non-free org.json sourcecode.
     42  */
     43 public class JSONObjectTest extends TestCase {
     44 
     45     public void testEmptyObject() throws JSONException {
     46         JSONObject object = new JSONObject();
     47         assertEquals(0, object.length());
     48 
     49         // bogus (but documented) behaviour: returns null rather than the empty object!
     50         assertNull(object.names());
     51 
     52         // returns null rather than an empty array!
     53         assertNull(object.toJSONArray(new JSONArray()));
     54         assertEquals("{}", object.toString());
     55         assertEquals("{}", object.toString(5));
     56         try {
     57             object.get("foo");
     58             fail();
     59         } catch (JSONException e) {
     60         }
     61         try {
     62             object.getBoolean("foo");
     63             fail();
     64         } catch (JSONException e) {
     65         }
     66         try {
     67             object.getDouble("foo");
     68             fail();
     69         } catch (JSONException e) {
     70         }
     71         try {
     72             object.getInt("foo");
     73             fail();
     74         } catch (JSONException e) {
     75         }
     76         try {
     77             object.getJSONArray("foo");
     78             fail();
     79         } catch (JSONException e) {
     80         }
     81         try {
     82             object.getJSONObject("foo");
     83             fail();
     84         } catch (JSONException e) {
     85         }
     86         try {
     87             object.getLong("foo");
     88             fail();
     89         } catch (JSONException e) {
     90         }
     91         try {
     92             object.getString("foo");
     93             fail();
     94         } catch (JSONException e) {
     95         }
     96         assertFalse(object.has("foo"));
     97         assertTrue(object.isNull("foo")); // isNull also means "is not present"
     98         assertNull(object.opt("foo"));
     99         assertEquals(false, object.optBoolean("foo"));
    100         assertEquals(true, object.optBoolean("foo", true));
    101         assertEquals(Double.NaN, object.optDouble("foo"));
    102         assertEquals(5.0, object.optDouble("foo", 5.0));
    103         assertEquals(0, object.optInt("foo"));
    104         assertEquals(5, object.optInt("foo", 5));
    105         assertEquals(null, object.optJSONArray("foo"));
    106         assertEquals(null, object.optJSONObject("foo"));
    107         assertEquals(0, object.optLong("foo"));
    108         assertEquals(Long.MAX_VALUE-1, object.optLong("foo", Long.MAX_VALUE-1));
    109         assertEquals("", object.optString("foo")); // empty string is default!
    110         assertEquals("bar", object.optString("foo", "bar"));
    111         assertNull(object.remove("foo"));
    112     }
    113 
    114     public void testEqualsAndHashCode() throws JSONException {
    115         JSONObject a = new JSONObject();
    116         JSONObject b = new JSONObject();
    117 
    118         // JSON object doesn't override either equals or hashCode (!)
    119         assertFalse(a.equals(b));
    120         assertEquals(a.hashCode(), System.identityHashCode(a));
    121     }
    122 
    123     public void testGet() throws JSONException {
    124         JSONObject object = new JSONObject();
    125         Object value = new Object();
    126         object.put("foo", value);
    127         object.put("bar", new Object());
    128         object.put("baz", new Object());
    129         assertSame(value, object.get("foo"));
    130         try {
    131             object.get("FOO");
    132             fail();
    133         } catch (JSONException e) {
    134         }
    135         try {
    136             object.put(null, value);
    137             fail();
    138         } catch (JSONException e) {
    139         }
    140         try {
    141             object.get(null);
    142             fail();
    143         } catch (JSONException e) {
    144         }
    145     }
    146 
    147     public void testPut() throws JSONException {
    148         JSONObject object = new JSONObject();
    149         assertSame(object, object.put("foo", true));
    150         object.put("foo", false);
    151         assertEquals(false, object.get("foo"));
    152 
    153         object.put("foo", 5.0d);
    154         assertEquals(5.0d, object.get("foo"));
    155         object.put("foo", 0);
    156         assertEquals(0, object.get("foo"));
    157         object.put("bar", Long.MAX_VALUE - 1);
    158         assertEquals(Long.MAX_VALUE - 1, object.get("bar"));
    159         object.put("baz", "x");
    160         assertEquals("x", object.get("baz"));
    161         object.put("bar", JSONObject.NULL);
    162         assertSame(JSONObject.NULL, object.get("bar"));
    163     }
    164 
    165     public void testPutNullRemoves() throws JSONException {
    166         JSONObject object = new JSONObject();
    167         object.put("foo", "bar");
    168         object.put("foo", (Collection) null);
    169         assertEquals(0, object.length());
    170         assertFalse(object.has("foo"));
    171         try {
    172             object.get("foo");
    173             fail();
    174         } catch (JSONException e) {
    175         }
    176     }
    177 
    178     public void testPutOpt() throws JSONException {
    179         JSONObject object = new JSONObject();
    180         object.put("foo", "bar");
    181         object.putOpt("foo", null);
    182         assertEquals("bar", object.get("foo"));
    183         object.putOpt(null, null);
    184         assertEquals(1, object.length());
    185         object.putOpt(null, "bar");
    186         assertEquals(1, object.length());
    187     }
    188 
    189     public void testPutOptUnsupportedNumbers() throws JSONException {
    190         JSONObject object = new JSONObject();
    191         try {
    192             object.putOpt("foo", Double.NaN);
    193             fail();
    194         } catch (JSONException e) {
    195         }
    196         try {
    197             object.putOpt("foo", Double.NEGATIVE_INFINITY);
    198             fail();
    199         } catch (JSONException e) {
    200         }
    201         try {
    202             object.putOpt("foo", Double.POSITIVE_INFINITY);
    203             fail();
    204         } catch (JSONException e) {
    205         }
    206     }
    207 
    208     public void testRemove() throws JSONException {
    209         JSONObject object = new JSONObject();
    210         object.put("foo", "bar");
    211         assertEquals(null, object.remove(null));
    212         assertEquals(null, object.remove(""));
    213         assertEquals(null, object.remove("bar"));
    214         assertEquals("bar", object.remove("foo"));
    215         assertEquals(null, object.remove("foo"));
    216     }
    217 
    218     public void testBooleans() throws JSONException {
    219         JSONObject object = new JSONObject();
    220         object.put("foo", true);
    221         object.put("bar", false);
    222         object.put("baz", "true");
    223         object.put("quux", "false");
    224         assertEquals(4, object.length());
    225         assertEquals(true, object.getBoolean("foo"));
    226         assertEquals(false, object.getBoolean("bar"));
    227         assertEquals(true, object.getBoolean("baz"));
    228         assertEquals(false, object.getBoolean("quux"));
    229         assertFalse(object.isNull("foo"));
    230         assertFalse(object.isNull("quux"));
    231         assertTrue(object.has("foo"));
    232         assertTrue(object.has("quux"));
    233         assertFalse(object.has("missing"));
    234         assertEquals(true, object.optBoolean("foo"));
    235         assertEquals(false, object.optBoolean("bar"));
    236         assertEquals(true, object.optBoolean("baz"));
    237         assertEquals(false, object.optBoolean("quux"));
    238         assertEquals(false, object.optBoolean("missing"));
    239         assertEquals(true, object.optBoolean("foo", true));
    240         assertEquals(false, object.optBoolean("bar", true));
    241         assertEquals(true, object.optBoolean("baz", true));
    242         assertEquals(false, object.optBoolean("quux", true));
    243         assertEquals(true, object.optBoolean("missing", true));
    244 
    245         object.put("foo", "truE");
    246         object.put("bar", "FALSE");
    247         assertEquals(true, object.getBoolean("foo"));
    248         assertEquals(false, object.getBoolean("bar"));
    249         assertEquals(true, object.optBoolean("foo"));
    250         assertEquals(false, object.optBoolean("bar"));
    251         assertEquals(true, object.optBoolean("foo", false));
    252         assertEquals(false, object.optBoolean("bar", false));
    253     }
    254 
    255     // http://code.google.com/p/android/issues/detail?id=16411
    256     public void testCoerceStringToBoolean() throws JSONException {
    257         JSONObject object = new JSONObject();
    258         object.put("foo", "maybe");
    259         try {
    260             object.getBoolean("foo");
    261             fail();
    262         } catch (JSONException expected) {
    263         }
    264         assertEquals(false, object.optBoolean("foo"));
    265         assertEquals(true, object.optBoolean("foo", true));
    266     }
    267 
    268     public void testNumbers() throws JSONException {
    269         JSONObject object = new JSONObject();
    270         object.put("foo", Double.MIN_VALUE);
    271         object.put("bar", 9223372036854775806L);
    272         object.put("baz", Double.MAX_VALUE);
    273         object.put("quux", -0d);
    274         assertEquals(4, object.length());
    275 
    276         String toString = object.toString();
    277         assertTrue(toString, toString.contains("\"foo\":4.9E-324"));
    278         assertTrue(toString, toString.contains("\"bar\":9223372036854775806"));
    279         assertTrue(toString, toString.contains("\"baz\":1.7976931348623157E308"));
    280 
    281         // toString() and getString() return different values for -0d!
    282         assertTrue(toString, toString.contains("\"quux\":-0}") // no trailing decimal point
    283                 || toString.contains("\"quux\":-0,"));
    284 
    285         assertEquals(Double.MIN_VALUE, object.get("foo"));
    286         assertEquals(9223372036854775806L, object.get("bar"));
    287         assertEquals(Double.MAX_VALUE, object.get("baz"));
    288         assertEquals(-0d, object.get("quux"));
    289         assertEquals(Double.MIN_VALUE, object.getDouble("foo"));
    290         assertEquals(9.223372036854776E18, object.getDouble("bar"));
    291         assertEquals(Double.MAX_VALUE, object.getDouble("baz"));
    292         assertEquals(-0d, object.getDouble("quux"));
    293         assertEquals(0, object.getLong("foo"));
    294         assertEquals(9223372036854775806L, object.getLong("bar"));
    295         assertEquals(Long.MAX_VALUE, object.getLong("baz"));
    296         assertEquals(0, object.getLong("quux"));
    297         assertEquals(0, object.getInt("foo"));
    298         assertEquals(-2, object.getInt("bar"));
    299         assertEquals(Integer.MAX_VALUE, object.getInt("baz"));
    300         assertEquals(0, object.getInt("quux"));
    301         assertEquals(Double.MIN_VALUE, object.opt("foo"));
    302         assertEquals(9223372036854775806L, object.optLong("bar"));
    303         assertEquals(Double.MAX_VALUE, object.optDouble("baz"));
    304         assertEquals(0, object.optInt("quux"));
    305         assertEquals(Double.MIN_VALUE, object.opt("foo"));
    306         assertEquals(9223372036854775806L, object.optLong("bar"));
    307         assertEquals(Double.MAX_VALUE, object.optDouble("baz"));
    308         assertEquals(0, object.optInt("quux"));
    309         assertEquals(Double.MIN_VALUE, object.optDouble("foo", 5.0d));
    310         assertEquals(9223372036854775806L, object.optLong("bar", 1L));
    311         assertEquals(Long.MAX_VALUE, object.optLong("baz", 1L));
    312         assertEquals(0, object.optInt("quux", -1));
    313         assertEquals("4.9E-324", object.getString("foo"));
    314         assertEquals("9223372036854775806", object.getString("bar"));
    315         assertEquals("1.7976931348623157E308", object.getString("baz"));
    316         assertEquals("-0.0", object.getString("quux"));
    317     }
    318 
    319     public void testFloats() throws JSONException {
    320         JSONObject object = new JSONObject();
    321         try {
    322             object.put("foo", (Float) Float.NaN);
    323             fail();
    324         } catch (JSONException e) {
    325         }
    326         try {
    327             object.put("foo", (Float) Float.NEGATIVE_INFINITY);
    328             fail();
    329         } catch (JSONException e) {
    330         }
    331         try {
    332             object.put("foo", (Float) Float.POSITIVE_INFINITY);
    333             fail();
    334         } catch (JSONException e) {
    335         }
    336     }
    337 
    338     public void testOtherNumbers() throws JSONException {
    339         Number nan = new Number() {
    340             public int intValue() {
    341                 throw new UnsupportedOperationException();
    342             }
    343             public long longValue() {
    344                 throw new UnsupportedOperationException();
    345             }
    346             public float floatValue() {
    347                 throw new UnsupportedOperationException();
    348             }
    349             public double doubleValue() {
    350                 return Double.NaN;
    351             }
    352             @Override public String toString() {
    353                 return "x";
    354             }
    355         };
    356 
    357         JSONObject object = new JSONObject();
    358         try {
    359             object.put("foo", nan);
    360             fail("Object.put() accepted a NaN (via a custom Number class)");
    361         } catch (JSONException e) {
    362         }
    363     }
    364 
    365     public void testForeignObjects() throws JSONException {
    366         Object foreign = new Object() {
    367             @Override public String toString() {
    368                 return "x";
    369             }
    370         };
    371 
    372         // foreign object types are accepted and treated as Strings!
    373         JSONObject object = new JSONObject();
    374         object.put("foo", foreign);
    375         assertEquals("{\"foo\":\"x\"}", object.toString());
    376     }
    377 
    378     public void testNullKeys() {
    379         try {
    380             new JSONObject().put(null, false);
    381             fail();
    382         } catch (JSONException e) {
    383         }
    384         try {
    385             new JSONObject().put(null, 0.0d);
    386             fail();
    387         } catch (JSONException e) {
    388         }
    389         try {
    390             new JSONObject().put(null, 5);
    391             fail();
    392         } catch (JSONException e) {
    393         }
    394         try {
    395             new JSONObject().put(null, 5L);
    396             fail();
    397         } catch (JSONException e) {
    398         }
    399         try {
    400             new JSONObject().put(null, "foo");
    401             fail();
    402         } catch (JSONException e) {
    403         }
    404     }
    405 
    406     public void testStrings() throws JSONException {
    407         JSONObject object = new JSONObject();
    408         object.put("foo", "true");
    409         object.put("bar", "5.5");
    410         object.put("baz", "9223372036854775806");
    411         object.put("quux", "null");
    412         object.put("height", "5\"8' tall");
    413 
    414         assertTrue(object.toString().contains("\"foo\":\"true\""));
    415         assertTrue(object.toString().contains("\"bar\":\"5.5\""));
    416         assertTrue(object.toString().contains("\"baz\":\"9223372036854775806\""));
    417         assertTrue(object.toString().contains("\"quux\":\"null\""));
    418         assertTrue(object.toString().contains("\"height\":\"5\\\"8' tall\""));
    419 
    420         assertEquals("true", object.get("foo"));
    421         assertEquals("null", object.getString("quux"));
    422         assertEquals("5\"8' tall", object.getString("height"));
    423         assertEquals("true", object.opt("foo"));
    424         assertEquals("5.5", object.optString("bar"));
    425         assertEquals("true", object.optString("foo", "x"));
    426         assertFalse(object.isNull("foo"));
    427 
    428         assertEquals(true, object.getBoolean("foo"));
    429         assertEquals(true, object.optBoolean("foo"));
    430         assertEquals(true, object.optBoolean("foo", false));
    431         assertEquals(0, object.optInt("foo"));
    432         assertEquals(-2, object.optInt("foo", -2));
    433 
    434         assertEquals(5.5d, object.getDouble("bar"));
    435         assertEquals(5L, object.getLong("bar"));
    436         assertEquals(5, object.getInt("bar"));
    437         assertEquals(5, object.optInt("bar", 3));
    438 
    439         // The last digit of the string is a 6 but getLong returns a 7. It's probably parsing as a
    440         // double and then converting that to a long. This is consistent with JavaScript.
    441         assertEquals(9223372036854775807L, object.getLong("baz"));
    442         assertEquals(9.223372036854776E18, object.getDouble("baz"));
    443         assertEquals(Integer.MAX_VALUE, object.getInt("baz"));
    444 
    445         assertFalse(object.isNull("quux"));
    446         try {
    447             object.getDouble("quux");
    448             fail();
    449         } catch (JSONException e) {
    450         }
    451         assertEquals(Double.NaN, object.optDouble("quux"));
    452         assertEquals(-1.0d, object.optDouble("quux", -1.0d));
    453 
    454         object.put("foo", "TRUE");
    455         assertEquals(true, object.getBoolean("foo"));
    456     }
    457 
    458     public void testJSONObjects() throws JSONException {
    459         JSONObject object = new JSONObject();
    460 
    461         JSONArray a = new JSONArray();
    462         JSONObject b = new JSONObject();
    463         object.put("foo", a);
    464         object.put("bar", b);
    465 
    466         assertSame(a, object.getJSONArray("foo"));
    467         assertSame(b, object.getJSONObject("bar"));
    468         try {
    469             object.getJSONObject("foo");
    470             fail();
    471         } catch (JSONException e) {
    472         }
    473         try {
    474             object.getJSONArray("bar");
    475             fail();
    476         } catch (JSONException e) {
    477         }
    478         assertEquals(a, object.optJSONArray("foo"));
    479         assertEquals(b, object.optJSONObject("bar"));
    480         assertEquals(null, object.optJSONArray("bar"));
    481         assertEquals(null, object.optJSONObject("foo"));
    482     }
    483 
    484     public void testNullCoercionToString() throws JSONException {
    485         JSONObject object = new JSONObject();
    486         object.put("foo", JSONObject.NULL);
    487         assertEquals("null", object.getString("foo"));
    488     }
    489 
    490     public void testArrayCoercion() throws JSONException {
    491         JSONObject object = new JSONObject();
    492         object.put("foo", "[true]");
    493         try {
    494             object.getJSONArray("foo");
    495             fail();
    496         } catch (JSONException e) {
    497         }
    498     }
    499 
    500     public void testObjectCoercion() throws JSONException {
    501         JSONObject object = new JSONObject();
    502         object.put("foo", "{}");
    503         try {
    504             object.getJSONObject("foo");
    505             fail();
    506         } catch (JSONException e) {
    507         }
    508     }
    509 
    510     public void testAccumulateValueChecking() throws JSONException {
    511         JSONObject object = new JSONObject();
    512         try {
    513             object.accumulate("foo", Double.NaN);
    514             fail();
    515         } catch (JSONException e) {
    516         }
    517         object.accumulate("foo", 1);
    518         try {
    519             object.accumulate("foo", Double.NaN);
    520             fail();
    521         } catch (JSONException e) {
    522         }
    523         object.accumulate("foo", 2);
    524         try {
    525             object.accumulate("foo", Double.NaN);
    526             fail();
    527         } catch (JSONException e) {
    528         }
    529     }
    530 
    531     public void testToJSONArray() throws JSONException {
    532         JSONObject object = new JSONObject();
    533         Object value = new Object();
    534         object.put("foo", true);
    535         object.put("bar", 5.0d);
    536         object.put("baz", -0.0d);
    537         object.put("quux", value);
    538 
    539         JSONArray names = new JSONArray();
    540         names.put("baz");
    541         names.put("quux");
    542         names.put("foo");
    543 
    544         JSONArray array = object.toJSONArray(names);
    545         assertEquals(-0.0d, array.get(0));
    546         assertEquals(value, array.get(1));
    547         assertEquals(true, array.get(2));
    548 
    549         object.put("foo", false);
    550         assertEquals(true, array.get(2));
    551     }
    552 
    553     public void testToJSONArrayMissingNames() throws JSONException {
    554         JSONObject object = new JSONObject();
    555         object.put("foo", true);
    556         object.put("bar", 5.0d);
    557         object.put("baz", JSONObject.NULL);
    558 
    559         JSONArray names = new JSONArray();
    560         names.put("bar");
    561         names.put("foo");
    562         names.put("quux");
    563         names.put("baz");
    564 
    565         JSONArray array = object.toJSONArray(names);
    566         assertEquals(4, array.length());
    567 
    568         assertEquals(5.0d, array.get(0));
    569         assertEquals(true, array.get(1));
    570         try {
    571             array.get(2);
    572             fail();
    573         } catch (JSONException e) {
    574         }
    575         assertEquals(JSONObject.NULL, array.get(3));
    576     }
    577 
    578     public void testToJSONArrayNull() throws JSONException {
    579         JSONObject object = new JSONObject();
    580         assertEquals(null, object.toJSONArray(null));
    581         object.put("foo", 5);
    582         try {
    583             object.toJSONArray(null);
    584         } catch (JSONException e) {
    585         }
    586     }
    587 
    588     public void testToJSONArrayEndsUpEmpty() throws JSONException {
    589         JSONObject object = new JSONObject();
    590         object.put("foo", 5);
    591         JSONArray array = new JSONArray();
    592         array.put("bar");
    593         assertEquals(1, object.toJSONArray(array).length());
    594     }
    595 
    596     public void testToJSONArrayNonString() throws JSONException {
    597         JSONObject object = new JSONObject();
    598         object.put("foo", 5);
    599         object.put("null", 10);
    600         object.put("false", 15);
    601 
    602         JSONArray names = new JSONArray();
    603         names.put(JSONObject.NULL);
    604         names.put(false);
    605         names.put("foo");
    606 
    607         // array elements are converted to strings to do name lookups on the map!
    608         JSONArray array = object.toJSONArray(names);
    609         assertEquals(3, array.length());
    610         assertEquals(10, array.get(0));
    611         assertEquals(15, array.get(1));
    612         assertEquals(5, array.get(2));
    613     }
    614 
    615     public void testPutUnsupportedNumbers() throws JSONException {
    616         JSONObject object = new JSONObject();
    617         try {
    618             object.put("foo", Double.NaN);
    619             fail();
    620         } catch (JSONException e) {
    621         }
    622         try {
    623             object.put("foo", Double.NEGATIVE_INFINITY);
    624             fail();
    625         } catch (JSONException e) {
    626         }
    627         try {
    628             object.put("foo", Double.POSITIVE_INFINITY);
    629             fail();
    630         } catch (JSONException e) {
    631         }
    632     }
    633 
    634     public void testPutUnsupportedNumbersAsObjects() throws JSONException {
    635         JSONObject object = new JSONObject();
    636         try {
    637             object.put("foo", (Double) Double.NaN);
    638             fail();
    639         } catch (JSONException e) {
    640         }
    641         try {
    642             object.put("foo", (Double) Double.NEGATIVE_INFINITY);
    643             fail();
    644         } catch (JSONException e) {
    645         }
    646         try {
    647             object.put("foo", (Double) Double.POSITIVE_INFINITY);
    648             fail();
    649         } catch (JSONException e) {
    650         }
    651     }
    652 
    653     /**
    654      * Although JSONObject is usually defensive about which numbers it accepts,
    655      * it doesn't check inputs in its constructor.
    656      */
    657     public void testCreateWithUnsupportedNumbers() throws JSONException {
    658         Map<String, Object> contents = new HashMap<String, Object>();
    659         contents.put("foo", Double.NaN);
    660         contents.put("bar", Double.NEGATIVE_INFINITY);
    661         contents.put("baz", Double.POSITIVE_INFINITY);
    662 
    663         JSONObject object = new JSONObject(contents);
    664         assertEquals(Double.NaN, object.get("foo"));
    665         assertEquals(Double.NEGATIVE_INFINITY, object.get("bar"));
    666         assertEquals(Double.POSITIVE_INFINITY, object.get("baz"));
    667     }
    668 
    669     public void testToStringWithUnsupportedNumbers() {
    670         // when the object contains an unsupported number, toString returns null!
    671         JSONObject object = new JSONObject(Collections.singletonMap("foo", Double.NaN));
    672         assertEquals(null, object.toString());
    673     }
    674 
    675     public void testMapConstructorCopiesContents() throws JSONException {
    676         Map<String, Object> contents = new HashMap<String, Object>();
    677         contents.put("foo", 5);
    678         JSONObject object = new JSONObject(contents);
    679         contents.put("foo", 10);
    680         assertEquals(5, object.get("foo"));
    681     }
    682 
    683     public void testMapConstructorWithBogusEntries() {
    684         Map<Object, Object> contents = new HashMap<Object, Object>();
    685         contents.put(5, 5);
    686 
    687         try {
    688             new JSONObject(contents);
    689             fail("JSONObject constructor doesn't validate its input!");
    690         } catch (Exception e) {
    691         }
    692     }
    693 
    694     public void testTokenerConstructor() throws JSONException {
    695         JSONObject object = new JSONObject(new JSONTokener("{\"foo\": false}"));
    696         assertEquals(1, object.length());
    697         assertEquals(false, object.get("foo"));
    698     }
    699 
    700     public void testTokenerConstructorWrongType() throws JSONException {
    701         try {
    702             new JSONObject(new JSONTokener("[\"foo\", false]"));
    703             fail();
    704         } catch (JSONException e) {
    705         }
    706     }
    707 
    708     public void testTokenerConstructorNull() throws JSONException {
    709         try {
    710             new JSONObject((JSONTokener) null);
    711             fail();
    712         } catch (NullPointerException e) {
    713         }
    714     }
    715 
    716     public void testTokenerConstructorParseFail() {
    717         try {
    718             new JSONObject(new JSONTokener("{"));
    719             fail();
    720         } catch (JSONException e) {
    721         }
    722     }
    723 
    724     public void testStringConstructor() throws JSONException {
    725         JSONObject object = new JSONObject("{\"foo\": false}");
    726         assertEquals(1, object.length());
    727         assertEquals(false, object.get("foo"));
    728     }
    729 
    730     public void testStringConstructorWrongType() throws JSONException {
    731         try {
    732             new JSONObject("[\"foo\", false]");
    733             fail();
    734         } catch (JSONException e) {
    735         }
    736     }
    737 
    738     public void testStringConstructorNull() throws JSONException {
    739         try {
    740             new JSONObject((String) null);
    741             fail();
    742         } catch (NullPointerException e) {
    743         }
    744     }
    745 
    746     public void testStringConstructorParseFail() {
    747         try {
    748             new JSONObject("{");
    749             fail();
    750         } catch (JSONException e) {
    751         }
    752     }
    753 
    754     public void testCopyConstructor() throws JSONException {
    755         JSONObject source = new JSONObject();
    756         source.put("a", JSONObject.NULL);
    757         source.put("b", false);
    758         source.put("c", 5);
    759 
    760         JSONObject copy = new JSONObject(source, new String[] { "a", "c" });
    761         assertEquals(2, copy.length());
    762         assertEquals(JSONObject.NULL, copy.get("a"));
    763         assertEquals(5, copy.get("c"));
    764         assertEquals(null, copy.opt("b"));
    765     }
    766 
    767     public void testCopyConstructorMissingName() throws JSONException {
    768         JSONObject source = new JSONObject();
    769         source.put("a", JSONObject.NULL);
    770         source.put("b", false);
    771         source.put("c", 5);
    772 
    773         JSONObject copy = new JSONObject(source, new String[]{ "a", "c", "d" });
    774         assertEquals(2, copy.length());
    775         assertEquals(JSONObject.NULL, copy.get("a"));
    776         assertEquals(5, copy.get("c"));
    777         assertEquals(0, copy.optInt("b"));
    778     }
    779 
    780     public void testAccumulateMutatesInPlace() throws JSONException {
    781         JSONObject object = new JSONObject();
    782         object.put("foo", 5);
    783         object.accumulate("foo", 6);
    784         JSONArray array = object.getJSONArray("foo");
    785         assertEquals("[5,6]", array.toString());
    786         object.accumulate("foo", 7);
    787         assertEquals("[5,6,7]", array.toString());
    788     }
    789 
    790     public void testAccumulateExistingArray() throws JSONException {
    791         JSONArray array = new JSONArray();
    792         JSONObject object = new JSONObject();
    793         object.put("foo", array);
    794         object.accumulate("foo", 5);
    795         assertEquals("[5]", array.toString());
    796     }
    797 
    798     public void testAccumulatePutArray() throws JSONException {
    799         JSONObject object = new JSONObject();
    800         object.accumulate("foo", 5);
    801         assertEquals("{\"foo\":5}", object.toString());
    802         object.accumulate("foo", new JSONArray());
    803         assertEquals("{\"foo\":[5,[]]}", object.toString());
    804     }
    805 
    806     public void testAccumulateNull() {
    807         JSONObject object = new JSONObject();
    808         try {
    809             object.accumulate(null, 5);
    810             fail();
    811         } catch (JSONException e) {
    812         }
    813     }
    814 
    815     public void testEmptyStringKey() throws JSONException {
    816         JSONObject object = new JSONObject();
    817         object.put("", 5);
    818         assertEquals(5, object.get(""));
    819         assertEquals("{\"\":5}", object.toString());
    820     }
    821 
    822     public void testNullValue() throws JSONException {
    823         JSONObject object = new JSONObject();
    824         object.put("foo", JSONObject.NULL);
    825         object.put("bar", (Collection) null);
    826 
    827         // there are two ways to represent null; each behaves differently!
    828         assertTrue(object.has("foo"));
    829         assertFalse(object.has("bar"));
    830         assertTrue(object.isNull("foo"));
    831         assertTrue(object.isNull("bar"));
    832     }
    833 
    834     public void testNullValue_equalsAndHashCode() {
    835         assertTrue(JSONObject.NULL.equals(null)); // guaranteed by javadoc
    836         // not guaranteed by javadoc, but seems like a good idea
    837         assertEquals(Objects.hashCode(null), JSONObject.NULL.hashCode());
    838     }
    839 
    840     public void testHas() throws JSONException {
    841         JSONObject object = new JSONObject();
    842         object.put("foo", 5);
    843         assertTrue(object.has("foo"));
    844         assertFalse(object.has("bar"));
    845         assertFalse(object.has(null));
    846     }
    847 
    848     public void testOptNull() throws JSONException {
    849         JSONObject object = new JSONObject();
    850         object.put("foo", "bar");
    851         assertEquals(null, object.opt(null));
    852         assertEquals(false, object.optBoolean(null));
    853         assertEquals(Double.NaN, object.optDouble(null));
    854         assertEquals(0, object.optInt(null));
    855         assertEquals(0L, object.optLong(null));
    856         assertEquals(null, object.optJSONArray(null));
    857         assertEquals(null, object.optJSONObject(null));
    858         assertEquals("", object.optString(null));
    859         assertEquals(true, object.optBoolean(null, true));
    860         assertEquals(0.0d, object.optDouble(null, 0.0d));
    861         assertEquals(1, object.optInt(null, 1));
    862         assertEquals(1L, object.optLong(null, 1L));
    863         assertEquals("baz", object.optString(null, "baz"));
    864     }
    865 
    866     public void testToStringWithIndentFactor() throws JSONException {
    867         JSONObject object = new JSONObject();
    868         object.put("foo", new JSONArray(Arrays.asList(5, 6)));
    869         object.put("bar", new JSONObject());
    870         String foobar = "{\n" +
    871                 "     \"foo\": [\n" +
    872                 "          5,\n" +
    873                 "          6\n" +
    874                 "     ],\n" +
    875                 "     \"bar\": {}\n" +
    876                 "}";
    877         String barfoo = "{\n" +
    878                 "     \"bar\": {},\n" +
    879                 "     \"foo\": [\n" +
    880                 "          5,\n" +
    881                 "          6\n" +
    882                 "     ]\n" +
    883                 "}";
    884         String string = object.toString(5);
    885         assertTrue(string, foobar.equals(string) || barfoo.equals(string));
    886     }
    887 
    888     public void testNames() throws JSONException {
    889         JSONObject object = new JSONObject();
    890         object.put("foo", 5);
    891         object.put("bar", 6);
    892         object.put("baz", 7);
    893         JSONArray array = object.names();
    894         assertTrue(array.toString().contains("foo"));
    895         assertTrue(array.toString().contains("bar"));
    896         assertTrue(array.toString().contains("baz"));
    897     }
    898 
    899     public void testKeysEmptyObject() {
    900         JSONObject object = new JSONObject();
    901         assertFalse(object.keys().hasNext());
    902         try {
    903             object.keys().next();
    904             fail();
    905         } catch (NoSuchElementException e) {
    906         }
    907     }
    908 
    909     public void testKeys() throws JSONException {
    910         JSONObject object = new JSONObject();
    911         object.put("foo", 5);
    912         object.put("bar", 6);
    913         object.put("foo", 7);
    914 
    915         @SuppressWarnings("unchecked")
    916         Iterator<String> keys = (Iterator<String>) object.keys();
    917         Set<String> result = new HashSet<String>();
    918         assertTrue(keys.hasNext());
    919         result.add(keys.next());
    920         assertTrue(keys.hasNext());
    921         result.add(keys.next());
    922         assertFalse(keys.hasNext());
    923         assertEquals(new HashSet<String>(Arrays.asList("foo", "bar")), result);
    924 
    925         try {
    926             keys.next();
    927             fail();
    928         } catch (NoSuchElementException e) {
    929         }
    930     }
    931 
    932     public void testMutatingKeysMutatesObject() throws JSONException {
    933         JSONObject object = new JSONObject();
    934         object.put("foo", 5);
    935         Iterator keys = object.keys();
    936         keys.next();
    937         keys.remove();
    938         assertEquals(0, object.length());
    939     }
    940 
    941     public void testQuote() {
    942         // covered by JSONStringerTest.testEscaping
    943     }
    944 
    945     public void testQuoteNull() throws JSONException {
    946         assertEquals("\"\"", JSONObject.quote(null));
    947     }
    948 
    949     public void testNumberToString() throws JSONException {
    950         assertEquals("5", JSONObject.numberToString(5));
    951         assertEquals("-0", JSONObject.numberToString(-0.0d));
    952         assertEquals("9223372036854775806", JSONObject.numberToString(9223372036854775806L));
    953         assertEquals("4.9E-324", JSONObject.numberToString(Double.MIN_VALUE));
    954         assertEquals("1.7976931348623157E308", JSONObject.numberToString(Double.MAX_VALUE));
    955         try {
    956             JSONObject.numberToString(Double.NaN);
    957             fail();
    958         } catch (JSONException e) {
    959         }
    960         try {
    961             JSONObject.numberToString(Double.NEGATIVE_INFINITY);
    962             fail();
    963         } catch (JSONException e) {
    964         }
    965         try {
    966             JSONObject.numberToString(Double.POSITIVE_INFINITY);
    967             fail();
    968         } catch (JSONException e) {
    969         }
    970         assertEquals("0.001", JSONObject.numberToString(new BigDecimal("0.001")));
    971         assertEquals("9223372036854775806",
    972                 JSONObject.numberToString(new BigInteger("9223372036854775806")));
    973         try {
    974             JSONObject.numberToString(null);
    975             fail();
    976         } catch (JSONException e) {
    977         }
    978     }
    979 
    980     public void test_wrap() throws Exception {
    981         assertEquals(JSONObject.NULL, JSONObject.wrap(null));
    982 
    983         JSONArray a = new JSONArray();
    984         assertEquals(a, JSONObject.wrap(a));
    985 
    986         JSONObject o = new JSONObject();
    987         assertEquals(o, JSONObject.wrap(o));
    988 
    989         assertEquals(JSONObject.NULL, JSONObject.wrap(JSONObject.NULL));
    990 
    991         assertTrue(JSONObject.wrap(new byte[0]) instanceof JSONArray);
    992         assertTrue(JSONObject.wrap(new ArrayList<String>()) instanceof JSONArray);
    993         assertTrue(JSONObject.wrap(new HashMap<String, String>()) instanceof JSONObject);
    994         assertTrue(JSONObject.wrap(Double.valueOf(0)) instanceof Double);
    995         assertTrue(JSONObject.wrap("hello") instanceof String);
    996     }
    997 
    998     // https://code.google.com/p/android/issues/detail?id=55114
    999     public void test_toString_listAsMapValue() throws Exception {
   1000         ArrayList<Object> list = new ArrayList<Object>();
   1001         list.add("a");
   1002         list.add(new ArrayList<String>());
   1003         Map<String, Object> map = new TreeMap<String, Object>();
   1004         map.put("x", "l");
   1005         map.put("y", list);
   1006         assertEquals("{\"x\":\"l\",\"y\":[\"a\",[]]}", new JSONObject(map).toString());
   1007     }
   1008 
   1009     public void testAppendExistingInvalidKey() throws JSONException {
   1010         JSONObject object = new JSONObject();
   1011         object.put("foo", 5);
   1012         try {
   1013             object.append("foo", 6);
   1014             fail();
   1015         } catch (JSONException expected) {
   1016         }
   1017     }
   1018 
   1019     public void testAppendExistingArray() throws JSONException {
   1020         JSONArray array = new JSONArray();
   1021         JSONObject object = new JSONObject();
   1022         object.put("foo", array);
   1023         object.append("foo", 5);
   1024         assertEquals("[5]", array.toString());
   1025     }
   1026 
   1027     public void testAppendPutArray() throws JSONException {
   1028         JSONObject object = new JSONObject();
   1029         object.append("foo", 5);
   1030         assertEquals("{\"foo\":[5]}", object.toString());
   1031         object.append("foo", new JSONArray());
   1032         assertEquals("{\"foo\":[5,[]]}", object.toString());
   1033     }
   1034 
   1035     public void testAppendNull() {
   1036         JSONObject object = new JSONObject();
   1037         try {
   1038             object.append(null, 5);
   1039             fail();
   1040         } catch (JSONException e) {
   1041         }
   1042     }
   1043 
   1044     // https://code.google.com/p/android/issues/detail?id=103641
   1045     public void testInvalidUnicodeEscape() {
   1046         try {
   1047             new JSONObject("{\"q\":\"\\u\", \"r\":[]}");
   1048             fail();
   1049         } catch (JSONException expected) {
   1050         }
   1051     }
   1052 }
   1053