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