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 junit.framework.TestCase; 20 21 import java.util.Arrays; 22 import java.util.List; 23 import java.util.Collections; 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 public void testNulls() throws JSONException { 126 JSONArray array = new JSONArray(); 127 array.put(3, null); 128 array.put(0, JSONObject.NULL); 129 assertEquals(4, array.length()); 130 assertEquals("[null,null,null,null]", array.toString()); 131 132 // there's 2 ways to represent null; each behaves differently! 133 assertEquals(JSONObject.NULL, array.get(0)); 134 try { 135 array.get(1); 136 fail(); 137 } catch (JSONException e) { 138 } 139 try { 140 array.get(2); 141 fail(); 142 } catch (JSONException e) { 143 } 144 try { 145 array.get(3); 146 fail(); 147 } catch (JSONException e) { 148 } 149 assertEquals(JSONObject.NULL, array.opt(0)); 150 assertEquals(null, array.opt(1)); 151 assertEquals(null, array.opt(2)); 152 assertEquals(null, array.opt(3)); 153 assertTrue(array.isNull(0)); 154 assertTrue(array.isNull(1)); 155 assertTrue(array.isNull(2)); 156 assertTrue(array.isNull(3)); 157 assertEquals("null", array.optString(0)); 158 assertEquals("", array.optString(1)); 159 assertEquals("", array.optString(2)); 160 assertEquals("", array.optString(3)); 161 } 162 163 /** 164 * Our behaviour is questioned by this bug: 165 * http://code.google.com/p/android/issues/detail?id=7257 166 */ 167 public void testParseNullYieldsJSONObjectNull() throws JSONException { 168 JSONArray array = new JSONArray("[\"null\",null]"); 169 array.put(null); 170 assertEquals("null", array.get(0)); 171 assertEquals(JSONObject.NULL, array.get(1)); 172 try { 173 array.get(2); 174 fail(); 175 } catch (JSONException e) { 176 } 177 assertEquals("null", array.getString(0)); 178 assertEquals("null", array.getString(1)); 179 try { 180 array.getString(2); 181 fail(); 182 } catch (JSONException e) { 183 } 184 } 185 186 public void testNumbers() throws JSONException { 187 JSONArray array = new JSONArray(); 188 array.put(Double.MIN_VALUE); 189 array.put(9223372036854775806L); 190 array.put(Double.MAX_VALUE); 191 array.put(-0d); 192 assertEquals(4, array.length()); 193 194 // toString() and getString(int) return different values for -0d 195 assertEquals("[4.9E-324,9223372036854775806,1.7976931348623157E308,-0]", array.toString()); 196 197 assertEquals(Double.MIN_VALUE, array.get(0)); 198 assertEquals(9223372036854775806L, array.get(1)); 199 assertEquals(Double.MAX_VALUE, array.get(2)); 200 assertEquals(-0d, array.get(3)); 201 assertEquals(Double.MIN_VALUE, array.getDouble(0)); 202 assertEquals(9.223372036854776E18, array.getDouble(1)); 203 assertEquals(Double.MAX_VALUE, array.getDouble(2)); 204 assertEquals(-0d, array.getDouble(3)); 205 assertEquals(0, array.getLong(0)); 206 assertEquals(9223372036854775806L, array.getLong(1)); 207 assertEquals(Long.MAX_VALUE, array.getLong(2)); 208 assertEquals(0, array.getLong(3)); 209 assertEquals(0, array.getInt(0)); 210 assertEquals(-2, array.getInt(1)); 211 assertEquals(Integer.MAX_VALUE, array.getInt(2)); 212 assertEquals(0, array.getInt(3)); 213 assertEquals(Double.MIN_VALUE, array.opt(0)); 214 assertEquals(Double.MIN_VALUE, array.optDouble(0)); 215 assertEquals(0, array.optLong(0, 1L)); 216 assertEquals(0, array.optInt(0, 1)); 217 assertEquals("4.9E-324", array.getString(0)); 218 assertEquals("9223372036854775806", array.getString(1)); 219 assertEquals("1.7976931348623157E308", array.getString(2)); 220 assertEquals("-0.0", array.getString(3)); 221 222 JSONArray other = new JSONArray(); 223 other.put(Double.MIN_VALUE); 224 other.put(9223372036854775806L); 225 other.put(Double.MAX_VALUE); 226 other.put(-0d); 227 assertTrue(array.equals(other)); 228 other.put(0, 0L); 229 assertFalse(array.equals(other)); 230 } 231 232 public void testStrings() throws JSONException { 233 JSONArray array = new JSONArray(); 234 array.put("true"); 235 array.put("5.5"); 236 array.put("9223372036854775806"); 237 array.put("null"); 238 array.put("5\"8' tall"); 239 assertEquals(5, array.length()); 240 assertEquals("[\"true\",\"5.5\",\"9223372036854775806\",\"null\",\"5\\\"8' tall\"]", 241 array.toString()); 242 243 // although the documentation doesn't mention it, join() escapes text and wraps 244 // strings in quotes 245 assertEquals("\"true\" \"5.5\" \"9223372036854775806\" \"null\" \"5\\\"8' tall\"", 246 array.join(" ")); 247 248 assertEquals("true", array.get(0)); 249 assertEquals("null", array.getString(3)); 250 assertEquals("5\"8' tall", array.getString(4)); 251 assertEquals("true", array.opt(0)); 252 assertEquals("5.5", array.optString(1)); 253 assertEquals("9223372036854775806", array.optString(2, null)); 254 assertEquals("null", array.optString(3, "-1")); 255 assertFalse(array.isNull(0)); 256 assertFalse(array.isNull(3)); 257 258 assertEquals(true, array.getBoolean(0)); 259 assertEquals(true, array.optBoolean(0)); 260 assertEquals(true, array.optBoolean(0, false)); 261 assertEquals(0, array.optInt(0)); 262 assertEquals(-2, array.optInt(0, -2)); 263 264 assertEquals(5.5d, array.getDouble(1)); 265 assertEquals(5L, array.getLong(1)); 266 assertEquals(5, array.getInt(1)); 267 assertEquals(5, array.optInt(1, 3)); 268 269 // The last digit of the string is a 6 but getLong returns a 7. It's probably parsing as a 270 // double and then converting that to a long. This is consistent with JavaScript. 271 assertEquals(9223372036854775807L, array.getLong(2)); 272 assertEquals(9.223372036854776E18, array.getDouble(2)); 273 assertEquals(Integer.MAX_VALUE, array.getInt(2)); 274 275 assertFalse(array.isNull(3)); 276 try { 277 array.getDouble(3); 278 fail(); 279 } catch (JSONException e) { 280 } 281 assertEquals(Double.NaN, array.optDouble(3)); 282 assertEquals(-1.0d, array.optDouble(3, -1.0d)); 283 } 284 285 public void testJoin() throws JSONException { 286 JSONArray array = new JSONArray(); 287 array.put(null); 288 assertEquals("null", array.join(" & ")); 289 array.put("\""); 290 assertEquals("null & \"\\\"\"", array.join(" & ")); 291 array.put(5); 292 assertEquals("null & \"\\\"\" & 5", array.join(" & ")); 293 array.put(true); 294 assertEquals("null & \"\\\"\" & 5 & true", array.join(" & ")); 295 array.put(new JSONArray(Arrays.asList(true, false))); 296 assertEquals("null & \"\\\"\" & 5 & true & [true,false]", array.join(" & ")); 297 array.put(new JSONObject(Collections.singletonMap("x", 6))); 298 assertEquals("null & \"\\\"\" & 5 & true & [true,false] & {\"x\":6}", array.join(" & ")); 299 } 300 301 public void testJoinWithNull() throws JSONException { 302 JSONArray array = new JSONArray(Arrays.asList(5, 6)); 303 assertEquals("5null6", array.join(null)); 304 } 305 306 public void testJoinWithSpecialCharacters() throws JSONException { 307 JSONArray array = new JSONArray(Arrays.asList(5, 6)); 308 assertEquals("5\"6", array.join("\"")); 309 } 310 311 public void testToJSONObject() throws JSONException { 312 JSONArray keys = new JSONArray(); 313 keys.put("a"); 314 keys.put("b"); 315 316 JSONArray values = new JSONArray(); 317 values.put(5.5d); 318 values.put(false); 319 320 JSONObject object = values.toJSONObject(keys); 321 assertEquals(5.5d, object.get("a")); 322 assertEquals(false, object.get("b")); 323 324 keys.put(0, "a"); 325 values.put(0, 11.0d); 326 assertEquals(5.5d, object.get("a")); 327 } 328 329 public void testToJSONObjectWithNulls() throws JSONException { 330 JSONArray keys = new JSONArray(); 331 keys.put("a"); 332 keys.put("b"); 333 334 JSONArray values = new JSONArray(); 335 values.put(5.5d); 336 values.put(null); 337 338 // null values are stripped! 339 JSONObject object = values.toJSONObject(keys); 340 assertEquals(1, object.length()); 341 assertFalse(object.has("b")); 342 assertEquals("{\"a\":5.5}", object.toString()); 343 } 344 345 public void testToJSONObjectMoreNamesThanValues() throws JSONException { 346 JSONArray keys = new JSONArray(); 347 keys.put("a"); 348 keys.put("b"); 349 JSONArray values = new JSONArray(); 350 values.put(5.5d); 351 JSONObject object = values.toJSONObject(keys); 352 assertEquals(1, object.length()); 353 assertEquals(5.5d, object.get("a")); 354 } 355 356 public void testToJSONObjectMoreValuesThanNames() throws JSONException { 357 JSONArray keys = new JSONArray(); 358 keys.put("a"); 359 JSONArray values = new JSONArray(); 360 values.put(5.5d); 361 values.put(11.0d); 362 JSONObject object = values.toJSONObject(keys); 363 assertEquals(1, object.length()); 364 assertEquals(5.5d, object.get("a")); 365 } 366 367 public void testToJSONObjectNullKey() throws JSONException { 368 JSONArray keys = new JSONArray(); 369 keys.put(JSONObject.NULL); 370 JSONArray values = new JSONArray(); 371 values.put(5.5d); 372 JSONObject object = values.toJSONObject(keys); 373 assertEquals(1, object.length()); 374 assertEquals(5.5d, object.get("null")); 375 } 376 377 public void testPutUnsupportedNumbers() throws JSONException { 378 JSONArray array = new JSONArray(); 379 380 try { 381 array.put(Double.NaN); 382 fail(); 383 } catch (JSONException e) { 384 } 385 try { 386 array.put(0, Double.NEGATIVE_INFINITY); 387 fail(); 388 } catch (JSONException e) { 389 } 390 try { 391 array.put(0, Double.POSITIVE_INFINITY); 392 fail(); 393 } catch (JSONException e) { 394 } 395 } 396 397 public void testPutUnsupportedNumbersAsObject() throws JSONException { 398 JSONArray array = new JSONArray(); 399 array.put(Double.valueOf(Double.NaN)); 400 array.put(Double.valueOf(Double.NEGATIVE_INFINITY)); 401 array.put(Double.valueOf(Double.POSITIVE_INFINITY)); 402 assertEquals(null, array.toString()); 403 } 404 405 /** 406 * Although JSONArray is usually defensive about which numbers it accepts, 407 * it doesn't check inputs in its constructor. 408 */ 409 public void testCreateWithUnsupportedNumbers() throws JSONException { 410 JSONArray array = new JSONArray(Arrays.asList(5.5, Double.NaN)); 411 assertEquals(2, array.length()); 412 assertEquals(5.5, array.getDouble(0)); 413 assertEquals(Double.NaN, array.getDouble(1)); 414 } 415 416 public void testToStringWithUnsupportedNumbers() throws JSONException { 417 // when the array contains an unsupported number, toString returns null! 418 JSONArray array = new JSONArray(Arrays.asList(5.5, Double.NaN)); 419 assertNull(array.toString()); 420 } 421 422 public void testListConstructorCopiesContents() throws JSONException { 423 List<Object> contents = Arrays.<Object>asList(5); 424 JSONArray array = new JSONArray(contents); 425 contents.set(0, 10); 426 assertEquals(5, array.get(0)); 427 } 428 429 public void testTokenerConstructor() throws JSONException { 430 JSONArray object = new JSONArray(new JSONTokener("[false]")); 431 assertEquals(1, object.length()); 432 assertEquals(false, object.get(0)); 433 } 434 435 public void testTokenerConstructorWrongType() throws JSONException { 436 try { 437 new JSONArray(new JSONTokener("{\"foo\": false}")); 438 fail(); 439 } catch (JSONException e) { 440 } 441 } 442 443 public void testTokenerConstructorNull() throws JSONException { 444 try { 445 new JSONArray((JSONTokener) null); 446 fail(); 447 } catch (NullPointerException e) { 448 } 449 } 450 451 public void testTokenerConstructorParseFail() { 452 try { 453 new JSONArray(new JSONTokener("[")); 454 fail(); 455 } catch (JSONException e) { 456 } catch (StackOverflowError e) { 457 fail("Stack overflowed on input: \"[\""); 458 } 459 } 460 461 public void testStringConstructor() throws JSONException { 462 JSONArray object = new JSONArray("[false]"); 463 assertEquals(1, object.length()); 464 assertEquals(false, object.get(0)); 465 } 466 467 public void testStringConstructorWrongType() throws JSONException { 468 try { 469 new JSONArray("{\"foo\": false}"); 470 fail(); 471 } catch (JSONException e) { 472 } 473 } 474 475 public void testStringConstructorNull() throws JSONException { 476 try { 477 new JSONArray((String) null); 478 fail(); 479 } catch (NullPointerException e) { 480 } 481 } 482 483 public void testStringConstructorParseFail() { 484 try { 485 new JSONArray("["); 486 fail(); 487 } catch (JSONException e) { 488 } catch (StackOverflowError e) { 489 fail("Stack overflowed on input: \"[\""); 490 } 491 } 492 493 public void testCreate() throws JSONException { 494 JSONArray array = new JSONArray(Arrays.asList(5.5, true)); 495 assertEquals(2, array.length()); 496 assertEquals(5.5, array.getDouble(0)); 497 assertEquals(true, array.get(1)); 498 assertEquals("[5.5,true]", array.toString()); 499 } 500 501 public void testAccessOutOfBounds() throws JSONException { 502 JSONArray array = new JSONArray(); 503 array.put("foo"); 504 assertEquals(null, array.opt(3)); 505 assertEquals(null, array.opt(-3)); 506 assertEquals("", array.optString(3)); 507 assertEquals("", array.optString(-3)); 508 try { 509 array.get(3); 510 fail(); 511 } catch (JSONException e) { 512 } 513 try { 514 array.get(-3); 515 fail(); 516 } catch (JSONException e) { 517 } 518 try { 519 array.getString(3); 520 fail(); 521 } catch (JSONException e) { 522 } 523 try { 524 array.getString(-3); 525 fail(); 526 } catch (JSONException e) { 527 } 528 } 529 } 530