File: decoding_test.rb

package info (click to toggle)
ruby-oj 3.16.3-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 1,852 kB
  • sloc: ansic: 19,402; ruby: 11,451; makefile: 17
file content (133 lines) | stat: -rw-r--r-- 5,920 bytes parent folder | download | duplicates (5)
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
# frozen_string_literal: true

require_relative "abstract_unit"
require "active_support/json"
require "active_support/time"
require_relative "time_zone_test_helpers"

require 'oj'

Oj::Rails.set_decoder()

class TestJSONDecoding < ActiveSupport::TestCase
  include TimeZoneTestHelpers

  # Added for testing if Oj is used.
  test "oj is used as an encoder" do
    assert_equal ActiveSupport.json_encoder, Oj::Rails::Encoder
  end

  class Foo
    def self.json_create(object)
      "Foo"
    end
  end

  TESTS = {
    %q({"returnTo":{"\/categories":"\/"}})        => { "returnTo" => { "/categories" => "/" } },
    %q({"return\\"To\\":":{"\/categories":"\/"}}) => { "return\"To\":" => { "/categories" => "/" } },
    %q({"returnTo":{"\/categories":1}}) => { "returnTo" => { "/categories" => 1 } },
    %({"returnTo":[1,"a"]})                    => { "returnTo" => [1, "a"] },
    %({"returnTo":[1,"\\"a\\",", "b"]})        => { "returnTo" => [1, "\"a\",", "b"] },
    %({"a": "'", "b": "5,000"})                  => { "a" => "'", "b" => "5,000" },
    %({"a": "a's, b's and c's", "b": "5,000"})   => { "a" => "a's, b's and c's", "b" => "5,000" },
    # multibyte
    %({"matzue": "松江", "asakusa": "浅草"}) => { "matzue" => "松江", "asakusa" => "浅草" },
    %({"a": "2007-01-01"})                       => { "a" => Date.new(2007, 1, 1) },
    %({"a": "2007-01-01 01:12:34 Z"})            => { "a" => Time.utc(2007, 1, 1, 1, 12, 34) },
    %(["2007-01-01 01:12:34 Z"])                 => [Time.utc(2007, 1, 1, 1, 12, 34)],
    %(["2007-01-01 01:12:34 Z", "2007-01-01 01:12:35 Z"]) => [Time.utc(2007, 1, 1, 1, 12, 34), Time.utc(2007, 1, 1, 1, 12, 35)],
    # no time zone
    %({"a": "2007-01-01 01:12:34"})              => { "a" => Time.new(2007, 1, 1, 1, 12, 34, "-05:00") },
    # invalid date
    %({"a": "1089-10-40"})                       => { "a" => "1089-10-40" },
    # xmlschema date notation
    %({"a": "2009-08-10T19:01:02"})              => { "a" => Time.new(2009, 8, 10, 19, 1, 2, "-04:00") },
    %({"a": "2009-08-10T19:01:02Z"})             => { "a" => Time.utc(2009, 8, 10, 19, 1, 2) },
    %({"a": "2009-08-10T19:01:02+02:00"})        => { "a" => Time.utc(2009, 8, 10, 17, 1, 2) },
    %({"a": "2009-08-10T19:01:02-05:00"})        => { "a" => Time.utc(2009, 8, 11, 00, 1, 2) },
    # needs to be *exact*
    %({"a": " 2007-01-01 01:12:34 Z "})          => { "a" => " 2007-01-01 01:12:34 Z " },
    %({"a": "2007-01-01 : it's your birthday"})  => { "a" => "2007-01-01 : it's your birthday" },
    %([])    => [],
    %({})    => {},
    %({"a":1}) => { "a" => 1 },
    %({"a": ""}) => { "a" => "" },
    %({"a":"\\""}) => { "a" => "\"" },
    %({"a": null})  => { "a" => nil },
    %({"a": true})  => { "a" => true },
    %({"a": false}) => { "a" => false },
    '{"bad":"\\\\","trailing":""}' => { "bad" => "\\", "trailing" => "" },
    %q({"a": "http:\/\/test.host\/posts\/1"}) => { "a" => "http://test.host/posts/1" },
    %q({"a": "\u003cunicode\u0020escape\u003e"}) => { "a" => "<unicode escape>" },
    '{"a": "\\\\u0020skip double backslashes"}' => { "a" => "\\u0020skip double backslashes" },
    %q({"a": "\u003cbr /\u003e"}) => { "a" => "<br />" },
    %q({"b":["\u003ci\u003e","\u003cb\u003e","\u003cu\u003e"]}) => { "b" => ["<i>", "<b>", "<u>"] },
    # test combination of dates and escaped or unicode encoded data in arrays
    %q([{"d":"1970-01-01", "s":"\u0020escape"},{"d":"1970-01-01", "s":"\u0020escape"}]) =>
      [{ "d" => Date.new(1970, 1, 1), "s" => " escape" }, { "d" => Date.new(1970, 1, 1), "s" => " escape" }],
    %q([{"d":"1970-01-01","s":"http:\/\/example.com"},{"d":"1970-01-01","s":"http:\/\/example.com"}]) =>
      [{ "d" => Date.new(1970, 1, 1), "s" => "http://example.com" },
       { "d" => Date.new(1970, 1, 1), "s" => "http://example.com" }],
    # tests escaping of "\n" char with Yaml backend
    %q({"a":"\n"}) => { "a" => "\n" },
    %q({"a":"\u000a"}) => { "a" => "\n" },
    %q({"a":"Line1\u000aLine2"}) => { "a" => "Line1\nLine2" },
    # prevent json unmarshalling
    '{"json_class":"TestJSONDecoding::Foo"}' => { "json_class" => "TestJSONDecoding::Foo" },
    # json "fragments" - these are invalid JSON, but ActionPack relies on this
    '"a string"' => "a string",
    "1.1" => 1.1,
    "1" => 1,
    "-1" => -1,
    "true" => true,
    "false" => false,
    "null" => nil
  }

  TESTS.each_with_index do |(json, expected), index|
    fail_message = "JSON decoding failed for #{json}"

    test "json decodes #{index}" do
      with_tz_default "Eastern Time (US & Canada)" do
        with_parse_json_times(true) do
          silence_warnings do
            if expected.nil?
              assert_nil ActiveSupport::JSON.decode(json), fail_message
            else
              assert_equal expected, ActiveSupport::JSON.decode(json), fail_message
            end
          end
        end
      end
    end
  end

  test "json decodes time json with time parsing disabled" do
    with_parse_json_times(false) do
      expected = { "a" => "2007-01-01 01:12:34 Z" }
      assert_equal expected, ActiveSupport::JSON.decode(%({"a": "2007-01-01 01:12:34 Z"}))
    end
  end

  def test_failed_json_decoding
    assert_raise(ActiveSupport::JSON.parse_error) { ActiveSupport::JSON.decode(%(undefined)) }
    assert_raise(ActiveSupport::JSON.parse_error) { ActiveSupport::JSON.decode(%({a: 1})) }
    assert_raise(ActiveSupport::JSON.parse_error) { ActiveSupport::JSON.decode(%({: 1})) }
    assert_raise(ActiveSupport::JSON.parse_error) { ActiveSupport::JSON.decode(%()) }
  end

  def test_cannot_pass_unsupported_options
    assert_raise(ArgumentError) { ActiveSupport::JSON.decode("", create_additions: true) }
  end

  private

    def with_parse_json_times(value)
      old_value = ActiveSupport.parse_json_times
      ActiveSupport.parse_json_times = value
      yield
    ensure
      ActiveSupport.parse_json_times = old_value
    end
end