oj 3.9.1 → 3.10.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/oj/compat.c +5 -5
  4. data/ext/oj/custom.c +6 -2
  5. data/ext/oj/dump.c +10 -13
  6. data/ext/oj/dump_compat.c +8 -10
  7. data/ext/oj/dump_object.c +18 -11
  8. data/ext/oj/dump_strict.c +6 -5
  9. data/ext/oj/extconf.rb +5 -0
  10. data/ext/oj/mimic_json.c +15 -3
  11. data/ext/oj/object.c +2 -1
  12. data/ext/oj/oj.c +47 -28
  13. data/ext/oj/oj.h +4 -2
  14. data/ext/oj/parse.c +16 -3
  15. data/ext/oj/parse.h +1 -0
  16. data/ext/oj/rails.c +37 -4
  17. data/ext/oj/sparse.c +5 -0
  18. data/ext/oj/util.c +5 -5
  19. data/ext/oj/wab.c +9 -9
  20. data/lib/oj/version.rb +1 -1
  21. data/pages/Rails.md +60 -21
  22. data/test/activesupport5/abstract_unit.rb +45 -0
  23. data/test/activesupport5/decoding_test.rb +68 -60
  24. data/test/activesupport5/encoding_test.rb +111 -96
  25. data/test/activesupport5/encoding_test_cases.rb +33 -25
  26. data/test/activesupport5/test_helper.rb +43 -21
  27. data/test/activesupport5/time_zone_test_helpers.rb +18 -3
  28. data/test/activesupport6/abstract_unit.rb +44 -0
  29. data/test/activesupport6/decoding_test.rb +133 -0
  30. data/test/activesupport6/encoding_test.rb +507 -0
  31. data/test/activesupport6/encoding_test_cases.rb +98 -0
  32. data/test/activesupport6/test_common.rb +17 -0
  33. data/test/activesupport6/test_helper.rb +163 -0
  34. data/test/activesupport6/time_zone_test_helpers.rb +39 -0
  35. data/test/bar.rb +21 -11
  36. data/test/baz.rb +16 -0
  37. data/test/foo.rb +39 -8
  38. data/test/test_compat.rb +0 -7
  39. data/test/test_custom.rb +25 -6
  40. data/test/test_integer_range.rb +1 -2
  41. data/test/test_object.rb +12 -3
  42. data/test/test_rails.rb +26 -0
  43. data/test/test_strict.rb +24 -1
  44. data/test/test_various.rb +41 -62
  45. data/test/tests.rb +1 -0
  46. metadata +23 -3
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bigdecimal"
4
+ require "date"
5
+ require "time"
6
+ require "pathname"
7
+ require "uri"
8
+
9
+ module JSONTest
10
+ class Foo
11
+ def initialize(a, b)
12
+ @a, @b = a, b
13
+ end
14
+ end
15
+
16
+ class Hashlike
17
+ def to_hash
18
+ { foo: "hello", bar: "world" }
19
+ end
20
+ end
21
+
22
+ class Custom
23
+ def initialize(serialized)
24
+ @serialized = serialized
25
+ end
26
+
27
+ def as_json(options = nil)
28
+ @serialized
29
+ end
30
+ end
31
+
32
+ MyStruct = Struct.new(:name, :value) do
33
+ def initialize(*)
34
+ @unused = "unused instance variable"
35
+ super
36
+ end
37
+ end
38
+
39
+ module EncodingTestCases
40
+ TrueTests = [[ true, %(true) ]]
41
+ FalseTests = [[ false, %(false) ]]
42
+ NilTests = [[ nil, %(null) ]]
43
+ NumericTests = [[ 1, %(1) ],
44
+ [ 2.5, %(2.5) ],
45
+ [ 0.0 / 0.0, %(null) ],
46
+ [ 1.0 / 0.0, %(null) ],
47
+ [ -1.0 / 0.0, %(null) ],
48
+ [ BigDecimal("0.0") / BigDecimal("0.0"), %(null) ],
49
+ [ BigDecimal("2.5"), %("#{BigDecimal('2.5')}") ]]
50
+
51
+ StringTests = [[ "this is the <string>", %("this is the \\u003cstring\\u003e")],
52
+ [ 'a "string" with quotes & an ampersand', %("a \\"string\\" with quotes \\u0026 an ampersand") ],
53
+ [ "http://test.host/posts/1", %("http://test.host/posts/1")],
54
+ [ "Control characters: \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\u2028\u2029",
55
+ %("Control characters: \\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f\\u2028\\u2029") ]]
56
+
57
+ ArrayTests = [[ ["a", "b", "c"], %([\"a\",\"b\",\"c\"]) ],
58
+ [ [1, "a", :b, nil, false], %([1,\"a\",\"b\",null,false]) ]]
59
+
60
+ HashTests = [[ { foo: "bar" }, %({\"foo\":\"bar\"}) ],
61
+ [ { 1 => 1, 2 => "a", 3 => :b, 4 => nil, 5 => false }, %({\"1\":1,\"2\":\"a\",\"3\":\"b\",\"4\":null,\"5\":false}) ]]
62
+
63
+ RangeTests = [[ 1..2, %("1..2")],
64
+ [ 1...2, %("1...2")],
65
+ [ 1.5..2.5, %("1.5..2.5")]]
66
+
67
+ SymbolTests = [[ :a, %("a") ],
68
+ [ :this, %("this") ],
69
+ [ :"a b", %("a b") ]]
70
+
71
+ ObjectTests = [[ Foo.new(1, 2), %({\"a\":1,\"b\":2}) ]]
72
+ HashlikeTests = [[ Hashlike.new, %({\"bar\":\"world\",\"foo\":\"hello\"}) ]]
73
+ StructTests = [[ MyStruct.new(:foo, "bar"), %({\"name\":\"foo\",\"value\":\"bar\"}) ],
74
+ [ MyStruct.new(nil, nil), %({\"name\":null,\"value\":null}) ]]
75
+ CustomTests = [[ Custom.new("custom"), '"custom"' ],
76
+ [ Custom.new(nil), "null" ],
77
+ [ Custom.new(:a), '"a"' ],
78
+ [ Custom.new([ :foo, "bar" ]), '["foo","bar"]' ],
79
+ [ Custom.new(foo: "hello", bar: "world"), '{"bar":"world","foo":"hello"}' ],
80
+ [ Custom.new(Hashlike.new), '{"bar":"world","foo":"hello"}' ],
81
+ [ Custom.new(Custom.new(Custom.new(:a))), '"a"' ]]
82
+
83
+ RegexpTests = [[ /^a/, '"(?-mix:^a)"' ], [/^\w{1,2}[a-z]+/ix, '"(?ix-m:^\\\\w{1,2}[a-z]+)"']]
84
+
85
+ URITests = [[ URI.parse("http://example.com"), %("http://example.com") ]]
86
+
87
+ PathnameTests = [[ Pathname.new("lib/index.rb"), %("lib/index.rb") ]]
88
+
89
+ DateTests = [[ Date.new(2005, 2, 1), %("2005/02/01") ]]
90
+ TimeTests = [[ Time.utc(2005, 2, 1, 15, 15, 10), %("2005/02/01 15:15:10 +0000") ]]
91
+ DateTimeTests = [[ DateTime.civil(2005, 2, 1, 15, 15, 10), %("2005/02/01 15:15:10 +0000") ]]
92
+
93
+ StandardDateTests = [[ Date.new(2005, 2, 1), %("2005-02-01") ]]
94
+ StandardTimeTests = [[ Time.utc(2005, 2, 1, 15, 15, 10), %("2005-02-01T15:15:10.000Z") ]]
95
+ StandardDateTimeTests = [[ DateTime.civil(2005, 2, 1, 15, 15, 10), %("2005-02-01T15:15:10.000+00:00") ]]
96
+ StandardStringTests = [[ "this is the <string>", %("this is the <string>")]]
97
+ end
98
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ if ENV["BUILDKITE"]
4
+ require "minitest/reporters"
5
+ require "fileutils"
6
+
7
+ module Minitest
8
+ def self.plugin_rails_ci_junit_format_test_report_for_buildkite_init(*)
9
+ dir = File.join(__dir__, "../test-reports/#{ENV['BUILDKITE_JOB_ID']}")
10
+ reporter << Minitest::Reporters::JUnitReporter.new(dir, false)
11
+ FileUtils.mkdir_p(dir)
12
+ end
13
+ end
14
+
15
+ Minitest.load_plugins
16
+ Minitest.extensions.unshift "rails_ci_junit_format_test_report_for_buildkite"
17
+ end
@@ -0,0 +1,163 @@
1
+ # frozen_string_literal: true
2
+
3
+ gem "minitest" # make sure we get the gem, not stdlib
4
+ require "minitest"
5
+ require "active_support/testing/tagged_logging"
6
+ require "active_support/testing/setup_and_teardown"
7
+ require "active_support/testing/assertions"
8
+ require "active_support/testing/deprecation"
9
+ require "active_support/testing/declarative"
10
+ require "active_support/testing/isolation"
11
+ require "active_support/testing/constant_lookup"
12
+ require "active_support/testing/time_helpers"
13
+ require "active_support/testing/file_fixtures"
14
+ require "active_support/testing/parallelization"
15
+ require "concurrent/utility/processor_counter"
16
+
17
+ module ActiveSupport
18
+ class TestCase < ::Minitest::Test
19
+ Assertion = Minitest::Assertion
20
+
21
+ class << self
22
+ # Sets the order in which test cases are run.
23
+ #
24
+ # ActiveSupport::TestCase.test_order = :random # => :random
25
+ #
26
+ # Valid values are:
27
+ # * +:random+ (to run tests in random order)
28
+ # * +:parallel+ (to run tests in parallel)
29
+ # * +:sorted+ (to run tests alphabetically by method name)
30
+ # * +:alpha+ (equivalent to +:sorted+)
31
+ def test_order=(new_order)
32
+ ActiveSupport.test_order = new_order
33
+ end
34
+
35
+ # Returns the order in which test cases are run.
36
+ #
37
+ # ActiveSupport::TestCase.test_order # => :random
38
+ #
39
+ # Possible values are +:random+, +:parallel+, +:alpha+, +:sorted+.
40
+ # Defaults to +:random+.
41
+ def test_order
42
+ ActiveSupport.test_order ||= :random
43
+ end
44
+
45
+ # Parallelizes the test suite.
46
+ #
47
+ # Takes a +workers+ argument that controls how many times the process
48
+ # is forked. For each process a new database will be created suffixed
49
+ # with the worker number.
50
+ #
51
+ # test-database-0
52
+ # test-database-1
53
+ #
54
+ # If <tt>ENV["PARALLEL_WORKERS"]</tt> is set the workers argument will be ignored
55
+ # and the environment variable will be used instead. This is useful for CI
56
+ # environments, or other environments where you may need more workers than
57
+ # you do for local testing.
58
+ #
59
+ # If the number of workers is set to +1+ or fewer, the tests will not be
60
+ # parallelized.
61
+ #
62
+ # If +workers+ is set to +:number_of_processors+, the number of workers will be
63
+ # set to the actual core count on the machine you are on.
64
+ #
65
+ # The default parallelization method is to fork processes. If you'd like to
66
+ # use threads instead you can pass <tt>with: :threads</tt> to the +parallelize+
67
+ # method. Note the threaded parallelization does not create multiple
68
+ # database and will not work with system tests at this time.
69
+ #
70
+ # parallelize(workers: :number_of_processors, with: :threads)
71
+ #
72
+ # The threaded parallelization uses minitest's parallel executor directly.
73
+ # The processes parallelization uses a Ruby DRb server.
74
+ def parallelize(workers: :number_of_processors, with: :processes)
75
+ workers = Concurrent.physical_processor_count if workers == :number_of_processors
76
+ workers = ENV["PARALLEL_WORKERS"].to_i if ENV["PARALLEL_WORKERS"]
77
+
78
+ return if workers <= 1
79
+
80
+ executor = case with
81
+ when :processes
82
+ Testing::Parallelization.new(workers)
83
+ when :threads
84
+ Minitest::Parallel::Executor.new(workers)
85
+ else
86
+ raise ArgumentError, "#{with} is not a supported parallelization executor."
87
+ end
88
+
89
+ self.lock_threads = false if defined?(self.lock_threads) && with == :threads
90
+
91
+ Minitest.parallel_executor = executor
92
+
93
+ parallelize_me!
94
+ end
95
+
96
+ # Set up hook for parallel testing. This can be used if you have multiple
97
+ # databases or any behavior that needs to be run after the process is forked
98
+ # but before the tests run.
99
+ #
100
+ # Note: this feature is not available with the threaded parallelization.
101
+ #
102
+ # In your +test_helper.rb+ add the following:
103
+ #
104
+ # class ActiveSupport::TestCase
105
+ # parallelize_setup do
106
+ # # create databases
107
+ # end
108
+ # end
109
+ def parallelize_setup(&block)
110
+ ActiveSupport::Testing::Parallelization.after_fork_hook do |worker|
111
+ yield worker
112
+ end
113
+ end
114
+
115
+ # Clean up hook for parallel testing. This can be used to drop databases
116
+ # if your app uses multiple write/read databases or other clean up before
117
+ # the tests finish. This runs before the forked process is closed.
118
+ #
119
+ # Note: this feature is not available with the threaded parallelization.
120
+ #
121
+ # In your +test_helper.rb+ add the following:
122
+ #
123
+ # class ActiveSupport::TestCase
124
+ # parallelize_teardown do
125
+ # # drop databases
126
+ # end
127
+ # end
128
+ def parallelize_teardown(&block)
129
+ ActiveSupport::Testing::Parallelization.run_cleanup_hook do |worker|
130
+ yield worker
131
+ end
132
+ end
133
+ end
134
+
135
+ alias_method :method_name, :name
136
+
137
+ include ActiveSupport::Testing::TaggedLogging
138
+ prepend ActiveSupport::Testing::SetupAndTeardown
139
+ include ActiveSupport::Testing::Assertions
140
+ include ActiveSupport::Testing::Deprecation
141
+ include ActiveSupport::Testing::TimeHelpers
142
+ include ActiveSupport::Testing::FileFixtures
143
+ extend ActiveSupport::Testing::Declarative
144
+
145
+ # test/unit backwards compatibility methods
146
+ alias :assert_raise :assert_raises
147
+ alias :assert_not_empty :refute_empty
148
+ alias :assert_not_equal :refute_equal
149
+ alias :assert_not_in_delta :refute_in_delta
150
+ alias :assert_not_in_epsilon :refute_in_epsilon
151
+ alias :assert_not_includes :refute_includes
152
+ alias :assert_not_instance_of :refute_instance_of
153
+ alias :assert_not_kind_of :refute_kind_of
154
+ alias :assert_no_match :refute_match
155
+ alias :assert_not_nil :refute_nil
156
+ alias :assert_not_operator :refute_operator
157
+ alias :assert_not_predicate :refute_predicate
158
+ alias :assert_not_respond_to :refute_respond_to
159
+ alias :assert_not_same :refute_same
160
+
161
+ ActiveSupport.run_load_hooks(:active_support_test_case, self)
162
+ end
163
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TimeZoneTestHelpers
4
+ def with_tz_default(tz = nil)
5
+ old_tz = Time.zone
6
+ Time.zone = tz
7
+ yield
8
+ ensure
9
+ Time.zone = old_tz
10
+ end
11
+
12
+ def with_env_tz(new_tz = "US/Eastern")
13
+ old_tz, ENV["TZ"] = ENV["TZ"], new_tz
14
+ yield
15
+ ensure
16
+ old_tz ? ENV["TZ"] = old_tz : ENV.delete("TZ")
17
+ end
18
+
19
+ def with_preserve_timezone(value)
20
+ old_preserve_tz = ActiveSupport.to_time_preserves_timezone
21
+ ActiveSupport.to_time_preserves_timezone = value
22
+ yield
23
+ ensure
24
+ ActiveSupport.to_time_preserves_timezone = old_preserve_tz
25
+ end
26
+
27
+ def with_tz_mappings(mappings)
28
+ old_mappings = ActiveSupport::TimeZone::MAPPING.dup
29
+ ActiveSupport::TimeZone.clear
30
+ ActiveSupport::TimeZone::MAPPING.clear
31
+ ActiveSupport::TimeZone::MAPPING.merge!(mappings)
32
+
33
+ yield
34
+ ensure
35
+ ActiveSupport::TimeZone.clear
36
+ ActiveSupport::TimeZone::MAPPING.clear
37
+ ActiveSupport::TimeZone::MAPPING.merge!(old_mappings)
38
+ end
39
+ end
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
2
 
4
3
  $: << File.dirname(__FILE__)
5
4
  $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
@@ -7,19 +6,30 @@ $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
7
6
  $: << File.join($oj_dir, dir)
8
7
  end
9
8
 
10
- require 'oj'
9
+ require 'active_support'
10
+ require "active_support/json"
11
+
12
+ $s = "\u2014 & \n \u{1F618}"
11
13
 
12
- #Oj.load_file(ARGV[0], mode: :strict) { |obj|
13
- # puts Oj.dump(obj, indent: 2)
14
- #}
14
+ =begin
15
+ def check(label)
16
+ puts "\n--- #{label} --------------------"
15
17
 
16
- data = open('invalid_unicode.data').read
18
+ ActiveSupport::JSON::Encoding.use_standard_json_time_format = true
19
+ puts "with standard_json == true: t.to_json - #{$t.to_json}"
20
+ ActiveSupport::JSON::Encoding.use_standard_json_time_format = false
21
+ puts "with standard_json == false: t.to_json - #{$t.to_json}"
22
+ end
17
23
 
18
- puts data
24
+ check('Before Oj')
25
+ =end
26
+
27
+ require 'oj'
19
28
 
20
- puts Oj.dump(data)
29
+ ActiveSupport::JSON::Encoding.escape_html_entities_in_json = false
30
+ puts "ActiveSupport.encode(s) - #{ActiveSupport::JSON.encode($s)}"
21
31
 
22
- Oj.mimic_JSON
23
- puts Oj.dump(data, escape_mode: :json)
32
+ Oj.optimize_rails
33
+ Oj.default_options = { mode: :rails }
24
34
 
25
- puts Oj.default_options
35
+ puts "Oj.dump(s) - #{Oj.dump($s)}"
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << File.dirname(__FILE__)
4
+ $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
5
+ %w(lib ext).each do |dir|
6
+ $: << File.join($oj_dir, dir)
7
+ end
8
+
9
+ require 'oj'
10
+ Oj.mimic_JSON()
11
+
12
+ begin
13
+ ::JSON.load('name=&email=&subject=&comment=&submit=Send+Message')
14
+ rescue ::JSON::ParserError
15
+ puts "*** Pass"
16
+ end
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
2
 
4
3
  $: << File.dirname(__FILE__)
5
4
  $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
@@ -7,15 +6,47 @@ $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
7
6
  $: << File.join($oj_dir, dir)
8
7
  end
9
8
 
9
+ require 'json'
10
+
11
+ t = [Time.now.utc]
12
+
13
+ puts "t.to_json - #{t.to_json}"
14
+
15
+ puts "--- active support"
16
+
17
+ require 'active_support'
18
+ require "active_support/json"
19
+
20
+ ActiveSupport::JSON::Encoding.use_standard_json_time_format = false
21
+
22
+ puts "t.as_json - #{t.as_json}"
23
+ puts "t.to_json - #{t.to_json}"
24
+
10
25
  require 'oj'
26
+
27
+ t = [Time.now.utc]
28
+
29
+ puts "-----------------------"
30
+
31
+ #puts "t.as_json - #{t.as_json}"
32
+ puts "t.to_json - #{t.to_json}"
33
+
34
+ #Oj.mimic_JSON
35
+
36
+ #puts "Oj - t.as_json - #{t.as_json}"
37
+
38
+ puts "--- active support"
39
+
11
40
  require 'active_support'
12
- require 'active_support/json'
13
- #require 'tracer'
41
+ require "active_support/json"
42
+
43
+ ActiveSupport::JSON::Encoding.use_standard_json_time_format = false
14
44
 
15
- Oj::Rails.set_encoder()
16
- Oj::Rails.set_decoder()
17
- Oj::Rails.optimize()
45
+ puts "t.as_json - #{t.as_json}"
46
+ puts "t.to_json - #{t.to_json}"
18
47
 
19
- #Oj::mimic_JSON
48
+ puts "--- optimize"
49
+ Oj.optimize_rails
20
50
 
21
- puts JSON.parse('{"a":1}', symbolize_names: true)
51
+ puts "t.as_json - #{t.as_json}"
52
+ puts "t.to_json - #{t.to_json}"
@@ -147,16 +147,9 @@ class CompatJuice < Minitest::Test
147
147
 
148
148
  def test_encode
149
149
  opts = Oj.default_options
150
- Oj.default_options = { :ascii_only => false }
151
- unless 'jruby' == $ruby
152
- dump_and_load("ぴーたー", false)
153
- end
154
150
  Oj.default_options = { :ascii_only => true }
155
151
  json = Oj.dump("ぴーたー")
156
152
  assert_equal(%{"\\u3074\\u30fc\\u305f\\u30fc"}, json)
157
- unless 'jruby' == $ruby
158
- dump_and_load("ぴーたー", false)
159
- end
160
153
  Oj.default_options = opts
161
154
  end
162
155