oj 2.18.3 → 3.13.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (182) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1324 -0
  3. data/README.md +51 -204
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +49 -72
  6. data/ext/oj/cache.c +326 -0
  7. data/ext/oj/cache.h +21 -0
  8. data/ext/oj/cache8.c +61 -64
  9. data/ext/oj/cache8.h +12 -39
  10. data/ext/oj/circarray.c +37 -68
  11. data/ext/oj/circarray.h +16 -42
  12. data/ext/oj/code.c +221 -0
  13. data/ext/oj/code.h +40 -0
  14. data/ext/oj/compat.c +231 -107
  15. data/ext/oj/custom.c +1125 -0
  16. data/ext/oj/debug.c +132 -0
  17. data/ext/oj/dump.c +935 -2513
  18. data/ext/oj/dump.h +108 -0
  19. data/ext/oj/dump_compat.c +936 -0
  20. data/ext/oj/dump_leaf.c +164 -0
  21. data/ext/oj/dump_object.c +761 -0
  22. data/ext/oj/dump_strict.c +410 -0
  23. data/ext/oj/encode.h +7 -42
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +40 -54
  26. data/ext/oj/err.h +52 -46
  27. data/ext/oj/extconf.rb +21 -30
  28. data/ext/oj/fast.c +1097 -1080
  29. data/ext/oj/intern.c +301 -0
  30. data/ext/oj/intern.h +26 -0
  31. data/ext/oj/mimic_json.c +893 -0
  32. data/ext/oj/object.c +549 -620
  33. data/ext/oj/odd.c +155 -167
  34. data/ext/oj/odd.h +37 -63
  35. data/ext/oj/oj.c +1661 -2063
  36. data/ext/oj/oj.h +341 -270
  37. data/ext/oj/parse.c +974 -737
  38. data/ext/oj/parse.h +105 -97
  39. data/ext/oj/parser.c +1526 -0
  40. data/ext/oj/parser.h +90 -0
  41. data/ext/oj/rails.c +1504 -0
  42. data/ext/oj/rails.h +18 -0
  43. data/ext/oj/reader.c +141 -163
  44. data/ext/oj/reader.h +75 -113
  45. data/ext/oj/resolve.c +45 -93
  46. data/ext/oj/resolve.h +7 -34
  47. data/ext/oj/rxclass.c +143 -0
  48. data/ext/oj/rxclass.h +26 -0
  49. data/ext/oj/saj.c +447 -511
  50. data/ext/oj/saj2.c +348 -0
  51. data/ext/oj/scp.c +91 -138
  52. data/ext/oj/sparse.c +793 -644
  53. data/ext/oj/stream_writer.c +331 -0
  54. data/ext/oj/strict.c +145 -109
  55. data/ext/oj/string_writer.c +493 -0
  56. data/ext/oj/trace.c +72 -0
  57. data/ext/oj/trace.h +28 -0
  58. data/ext/oj/usual.c +1254 -0
  59. data/ext/oj/util.c +136 -0
  60. data/ext/oj/util.h +20 -0
  61. data/ext/oj/val_stack.c +62 -70
  62. data/ext/oj/val_stack.h +95 -129
  63. data/ext/oj/validate.c +51 -0
  64. data/ext/oj/wab.c +622 -0
  65. data/lib/oj/bag.rb +1 -0
  66. data/lib/oj/easy_hash.rb +17 -8
  67. data/lib/oj/error.rb +10 -11
  68. data/lib/oj/json.rb +176 -0
  69. data/lib/oj/mimic.rb +158 -19
  70. data/lib/oj/state.rb +132 -0
  71. data/lib/oj/version.rb +2 -2
  72. data/lib/oj.rb +1 -31
  73. data/pages/Advanced.md +22 -0
  74. data/pages/Compatibility.md +25 -0
  75. data/pages/Custom.md +23 -0
  76. data/pages/Encoding.md +65 -0
  77. data/pages/JsonGem.md +94 -0
  78. data/pages/Modes.md +161 -0
  79. data/pages/Options.md +327 -0
  80. data/pages/Parser.md +309 -0
  81. data/pages/Rails.md +167 -0
  82. data/pages/Security.md +20 -0
  83. data/pages/WAB.md +13 -0
  84. data/test/activerecord/result_test.rb +32 -0
  85. data/test/activesupport4/decoding_test.rb +108 -0
  86. data/test/activesupport4/encoding_test.rb +531 -0
  87. data/test/activesupport4/test_helper.rb +41 -0
  88. data/test/activesupport5/abstract_unit.rb +45 -0
  89. data/test/activesupport5/decoding_test.rb +133 -0
  90. data/test/activesupport5/encoding_test.rb +500 -0
  91. data/test/activesupport5/encoding_test_cases.rb +98 -0
  92. data/test/activesupport5/test_helper.rb +72 -0
  93. data/test/activesupport5/time_zone_test_helpers.rb +39 -0
  94. data/test/activesupport6/abstract_unit.rb +44 -0
  95. data/test/activesupport6/decoding_test.rb +133 -0
  96. data/test/activesupport6/encoding_test.rb +507 -0
  97. data/test/activesupport6/encoding_test_cases.rb +98 -0
  98. data/test/activesupport6/test_common.rb +17 -0
  99. data/test/activesupport6/test_helper.rb +163 -0
  100. data/test/activesupport6/time_zone_test_helpers.rb +39 -0
  101. data/test/activesupport7/abstract_unit.rb +49 -0
  102. data/test/activesupport7/decoding_test.rb +125 -0
  103. data/test/activesupport7/encoding_test.rb +486 -0
  104. data/test/activesupport7/encoding_test_cases.rb +104 -0
  105. data/test/activesupport7/time_zone_test_helpers.rb +47 -0
  106. data/test/bar.rb +9 -0
  107. data/test/baz.rb +16 -0
  108. data/test/bug.rb +11 -46
  109. data/test/foo.rb +69 -16
  110. data/test/helper.rb +10 -1
  111. data/test/isolated/shared.rb +12 -8
  112. data/test/isolated/test_mimic_rails_after.rb +3 -3
  113. data/test/isolated/test_mimic_rails_before.rb +3 -3
  114. data/test/json_gem/json_addition_test.rb +216 -0
  115. data/test/json_gem/json_common_interface_test.rb +153 -0
  116. data/test/json_gem/json_encoding_test.rb +107 -0
  117. data/test/json_gem/json_ext_parser_test.rb +20 -0
  118. data/test/json_gem/json_fixtures_test.rb +35 -0
  119. data/test/json_gem/json_generator_test.rb +397 -0
  120. data/test/json_gem/json_generic_object_test.rb +90 -0
  121. data/test/json_gem/json_parser_test.rb +470 -0
  122. data/test/json_gem/json_string_matching_test.rb +42 -0
  123. data/test/json_gem/test_helper.rb +26 -0
  124. data/test/mem.rb +33 -0
  125. data/test/perf.rb +1 -1
  126. data/test/perf_compat.rb +30 -28
  127. data/test/perf_dump.rb +50 -0
  128. data/test/perf_object.rb +1 -1
  129. data/test/perf_once.rb +58 -0
  130. data/test/perf_parser.rb +189 -0
  131. data/test/perf_scp.rb +11 -10
  132. data/test/perf_strict.rb +30 -19
  133. data/test/perf_wab.rb +131 -0
  134. data/test/prec.rb +23 -0
  135. data/test/sample.rb +0 -1
  136. data/test/sample_json.rb +1 -1
  137. data/test/test_compat.rb +219 -102
  138. data/test/test_custom.rb +533 -0
  139. data/test/test_fast.rb +107 -35
  140. data/test/test_file.rb +19 -25
  141. data/test/test_generate.rb +21 -0
  142. data/test/test_hash.rb +11 -1
  143. data/test/test_integer_range.rb +72 -0
  144. data/test/test_null.rb +376 -0
  145. data/test/test_object.rb +357 -70
  146. data/test/test_parser.rb +27 -0
  147. data/test/test_parser_saj.rb +245 -0
  148. data/test/test_parser_usual.rb +217 -0
  149. data/test/test_rails.rb +35 -0
  150. data/test/test_saj.rb +1 -1
  151. data/test/test_scp.rb +39 -2
  152. data/test/test_strict.rb +186 -7
  153. data/test/test_various.rb +160 -774
  154. data/test/test_wab.rb +307 -0
  155. data/test/test_writer.rb +90 -2
  156. data/test/tests.rb +24 -0
  157. data/test/tests_mimic.rb +14 -0
  158. data/test/tests_mimic_addition.rb +7 -0
  159. data/test/zoo.rb +13 -0
  160. metadata +194 -56
  161. data/ext/oj/hash.c +0 -163
  162. data/ext/oj/hash.h +0 -46
  163. data/ext/oj/hash_test.c +0 -512
  164. data/test/activesupport_datetime_test.rb +0 -23
  165. data/test/bug2.rb +0 -10
  166. data/test/bug3.rb +0 -46
  167. data/test/bug_fast.rb +0 -32
  168. data/test/bug_load.rb +0 -24
  169. data/test/crash.rb +0 -111
  170. data/test/curl/curl_oj.rb +0 -46
  171. data/test/curl/get_oj.rb +0 -24
  172. data/test/curl/just_curl.rb +0 -31
  173. data/test/curl/just_oj.rb +0 -51
  174. data/test/example.rb +0 -11
  175. data/test/io.rb +0 -48
  176. data/test/isolated/test_mimic_rails_datetime.rb +0 -27
  177. data/test/mod.rb +0 -16
  178. data/test/rails.rb +0 -50
  179. data/test/russian.rb +0 -18
  180. data/test/struct.rb +0 -29
  181. data/test/test_serializer.rb +0 -59
  182. data/test/write_timebars.rb +0 -31
data/test/bug.rb CHANGED
@@ -1,51 +1,16 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
1
+ $: << '.'
2
+ $: << File.join(File.dirname(__FILE__), "../lib")
3
+ $: << File.join(File.dirname(__FILE__), "../ext")
3
4
 
4
- $: << File.dirname(__FILE__)
5
5
 
6
- require 'helper'
6
+ #require 'bundler/setup'
7
+ require 'oj'
8
+ require 'active_support'
9
+ require 'active_support/time_with_zone'
10
+ require 'tzinfo'
7
11
 
8
- class Handler
9
- def initialize
10
- @state = []
11
- end
12
+ puts ActiveSupport::TimeWithZone
12
13
 
13
- def hash_start
14
- @state << {}
15
- @state.last
16
- end
14
+ json = File.read('./bug.json')
17
15
 
18
- def hash_end
19
- @state.pop
20
- end
21
-
22
- def hash_set(h,k,v)
23
- h.store(k,v)
24
- end
25
-
26
- def array_start
27
- @state << []
28
- @state.last
29
- end
30
-
31
-
32
- def array_end
33
- @state.pop
34
- end
35
-
36
- def array_append(a,v)
37
- a << v
38
- end
39
-
40
- def add_value(v)
41
- p v
42
- end
43
-
44
- def error(message, line, column); p "ERROR: #{message}" end
45
- end
46
-
47
- $handler = Handler.new
48
-
49
- IO.popen("cat tst") { |p| puts Oj.sc_parse($handler, p) }
50
-
51
- #File.open('tst', 'r') { |file| Oj.sc_parse($handler, file) }
16
+ Oj.load(json)
data/test/foo.rb CHANGED
@@ -1,24 +1,77 @@
1
1
  #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
2
 
4
- $VERBOSE = true
3
+ $: << '.'
4
+ $: << File.join(File.dirname(__FILE__), "../lib")
5
+ $: << File.join(File.dirname(__FILE__), "../ext")
5
6
 
6
- here = File.expand_path(File.dirname(__FILE__))
7
- $: << File.dirname(__FILE__)
8
- $: << File.join(File.dirname(here), 'ext')
9
- $: << File.join(File.dirname(here), 'lib')
7
+ require "oj"
8
+ require "socket"
9
+ require 'io/nonblock'
10
10
 
11
- require 'oj'
12
-
13
- Oj.mimic_JSON()
11
+ #pid = spawn("nc -d 0.1 -l 5000", out: "/dev/null")
12
+ pid = spawn("nc -i 1 -l 7777", out: "/dev/null")
13
+ at_exit { Process.kill 9, pid }
14
+ sleep 0.2
15
+ s = Socket.tcp("localhost", 7777)
16
+ s.nonblock = false
17
+ 1_000_000.times do |x|
18
+ Oj.to_stream(s, { x: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]})
19
+ end
14
20
 
15
- class Foo
16
- def as_json
17
- { foo: 'bar' }
21
+ =begin
22
+ IO.pipe do |r, w|
23
+ if fork
24
+ r.close
25
+ #w.nonblock = false
26
+ 1_000_000.times do |i|
27
+ begin
28
+ Oj.to_stream(w, { x: i})
29
+ rescue IOError => e
30
+ puts "*** #{i} raised #{e.class}: #{e}"
31
+ IO.select(nil, [w])
32
+ retry
33
+ end
34
+ w.puts
35
+ end
36
+ else
37
+ w.close
38
+ sleep(0.1)
39
+ r.each_line { |b|
40
+ #print b
41
+ }
42
+ r.close
43
+ Process.exit(0)
18
44
  end
19
45
  end
46
+ =end
20
47
 
21
- opts = {}
22
-
23
- puts Foo.new.to_json
24
- puts Foo.new.to_json(opts)
48
+ =begin
49
+ IO.pipe do |r, w|
50
+ if fork
51
+ r.close
52
+ #w.nonblock = false
53
+ a = []
54
+ 10_000.times do |i|
55
+ a << i
56
+ end
57
+ begin
58
+ Oj.to_stream(w, a, indent: 2)
59
+ rescue IOError => e
60
+ puts "*** raised #{e.class}: #{e}"
61
+ puts "*** fileno: #{w.fileno}"
62
+ puts "*** is an IO?: #{w.kind_of?(IO)}"
63
+ IO.select(nil, [w])
64
+ retry
65
+ end
66
+ w.puts
67
+ else
68
+ w.close
69
+ sleep(0.5)
70
+ r.each_line { |b|
71
+ #print b
72
+ }
73
+ r.close
74
+ Process.exit(0)
75
+ end
76
+ end
77
+ =end
data/test/helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+ #
1
3
  # Ubuntu does not accept arguments to ruby when called using env. To get warnings to show up the -w options is
2
4
  # required. That can be set in the RUBYOPT environment variable.
3
5
  # export RUBYOPT=-w
@@ -8,7 +10,6 @@ $VERBOSE = true
8
10
  $LOAD_PATH.unshift File.expand_path("../../#{dir}", __FILE__)
9
11
  end
10
12
 
11
- require 'rubygems' if RUBY_VERSION.start_with?('1.8.')
12
13
  require 'minitest'
13
14
  require 'minitest/autorun'
14
15
  require 'stringio'
@@ -17,6 +18,14 @@ require 'bigdecimal'
17
18
  require 'pp'
18
19
  require 'oj'
19
20
 
21
+
22
+ if defined?(GC.verify_compaction_references) == 'method'
23
+ # This method was added in Ruby 3.0.0. Calling it this way asks the GC to
24
+ # move objects around, helping to find object movement bugs.
25
+ GC.verify_compaction_references(double_heap: true, toward: :empty)
26
+ end
27
+
28
+
20
29
  $ruby = RUBY_DESCRIPTION.split(' ')[0]
21
30
  $ruby = 'ree' if 'ruby' == $ruby && RUBY_DESCRIPTION.include?('Ruby Enterprise Edition')
22
31
 
@@ -36,8 +36,6 @@ class SharedMimicTest < Minitest::Test
36
36
  @expected_time_string =
37
37
  if defined?(Rails)
38
38
  %{"2014-05-13T16:53:20.000Z"}
39
- elsif RUBY_VERSION.start_with?('1.8')
40
- %{"Tue May 13 16:53:20 UTC 2014"}
41
39
  else
42
40
  %{"2014-05-13 16:53:20 UTC"}
43
41
  end
@@ -145,7 +143,7 @@ class SharedMimicTest < Minitest::Test
145
143
  Oj.mimic_JSON
146
144
  children = []
147
145
  json = %{{"a":1,"b":[true,false]}}
148
- if 'rubinius' == $ruby || '1.8.7' == RUBY_VERSION
146
+ if 'rubinius' == $ruby
149
147
  obj = JSON.load(json) {|x| children << x }
150
148
  else
151
149
  p = Proc.new {|x| children << x }
@@ -164,6 +162,12 @@ class SharedMimicTest < Minitest::Test
164
162
  assert_raises(JSON::ParserError) { JSON.parse(json) }
165
163
  end
166
164
 
165
+ def test_parse_with_empty_string
166
+ Oj.mimic_JSON
167
+ assert_raises(JSON::ParserError) { JSON.parse(' ') }
168
+ assert_raises(JSON::ParserError) { JSON.parse("\t\t\n ") }
169
+ end
170
+
167
171
  # []
168
172
  def test_bracket_load
169
173
  json = %{{"a":1,"b":[true,false]}}
@@ -217,18 +221,18 @@ class SharedMimicTest < Minitest::Test
217
221
  def test_pretty_generate
218
222
  json = JSON.pretty_generate({ 'a' => 1, 'b' => [true, false]})
219
223
  assert(%{{
220
- "a" : 1,
221
- "b" : [
224
+ "a": 1,
225
+ "b": [
222
226
  true,
223
227
  false
224
228
  ]
225
229
  }} == json ||
226
230
  %{{
227
- "b" : [
231
+ "b": [
228
232
  true,
229
233
  false
230
234
  ],
231
- "a" : 1
235
+ "a": 1
232
236
  }} == json)
233
237
  end
234
238
 
@@ -269,7 +273,7 @@ class SharedMimicTest < Minitest::Test
269
273
  children = []
270
274
  JSON.recurse_proc({ 'a' => 1, 'b' => [true, false]}) { |x| children << x }
271
275
  # JRuby 1.7.0 rb_yield() is broken and converts the [true, false] array into true
272
- unless 'jruby' == $ruby && '1.9.3' == RUBY_VERSION
276
+ unless 'jruby' == $ruby
273
277
  assert([1, true, false, [true, false], { 'a' => 1, 'b' => [true, false]}] == children ||
274
278
  [true, false, [true, false], 1, { 'b' => [true, false], 'a' => 1}] == children)
275
279
  end
@@ -7,9 +7,9 @@ require 'helper'
7
7
 
8
8
  begin
9
9
  require 'rails/all'
10
- rescue Exception => e
11
- puts "*** #{e.class}: #{e.message}"
12
- Process.exit!(false)
10
+ rescue LoadError => e
11
+ puts "Rails are not in the gemfile, skipping tests"
12
+ Process.exit
13
13
  end
14
14
 
15
15
  Oj.mimic_JSON
@@ -8,9 +8,9 @@ require 'helper'
8
8
  Oj.mimic_JSON
9
9
  begin
10
10
  require 'rails/all'
11
- rescue Exception
12
- puts "*** require of rails failed"
13
- Process.exit!(true)
11
+ rescue LoadError => e
12
+ puts "Rails are not in the gemfile, skipping tests"
13
+ Process.exit
14
14
  end
15
15
 
16
16
  require 'isolated/shared'
@@ -0,0 +1,216 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ #frozen_string_literal: false
5
+
6
+ require 'json_gem/test_helper'
7
+ require 'date'
8
+
9
+ if REAL_JSON_GEM
10
+ require 'json/add/core'
11
+ require 'json/add/complex'
12
+ require 'json/add/rational'
13
+ require 'json/add/bigdecimal'
14
+ require 'json/add/ostruct'
15
+ else
16
+ #Oj.add_to_json()
17
+ Oj.add_to_json(Array, BigDecimal, Complex, Date, DateTime, Exception, Hash, Integer, OpenStruct, Range, Rational, Regexp, Struct, Time)
18
+ end
19
+
20
+ class JSONAdditionTest < Test::Unit::TestCase
21
+ include Test::Unit::TestCaseOmissionSupport
22
+ include Test::Unit::TestCasePendingSupport
23
+
24
+ class A
25
+ def self.json_creatable?
26
+ true
27
+ end
28
+
29
+ def initialize(a)
30
+ @a = a
31
+ end
32
+
33
+ attr_reader :a
34
+
35
+ def ==(other)
36
+ a == other.a
37
+ end
38
+
39
+ def self.json_create(object)
40
+ new(*object['args'])
41
+ end
42
+
43
+ def to_json(*args)
44
+ {
45
+ 'json_class' => self.class.name,
46
+ 'args' => [ @a ],
47
+ }.to_json(*args)
48
+ end
49
+ end
50
+
51
+ class A2 < A
52
+ def to_json(*args)
53
+ {
54
+ 'json_class' => self.class.name,
55
+ 'args' => [ @a ],
56
+ }.to_json(*args)
57
+ end
58
+ end
59
+
60
+ class B
61
+ def self.json_creatable?
62
+ false
63
+ end
64
+
65
+ def to_json(*args)
66
+ {
67
+ 'json_class' => self.class.name,
68
+ }.to_json(*args)
69
+ end
70
+ end
71
+
72
+ class C
73
+ def self.json_creatable?
74
+ false
75
+ end
76
+
77
+ def to_json(*args)
78
+ {
79
+ 'json_class' => 'JSONAdditionTest::Nix',
80
+ }.to_json(*args)
81
+ end
82
+ end
83
+
84
+ def test_extended_json
85
+ a = A.new(666)
86
+ assert A.json_creatable?
87
+ json = JSON.generate(a)
88
+ a_again = JSON.parse(json, :create_additions => true)
89
+ assert_kind_of a.class, a_again
90
+ assert_equal a, a_again
91
+ end
92
+
93
+ def test_extended_json_default
94
+ a = A.new(666)
95
+ assert A.json_creatable?
96
+ json = JSON.generate(a)
97
+ a_hash = JSON.parse(json)
98
+ assert_kind_of Hash, a_hash
99
+ end
100
+
101
+ def test_extended_json_disabled
102
+ a = A.new(666)
103
+ assert A.json_creatable?
104
+ json = JSON.generate(a)
105
+ a_again = JSON.parse(json, :create_additions => true)
106
+ assert_kind_of a.class, a_again
107
+ assert_equal a, a_again
108
+ a_hash = JSON.parse(json, :create_additions => false)
109
+ assert_kind_of Hash, a_hash
110
+ assert_equal(
111
+ {"args"=>[666], "json_class"=>"JSONAdditionTest::A"}.sort_by { |k,| k },
112
+ a_hash.sort_by { |k,| k }
113
+ )
114
+ end
115
+
116
+ def test_extended_json_fail1
117
+ b = B.new
118
+ assert !B.json_creatable?
119
+ json = JSON.generate(b)
120
+ assert_equal({ "json_class"=>"JSONAdditionTest::B" }, JSON.parse(json))
121
+ end
122
+
123
+ def test_extended_json_fail2
124
+ c = C.new
125
+ assert !C.json_creatable?
126
+ json = JSON.generate(c)
127
+ assert_raise(ArgumentError, NameError) { JSON.parse(json, :create_additions => true) }
128
+ end
129
+
130
+ def test_raw_strings
131
+ raw = ''
132
+ raw.respond_to?(:encode!) and raw.encode!(Encoding::ASCII_8BIT)
133
+ raw_array = []
134
+ for i in 0..255
135
+ raw << i
136
+ raw_array << i
137
+ end
138
+ json = raw.to_json_raw
139
+ json_raw_object = raw.to_json_raw_object
140
+ hash = { 'json_class' => 'String', 'raw'=> raw_array }
141
+ assert_equal hash, json_raw_object
142
+ assert_match(/\A\{.*\}\z/, json)
143
+ assert_match(/"json_class":"String"/, json)
144
+ 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)
145
+
146
+ raw_again = JSON.parse(json, :create_additions => true)
147
+ assert_equal raw, raw_again
148
+ end
149
+
150
+ MyJsonStruct = Struct.new 'MyJsonStruct', :foo, :bar
151
+
152
+ def test_core
153
+ t = Time.now
154
+ assert_equal t, JSON(JSON(t), :create_additions => true)
155
+
156
+ d = Date.today
157
+ assert_equal d, JSON(JSON(d), :create_additions => true)
158
+
159
+ d = DateTime.civil(2007, 6, 14, 14, 57, 10, Rational(1, 12), 2299161)
160
+ assert_equal d, JSON(JSON(d), :create_additions => true)
161
+
162
+ assert_equal 1..10, JSON(JSON(1..10), :create_additions => true)
163
+ assert_equal 1...10, JSON(JSON(1...10), :create_additions => true)
164
+ assert_equal "a".."c", JSON(JSON("a".."c"), :create_additions => true)
165
+ assert_equal "a"..."c", JSON(JSON("a"..."c"), :create_additions => true)
166
+
167
+ s = MyJsonStruct.new 4711, 'foot'
168
+ assert_equal s, JSON(JSON(s), :create_additions => true)
169
+
170
+ struct = Struct.new :foo, :bar
171
+ s = struct.new 4711, 'foot'
172
+ assert_raise(JSON::JSONError) { JSON(s) }
173
+
174
+ begin
175
+ raise TypeError, "test me"
176
+ rescue TypeError => e
177
+ e_json = JSON.generate e
178
+ e_again = JSON e_json, :create_additions => true
179
+ assert_kind_of TypeError, e_again
180
+ assert_equal e.message, e_again.message
181
+ assert_equal e.backtrace, e_again.backtrace
182
+ end
183
+
184
+ assert_equal(/foo/, JSON(JSON(/foo/), :create_additions => true))
185
+ assert_equal(/foo/i, JSON(JSON(/foo/i), :create_additions => true))
186
+ end
187
+
188
+ def test_utc_datetime
189
+ now = Time.now
190
+ d = DateTime.parse(now.to_s, :create_additions => true) # usual case
191
+ assert_equal d, JSON.parse(d.to_json, :create_additions => true)
192
+ d = DateTime.parse(now.utc.to_s) # of = 0
193
+ assert_equal d, JSON.parse(d.to_json, :create_additions => true)
194
+ d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(1,24))
195
+ assert_equal d, JSON.parse(d.to_json, :create_additions => true)
196
+ d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(12,24))
197
+ assert_equal d, JSON.parse(d.to_json, :create_additions => true)
198
+ end
199
+
200
+ def test_rational_complex
201
+ assert_equal Rational(2, 9), JSON.parse(JSON(Rational(2, 9)), :create_additions => true)
202
+ assert_equal Complex(2, 9), JSON.parse(JSON(Complex(2, 9)), :create_additions => true)
203
+ end
204
+
205
+ def test_bigdecimal
206
+ assert_equal BigDecimal('3.141', 23), JSON(JSON(BigDecimal('3.141', 23)), :create_additions => true)
207
+ assert_equal BigDecimal('3.141', 666), JSON(JSON(BigDecimal('3.141', 666)), :create_additions => true)
208
+ end
209
+
210
+ def test_ostruct
211
+ o = OpenStruct.new
212
+ # XXX this won't work; o.foo = { :bar => true }
213
+ o.foo = { 'bar' => true }
214
+ assert_equal o, JSON.parse(JSON(o), :create_additions => true)
215
+ end
216
+ end
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ #frozen_string_literal: false
5
+
6
+ require 'json_gem/test_helper'
7
+
8
+ require 'stringio'
9
+ require 'tempfile'
10
+
11
+ class JSONCommonInterfaceTest < Test::Unit::TestCase
12
+ include Test::Unit::TestCaseOmissionSupport
13
+ include Test::Unit::TestCasePendingSupport
14
+
15
+ def setup
16
+ @hash = {
17
+ 'a' => 2,
18
+ #'b' => 5.23683071,
19
+ 'c' => 'c',
20
+ 'd' => [ 1, "b", 3.14 ],
21
+ 'e' => { 'foo' => 'bar' },
22
+ 'g' => "\"\0\037",
23
+ 'h' => 1000.0,
24
+ 'i' => 0.001
25
+ }
26
+ # Tired of chasing floating point rounding and precision. Oj now uses the
27
+ # Ruby float parser in compat mode yet on i386 machines there are issues
28
+ # with this test when the float is included.
29
+ #@json = '{"a":2,"b":5.23683071,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},'\
30
+ #'"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
31
+ @json = '{"a":2,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},'\
32
+ '"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
33
+ end
34
+
35
+ def test_index
36
+ assert_equal @json, JSON[@hash]
37
+ assert_equal @hash, JSON[@json]
38
+ end
39
+
40
+ ##############################################################################
41
+ # The next tests are omitted as implementing them and using them is a
42
+ # performance hit. Use of the JSON.parse() and similar provide the same
43
+ # functionality and perform better.
44
+
45
+ def test_parser
46
+ assert_match /::Parser\z/, JSON.parser.name
47
+ end
48
+
49
+ def test_generator
50
+ assert_match /::Generator\z/, JSON.generator.name
51
+ end
52
+
53
+ def test_state
54
+ assert_match /::Generator::State\z/, JSON.state.name
55
+ end
56
+
57
+ # This doesn't have anything to do with JSON parsing or generation. It seems
58
+ # to be more of an internal tool that is exposed to users.
59
+ def test_deep_const_get
60
+ omit("mimic_JSON") unless REAL_JSON_GEM
61
+ assert_raise(ArgumentError) { JSON.deep_const_get('Nix::Da') }
62
+ assert_equal File::SEPARATOR, JSON.deep_const_get('File::SEPARATOR')
63
+ end
64
+ ##############################################################################
65
+
66
+ def test_create_id
67
+ assert_equal 'json_class', JSON.create_id
68
+ JSON.create_id = 'foo_bar'
69
+ assert_equal 'foo_bar', JSON.create_id
70
+ ensure
71
+ JSON.create_id = 'json_class'
72
+ end
73
+
74
+ def test_parse
75
+ assert_equal [ 1, 2, 3, ], JSON.parse('[ 1, 2, 3 ]')
76
+ end
77
+
78
+ def test_parse_bang
79
+ # Modified this test to compare strings since NaN comparison fails if NaN
80
+ # was defined in different places even if it represents the same value.
81
+ assert_equal [ 1, NaN, 3, ].to_s, JSON.parse!('[ 1, NaN, 3 ]').to_s
82
+ end
83
+
84
+ def test_generate
85
+ assert_equal '[1,2,3]', JSON.generate([ 1, 2, 3 ])
86
+ end
87
+
88
+ def test_fast_generate
89
+ assert_equal '[1,2,3]', JSON.generate([ 1, 2, 3 ])
90
+ end
91
+
92
+ def test_pretty_generate
93
+ assert_equal "[\n 1,\n 2,\n 3\n]", JSON.pretty_generate([ 1, 2, 3 ])
94
+ end
95
+
96
+ def test_load
97
+ assert_equal @hash, JSON.load(@json)
98
+ tempfile = Tempfile.open('@json')
99
+ tempfile.write @json
100
+ tempfile.rewind
101
+ assert_equal @hash, JSON.load(tempfile)
102
+ stringio = StringIO.new(@json)
103
+ stringio.rewind
104
+ assert_equal @hash, JSON.load(stringio)
105
+ assert_equal nil, JSON.load(nil)
106
+ assert_equal nil, JSON.load('')
107
+ ensure
108
+ tempfile.close!
109
+ end
110
+
111
+ def test_load_with_options
112
+ json = '{ "foo": NaN }'
113
+ assert JSON.load(json, nil, :allow_nan => true)['foo'].nan?
114
+ end
115
+
116
+ def test_load_null
117
+ assert_equal nil, JSON.load(nil, nil, :allow_blank => true)
118
+ assert_raise(TypeError) { JSON.load(nil, nil, :allow_blank => false) }
119
+ assert_raise(JSON::ParserError) { JSON.load('', nil, :allow_blank => false) }
120
+ # The next tests are added by Oj to catch additional cases.
121
+ assert_equal nil, JSON.load('', nil, :allow_blank => true)
122
+ assert_raise(JSON::ParserError) { JSON.load('', nil, :allow_blank => false) }
123
+ assert_raise(JSON::ParserError) { JSON.load(' ', nil, :allow_blank => true) }
124
+ assert_raise(JSON::ParserError) { JSON.load(' ', nil, :allow_blank => false) }
125
+ end
126
+
127
+ def test_dump
128
+ too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
129
+ assert_equal too_deep, JSON.dump(eval(too_deep))
130
+ assert_kind_of String, Marshal.dump(eval(too_deep))
131
+ assert_raise(ArgumentError) { JSON.dump(eval(too_deep), 100) }
132
+ assert_raise(ArgumentError) { Marshal.dump(eval(too_deep), 100) }
133
+ assert_equal too_deep, JSON.dump(eval(too_deep), 101)
134
+ assert_kind_of String, Marshal.dump(eval(too_deep), 101)
135
+ output = StringIO.new
136
+ JSON.dump(eval(too_deep), output)
137
+ assert_equal too_deep, output.string
138
+ output = StringIO.new
139
+ JSON.dump(eval(too_deep), output, 101)
140
+ assert_equal too_deep, output.string
141
+ end
142
+
143
+ def test_dump_should_modify_defaults
144
+ max_nesting = JSON.dump_default_options[:max_nesting]
145
+ JSON.dump([], StringIO.new, 10)
146
+ assert_equal max_nesting, JSON.dump_default_options[:max_nesting]
147
+ end
148
+
149
+ def test_JSON
150
+ assert_equal @json, JSON(@hash)
151
+ assert_equal @hash, JSON(@json)
152
+ end
153
+ end