json 1.8.2 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/.travis.yml +11 -9
  4. data/{CHANGES → CHANGES.md} +220 -89
  5. data/Gemfile +10 -6
  6. data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
  7. data/{README.rdoc → README.md} +204 -137
  8. data/Rakefile +35 -113
  9. data/VERSION +1 -1
  10. data/ext/json/ext/fbuffer/fbuffer.h +0 -3
  11. data/ext/json/ext/generator/generator.c +215 -110
  12. data/ext/json/ext/generator/generator.h +18 -5
  13. data/ext/json/ext/parser/extconf.rb +3 -0
  14. data/ext/json/ext/parser/parser.c +422 -508
  15. data/ext/json/ext/parser/parser.h +15 -8
  16. data/ext/json/ext/parser/parser.rl +151 -200
  17. data/ext/json/extconf.rb +0 -1
  18. data/java/src/json/ext/ByteListTranscoder.java +1 -2
  19. data/java/src/json/ext/Generator.java +44 -22
  20. data/java/src/json/ext/GeneratorMethods.java +1 -2
  21. data/java/src/json/ext/GeneratorService.java +1 -2
  22. data/java/src/json/ext/GeneratorState.java +3 -56
  23. data/java/src/json/ext/OptionsReader.java +2 -3
  24. data/java/src/json/ext/Parser.java +132 -415
  25. data/java/src/json/ext/Parser.rl +48 -124
  26. data/java/src/json/ext/ParserService.java +1 -2
  27. data/java/src/json/ext/RuntimeInfo.java +1 -6
  28. data/java/src/json/ext/StringDecoder.java +1 -2
  29. data/java/src/json/ext/StringEncoder.java +5 -0
  30. data/java/src/json/ext/Utils.java +1 -2
  31. data/json-java.gemspec +16 -2
  32. data/json.gemspec +0 -0
  33. data/json_pure.gemspec +22 -29
  34. data/lib/json.rb +379 -29
  35. data/lib/json/add/bigdecimal.rb +3 -2
  36. data/lib/json/add/complex.rb +4 -3
  37. data/lib/json/add/core.rb +1 -0
  38. data/lib/json/add/date.rb +1 -1
  39. data/lib/json/add/date_time.rb +1 -1
  40. data/lib/json/add/exception.rb +1 -1
  41. data/lib/json/add/ostruct.rb +3 -3
  42. data/lib/json/add/range.rb +1 -1
  43. data/lib/json/add/rational.rb +3 -2
  44. data/lib/json/add/regexp.rb +3 -3
  45. data/lib/json/add/set.rb +29 -0
  46. data/lib/json/add/struct.rb +1 -1
  47. data/lib/json/add/symbol.rb +1 -1
  48. data/lib/json/add/time.rb +1 -1
  49. data/lib/json/common.rb +335 -128
  50. data/lib/json/ext.rb +0 -6
  51. data/lib/json/generic_object.rb +5 -4
  52. data/lib/json/pure.rb +2 -8
  53. data/lib/json/pure/generator.rb +64 -127
  54. data/lib/json/pure/parser.rb +42 -82
  55. data/lib/json/version.rb +2 -1
  56. data/references/rfc7159.txt +899 -0
  57. data/tests/fixtures/obsolete_fail1.json +1 -0
  58. data/tests/{test_json_addition.rb → json_addition_test.rb} +32 -25
  59. data/tests/json_common_interface_test.rb +126 -0
  60. data/tests/json_encoding_test.rb +107 -0
  61. data/tests/json_ext_parser_test.rb +15 -0
  62. data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +10 -8
  63. data/tests/{test_json_generate.rb → json_generator_test.rb} +123 -39
  64. data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
  65. data/tests/json_parser_test.rb +472 -0
  66. data/tests/json_string_matching_test.rb +38 -0
  67. data/tests/{setup_variant.rb → test_helper.rb} +6 -0
  68. data/tools/diff.sh +18 -0
  69. data/tools/fuzz.rb +1 -9
  70. metadata +46 -53
  71. data/COPYING +0 -58
  72. data/COPYING-json-jruby +0 -57
  73. data/GPL +0 -340
  74. data/TODO +0 -1
  75. data/data/example.json +0 -1
  76. data/data/index.html +0 -38
  77. data/data/prototype.js +0 -4184
  78. data/tests/fixtures/fail1.json +0 -1
  79. data/tests/test_json.rb +0 -553
  80. data/tests/test_json_encoding.rb +0 -65
  81. data/tests/test_json_string_matching.rb +0 -39
  82. data/tests/test_json_unicode.rb +0 -72
@@ -0,0 +1 @@
1
+ "A JSON payload should be an object or array, not a string."
@@ -1,16 +1,14 @@
1
- #!/usr/bin/env ruby
2
- # -*- coding:utf-8 -*-
3
-
4
- require 'test/unit'
5
- require File.join(File.dirname(__FILE__), 'setup_variant')
1
+ #frozen_string_literal: false
2
+ require 'test_helper'
6
3
  require 'json/add/core'
7
4
  require 'json/add/complex'
8
5
  require 'json/add/rational'
9
6
  require 'json/add/bigdecimal'
10
7
  require 'json/add/ostruct'
8
+ require 'json/add/set'
11
9
  require 'date'
12
10
 
13
- class TestJSONAddition < Test::Unit::TestCase
11
+ class JSONAdditionTest < Test::Unit::TestCase
14
12
  include JSON
15
13
 
16
14
  class A
@@ -64,7 +62,7 @@ class TestJSONAddition < Test::Unit::TestCase
64
62
 
65
63
  def to_json(*args)
66
64
  {
67
- 'json_class' => 'TestJSONAddition::Nix',
65
+ 'json_class' => 'JSONAdditionTest::Nix',
68
66
  }.to_json(*args)
69
67
  end
70
68
  end
@@ -73,7 +71,7 @@ class TestJSONAddition < Test::Unit::TestCase
73
71
  a = A.new(666)
74
72
  assert A.json_creatable?
75
73
  json = generate(a)
76
- a_again = JSON.parse(json, :create_additions => true)
74
+ a_again = parse(json, :create_additions => true)
77
75
  assert_kind_of a.class, a_again
78
76
  assert_equal a, a_again
79
77
  end
@@ -82,7 +80,7 @@ class TestJSONAddition < Test::Unit::TestCase
82
80
  a = A.new(666)
83
81
  assert A.json_creatable?
84
82
  json = generate(a)
85
- a_hash = JSON.parse(json)
83
+ a_hash = parse(json)
86
84
  assert_kind_of Hash, a_hash
87
85
  end
88
86
 
@@ -90,13 +88,13 @@ class TestJSONAddition < Test::Unit::TestCase
90
88
  a = A.new(666)
91
89
  assert A.json_creatable?
92
90
  json = generate(a)
93
- a_again = JSON.parse(json, :create_additions => true)
91
+ a_again = parse(json, :create_additions => true)
94
92
  assert_kind_of a.class, a_again
95
93
  assert_equal a, a_again
96
- a_hash = JSON.parse(json, :create_additions => false)
94
+ a_hash = parse(json, :create_additions => false)
97
95
  assert_kind_of Hash, a_hash
98
96
  assert_equal(
99
- {"args"=>[666], "json_class"=>"TestJSONAddition::A"}.sort_by { |k,| k },
97
+ {"args"=>[666], "json_class"=>"JSONAdditionTest::A"}.sort_by { |k,| k },
100
98
  a_hash.sort_by { |k,| k }
101
99
  )
102
100
  end
@@ -105,14 +103,14 @@ class TestJSONAddition < Test::Unit::TestCase
105
103
  b = B.new
106
104
  assert !B.json_creatable?
107
105
  json = generate(b)
108
- assert_equal({ "json_class"=>"TestJSONAddition::B" }, JSON.parse(json))
106
+ assert_equal({ "json_class"=>"JSONAdditionTest::B" }, parse(json))
109
107
  end
110
108
 
111
109
  def test_extended_json_fail2
112
110
  c = C.new
113
111
  assert !C.json_creatable?
114
112
  json = generate(c)
115
- assert_raises(ArgumentError, NameError) { JSON.parse(json, :create_additions => true) }
113
+ assert_raise(ArgumentError, NameError) { parse(json, :create_additions => true) }
116
114
  end
117
115
 
118
116
  def test_raw_strings
@@ -130,7 +128,7 @@ class TestJSONAddition < Test::Unit::TestCase
130
128
  assert_match(/\A\{.*\}\z/, json)
131
129
  assert_match(/"json_class":"String"/, json)
132
130
  assert_match(/"raw":\[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\]/, json)
133
- raw_again = JSON.parse(json, :create_additions => true)
131
+ raw_again = parse(json, :create_additions => true)
134
132
  assert_equal raw, raw_again
135
133
  end
136
134
 
@@ -151,7 +149,7 @@ class TestJSONAddition < Test::Unit::TestCase
151
149
  assert_equal s, JSON(JSON(s), :create_additions => true)
152
150
  struct = Struct.new :foo, :bar
153
151
  s = struct.new 4711, 'foot'
154
- assert_raises(JSONError) { JSON(s) }
152
+ assert_raise(JSONError) { JSON(s) }
155
153
  begin
156
154
  raise TypeError, "test me"
157
155
  rescue TypeError => e
@@ -167,19 +165,19 @@ class TestJSONAddition < Test::Unit::TestCase
167
165
 
168
166
  def test_utc_datetime
169
167
  now = Time.now
170
- d = DateTime.parse(now.to_s, :create_additions => true) # usual case
171
- assert_equal d, JSON.parse(d.to_json, :create_additions => true)
172
- d = DateTime.parse(now.utc.to_s) # of = 0
173
- assert_equal d, JSON.parse(d.to_json, :create_additions => true)
168
+ d = DateTime.parse(now.to_s, :create_additions => true) # usual case
169
+ assert_equal d, parse(d.to_json, :create_additions => true)
170
+ d = DateTime.parse(now.utc.to_s) # of = 0
171
+ assert_equal d, parse(d.to_json, :create_additions => true)
174
172
  d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(1,24))
175
- assert_equal d, JSON.parse(d.to_json, :create_additions => true)
173
+ assert_equal d, parse(d.to_json, :create_additions => true)
176
174
  d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(12,24))
177
- assert_equal d, JSON.parse(d.to_json, :create_additions => true)
175
+ assert_equal d, parse(d.to_json, :create_additions => true)
178
176
  end
179
177
 
180
178
  def test_rational_complex
181
- assert_equal Rational(2, 9), JSON.parse(JSON(Rational(2, 9)), :create_additions => true)
182
- assert_equal Complex(2, 9), JSON.parse(JSON(Complex(2, 9)), :create_additions => true)
179
+ assert_equal Rational(2, 9), parse(JSON(Rational(2, 9)), :create_additions => true)
180
+ assert_equal Complex(2, 9), parse(JSON(Complex(2, 9)), :create_additions => true)
183
181
  end
184
182
 
185
183
  def test_bigdecimal
@@ -191,6 +189,15 @@ class TestJSONAddition < Test::Unit::TestCase
191
189
  o = OpenStruct.new
192
190
  # XXX this won't work; o.foo = { :bar => true }
193
191
  o.foo = { 'bar' => true }
194
- assert_equal o, JSON.parse(JSON(o), :create_additions => true)
192
+ assert_equal o, parse(JSON(o), :create_additions => true)
193
+ end
194
+
195
+ def test_set
196
+ s = Set.new([:a, :b, :c, :a])
197
+ assert_equal s, JSON.parse(JSON(s), :create_additions => true)
198
+ ss = SortedSet.new([:d, :b, :a, :c])
199
+ ss_again = JSON.parse(JSON(ss), :create_additions => true)
200
+ assert_kind_of ss.class, ss_again
201
+ assert_equal ss, ss_again
195
202
  end
196
203
  end
@@ -0,0 +1,126 @@
1
+ #frozen_string_literal: false
2
+ require 'test_helper'
3
+ require 'stringio'
4
+ require 'tempfile'
5
+
6
+ class JSONCommonInterfaceTest < Test::Unit::TestCase
7
+ include JSON
8
+
9
+ def setup
10
+ @hash = {
11
+ 'a' => 2,
12
+ 'b' => 3.141,
13
+ 'c' => 'c',
14
+ 'd' => [ 1, "b", 3.14 ],
15
+ 'e' => { 'foo' => 'bar' },
16
+ 'g' => "\"\0\037",
17
+ 'h' => 1000.0,
18
+ 'i' => 0.001
19
+ }
20
+ @json = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},'\
21
+ '"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
22
+ end
23
+
24
+ def test_index
25
+ assert_equal @json, JSON[@hash]
26
+ assert_equal @hash, JSON[@json]
27
+ end
28
+
29
+ def test_parser
30
+ assert_match(/::Parser\z/, JSON.parser.name)
31
+ end
32
+
33
+ def test_generator
34
+ assert_match(/::Generator\z/, JSON.generator.name)
35
+ end
36
+
37
+ def test_state
38
+ assert_match(/::Generator::State\z/, JSON.state.name)
39
+ end
40
+
41
+ def test_create_id
42
+ assert_equal 'json_class', JSON.create_id
43
+ JSON.create_id = 'foo_bar'
44
+ assert_equal 'foo_bar', JSON.create_id
45
+ ensure
46
+ JSON.create_id = 'json_class'
47
+ end
48
+
49
+ def test_deep_const_get
50
+ assert_raise(ArgumentError) { JSON.deep_const_get('Nix::Da') }
51
+ assert_equal File::SEPARATOR, JSON.deep_const_get('File::SEPARATOR')
52
+ end
53
+
54
+ def test_parse
55
+ assert_equal [ 1, 2, 3, ], JSON.parse('[ 1, 2, 3 ]')
56
+ end
57
+
58
+ def test_parse_bang
59
+ assert_equal [ 1, Infinity, 3, ], JSON.parse!('[ 1, Infinity, 3 ]')
60
+ end
61
+
62
+ def test_generate
63
+ assert_equal '[1,2,3]', JSON.generate([ 1, 2, 3 ])
64
+ end
65
+
66
+ def test_fast_generate
67
+ assert_equal '[1,2,3]', JSON.generate([ 1, 2, 3 ])
68
+ end
69
+
70
+ def test_pretty_generate
71
+ assert_equal "[\n 1,\n 2,\n 3\n]", JSON.pretty_generate([ 1, 2, 3 ])
72
+ end
73
+
74
+ def test_load
75
+ assert_equal @hash, JSON.load(@json)
76
+ tempfile = Tempfile.open('@json')
77
+ tempfile.write @json
78
+ tempfile.rewind
79
+ assert_equal @hash, JSON.load(tempfile)
80
+ stringio = StringIO.new(@json)
81
+ stringio.rewind
82
+ assert_equal @hash, JSON.load(stringio)
83
+ assert_equal nil, JSON.load(nil)
84
+ assert_equal nil, JSON.load('')
85
+ ensure
86
+ tempfile.close!
87
+ end
88
+
89
+ def test_load_with_options
90
+ json = '{ "foo": NaN }'
91
+ assert JSON.load(json, nil, :allow_nan => true)['foo'].nan?
92
+ end
93
+
94
+ def test_load_null
95
+ assert_equal nil, JSON.load(nil, nil, :allow_blank => true)
96
+ assert_raise(TypeError) { JSON.load(nil, nil, :allow_blank => false) }
97
+ assert_raise(JSON::ParserError) { JSON.load('', nil, :allow_blank => false) }
98
+ end
99
+
100
+ def test_dump
101
+ too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
102
+ assert_equal too_deep, dump(eval(too_deep))
103
+ assert_kind_of String, Marshal.dump(eval(too_deep))
104
+ assert_raise(ArgumentError) { dump(eval(too_deep), 100) }
105
+ assert_raise(ArgumentError) { Marshal.dump(eval(too_deep), 100) }
106
+ assert_equal too_deep, dump(eval(too_deep), 101)
107
+ assert_kind_of String, Marshal.dump(eval(too_deep), 101)
108
+ output = StringIO.new
109
+ dump(eval(too_deep), output)
110
+ assert_equal too_deep, output.string
111
+ output = StringIO.new
112
+ dump(eval(too_deep), output, 101)
113
+ assert_equal too_deep, output.string
114
+ end
115
+
116
+ def test_dump_should_modify_defaults
117
+ max_nesting = JSON.dump_default_options[:max_nesting]
118
+ dump([], StringIO.new, 10)
119
+ assert_equal max_nesting, JSON.dump_default_options[:max_nesting]
120
+ end
121
+
122
+ def test_JSON
123
+ assert_equal @json, JSON(@hash)
124
+ assert_equal @hash, JSON(@json)
125
+ end
126
+ end
@@ -0,0 +1,107 @@
1
+ # encoding: utf-8
2
+ #frozen_string_literal: false
3
+ require 'test_helper'
4
+
5
+ class JSONEncodingTest < Test::Unit::TestCase
6
+ include JSON
7
+
8
+ def setup
9
+ @utf_8 = '"© ≠ €!"'
10
+ @ascii_8bit = @utf_8.dup.force_encoding('ascii-8bit')
11
+ @parsed = "© ≠ €!"
12
+ @generated = '"\u00a9 \u2260 \u20ac!"'
13
+ if String.method_defined?(:encode)
14
+ @utf_16_data = @parsed.encode('utf-16be', 'utf-8')
15
+ @utf_16be = @utf_8.encode('utf-16be', 'utf-8')
16
+ @utf_16le = @utf_8.encode('utf-16le', 'utf-8')
17
+ @utf_32be = @utf_8.encode('utf-32be', 'utf-8')
18
+ @utf_32le = @utf_8.encode('utf-32le', 'utf-8')
19
+ else
20
+ require 'iconv'
21
+ @utf_16_data, = Iconv.iconv('utf-16be', 'utf-8', @parsed)
22
+ @utf_16be, = Iconv.iconv('utf-16be', 'utf-8', @utf_8)
23
+ @utf_16le, = Iconv.iconv('utf-16le', 'utf-8', @utf_8)
24
+ @utf_32be, = Iconv.iconv('utf-32be', 'utf-8', @utf_8)
25
+ @utf_32le, = Iconv.iconv('utf-32le', 'utf-8', @utf_8)
26
+ end
27
+ end
28
+
29
+ def test_parse
30
+ assert_equal @parsed, JSON.parse(@ascii_8bit)
31
+ assert_equal @parsed, JSON.parse(@utf_8)
32
+ assert_equal @parsed, JSON.parse(@utf_16be)
33
+ assert_equal @parsed, JSON.parse(@utf_16le)
34
+ assert_equal @parsed, JSON.parse(@utf_32be)
35
+ assert_equal @parsed, JSON.parse(@utf_32le)
36
+ end
37
+
38
+ def test_generate
39
+ assert_equal @generated, JSON.generate(@parsed, :ascii_only => true)
40
+ assert_equal @generated, JSON.generate(@utf_16_data, :ascii_only => true)
41
+ end
42
+
43
+ def test_unicode
44
+ assert_equal '""', ''.to_json
45
+ assert_equal '"\\b"', "\b".to_json
46
+ assert_equal '"\u0001"', 0x1.chr.to_json
47
+ assert_equal '"\u001f"', 0x1f.chr.to_json
48
+ assert_equal '" "', ' '.to_json
49
+ assert_equal "\"#{0x7f.chr}\"", 0x7f.chr.to_json
50
+ utf8 = [ "© ≠ €! \01" ]
51
+ json = '["© ≠ €! \u0001"]'
52
+ assert_equal json, utf8.to_json(:ascii_only => false)
53
+ assert_equal utf8, parse(json)
54
+ json = '["\u00a9 \u2260 \u20ac! \u0001"]'
55
+ assert_equal json, utf8.to_json(:ascii_only => true)
56
+ assert_equal utf8, parse(json)
57
+ utf8 = ["\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212"]
58
+ json = "[\"\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212\"]"
59
+ assert_equal utf8, parse(json)
60
+ assert_equal json, utf8.to_json(:ascii_only => false)
61
+ utf8 = ["\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212"]
62
+ assert_equal utf8, parse(json)
63
+ json = "[\"\\u3042\\u3044\\u3046\\u3048\\u304a\"]"
64
+ assert_equal json, utf8.to_json(:ascii_only => true)
65
+ assert_equal utf8, parse(json)
66
+ utf8 = ['საქართველო']
67
+ json = '["საქართველო"]'
68
+ assert_equal json, utf8.to_json(:ascii_only => false)
69
+ json = "[\"\\u10e1\\u10d0\\u10e5\\u10d0\\u10e0\\u10d7\\u10d5\\u10d4\\u10da\\u10dd\"]"
70
+ assert_equal json, utf8.to_json(:ascii_only => true)
71
+ assert_equal utf8, parse(json)
72
+ assert_equal '["Ã"]', generate(["Ã"], :ascii_only => false)
73
+ assert_equal '["\\u00c3"]', generate(["Ã"], :ascii_only => true)
74
+ assert_equal ["€"], parse('["\u20ac"]')
75
+ utf8 = ["\xf0\xa0\x80\x81"]
76
+ json = "[\"\xf0\xa0\x80\x81\"]"
77
+ assert_equal json, generate(utf8, :ascii_only => false)
78
+ assert_equal utf8, parse(json)
79
+ json = '["\ud840\udc01"]'
80
+ assert_equal json, generate(utf8, :ascii_only => true)
81
+ assert_equal utf8, parse(json)
82
+ assert_raise(JSON::ParserError) { parse('"\u"') }
83
+ assert_raise(JSON::ParserError) { parse('"\ud800"') }
84
+ end
85
+
86
+ def test_chars
87
+ (0..0x7f).each do |i|
88
+ json = '["\u%04x"]' % i
89
+ if RUBY_VERSION >= "1.9."
90
+ i = i.chr
91
+ end
92
+ assert_equal i, parse(json).first[0]
93
+ if i == ?\b
94
+ generated = generate(["" << i])
95
+ assert '["\b"]' == generated || '["\10"]' == generated
96
+ elsif [?\n, ?\r, ?\t, ?\f].include?(i)
97
+ assert_equal '[' << ('' << i).dump << ']', generate(["" << i])
98
+ elsif i.chr < 0x20.chr
99
+ assert_equal json, generate(["" << i])
100
+ end
101
+ end
102
+ assert_raise(JSON::GeneratorError) do
103
+ generate(["\x80"], :ascii_only => true)
104
+ end
105
+ assert_equal "\302\200", parse('["\u0080"]').first
106
+ end
107
+ end
@@ -0,0 +1,15 @@
1
+ #frozen_string_literal: false
2
+ require 'test_helper'
3
+
4
+ class JSONExtParserTest < Test::Unit::TestCase
5
+ if defined?(JSON::Ext::Parser)
6
+ def test_allocate
7
+ parser = JSON::Ext::Parser.new("{}")
8
+ assert_raise(TypeError, '[ruby-core:35079]') do
9
+ parser.__send__(:initialize, "{}")
10
+ end
11
+ parser = JSON::Ext::Parser.allocate
12
+ assert_raise(TypeError, '[ruby-core:35079]') { parser.source }
13
+ end
14
+ end
15
+ end
@@ -1,12 +1,9 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
1
+ #frozen_string_literal: false
2
+ require 'test_helper'
3
3
 
4
- require 'test/unit'
5
- require File.join(File.dirname(__FILE__), 'setup_variant')
6
-
7
- class TestJSONFixtures < Test::Unit::TestCase
4
+ class JSONFixturesTest < Test::Unit::TestCase
8
5
  def setup
9
- fixtures = File.join(File.dirname(__FILE__), 'fixtures/*.json')
6
+ fixtures = File.join(File.dirname(__FILE__), 'fixtures/{fail,pass}*.json')
10
7
  passed, failed = Dir[fixtures].partition { |f| f['pass'] }
11
8
  @passed = passed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
12
9
  @failed = failed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
@@ -26,10 +23,15 @@ class TestJSONFixtures < Test::Unit::TestCase
26
23
 
27
24
  def test_failing
28
25
  for name, source in @failed
29
- assert_raises(JSON::ParserError, JSON::NestingError,
26
+ assert_raise(JSON::ParserError, JSON::NestingError,
30
27
  "Did not fail for fixture '#{name}': #{source.inspect}") do
31
28
  JSON.parse(source)
32
29
  end
33
30
  end
34
31
  end
32
+
33
+ def test_sanity
34
+ assert(@passed.size > 5)
35
+ assert(@failed.size > 20)
36
+ end
35
37
  end
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: utf-8
3
+ # frozen_string_literal: false
3
4
 
4
- require 'test/unit'
5
- require File.join(File.dirname(__FILE__), 'setup_variant')
5
+ require 'test_helper'
6
6
 
7
- class TestJSONGenerate < Test::Unit::TestCase
7
+ class JSONGeneratorTest < Test::Unit::TestCase
8
8
  include JSON
9
9
 
10
10
  def setup
@@ -40,25 +40,63 @@ class TestJSONGenerate < Test::Unit::TestCase
40
40
  EOT
41
41
  end
42
42
 
43
+ def silence
44
+ v = $VERBOSE
45
+ $VERBOSE = nil
46
+ yield
47
+ ensure
48
+ $VERBOSE = v
49
+ end
50
+
51
+ def test_remove_const_segv
52
+ return if RUBY_ENGINE == 'jruby'
53
+ stress = GC.stress
54
+ const = JSON::SAFE_STATE_PROTOTYPE.dup
55
+
56
+ bignum_too_long_to_embed_as_string = 1234567890123456789012345
57
+ expect = bignum_too_long_to_embed_as_string.to_s
58
+ GC.stress = true
59
+
60
+ 10.times do |i|
61
+ tmp = bignum_too_long_to_embed_as_string.to_json
62
+ raise "'\#{expect}' is expected, but '\#{tmp}'" unless tmp == expect
63
+ end
64
+
65
+ silence do
66
+ JSON.const_set :SAFE_STATE_PROTOTYPE, nil
67
+ end
68
+
69
+ 10.times do |i|
70
+ assert_raise TypeError do
71
+ bignum_too_long_to_embed_as_string.to_json
72
+ end
73
+ end
74
+ ensure
75
+ GC.stress = stress
76
+ silence do
77
+ JSON.const_set :SAFE_STATE_PROTOTYPE, const
78
+ end
79
+ end if JSON.const_defined?("Ext")
80
+
43
81
  def test_generate
44
82
  json = generate(@hash)
45
- assert_equal(JSON.parse(@json2), JSON.parse(json))
83
+ assert_equal(parse(@json2), parse(json))
46
84
  json = JSON[@hash]
47
- assert_equal(JSON.parse(@json2), JSON.parse(json))
85
+ assert_equal(parse(@json2), parse(json))
48
86
  parsed_json = parse(json)
49
87
  assert_equal(@hash, parsed_json)
50
88
  json = generate({1=>2})
51
89
  assert_equal('{"1":2}', json)
52
90
  parsed_json = parse(json)
53
91
  assert_equal({"1"=>2}, parsed_json)
54
- assert_raise(GeneratorError) { generate(666) }
55
- assert_equal '666', generate(666, :quirks_mode => true)
92
+ assert_equal '666', generate(666)
56
93
  end
57
94
 
58
95
  def test_generate_pretty
59
96
  json = pretty_generate(@hash)
60
- # hashes aren't (insertion) ordered on every ruby implementation assert_equal(@json3, json)
61
- assert_equal(JSON.parse(@json3), JSON.parse(json))
97
+ # hashes aren't (insertion) ordered on every ruby implementation
98
+ # assert_equal(@json3, json)
99
+ assert_equal(parse(@json3), parse(json))
62
100
  parsed_json = parse(json)
63
101
  assert_equal(@hash, parsed_json)
64
102
  json = pretty_generate({1=>2})
@@ -69,8 +107,7 @@ EOT
69
107
  EOT
70
108
  parsed_json = parse(json)
71
109
  assert_equal({"1"=>2}, parsed_json)
72
- assert_raise(GeneratorError) { pretty_generate(666) }
73
- assert_equal '666', pretty_generate(666, :quirks_mode => true)
110
+ assert_equal '666', pretty_generate(666)
74
111
  end
75
112
 
76
113
  def test_generate_custom
@@ -88,30 +125,26 @@ EOT
88
125
 
89
126
  def test_fast_generate
90
127
  json = fast_generate(@hash)
91
- assert_equal(JSON.parse(@json2), JSON.parse(json))
128
+ assert_equal(parse(@json2), parse(json))
92
129
  parsed_json = parse(json)
93
130
  assert_equal(@hash, parsed_json)
94
131
  json = fast_generate({1=>2})
95
132
  assert_equal('{"1":2}', json)
96
133
  parsed_json = parse(json)
97
134
  assert_equal({"1"=>2}, parsed_json)
98
- assert_raise(GeneratorError) { fast_generate(666) }
99
- assert_equal '666', fast_generate(666, :quirks_mode => true)
135
+ assert_equal '666', fast_generate(666)
100
136
  end
101
137
 
102
138
  def test_own_state
103
139
  state = State.new
104
140
  json = generate(@hash, state)
105
- assert_equal(JSON.parse(@json2), JSON.parse(json))
141
+ assert_equal(parse(@json2), parse(json))
106
142
  parsed_json = parse(json)
107
143
  assert_equal(@hash, parsed_json)
108
144
  json = generate({1=>2}, state)
109
145
  assert_equal('{"1":2}', json)
110
146
  parsed_json = parse(json)
111
147
  assert_equal({"1"=>2}, parsed_json)
112
- assert_raise(GeneratorError) { generate(666, state) }
113
- state.quirks_mode = true
114
- assert state.quirks_mode?
115
148
  assert_equal '666', generate(666, state)
116
149
  end
117
150
 
@@ -123,12 +156,12 @@ EOT
123
156
  assert s[:check_circular?]
124
157
  h = { 1=>2 }
125
158
  h[3] = h
126
- assert_raises(JSON::NestingError) { generate(h) }
127
- assert_raises(JSON::NestingError) { generate(h, s) }
159
+ assert_raise(JSON::NestingError) { generate(h) }
160
+ assert_raise(JSON::NestingError) { generate(h, s) }
128
161
  s = JSON.state.new
129
162
  a = [ 1, 2 ]
130
163
  a << a
131
- assert_raises(JSON::NestingError) { generate(a, s) }
164
+ assert_raise(JSON::NestingError) { generate(a, s) }
132
165
  assert s.check_circular?
133
166
  assert s[:check_circular?]
134
167
  end
@@ -140,7 +173,6 @@ EOT
140
173
  :array_nl => "\n",
141
174
  :ascii_only => false,
142
175
  :buffer_initial_length => 1024,
143
- :quirks_mode => false,
144
176
  :depth => 0,
145
177
  :indent => " ",
146
178
  :max_nesting => 100,
@@ -157,7 +189,6 @@ EOT
157
189
  :array_nl => "",
158
190
  :ascii_only => false,
159
191
  :buffer_initial_length => 1024,
160
- :quirks_mode => false,
161
192
  :depth => 0,
162
193
  :indent => "",
163
194
  :max_nesting => 100,
@@ -174,7 +205,6 @@ EOT
174
205
  :array_nl => "",
175
206
  :ascii_only => false,
176
207
  :buffer_initial_length => 1024,
177
- :quirks_mode => false,
178
208
  :depth => 0,
179
209
  :indent => "",
180
210
  :max_nesting => 0,
@@ -185,34 +215,34 @@ EOT
185
215
  end
186
216
 
187
217
  def test_allow_nan
188
- assert_raises(GeneratorError) { generate([JSON::NaN]) }
218
+ assert_raise(GeneratorError) { generate([JSON::NaN]) }
189
219
  assert_equal '[NaN]', generate([JSON::NaN], :allow_nan => true)
190
- assert_raises(GeneratorError) { fast_generate([JSON::NaN]) }
191
- assert_raises(GeneratorError) { pretty_generate([JSON::NaN]) }
220
+ assert_raise(GeneratorError) { fast_generate([JSON::NaN]) }
221
+ assert_raise(GeneratorError) { pretty_generate([JSON::NaN]) }
192
222
  assert_equal "[\n NaN\n]", pretty_generate([JSON::NaN], :allow_nan => true)
193
- assert_raises(GeneratorError) { generate([JSON::Infinity]) }
223
+ assert_raise(GeneratorError) { generate([JSON::Infinity]) }
194
224
  assert_equal '[Infinity]', generate([JSON::Infinity], :allow_nan => true)
195
- assert_raises(GeneratorError) { fast_generate([JSON::Infinity]) }
196
- assert_raises(GeneratorError) { pretty_generate([JSON::Infinity]) }
225
+ assert_raise(GeneratorError) { fast_generate([JSON::Infinity]) }
226
+ assert_raise(GeneratorError) { pretty_generate([JSON::Infinity]) }
197
227
  assert_equal "[\n Infinity\n]", pretty_generate([JSON::Infinity], :allow_nan => true)
198
- assert_raises(GeneratorError) { generate([JSON::MinusInfinity]) }
228
+ assert_raise(GeneratorError) { generate([JSON::MinusInfinity]) }
199
229
  assert_equal '[-Infinity]', generate([JSON::MinusInfinity], :allow_nan => true)
200
- assert_raises(GeneratorError) { fast_generate([JSON::MinusInfinity]) }
201
- assert_raises(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
230
+ assert_raise(GeneratorError) { fast_generate([JSON::MinusInfinity]) }
231
+ assert_raise(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
202
232
  assert_equal "[\n -Infinity\n]", pretty_generate([JSON::MinusInfinity], :allow_nan => true)
203
233
  end
204
234
 
205
235
  def test_depth
206
236
  ary = []; ary << ary
207
237
  assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
208
- assert_raises(JSON::NestingError) { JSON.generate(ary) }
238
+ assert_raise(JSON::NestingError) { generate(ary) }
209
239
  assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
210
240
  assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
211
- assert_raises(JSON::NestingError) { JSON.pretty_generate(ary) }
241
+ assert_raise(JSON::NestingError) { JSON.pretty_generate(ary) }
212
242
  assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
213
243
  s = JSON.state.new
214
244
  assert_equal 0, s.depth
215
- assert_raises(JSON::NestingError) { ary.to_json(s) }
245
+ assert_raise(JSON::NestingError) { ary.to_json(s) }
216
246
  assert_equal 100, s.depth
217
247
  end
218
248
 
@@ -285,12 +315,13 @@ EOT
285
315
  if defined?(JSON::Ext::Generator)
286
316
  def test_broken_bignum # [ruby-core:38867]
287
317
  pid = fork do
288
- Bignum.class_eval do
318
+ x = 1 << 64
319
+ x.class.class_eval do
289
320
  def to_s
290
321
  end
291
322
  end
292
323
  begin
293
- JSON::Ext::Generator::State.new.generate(1<<64)
324
+ JSON::Ext::Generator::State.new.generate(x)
294
325
  exit 1
295
326
  rescue TypeError
296
327
  exit 0
@@ -331,7 +362,60 @@ EOT
331
362
 
332
363
  def test_json_generate
333
364
  assert_raise JSON::GeneratorError do
334
- assert_equal true, JSON.generate(["\xea"])
365
+ assert_equal true, generate(["\xea"])
366
+ end
367
+ end
368
+
369
+ def test_nesting
370
+ too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
371
+ too_deep_ary = eval too_deep
372
+ assert_raise(JSON::NestingError) { generate too_deep_ary }
373
+ assert_raise(JSON::NestingError) { generate too_deep_ary, :max_nesting => 100 }
374
+ ok = generate too_deep_ary, :max_nesting => 101
375
+ assert_equal too_deep, ok
376
+ ok = generate too_deep_ary, :max_nesting => nil
377
+ assert_equal too_deep, ok
378
+ ok = generate too_deep_ary, :max_nesting => false
379
+ assert_equal too_deep, ok
380
+ ok = generate too_deep_ary, :max_nesting => 0
381
+ assert_equal too_deep, ok
382
+ end
383
+
384
+ def test_backslash
385
+ data = [ '\\.(?i:gif|jpe?g|png)$' ]
386
+ json = '["\\\\.(?i:gif|jpe?g|png)$"]'
387
+ assert_equal json, generate(data)
388
+ #
389
+ data = [ '\\"' ]
390
+ json = '["\\\\\""]'
391
+ assert_equal json, generate(data)
392
+ #
393
+ data = [ '/' ]
394
+ json = '["/"]'
395
+ assert_equal json, generate(data)
396
+ #
397
+ data = ['"']
398
+ json = '["\""]'
399
+ assert_equal json, generate(data)
400
+ #
401
+ data = ["'"]
402
+ json = '["\\\'"]'
403
+ assert_equal '["\'"]', generate(data)
404
+ end
405
+
406
+ def test_string_subclass
407
+ s = Class.new(String) do
408
+ def to_s; self; end
409
+ undef to_json
410
+ end
411
+ assert_nothing_raised(SystemStackError) do
412
+ assert_equal '["foo"]', JSON.generate([s.new('foo')])
413
+ end
414
+ end
415
+
416
+ if defined?(Encoding)
417
+ def test_nonutf8_encoding
418
+ assert_equal("\"5\u{b0}\"", "5\xb0".force_encoding("iso-8859-1").to_json)
335
419
  end
336
420
  end
337
421
  end