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