[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/_test/tests/inc/ -> json.test.php (source)

   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