#!/usr/bin/env ruby # encoding: UTF-8 $: << File.dirname(__FILE__) $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__))) %w(lib ext).each do |dir| $: << File.join($oj_dir, dir) end require 'minitest' require 'minitest/autorun' require 'stringio' require 'date' require 'bigdecimal' require 'oj' class NullJuice < Minitest::Test module TestModule end class Jeez attr_accessor :x, :y def initialize(x, y) @x = x @y = y end end def setup @default_options = Oj.default_options # in null mode other options other than the number formats are not used. Oj.default_options = { :mode => :null } end def teardown Oj.default_options = @default_options end def test_nil dump_and_load(nil, false) end def test_true dump_and_load(true, false) end def test_false dump_and_load(false, false) end def test_fixnum dump_and_load(0, false) dump_and_load(12345, false) dump_and_load(-54321, false) dump_and_load(1, false) end def test_float dump_and_load(0.0, false) dump_and_load(12345.6789, false) dump_and_load(70.35, false) dump_and_load(-54321.012, false) dump_and_load(1.7775, false) dump_and_load(2.5024, false) dump_and_load(2.48e16, false) dump_and_load(2.48e100 * 1.0e10, false) dump_and_load(-2.48e100 * 1.0e10, false) end def test_nan_dump assert_equal('null', Oj.dump(0/0.0, :nan => :null)) assert_equal('3.3e14159265358979323846', Oj.dump(0/0.0, :nan => :huge)) begin Oj.dump(0/0.0, :nan => :word) rescue Exception assert(true) return end assert(false, "*** expected an exception") end def test_infinity_dump assert_equal('null', Oj.dump(1/0.0, :nan => :null)) assert_equal('3.0e14159265358979323846', Oj.dump(1/0.0, :nan => :huge)) begin Oj.dump(1/0.0, :nan => :word) rescue Exception assert(true) return end assert(false, "*** expected an exception") end def test_neg_infinity_dump assert_equal('null', Oj.dump(-1/0.0, :nan => :null)) assert_equal('-3.0e14159265358979323846', Oj.dump(-1/0.0, :nan => :huge)) begin Oj.dump(-1/0.0, :nan => :word) rescue Exception assert(true) return end assert(false, "*** expected an exception") end def test_string dump_and_load('', false) dump_and_load('abc', false) dump_and_load("abc\ndef", false) dump_and_load("a\u0041", false) end def test_encode opts = Oj.default_options Oj.default_options = { :ascii_only => false } unless 'jruby' == $ruby dump_and_load("ぴーたー", false) end Oj.default_options = { :ascii_only => true } json = Oj.dump("ぴーたー") assert_equal(%{"\\u3074\\u30fc\\u305f\\u30fc"}, json) unless 'jruby' == $ruby dump_and_load("ぴーたー", false) end Oj.default_options = opts end def test_unicode # hits the 3 normal ranges and one extended surrogate pair json = %{"\\u019f\\u05e9\\u3074\\ud834\\udd1e"} obj = Oj.load(json) json2 = Oj.dump(obj, :ascii_only => true) assert_equal(json, json2) end def test_unicode_long # tests buffer overflow json = %{"\\u019f\\u05e9\\u3074\\ud834\\udd1e #{'x' * 2000}"} obj = Oj.load(json) json2 = Oj.dump(obj, :ascii_only => true) assert_equal(json, json2) end def test_array dump_and_load([], false) dump_and_load([true, false], false) dump_and_load(['a', 1, nil], false) dump_and_load([[nil]], false) dump_and_load([[nil], 58], false) end def test_array_deep dump_and_load([1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,[14,[15,[16,[17,[18,[19,[20]]]]]]]]]]]]]]]]]]]], false) end # Hash def test_hash dump_and_load({}, false) dump_and_load({ 'true' => true, 'false' => false}, false) dump_and_load({ 'true' => true, 'array' => [], 'hash' => { }}, false) end def test_hash_deep dump_and_load({'1' => { '2' => { '3' => { '4' => { '5' => { '6' => { '7' => { '8' => { '9' => { '10' => { '11' => { '12' => { '13' => { '14' => { '15' => { '16' => { '17' => { '18' => { '19' => { '20' => {}}}}}}}}}}}}}}}}}}}}}, false) end def test_hash_escaped_key json = %{{"a\nb":true,"c\td":false}} obj = Oj.strict_load(json) assert_equal({"a\nb" => true, "c\td" => false}, obj) end def test_non_str_hash begin Oj.dump({ 1 => true, 0 => false }) rescue Exception assert(true) return end assert(false, "*** expected an exception") end def test_bignum_object dump_and_load(7 ** 55, false) end # BigDecimal def test_bigdecimal_strict Oj.default_options = { :bigdecimal_load => true} dump_and_load(BigDecimal('3.14159265358979323846'), false) end def test_bigdecimal_load orig = BigDecimal('80.51') json = Oj.dump(orig, :mode => :strict, :bigdecimal_as_decimal => true) bg = Oj.load(json, :mode => :strict, :bigdecimal_load => true) assert_equal(BigDecimal, bg.class) assert_equal(orig, bg) end def test_json_object obj = Jeez.new(true, 58) json = Oj.dump(obj) assert_equal('null', json) end def test_range json = Oj.dump(1..7) assert_equal('null', json) end # Stream IO def test_io_string json = %{{ "x":true, "y":58, "z": [1,2,3] } } input = StringIO.new(json) obj = Oj.strict_load(input) assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj) end def test_io_file filename = File.join(File.dirname(__FILE__), 'open_file_test.json') File.open(filename, 'w') { |f| f.write(%{{ "x":true, "y":58, "z": [1,2,3] } }) } f = File.new(filename) obj = Oj.strict_load(f) f.close() assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj) end def test_symbol json = Oj.dump(:abc) assert_equal('"abc"', json) end def test_time t = Time.local(2012, 1, 5, 23, 58, 7) json = Oj.dump(t) assert_equal('null', json) end def test_class json = Oj.dump(NullJuice) assert_equal('null', json) end def test_module json = Oj.dump(TestModule) assert_equal('null', json) end # symbol_keys option def test_symbol_keys json = %{{ "x":true, "y":58, "z": [1,2,3] } } obj = Oj.strict_load(json, :symbol_keys => true) assert_equal({ :x => true, :y => 58, :z => [1, 2, 3]}, obj) end def test_symbol_keys_safe json = %{{ "x":true, "y":58, "z": [1,2,3] } } obj = Oj.safe_load(json) assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj) end # comments def test_comment_slash json = %{{ "x":true,//three "y":58, "z": [1,2, 3 // six ]} } obj = Oj.strict_load(json) assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj) end def test_comment_c json = %{{ "x"/*one*/:/*two*/true, "y":58, "z": [1,2,3]} } obj = Oj.strict_load(json) assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj) end def test_comment json = %{{ "x"/*one*/:/*two*/true,//three "y":58/*four*/, "z": [1,2/*five*/, 3 // six ] } } obj = Oj.strict_load(json) assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj) end def test_double json = %{{ "x": 1}{ "y": 2}} results = [] Oj.load(json, :mode => :strict) { |x| results << x } assert_equal([{ 'x' => 1 }, { 'y' => 2 }], results) end def test_circular_hash h = { 'a' => 7 } h['b'] = h json = Oj.dump(h, :indent => 2, :circular => true, :mode => :null) assert_equal(%|{ "a":7, "b":null } |, json) end def test_omit_nil json = Oj.dump({'x' => {'a' => 1, 'b' => nil }, 'y' => nil}, :omit_nil => true) assert_equal(%|{"x":{"a":1}}|, json) end def dump_and_load(obj, trace=false) json = Oj.dump(obj, :indent => 2) puts json if trace loaded = Oj.strict_load(json); if obj.nil? assert_nil(loaded) else assert_equal(obj, loaded) end loaded end end