[ Index ] |
PHP Cross Reference of DokuWiki |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Unit tests for JSON. 4 * 5 * @author Michal Migurski <mike-json@teczno.com> 6 * @author Matt Knapp <mdknapp[at]gmail[dot]com> 7 * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com> 8 * @copyright 2005 Michal Migurski 9 * @version CVS: $Id: Test-JSON.php,v 1.28 2006/06/28 05:54:17 migurski Exp $ 10 * @license http://www.opensource.org/licenses/bsd-license.php 11 * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 12 * @link http://mike.teczno.com/JSON/Test-JSON.phps 13 */ 14 15 class JSON_EncDec_TestCase extends DokuWikiTest { 16 17 protected $json; 18 19 function setUp() { 20 parent::setUp(); 21 22 $this->json = new JSON(); 23 $this->json->skipnative = true; 24 25 $obj = new stdClass(); 26 $obj->a_string = '"he":llo}:{world'; 27 $obj->an_array = array(1, 2, 3); 28 $obj->obj = new stdClass(); 29 $obj->obj->a_number = 123; 30 31 $this->obj = $obj; 32 $this->obj_j = '{"a_string":"\"he\":llo}:{world","an_array":[1,2,3],"obj":{"a_number":123}}'; 33 $this->obj_d = 'object with properties, nested object and arrays'; 34 35 $this->arr = array(null, true, array(1, 2, 3), "hello\"],[world!"); 36 $this->arr_j = '[null,true,[1,2,3],"hello\"],[world!"]'; 37 $this->arr_d = 'array with elements and nested arrays'; 38 39 $this->str1 = 'hello world'; 40 $this->str1_j = '"hello world"'; 41 $this->str1_j_ = "'hello world'"; 42 $this->str1_d = 'hello world'; 43 $this->str1_d_ = 'hello world, double quotes'; 44 45 $this->str2 = "hello\t\"world\""; 46 $this->str2_j = '"hello\\t\\"world\\""'; 47 $this->str2_d = 'hello world, with tab, double-quotes'; 48 49 $this->str3 = "\\\r\n\t\"/"; 50 $this->str3_j = '"\\\\\\r\\n\\t\\"\\/"'; 51 $this->str3_d = 'backslash, return, newline, tab, double-quote'; 52 53 $this->str4 = 'héllö wørłd'; 54 $this->str4_j = '"h\u00e9ll\u00f6 w\u00f8r\u0142d"'; 55 $this->str4_j_ = '"héllö wørłd"'; 56 $this->str4_d = 'hello world, with unicode'; 57 } 58 59 function test_to_JSON() { 60 $this->assertEquals('null', $this->json->encode(null), 'type case: null'); 61 $this->assertEquals('true', $this->json->encode(true), 'type case: boolean true'); 62 $this->assertEquals('false', $this->json->encode(false), 'type case: boolean false'); 63 64 $this->assertEquals('1', $this->json->encode(1), 'numeric case: 1'); 65 $this->assertEquals('-1', $this->json->encode(-1), 'numeric case: -1'); 66 $this->assertEquals('1.000000', $this->json->encode(1.0), 'numeric case: 1.0'); 67 $this->assertEquals('1.100000', $this->json->encode(1.1), 'numeric case: 1.1'); 68 69 $this->assertEquals($this->str1_j, $this->json->encode($this->str1), "string case: {$this->str1_d}"); 70 $this->assertEquals($this->str2_j, $this->json->encode($this->str2), "string case: {$this->str2_d}"); 71 $this->assertEquals($this->str3_j, $this->json->encode($this->str3), "string case: {$this->str3_d}"); 72 $this->assertEquals($this->str4_j, $this->json->encode($this->str4), "string case: {$this->str4_d}"); 73 74 $this->assertEquals($this->arr_j, $this->json->encode($this->arr), "array case: {$this->arr_d}"); 75 $this->assertEquals($this->obj_j, $this->json->encode($this->obj), "object case: {$this->obj_d}"); 76 } 77 78 function test_from_JSON() { 79 $this->assertEquals(null, $this->json->decode('null'), 'type case: null'); 80 $this->assertEquals(true, $this->json->decode('true'), 'type case: boolean true'); 81 $this->assertEquals(false, $this->json->decode('false'), 'type case: boolean false'); 82 83 $this->assertEquals(1, $this->json->decode('1'), 'numeric case: 1'); 84 $this->assertEquals(-1, $this->json->decode('-1'), 'numeric case: -1'); 85 $this->assertEquals(1.0, $this->json->decode('1.0'), 'numeric case: 1.0'); 86 $this->assertEquals(1.1, $this->json->decode('1.1'), 'numeric case: 1.1'); 87 88 $this->assertEquals(11.0, $this->json->decode('1.1e1'), 'numeric case: 1.1e1'); 89 $this->assertEquals(11.0, $this->json->decode('1.10e+1'), 'numeric case: 1.10e+1'); 90 $this->assertEquals(0.11, $this->json->decode('1.1e-1'), 'numeric case: 1.1e-1'); 91 $this->assertEquals(-0.11, $this->json->decode('-1.1e-1'), 'numeric case: -1.1e-1'); 92 93 $this->assertEquals($this->str1, $this->json->decode($this->str1_j), "string case: {$this->str1_d}"); 94 $this->assertEquals($this->str1, $this->json->decode($this->str1_j_), "string case: {$this->str1_d_}"); 95 $this->assertEquals($this->str2, $this->json->decode($this->str2_j), "string case: {$this->str2_d}"); 96 $this->assertEquals($this->str3, $this->json->decode($this->str3_j), "string case: {$this->str3_d}"); 97 $this->assertEquals($this->str4, $this->json->decode($this->str4_j), "string case: {$this->str4_d}"); 98 $this->assertEquals($this->str4, $this->json->decode($this->str4_j_), "string case: {$this->str4_d}"); 99 100 $this->assertEquals($this->arr, $this->json->decode($this->arr_j), "array case: {$this->arr_d}"); 101 $this->assertEquals($this->obj, $this->json->decode($this->obj_j), "object case: {$this->obj_d}"); 102 } 103 104 function test_to_then_from_JSON() { 105 $this->assertEquals(null, $this->json->decode($this->json->encode(null)), 'type case: null'); 106 $this->assertEquals(true, $this->json->decode($this->json->encode(true)), 'type case: boolean true'); 107 $this->assertEquals(false, $this->json->decode($this->json->encode(false)), 'type case: boolean false'); 108 109 $this->assertEquals(1, $this->json->decode($this->json->encode(1)), 'numeric case: 1'); 110 $this->assertEquals(-1, $this->json->decode($this->json->encode(-1)), 'numeric case: -1'); 111 $this->assertEquals(1.0, $this->json->decode($this->json->encode(1.0)), 'numeric case: 1.0'); 112 $this->assertEquals(1.1, $this->json->decode($this->json->encode(1.1)), 'numeric case: 1.1'); 113 114 $this->assertEquals($this->str1, $this->json->decode($this->json->encode($this->str1)), "string case: {$this->str1_d}"); 115 $this->assertEquals($this->str2, $this->json->decode($this->json->encode($this->str2)), "string case: {$this->str2_d}"); 116 $this->assertEquals($this->str3, $this->json->decode($this->json->encode($this->str3)), "string case: {$this->str3_d}"); 117 $this->assertEquals($this->str4, $this->json->decode($this->json->encode($this->str4)), "string case: {$this->str4_d}"); 118 119 $this->assertEquals($this->arr, $this->json->decode($this->json->encode($this->arr)), "array case: {$this->arr_d}"); 120 $this->assertEquals($this->obj, $this->json->decode($this->json->encode($this->obj)), "object case: {$this->obj_d}"); 121 } 122 123 function test_from_then_to_JSON() { 124 $this->assertEquals('null', $this->json->encode($this->json->decode('null')), 'type case: null'); 125 $this->assertEquals('true', $this->json->encode($this->json->decode('true')), 'type case: boolean true'); 126 $this->assertEquals('false', $this->json->encode($this->json->decode('false')), 'type case: boolean false'); 127 128 $this->assertEquals('1', $this->json->encode($this->json->decode('1')), 'numeric case: 1'); 129 $this->assertEquals('-1', $this->json->encode($this->json->decode('-1')), 'numeric case: -1'); 130 $this->assertEquals('1.0', $this->json->encode($this->json->decode('1.0')), 'numeric case: 1.0'); 131 $this->assertEquals('1.1', $this->json->encode($this->json->decode('1.1')), 'numeric case: 1.1'); 132 133 $this->assertEquals($this->str1_j, $this->json->encode($this->json->decode($this->str1_j)), "string case: {$this->str1_d}"); 134 $this->assertEquals($this->str2_j, $this->json->encode($this->json->decode($this->str2_j)), "string case: {$this->str2_d}"); 135 $this->assertEquals($this->str3_j, $this->json->encode($this->json->decode($this->str3_j)), "string case: {$this->str3_d}"); 136 $this->assertEquals($this->str4_j, $this->json->encode($this->json->decode($this->str4_j)), "string case: {$this->str4_d}"); 137 $this->assertEquals($this->str4_j, $this->json->encode($this->json->decode($this->str4_j_)), "string case: {$this->str4_d}"); 138 139 $this->assertEquals($this->arr_j, $this->json->encode($this->json->decode($this->arr_j)), "array case: {$this->arr_d}"); 140 $this->assertEquals($this->obj_j, $this->json->encode($this->json->decode($this->obj_j)), "object case: {$this->obj_d}"); 141 } 142 } 143 144 class JSON_AssocArray_TestCase extends DokuWikiTest { 145 146 function setUp() { 147 parent::setUp(); 148 149 $this->json_l = new JSON(JSON_LOOSE_TYPE); 150 $this->json_l->skipnative = true; 151 $this->json_s = new JSON(); 152 $this->json_s->skipnative = true; 153 154 $this->arr = array('car1'=> array('color'=> 'tan', 'model' => 'sedan'), 155 'car2' => array('color' => 'red', 'model' => 'sports')); 156 $this->arr_jo = '{"car1":{"color":"tan","model":"sedan"},"car2":{"color":"red","model":"sports"}}'; 157 $this->arr_d = 'associative array with nested associative arrays'; 158 159 $this->arn = array(0=> array(0=> 'tan\\', 'model\\' => 'sedan'), 1 => array(0 => 'red', 'model' => 'sports')); 160 $this->arn_ja = '[{"0":"tan\\\\","model\\\\":"sedan"},{"0":"red","model":"sports"}]'; 161 $this->arn_d = 'associative array with nested associative arrays, and some numeric keys thrown in'; 162 163 $this->arrs = array (1 => 'one', 2 => 'two', 5 => 'five'); 164 $this->arrs_jo = '{"1":"one","2":"two","5":"five"}'; 165 $this->arrs_d = 'associative array numeric keys which are not fully populated in a range of 0 to length-1'; 166 } 167 168 function test_type() { 169 $this->assertEquals('array', gettype($this->json_l->decode($this->arn_ja)), "loose type should be array"); 170 $this->assertEquals('array', gettype($this->json_s->decode($this->arn_ja)), "strict type should be array"); 171 } 172 173 function test_to_JSON() { 174 // both strict and loose JSON should result in an object 175 $this->assertEquals($this->arr_jo, $this->json_l->encode($this->arr), "array case - loose: {$this->arr_d}"); 176 $this->assertEquals($this->arr_jo, $this->json_s->encode($this->arr), "array case - strict: {$this->arr_d}"); 177 178 // ...unless the input array has some numeric indeces, in which case the behavior is to degrade to a regular array 179 $this->assertEquals($this->arn_ja, $this->json_s->encode($this->arn), "array case - strict: {$this->arn_d}"); 180 181 // Test a sparsely populated numerically indexed associative array 182 $this->assertEquals($this->arrs_jo, $this->json_l->encode($this->arrs), "sparse numeric assoc array: {$this->arrs_d}"); 183 } 184 185 function test_to_then_from_JSON() { 186 // these tests motivated by a bug in which strings that end 187 // with backslashes followed by quotes were incorrectly decoded. 188 189 foreach(array('\\"', '\\\\"', '\\"\\"', '\\""\\""', '\\\\"\\\\"') as $v) { 190 $this->assertEquals(array($v), $this->json_l->decode($this->json_l->encode(array($v)))); 191 $this->assertEquals(array('a' => $v), $this->json_l->decode($this->json_l->encode(array('a' => $v)))); 192 } 193 } 194 } 195 196 class JSON_NestedArray_TestCase extends DokuWikiTest { 197 198 function setUp() { 199 parent::setUp(); 200 201 $this->json = new JSON(JSON_LOOSE_TYPE); 202 $this->json->skipnative = true; 203 204 $this->str1 = '[{"this":"that"}]'; 205 $this->arr1 = array(array('this' => 'that')); 206 207 $this->str2 = '{"this":["that"]}'; 208 $this->arr2 = array('this' => array('that')); 209 210 $this->str3 = '{"params":[{"foo":["1"],"bar":"1"}]}'; 211 $this->arr3 = array('params' => array(array('foo' => array('1'), 'bar' => '1'))); 212 213 $this->str4 = '{"0": {"foo": "bar", "baz": "winkle"}}'; 214 $this->arr4 = array('0' => array('foo' => 'bar', 'baz' => 'winkle')); 215 216 $this->str5 = '{"params":[{"options": {"old": [ ], "new": {"0": {"elements": {"old": [], "new": {"0": {"elementName": "aa", "isDefault": false, "elementRank": "0", "priceAdjust": "0", "partNumber": ""}}}, "optionName": "aa", "isRequired": false, "optionDesc": null}}}}]}'; 217 $this->arr5 = array ( 218 'params' => array ( 219 0 => array ( 220 'options' => 221 array ( 222 'old' => array(), 223 'new' => array ( 224 0 => array ( 225 'elements' => array ( 226 'old' => array(), 227 'new' => array ( 228 0 => array ( 229 'elementName' => 'aa', 230 'isDefault' => false, 231 'elementRank' => '0', 232 'priceAdjust' => '0', 233 'partNumber' => '', 234 ), 235 ), 236 ), 237 'optionName' => 'aa', 238 'isRequired' => false, 239 'optionDesc' => NULL, 240 ), 241 ), 242 ), 243 ), 244 ), 245 ); 246 } 247 248 function test_type() { 249 $this->assertEquals('array', gettype($this->json->decode($this->str1)), "loose type should be array"); 250 $this->assertEquals('array', gettype($this->json->decode($this->str2)), "loose type should be array"); 251 $this->assertEquals('array', gettype($this->json->decode($this->str3)), "loose type should be array"); 252 } 253 254 function test_from_JSON() { 255 $this->assertEquals($this->arr1, $this->json->decode($this->str1), "simple compactly-nested array"); 256 $this->assertEquals($this->arr2, $this->json->decode($this->str2), "simple compactly-nested array"); 257 $this->assertEquals($this->arr3, $this->json->decode($this->str3), "complex compactly nested array"); 258 $this->assertEquals($this->arr4, $this->json->decode($this->str4), "complex compactly nested array"); 259 $this->assertEquals($this->arr5, $this->json->decode($this->str5), "super complex compactly nested array"); 260 } 261 262 function _test_from_JSON() { 263 $super = '{"params":[{"options": {"old": {}, "new": {"0": {"elements": {"old": {}, "new": {"0": {"elementName": "aa", "isDefault": false, "elementRank": "0", "priceAdjust": "0", "partNumber": ""}}}, "optionName": "aa", "isRequired": false, "optionDesc": ""}}}}]}'; 264 print("trying {$super}...\n"); 265 print var_export($this->json->decode($super)); 266 } 267 } 268 269 class JSON_Object_TestCase extends DokuWikiTest { 270 271 function setUp() { 272 parent::setUp(); 273 274 $this->json_l = new JSON(JSON_LOOSE_TYPE); 275 $this->json_l->skipnative = true; 276 $this->json_s = new JSON(); 277 $this->json_s->skipnative = true; 278 279 $this->obj_j = '{"a_string":"\"he\":llo}:{world","an_array":[1,2,3],"obj":{"a_number":123}}'; 280 281 $this->obj1 = new stdClass(); 282 $this->obj1->car1 = new stdClass(); 283 $this->obj1->car1->color = 'tan'; 284 $this->obj1->car1->model = 'sedan'; 285 $this->obj1->car2 = new stdClass(); 286 $this->obj1->car2->color = 'red'; 287 $this->obj1->car2->model = 'sports'; 288 $this->obj1_j = '{"car1":{"color":"tan","model":"sedan"},"car2":{"color":"red","model":"sports"}}'; 289 $this->obj1_d = 'Object with nested objects'; 290 } 291 292 function test_type() { 293 $this->assertEquals('object', gettype($this->json_s->decode($this->obj_j)), "checking whether decoded type is object"); 294 $this->assertEquals('array', gettype($this->json_l->decode($this->obj_j)), "checking whether decoded type is array"); 295 } 296 297 function test_to_JSON() { 298 $this->assertEquals($this->obj1_j, $this->json_s->encode($this->obj1), "object - strict: {$this->obj1_d}"); 299 $this->assertEquals($this->obj1_j, $this->json_l->encode($this->obj1), "object - loose: {$this->obj1_d}"); 300 } 301 302 function test_from_then_to_JSON() { 303 $this->assertEquals($this->obj_j, $this->json_s->encode($this->json_s->decode($this->obj_j)), "object case"); 304 $this->assertEquals($this->obj_j, $this->json_l->encode($this->json_l->decode($this->obj_j)), "array case"); 305 } 306 } 307 308 class JSON_Spaces_Comments_TestCase extends DokuWikiTest { 309 310 function setUp() { 311 parent::setUp(); 312 313 $this->json = new JSON(JSON_LOOSE_TYPE); 314 $this->json->skipnative = true; 315 316 $this->obj_j = '{"a_string":"\"he\":llo}:{world","an_array":[1,2,3],"obj":{"a_number":123}}'; 317 318 $this->obj_js = '{"a_string": "\"he\":llo}:{world", 319 "an_array":[1, 2, 3], 320 "obj": {"a_number":123}}'; 321 322 $this->obj_jc1 = '{"a_string": "\"he\":llo}:{world", 323 // here is a comment, hoorah 324 "an_array":[1, 2, 3], 325 "obj": {"a_number":123}}'; 326 327 $this->obj_jc2 = '/* this here is the sneetch */ "the sneetch" 328 // this has been the sneetch.'; 329 330 $this->obj_jc3 = '{"a_string": "\"he\":llo}:{world", 331 /* here is a comment, hoorah */ 332 "an_array":[1, 2, 3 /* and here is another */], 333 "obj": {"a_number":123}}'; 334 335 $this->obj_jc4 = '{\'a_string\': "\"he\":llo}:{world", 336 /* here is a comment, hoorah */ 337 \'an_array\':[1, 2, 3 /* and here is another */], 338 "obj": {"a_number":123}}'; 339 } 340 341 function test_spaces() { 342 $this->assertEquals($this->json->decode($this->obj_j), $this->json->decode($this->obj_js), "checking whether notation with spaces works"); 343 } 344 345 function test_comments() { 346 $this->assertEquals($this->json->decode($this->obj_j), $this->json->decode($this->obj_jc1), "checking whether notation with single line comments works"); 347 $this->assertEquals('the sneetch', $this->json->decode($this->obj_jc2), "checking whether notation with multiline comments works"); 348 $this->assertEquals($this->json->decode($this->obj_j), $this->json->decode($this->obj_jc3), "checking whether notation with multiline comments works"); 349 $this->assertEquals($this->json->decode($this->obj_j), $this->json->decode($this->obj_jc4), "checking whether notation with single-quotes and multiline comments works"); 350 } 351 } 352 353 class JSON_Empties_TestCase extends DokuWikiTest { 354 355 function setUp() { 356 parent::setUp(); 357 358 $this->json_l = new JSON(JSON_LOOSE_TYPE); 359 $this->json_l->skipnative = true; 360 $this->json_l->skipnative = true; 361 $this->json_s = new JSON(); 362 $this->json_s->skipnative = true; 363 364 $this->obj0_j = '{}'; 365 $this->arr0_j = '[]'; 366 367 $this->obj1_j = '{ }'; 368 $this->arr1_j = '[ ]'; 369 370 $this->obj2_j = '{ /* comment inside */ }'; 371 $this->arr2_j = '[ /* comment inside */ ]'; 372 } 373 374 function test_type() { 375 $this->assertEquals('array', gettype($this->json_l->decode($this->arr0_j)), "should be array"); 376 $this->assertEquals('object', gettype($this->json_s->decode($this->obj0_j)), "should be object"); 377 378 $this->assertEquals(0, count($this->json_l->decode($this->arr0_j)), "should be empty array"); 379 $this->assertEquals(0, count(get_object_vars($this->json_s->decode($this->obj0_j))), "should be empty object"); 380 381 $this->assertEquals('array', gettype($this->json_l->decode($this->arr1_j)), "should be array, even with space"); 382 $this->assertEquals('object', gettype($this->json_s->decode($this->obj1_j)), "should be object, even with space"); 383 384 $this->assertEquals(0, count($this->json_l->decode($this->arr1_j)), "should be empty array, even with space"); 385 $this->assertEquals(0, count(get_object_vars($this->json_s->decode($this->obj1_j))), "should be empty object, even with space"); 386 387 $this->assertEquals('array', gettype($this->json_l->decode($this->arr2_j)), "should be array, despite comment"); 388 $this->assertEquals('object', gettype($this->json_s->decode($this->obj2_j)), "should be object, despite comment"); 389 390 $this->assertEquals(0, count($this->json_l->decode($this->arr2_j)), "should be empty array, despite comment"); 391 $this->assertEquals(0, count(get_object_vars($this->json_s->decode($this->obj2_j))), "should be empty object, despite commentt"); 392 } 393 } 394 395 class JSON_UnquotedKeys_TestCase extends DokuWikiTest { 396 397 function setUp() { 398 parent::setUp(); 399 400 $this->json = new JSON(JSON_LOOSE_TYPE); 401 $this->json->skipnative = true; 402 403 $this->arn = array(0=> array(0=> 'tan', 'model' => 'sedan'), 1 => array(0 => 'red', 'model' => 'sports')); 404 $this->arn_ja = '[{0:"tan","model":"sedan"},{"0":"red",model:"sports"}]'; 405 $this->arn_d = 'associative array with unquoted keys, nested associative arrays, and some numeric keys thrown in'; 406 407 $this->arrs = array (1 => 'one', 2 => 'two', 5 => 'fi"ve'); 408 $this->arrs_jo = '{"1":"one",2:"two","5":\'fi"ve\'}'; 409 $this->arrs_d = 'associative array with unquoted keys, single-quoted values, numeric keys which are not fully populated in a range of 0 to length-1'; 410 } 411 412 function test_from_JSON() { 413 // ...unless the input array has some numeric indeces, in which case the behavior is to degrade to a regular array 414 $this->assertEquals($this->arn, $this->json->decode($this->arn_ja), "array case - strict: {$this->arn_d}"); 415 416 // Test a sparsely populated numerically indexed associative array 417 $this->assertEquals($this->arrs, $this->json->decode($this->arrs_jo), "sparse numeric assoc array: {$this->arrs_d}"); 418 } 419 } 420
title
Description
Body
title
Description
Body
title
Description
Body
title
Body