1#!/usr/bin/env ruby 2# encoding: utf-8 3 4require 'test/unit' 5require File.join(File.dirname(__FILE__), 'setup_variant') 6require 'stringio' 7require 'tempfile' 8require 'ostruct' 9 10unless Array.method_defined?(:permutation) 11 begin 12 require 'enumerator' 13 require 'permutation' 14 class Array 15 def permutation 16 Permutation.for(self).to_enum.map { |x| x.project } 17 end 18 end 19 rescue LoadError 20 warn "Skipping permutation tests." 21 end 22end 23 24class TestJSON < Test::Unit::TestCase 25 include JSON 26 27 def setup 28 @ary = [1, "foo", 3.14, 4711.0, 2.718, nil, [1,-2,3], false, true].map do 29 |x| [x] 30 end 31 @ary_to_parse = ["1", '"foo"', "3.14", "4711.0", "2.718", "null", 32 "[1,-2,3]", "false", "true"].map do 33 |x| "[#{x}]" 34 end 35 @hash = { 36 'a' => 2, 37 'b' => 3.141, 38 'c' => 'c', 39 'd' => [ 1, "b", 3.14 ], 40 'e' => { 'foo' => 'bar' }, 41 'g' => "\"\0\037", 42 'h' => 1000.0, 43 'i' => 0.001 44 } 45 @json = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},'\ 46 '"g":"\\"\\u0000\\u001f","h":1.0E3,"i":1.0E-3}' 47 end 48 49 def test_construction 50 parser = JSON::Parser.new('test') 51 assert_equal 'test', parser.source 52 end 53 54 def assert_equal_float(expected, is) 55 assert_in_delta(expected.first, is.first, 1e-2) 56 end 57 58 def test_parse_simple_arrays 59 assert_equal([], parse('[]')) 60 assert_equal([], parse(' [ ] ')) 61 assert_equal([nil], parse('[null]')) 62 assert_equal([false], parse('[false]')) 63 assert_equal([true], parse('[true]')) 64 assert_equal([-23], parse('[-23]')) 65 assert_equal([23], parse('[23]')) 66 assert_equal([0.23], parse('[0.23]')) 67 assert_equal([0.0], parse('[0e0]')) 68 assert_raises(JSON::ParserError) { parse('[+23.2]') } 69 assert_raises(JSON::ParserError) { parse('[+23]') } 70 assert_raises(JSON::ParserError) { parse('[.23]') } 71 assert_raises(JSON::ParserError) { parse('[023]') } 72 assert_equal_float [3.141], parse('[3.141]') 73 assert_equal_float [-3.141], parse('[-3.141]') 74 assert_equal_float [3.141], parse('[3141e-3]') 75 assert_equal_float [3.141], parse('[3141.1e-3]') 76 assert_equal_float [3.141], parse('[3141E-3]') 77 assert_equal_float [3.141], parse('[3141.0E-3]') 78 assert_equal_float [-3.141], parse('[-3141.0e-3]') 79 assert_equal_float [-3.141], parse('[-3141e-3]') 80 assert_raises(ParserError) { parse('[NaN]') } 81 assert parse('[NaN]', :allow_nan => true).first.nan? 82 assert_raises(ParserError) { parse('[Infinity]') } 83 assert_equal [1.0/0], parse('[Infinity]', :allow_nan => true) 84 assert_raises(ParserError) { parse('[-Infinity]') } 85 assert_equal [-1.0/0], parse('[-Infinity]', :allow_nan => true) 86 assert_equal([""], parse('[""]')) 87 assert_equal(["foobar"], parse('["foobar"]')) 88 assert_equal([{}], parse('[{}]')) 89 end 90 91 def test_parse_simple_objects 92 assert_equal({}, parse('{}')) 93 assert_equal({}, parse(' { } ')) 94 assert_equal({ "a" => nil }, parse('{ "a" : null}')) 95 assert_equal({ "a" => nil }, parse('{"a":null}')) 96 assert_equal({ "a" => false }, parse('{ "a" : false } ')) 97 assert_equal({ "a" => false }, parse('{"a":false}')) 98 assert_raises(JSON::ParserError) { parse('{false}') } 99 assert_equal({ "a" => true }, parse('{"a":true}')) 100 assert_equal({ "a" => true }, parse(' { "a" : true } ')) 101 assert_equal({ "a" => -23 }, parse(' { "a" : -23 } ')) 102 assert_equal({ "a" => -23 }, parse(' { "a" : -23 } ')) 103 assert_equal({ "a" => 23 }, parse('{"a":23 } ')) 104 assert_equal({ "a" => 23 }, parse(' { "a" : 23 } ')) 105 assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } ')) 106 assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } ')) 107 end 108 109 def test_parse_json_primitive_values 110 assert_raise(JSON::ParserError) { JSON.parse('') } 111 assert_raise(JSON::ParserError) { JSON.parse('', :quirks_mode => true) } 112 assert_raise(TypeError) { JSON::Parser.new(nil).parse } 113 assert_raise(TypeError) { JSON::Parser.new(nil, :quirks_mode => true).parse } 114 assert_raise(TypeError) { JSON.parse(nil) } 115 assert_raise(TypeError) { JSON.parse(nil, :quirks_mode => true) } 116 assert_raise(JSON::ParserError) { JSON.parse(' /* foo */ ') } 117 assert_raise(JSON::ParserError) { JSON.parse(' /* foo */ ', :quirks_mode => true) } 118 parser = JSON::Parser.new('null') 119 assert_equal false, parser.quirks_mode? 120 assert_raise(JSON::ParserError) { parser.parse } 121 assert_raise(JSON::ParserError) { JSON.parse('null') } 122 assert_equal nil, JSON.parse('null', :quirks_mode => true) 123 parser = JSON::Parser.new('null', :quirks_mode => true) 124 assert_equal true, parser.quirks_mode? 125 assert_equal nil, parser.parse 126 assert_raise(JSON::ParserError) { JSON.parse('false') } 127 assert_equal false, JSON.parse('false', :quirks_mode => true) 128 assert_raise(JSON::ParserError) { JSON.parse('true') } 129 assert_equal true, JSON.parse('true', :quirks_mode => true) 130 assert_raise(JSON::ParserError) { JSON.parse('23') } 131 assert_equal 23, JSON.parse('23', :quirks_mode => true) 132 assert_raise(JSON::ParserError) { JSON.parse('1') } 133 assert_equal 1, JSON.parse('1', :quirks_mode => true) 134 assert_raise(JSON::ParserError) { JSON.parse('3.141') } 135 assert_in_delta 3.141, JSON.parse('3.141', :quirks_mode => true), 1E-3 136 assert_raise(JSON::ParserError) { JSON.parse('18446744073709551616') } 137 assert_equal 2 ** 64, JSON.parse('18446744073709551616', :quirks_mode => true) 138 assert_raise(JSON::ParserError) { JSON.parse('"foo"') } 139 assert_equal 'foo', JSON.parse('"foo"', :quirks_mode => true) 140 assert_raise(JSON::ParserError) { JSON.parse('NaN', :allow_nan => true) } 141 assert JSON.parse('NaN', :quirks_mode => true, :allow_nan => true).nan? 142 assert_raise(JSON::ParserError) { JSON.parse('Infinity', :allow_nan => true) } 143 assert JSON.parse('Infinity', :quirks_mode => true, :allow_nan => true).infinite? 144 assert_raise(JSON::ParserError) { JSON.parse('-Infinity', :allow_nan => true) } 145 assert JSON.parse('-Infinity', :quirks_mode => true, :allow_nan => true).infinite? 146 assert_raise(JSON::ParserError) { JSON.parse('[ 1, ]', :quirks_mode => true) } 147 end 148 149 if Array.method_defined?(:permutation) 150 def test_parse_more_complex_arrays 151 a = [ nil, false, true, "foßbar", [ "n€st€d", true ], { "nested" => true, "n€ßt€ð2" => {} }] 152 a.permutation.each do |perm| 153 json = pretty_generate(perm) 154 assert_equal perm, parse(json) 155 end 156 end 157 158 def test_parse_complex_objects 159 a = [ nil, false, true, "foßbar", [ "n€st€d", true ], { "nested" => true, "n€ßt€ð2" => {} }] 160 a.permutation.each do |perm| 161 s = "a" 162 orig_obj = perm.inject({}) { |h, x| h[s.dup] = x; s = s.succ; h } 163 json = pretty_generate(orig_obj) 164 assert_equal orig_obj, parse(json) 165 end 166 end 167 end 168 169 def test_parse_arrays 170 assert_equal([1,2,3], parse('[1,2,3]')) 171 assert_equal([1.2,2,3], parse('[1.2,2,3]')) 172 assert_equal([[],[[],[]]], parse('[[],[[],[]]]')) 173 end 174 175 def test_parse_values 176 assert_equal([""], parse('[""]')) 177 assert_equal(["\\"], parse('["\\\\"]')) 178 assert_equal(['"'], parse('["\""]')) 179 assert_equal(['\\"\\'], parse('["\\\\\\"\\\\"]')) 180 assert_equal(["\"\b\n\r\t\0\037"], 181 parse('["\"\b\n\r\t\u0000\u001f"]')) 182 for i in 0 ... @ary.size 183 assert_equal(@ary[i], parse(@ary_to_parse[i])) 184 end 185 end 186 187 def test_parse_array 188 assert_equal([], parse('[]')) 189 assert_equal([], parse(' [ ] ')) 190 assert_equal([1], parse('[1]')) 191 assert_equal([1], parse(' [ 1 ] ')) 192 assert_equal(@ary, 193 parse('[[1],["foo"],[3.14],[47.11e+2],[2718.0E-3],[null],[[1,-2,3]]'\ 194 ',[false],[true]]')) 195 assert_equal(@ary, parse(%Q{ [ [1] , ["foo"] , [3.14] \t , [47.11e+2]\s 196 , [2718.0E-3 ],\r[ null] , [[1, -2, 3 ]], [false ],[ true]\n ] })) 197 end 198 199 class SubArray < Array 200 def <<(v) 201 @shifted = true 202 super 203 end 204 205 def shifted? 206 @shifted 207 end 208 end 209 210 class SubArray2 < Array 211 def to_json(*a) 212 { 213 JSON.create_id => self.class.name, 214 'ary' => to_a, 215 }.to_json(*a) 216 end 217 218 def self.json_create(o) 219 o.delete JSON.create_id 220 o['ary'] 221 end 222 end 223 224 class SubArrayWrapper 225 def initialize 226 @data = [] 227 end 228 229 attr_reader :data 230 231 def [](index) 232 @data[index] 233 end 234 235 def <<(value) 236 @data << value 237 @shifted = true 238 end 239 240 def shifted? 241 @shifted 242 end 243 end 244 245 def test_parse_array_custom_array_derived_class 246 res = parse('[1,2]', :array_class => SubArray) 247 assert_equal([1,2], res) 248 assert_equal(SubArray, res.class) 249 assert res.shifted? 250 end 251 252 def test_parse_array_custom_non_array_derived_class 253 res = parse('[1,2]', :array_class => SubArrayWrapper) 254 assert_equal([1,2], res.data) 255 assert_equal(SubArrayWrapper, res.class) 256 assert res.shifted? 257 end 258 259 def test_parse_object 260 assert_equal({}, parse('{}')) 261 assert_equal({}, parse(' { } ')) 262 assert_equal({'foo'=>'bar'}, parse('{"foo":"bar"}')) 263 assert_equal({'foo'=>'bar'}, parse(' { "foo" : "bar" } ')) 264 end 265 266 class SubHash < Hash 267 def []=(k, v) 268 @item_set = true 269 super 270 end 271 272 def item_set? 273 @item_set 274 end 275 end 276 277 class SubHash2 < Hash 278 def to_json(*a) 279 { 280 JSON.create_id => self.class.name, 281 }.merge(self).to_json(*a) 282 end 283 284 def self.json_create(o) 285 o.delete JSON.create_id 286 self[o] 287 end 288 end 289 290 class SubOpenStruct < OpenStruct 291 def [](k) 292 __send__(k) 293 end 294 295 def []=(k, v) 296 @item_set = true 297 __send__("#{k}=", v) 298 end 299 300 def item_set? 301 @item_set 302 end 303 end 304 305 def test_parse_object_custom_hash_derived_class 306 res = parse('{"foo":"bar"}', :object_class => SubHash) 307 assert_equal({"foo" => "bar"}, res) 308 assert_equal(SubHash, res.class) 309 assert res.item_set? 310 end 311 312 def test_parse_object_custom_non_hash_derived_class 313 res = parse('{"foo":"bar"}', :object_class => SubOpenStruct) 314 assert_equal "bar", res.foo 315 assert_equal(SubOpenStruct, res.class) 316 assert res.item_set? 317 end 318 319 def test_parse_generic_object 320 res = parse('{"foo":"bar", "baz":{}}', :object_class => JSON::GenericObject) 321 assert_equal(JSON::GenericObject, res.class) 322 assert_equal "bar", res.foo 323 assert_equal "bar", res["foo"] 324 assert_equal "bar", res[:foo] 325 assert_equal "bar", res.to_hash[:foo] 326 assert_equal(JSON::GenericObject, res.baz.class) 327 end 328 329 def test_generate_core_subclasses_with_new_to_json 330 obj = SubHash2["foo" => SubHash2["bar" => true]] 331 obj_json = JSON(obj) 332 obj_again = JSON.parse(obj_json, :create_additions => true) 333 assert_kind_of SubHash2, obj_again 334 assert_kind_of SubHash2, obj_again['foo'] 335 assert obj_again['foo']['bar'] 336 assert_equal obj, obj_again 337 assert_equal ["foo"], JSON(JSON(SubArray2["foo"]), :create_additions => true) 338 end 339 340 def test_generate_core_subclasses_with_default_to_json 341 assert_equal '{"foo":"bar"}', JSON(SubHash["foo" => "bar"]) 342 assert_equal '["foo"]', JSON(SubArray["foo"]) 343 end 344 345 def test_generate_of_core_subclasses 346 obj = SubHash["foo" => SubHash["bar" => true]] 347 obj_json = JSON(obj) 348 obj_again = JSON(obj_json) 349 assert_kind_of Hash, obj_again 350 assert_kind_of Hash, obj_again['foo'] 351 assert obj_again['foo']['bar'] 352 assert_equal obj, obj_again 353 end 354 355 def test_parser_reset 356 parser = Parser.new(@json) 357 assert_equal(@hash, parser.parse) 358 assert_equal(@hash, parser.parse) 359 end 360 361 def test_comments 362 json = <<EOT 363{ 364 "key1":"value1", // eol comment 365 "key2":"value2" /* multi line 366 * comment */, 367 "key3":"value3" /* multi line 368 // nested eol comment 369 * comment */ 370} 371EOT 372 assert_equal( 373 { "key1" => "value1", "key2" => "value2", "key3" => "value3" }, 374 parse(json)) 375 json = <<EOT 376{ 377 "key1":"value1" /* multi line 378 // nested eol comment 379 /* illegal nested multi line comment */ 380 * comment */ 381} 382EOT 383 assert_raises(ParserError) { parse(json) } 384 json = <<EOT 385{ 386 "key1":"value1" /* multi line 387 // nested eol comment 388 closed multi comment */ 389 and again, throw an Error */ 390} 391EOT 392 assert_raises(ParserError) { parse(json) } 393 json = <<EOT 394{ 395 "key1":"value1" /*/*/ 396} 397EOT 398 assert_equal({ "key1" => "value1" }, parse(json)) 399 end 400 401 def test_backslash 402 data = [ '\\.(?i:gif|jpe?g|png)$' ] 403 json = '["\\\\.(?i:gif|jpe?g|png)$"]' 404 assert_equal json, JSON.generate(data) 405 assert_equal data, JSON.parse(json) 406 # 407 data = [ '\\"' ] 408 json = '["\\\\\""]' 409 assert_equal json, JSON.generate(data) 410 assert_equal data, JSON.parse(json) 411 # 412 json = '["/"]' 413 data = JSON.parse(json) 414 assert_equal ['/'], data 415 assert_equal json, JSON.generate(data) 416 # 417 json = '["\""]' 418 data = JSON.parse(json) 419 assert_equal ['"'], data 420 assert_equal json, JSON.generate(data) 421 json = '["\\\'"]' 422 data = JSON.parse(json) 423 assert_equal ["'"], data 424 assert_equal '["\'"]', JSON.generate(data) 425 end 426 427 def test_wrong_inputs 428 assert_raises(ParserError) { JSON.parse('"foo"') } 429 assert_raises(ParserError) { JSON.parse('123') } 430 assert_raises(ParserError) { JSON.parse('[] bla') } 431 assert_raises(ParserError) { JSON.parse('[] 1') } 432 assert_raises(ParserError) { JSON.parse('[] []') } 433 assert_raises(ParserError) { JSON.parse('[] {}') } 434 assert_raises(ParserError) { JSON.parse('{} []') } 435 assert_raises(ParserError) { JSON.parse('{} {}') } 436 assert_raises(ParserError) { JSON.parse('[NULL]') } 437 assert_raises(ParserError) { JSON.parse('[FALSE]') } 438 assert_raises(ParserError) { JSON.parse('[TRUE]') } 439 assert_raises(ParserError) { JSON.parse('[07] ') } 440 assert_raises(ParserError) { JSON.parse('[0a]') } 441 assert_raises(ParserError) { JSON.parse('[1.]') } 442 assert_raises(ParserError) { JSON.parse(' ') } 443 end 444 445 def test_nesting 446 assert_raises(JSON::NestingError) { JSON.parse '[[]]', :max_nesting => 1 } 447 assert_raises(JSON::NestingError) { JSON.parser.new('[[]]', :max_nesting => 1).parse } 448 assert_equal [[]], JSON.parse('[[]]', :max_nesting => 2) 449 too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' 450 too_deep_ary = eval too_deep 451 assert_raises(JSON::NestingError) { JSON.parse too_deep } 452 assert_raises(JSON::NestingError) { JSON.parser.new(too_deep).parse } 453 assert_raises(JSON::NestingError) { JSON.parse too_deep, :max_nesting => 100 } 454 ok = JSON.parse too_deep, :max_nesting => 101 455 assert_equal too_deep_ary, ok 456 ok = JSON.parse too_deep, :max_nesting => nil 457 assert_equal too_deep_ary, ok 458 ok = JSON.parse too_deep, :max_nesting => false 459 assert_equal too_deep_ary, ok 460 ok = JSON.parse too_deep, :max_nesting => 0 461 assert_equal too_deep_ary, ok 462 assert_raises(JSON::NestingError) { JSON.generate [[]], :max_nesting => 1 } 463 assert_equal '[[]]', JSON.generate([[]], :max_nesting => 2) 464 assert_raises(JSON::NestingError) { JSON.generate too_deep_ary } 465 assert_raises(JSON::NestingError) { JSON.generate too_deep_ary, :max_nesting => 100 } 466 ok = JSON.generate too_deep_ary, :max_nesting => 101 467 assert_equal too_deep, ok 468 ok = JSON.generate too_deep_ary, :max_nesting => nil 469 assert_equal too_deep, ok 470 ok = JSON.generate too_deep_ary, :max_nesting => false 471 assert_equal too_deep, ok 472 ok = JSON.generate too_deep_ary, :max_nesting => 0 473 assert_equal too_deep, ok 474 end 475 476 def test_symbolize_names 477 assert_equal({ "foo" => "bar", "baz" => "quux" }, 478 JSON.parse('{"foo":"bar", "baz":"quux"}')) 479 assert_equal({ :foo => "bar", :baz => "quux" }, 480 JSON.parse('{"foo":"bar", "baz":"quux"}', :symbolize_names => true)) 481 end 482 483 def test_load 484 assert_equal @hash, JSON.load(@json) 485 tempfile = Tempfile.open('json') 486 tempfile.write @json 487 tempfile.rewind 488 assert_equal @hash, JSON.load(tempfile) 489 stringio = StringIO.new(@json) 490 stringio.rewind 491 assert_equal @hash, JSON.load(stringio) 492 assert_equal nil, JSON.load(nil) 493 assert_equal nil, JSON.load('') 494 end 495 496 def test_load_with_options 497 small_hash = JSON("foo" => 'bar') 498 symbol_hash = { :foo => 'bar' } 499 assert_equal symbol_hash, JSON.load(small_hash, nil, :symbolize_names => true) 500 end 501 502 def test_dump 503 too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' 504 assert_equal too_deep, JSON.dump(eval(too_deep)) 505 assert_kind_of String, Marshal.dump(eval(too_deep)) 506 assert_raises(ArgumentError) { JSON.dump(eval(too_deep), 100) } 507 assert_raises(ArgumentError) { Marshal.dump(eval(too_deep), 100) } 508 assert_equal too_deep, JSON.dump(eval(too_deep), 101) 509 assert_kind_of String, Marshal.dump(eval(too_deep), 101) 510 output = StringIO.new 511 JSON.dump(eval(too_deep), output) 512 assert_equal too_deep, output.string 513 output = StringIO.new 514 JSON.dump(eval(too_deep), output, 101) 515 assert_equal too_deep, output.string 516 end 517 518 def test_big_integers 519 json1 = JSON([orig = (1 << 31) - 1]) 520 assert_equal orig, JSON[json1][0] 521 json2 = JSON([orig = 1 << 31]) 522 assert_equal orig, JSON[json2][0] 523 json3 = JSON([orig = (1 << 62) - 1]) 524 assert_equal orig, JSON[json3][0] 525 json4 = JSON([orig = 1 << 62]) 526 assert_equal orig, JSON[json4][0] 527 json5 = JSON([orig = 1 << 64]) 528 assert_equal orig, JSON[json5][0] 529 end 530 531 if defined?(JSON::Ext::Parser) 532 def test_allocate 533 parser = JSON::Ext::Parser.new("{}") 534 assert_raise(TypeError, '[ruby-core:35079]') {parser.__send__(:initialize, "{}")} 535 parser = JSON::Ext::Parser.allocate 536 assert_raise(TypeError, '[ruby-core:35079]') {parser.source} 537 end 538 end 539 540 def test_argument_encoding 541 source = "{}".force_encoding("ascii-8bit") 542 JSON::Parser.new(source) 543 assert_equal Encoding::ASCII_8BIT, source.encoding 544 end if defined?(Encoding::ASCII_8BIT) 545end 546