1#!/usr/bin/env ruby 2# encoding: utf-8 3 4require 'test/unit' 5require File.join(File.dirname(__FILE__), 'setup_variant') 6 7class TestJSONGenerate < Test::Unit::TestCase 8 include JSON 9 10 def setup 11 @hash = { 12 'a' => 2, 13 'b' => 3.141, 14 'c' => 'c', 15 'd' => [ 1, "b", 3.14 ], 16 'e' => { 'foo' => 'bar' }, 17 'g' => "\"\0\037", 18 'h' => 1000.0, 19 'i' => 0.001 20 } 21 @json2 = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},' + 22 '"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}' 23 @json3 = <<'EOT'.chomp 24{ 25 "a": 2, 26 "b": 3.141, 27 "c": "c", 28 "d": [ 29 1, 30 "b", 31 3.14 32 ], 33 "e": { 34 "foo": "bar" 35 }, 36 "g": "\"\u0000\u001f", 37 "h": 1000.0, 38 "i": 0.001 39} 40EOT 41 end 42 43 def test_generate 44 json = generate(@hash) 45 assert_equal(JSON.parse(@json2), JSON.parse(json)) 46 json = JSON[@hash] 47 assert_equal(JSON.parse(@json2), JSON.parse(json)) 48 parsed_json = parse(json) 49 assert_equal(@hash, parsed_json) 50 json = generate({1=>2}) 51 assert_equal('{"1":2}', json) 52 parsed_json = parse(json) 53 assert_equal({"1"=>2}, parsed_json) 54 assert_raise(GeneratorError) { generate(666) } 55 assert_equal '666', generate(666, :quirks_mode => true) 56 end 57 58 def test_generate_pretty 59 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)) 62 parsed_json = parse(json) 63 assert_equal(@hash, parsed_json) 64 json = pretty_generate({1=>2}) 65 assert_equal(<<'EOT'.chomp, json) 66{ 67 "1": 2 68} 69EOT 70 parsed_json = parse(json) 71 assert_equal({"1"=>2}, parsed_json) 72 assert_raise(GeneratorError) { pretty_generate(666) } 73 assert_equal '666', pretty_generate(666, :quirks_mode => true) 74 end 75 76 def test_fast_generate 77 json = fast_generate(@hash) 78 assert_equal(JSON.parse(@json2), JSON.parse(json)) 79 parsed_json = parse(json) 80 assert_equal(@hash, parsed_json) 81 json = fast_generate({1=>2}) 82 assert_equal('{"1":2}', json) 83 parsed_json = parse(json) 84 assert_equal({"1"=>2}, parsed_json) 85 assert_raise(GeneratorError) { fast_generate(666) } 86 assert_equal '666', fast_generate(666, :quirks_mode => true) 87 end 88 89 def test_own_state 90 state = State.new 91 json = generate(@hash, state) 92 assert_equal(JSON.parse(@json2), JSON.parse(json)) 93 parsed_json = parse(json) 94 assert_equal(@hash, parsed_json) 95 json = generate({1=>2}, state) 96 assert_equal('{"1":2}', json) 97 parsed_json = parse(json) 98 assert_equal({"1"=>2}, parsed_json) 99 assert_raise(GeneratorError) { generate(666, state) } 100 state.quirks_mode = true 101 assert state.quirks_mode? 102 assert_equal '666', generate(666, state) 103 end 104 105 def test_states 106 json = generate({1=>2}, nil) 107 assert_equal('{"1":2}', json) 108 s = JSON.state.new 109 assert s.check_circular? 110 assert s[:check_circular?] 111 h = { 1=>2 } 112 h[3] = h 113 assert_raises(JSON::NestingError) { generate(h) } 114 assert_raises(JSON::NestingError) { generate(h, s) } 115 s = JSON.state.new 116 a = [ 1, 2 ] 117 a << a 118 assert_raises(JSON::NestingError) { generate(a, s) } 119 assert s.check_circular? 120 assert s[:check_circular?] 121 end 122 123 def test_pretty_state 124 state = PRETTY_STATE_PROTOTYPE.dup 125 assert_equal({ 126 :allow_nan => false, 127 :array_nl => "\n", 128 :ascii_only => false, 129 :buffer_initial_length => 1024, 130 :quirks_mode => false, 131 :depth => 0, 132 :indent => " ", 133 :max_nesting => 100, 134 :object_nl => "\n", 135 :space => " ", 136 :space_before => "", 137 }.sort_by { |n,| n.to_s }, state.to_h.sort_by { |n,| n.to_s }) 138 end 139 140 def test_safe_state 141 state = SAFE_STATE_PROTOTYPE.dup 142 assert_equal({ 143 :allow_nan => false, 144 :array_nl => "", 145 :ascii_only => false, 146 :buffer_initial_length => 1024, 147 :quirks_mode => false, 148 :depth => 0, 149 :indent => "", 150 :max_nesting => 100, 151 :object_nl => "", 152 :space => "", 153 :space_before => "", 154 }.sort_by { |n,| n.to_s }, state.to_h.sort_by { |n,| n.to_s }) 155 end 156 157 def test_fast_state 158 state = FAST_STATE_PROTOTYPE.dup 159 assert_equal({ 160 :allow_nan => false, 161 :array_nl => "", 162 :ascii_only => false, 163 :buffer_initial_length => 1024, 164 :quirks_mode => false, 165 :depth => 0, 166 :indent => "", 167 :max_nesting => 0, 168 :object_nl => "", 169 :space => "", 170 :space_before => "", 171 }.sort_by { |n,| n.to_s }, state.to_h.sort_by { |n,| n.to_s }) 172 end 173 174 def test_allow_nan 175 assert_raises(GeneratorError) { generate([JSON::NaN]) } 176 assert_equal '[NaN]', generate([JSON::NaN], :allow_nan => true) 177 assert_raises(GeneratorError) { fast_generate([JSON::NaN]) } 178 assert_raises(GeneratorError) { pretty_generate([JSON::NaN]) } 179 assert_equal "[\n NaN\n]", pretty_generate([JSON::NaN], :allow_nan => true) 180 assert_raises(GeneratorError) { generate([JSON::Infinity]) } 181 assert_equal '[Infinity]', generate([JSON::Infinity], :allow_nan => true) 182 assert_raises(GeneratorError) { fast_generate([JSON::Infinity]) } 183 assert_raises(GeneratorError) { pretty_generate([JSON::Infinity]) } 184 assert_equal "[\n Infinity\n]", pretty_generate([JSON::Infinity], :allow_nan => true) 185 assert_raises(GeneratorError) { generate([JSON::MinusInfinity]) } 186 assert_equal '[-Infinity]', generate([JSON::MinusInfinity], :allow_nan => true) 187 assert_raises(GeneratorError) { fast_generate([JSON::MinusInfinity]) } 188 assert_raises(GeneratorError) { pretty_generate([JSON::MinusInfinity]) } 189 assert_equal "[\n -Infinity\n]", pretty_generate([JSON::MinusInfinity], :allow_nan => true) 190 end 191 192 def test_depth 193 ary = []; ary << ary 194 assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth 195 assert_raises(JSON::NestingError) { JSON.generate(ary) } 196 assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth 197 assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth 198 assert_raises(JSON::NestingError) { JSON.pretty_generate(ary) } 199 assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth 200 s = JSON.state.new 201 assert_equal 0, s.depth 202 assert_raises(JSON::NestingError) { ary.to_json(s) } 203 assert_equal 100, s.depth 204 end 205 206 def test_buffer_initial_length 207 s = JSON.state.new 208 assert_equal 1024, s.buffer_initial_length 209 s.buffer_initial_length = 0 210 assert_equal 1024, s.buffer_initial_length 211 s.buffer_initial_length = -1 212 assert_equal 1024, s.buffer_initial_length 213 s.buffer_initial_length = 128 214 assert_equal 128, s.buffer_initial_length 215 end 216 217 def test_gc 218 require_relative '../ruby/envutil.rb' 219 assert_in_out_err(%w[-rjson --disable-gems], <<-EOS, [], []) 220 bignum_too_long_to_embed_as_string = 1234567890123456789012345 221 expect = bignum_too_long_to_embed_as_string.to_s 222 GC.stress = true 223 224 10.times do |i| 225 tmp = bignum_too_long_to_embed_as_string.to_json 226 raise "'\#{expect}' is expected, but '\#{tmp}'" unless tmp == expect 227 end 228 EOS 229 end if GC.respond_to?(:stress=) 230 231 def test_configure_using_configure_and_merge 232 numbered_state = { 233 :indent => "1", 234 :space => '2', 235 :space_before => '3', 236 :object_nl => '4', 237 :array_nl => '5' 238 } 239 state1 = JSON.state.new 240 state1.merge(numbered_state) 241 assert_equal '1', state1.indent 242 assert_equal '2', state1.space 243 assert_equal '3', state1.space_before 244 assert_equal '4', state1.object_nl 245 assert_equal '5', state1.array_nl 246 state2 = JSON.state.new 247 state2.configure(numbered_state) 248 assert_equal '1', state2.indent 249 assert_equal '2', state2.space 250 assert_equal '3', state2.space_before 251 assert_equal '4', state2.object_nl 252 assert_equal '5', state2.array_nl 253 end 254 255 if defined?(JSON::Ext::Generator) 256 def test_broken_bignum # [ruby-core:38867] 257 pid = fork do 258 Bignum.class_eval do 259 def to_s 260 end 261 end 262 begin 263 JSON::Ext::Generator::State.new.generate(1<<64) 264 exit 1 265 rescue TypeError 266 exit 0 267 end 268 end 269 _, status = Process.waitpid2(pid) 270 assert status.success? 271 rescue NotImplementedError 272 # forking to avoid modifying core class of a parent process and 273 # introducing race conditions of tests are run in parallel 274 end 275 end 276 277 def test_hash_likeness_set_symbol 278 state = JSON.state.new 279 assert_equal nil, state[:foo] 280 assert_equal nil.class, state[:foo].class 281 assert_equal nil, state['foo'] 282 state[:foo] = :bar 283 assert_equal :bar, state[:foo] 284 assert_equal :bar, state['foo'] 285 state_hash = state.to_hash 286 assert_kind_of Hash, state_hash 287 assert_equal :bar, state_hash[:foo] 288 end 289 290 def test_hash_likeness_set_string 291 state = JSON.state.new 292 assert_equal nil, state[:foo] 293 assert_equal nil, state['foo'] 294 state['foo'] = :bar 295 assert_equal :bar, state[:foo] 296 assert_equal :bar, state['foo'] 297 state_hash = state.to_hash 298 assert_kind_of Hash, state_hash 299 assert_equal :bar, state_hash[:foo] 300 end 301end 302