json-stream 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +19 -0
- data/README +82 -0
- data/Rakefile +38 -0
- data/lib/json/stream.rb +15 -0
- data/lib/json/stream/buffer.rb +63 -0
- data/lib/json/stream/builder.rb +92 -0
- data/lib/json/stream/parser.rb +430 -0
- data/test/buffer_test.rb +87 -0
- data/test/builder_test.rb +123 -0
- data/test/parser_test.rb +451 -0
- metadata +84 -0
data/test/buffer_test.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'json/stream'
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
class BufferTest < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@buf = JSON::Stream::Buffer.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_single_byte_chars
|
12
|
+
assert_equal("", @buf << "")
|
13
|
+
assert_equal("abc", @buf << "abc")
|
14
|
+
assert_equal("\u0000abc", @buf << "\u0000abc")
|
15
|
+
end
|
16
|
+
|
17
|
+
# The é character can be a single codepoint \u00e9 or two codepoints
|
18
|
+
# \u0065\u0301. The first is encoded in 2 bytes, the second in 3 bytes.
|
19
|
+
# The json and yajl-ruby gems and CouchDB do not normalize unicode text
|
20
|
+
# so neither will we. Although, a good way to normalize is by calling
|
21
|
+
# ActiveSupport::Multibyte::Chars.new("é").normalize(:c).
|
22
|
+
def test_combined_chars
|
23
|
+
assert_equal("\u0065\u0301", @buf << "\u0065\u0301")
|
24
|
+
assert_equal(3, (@buf << "\u0065\u0301").bytesize)
|
25
|
+
assert_equal(2, (@buf << "\u0065\u0301").size)
|
26
|
+
|
27
|
+
assert_equal("\u00e9", @buf << "\u00e9")
|
28
|
+
assert_equal(2, (@buf << "\u00e9").bytesize)
|
29
|
+
assert_equal(1, (@buf << "\u00e9").size)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_valid_two_byte_chars
|
33
|
+
assert_equal("abcé", @buf << "abcé")
|
34
|
+
assert_equal("a", @buf << "a\xC3")
|
35
|
+
assert_equal("é", @buf << "\xA9")
|
36
|
+
assert_equal("", @buf << "\xC3")
|
37
|
+
assert_equal("é", @buf << "\xA9")
|
38
|
+
assert_equal("é", @buf << "\xC3\xA9")
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_valid_three_byte_chars
|
42
|
+
assert_equal("abcé\u2603", @buf << "abcé\u2603")
|
43
|
+
assert_equal("a", @buf << "a\xE2")
|
44
|
+
assert_equal("", @buf << "\x98")
|
45
|
+
assert_equal("\u2603", @buf << "\x83")
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_valid_four_byte_chars
|
49
|
+
assert_equal("abcé\u2603\u{10102}é", @buf << "abcé\u2603\u{10102}é")
|
50
|
+
assert_equal("a", @buf << "a\xF0")
|
51
|
+
assert_equal("", @buf << "\x90")
|
52
|
+
assert_equal("", @buf << "\x84")
|
53
|
+
assert_equal("\u{10102}", @buf << "\x82")
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_invalid_two_byte_start_chars
|
57
|
+
assert_raise(JSON::Stream::ParserError) { @buf << "\xC3\xC3" }
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_invalid_three_byte_start_chars
|
61
|
+
assert_raise(JSON::Stream::ParserError) { @buf << "\xE2\xE2" }
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_invalid_four_byte_start_chars
|
65
|
+
assert_raise(JSON::Stream::ParserError) { @buf << "\xF0\xF0" }
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_two_byte_start_with_single_byte_continuation_char
|
69
|
+
assert_raise(JSON::Stream::ParserError) { @buf << "\xC3\u0000" }
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_three_byte_start_with_single_byte_continuation_char
|
73
|
+
assert_raise(JSON::Stream::ParserError) { @buf << "\xE2\u0010" }
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_four_byte_start_with_single_byte_continuation_char
|
77
|
+
assert_raise(JSON::Stream::ParserError) { @buf << "\xF0a" }
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_invalid_continuation_char
|
81
|
+
assert_raise(JSON::Stream::ParserError) { @buf << "\xA9" }
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_overlong_form
|
85
|
+
assert_raise(JSON::Stream::ParserError) { @buf << "\xC0\x80" }
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'json/stream'
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
class BuilderTest < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@b = JSON::Stream::Builder.new(JSON::Stream::Parser.new)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_empty_array
|
12
|
+
assert_nil(@b.result)
|
13
|
+
@b.start_document
|
14
|
+
@b.start_array
|
15
|
+
@b.end_array
|
16
|
+
assert_nil(@b.result)
|
17
|
+
@b.end_document
|
18
|
+
assert_equal([], @b.result)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_number_array
|
22
|
+
@b.start_document
|
23
|
+
@b.start_array
|
24
|
+
@b.value(1)
|
25
|
+
@b.value(2)
|
26
|
+
@b.value(3)
|
27
|
+
@b.end_array
|
28
|
+
@b.end_document
|
29
|
+
assert_equal([1,2,3], @b.result)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_nested_empty_arrays
|
33
|
+
@b.start_document
|
34
|
+
@b.start_array
|
35
|
+
@b.start_array
|
36
|
+
@b.end_array
|
37
|
+
@b.end_array
|
38
|
+
@b.end_document
|
39
|
+
assert_equal([[]], @b.result)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_nested_arrays
|
43
|
+
@b.start_document
|
44
|
+
@b.start_array
|
45
|
+
@b.value(1)
|
46
|
+
@b.start_array
|
47
|
+
@b.value(2)
|
48
|
+
@b.end_array
|
49
|
+
@b.value(3)
|
50
|
+
@b.end_array
|
51
|
+
@b.end_document
|
52
|
+
assert_equal([1,[2],3], @b.result)
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_empty_object
|
56
|
+
@b.start_document
|
57
|
+
@b.start_object
|
58
|
+
@b.end_object
|
59
|
+
@b.end_document
|
60
|
+
assert_equal({}, @b.result)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_object
|
64
|
+
@b.start_document
|
65
|
+
@b.start_object
|
66
|
+
@b.key("k1")
|
67
|
+
@b.value(1)
|
68
|
+
@b.key("k2")
|
69
|
+
@b.value(nil)
|
70
|
+
@b.key("k3")
|
71
|
+
@b.value(true)
|
72
|
+
@b.key("k4")
|
73
|
+
@b.value(false)
|
74
|
+
@b.key("k5")
|
75
|
+
@b.value("string value")
|
76
|
+
@b.end_object
|
77
|
+
@b.end_document
|
78
|
+
expected = {"k1" => 1, "k2" => nil, "k3" => true,
|
79
|
+
"k4" => false, "k5" => "string value"}
|
80
|
+
assert_equal(expected, @b.result)
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_nested_object
|
84
|
+
@b.start_document
|
85
|
+
@b.start_object
|
86
|
+
@b.key("k1")
|
87
|
+
@b.value(1)
|
88
|
+
|
89
|
+
@b.key("k2")
|
90
|
+
@b.start_object
|
91
|
+
@b.end_object
|
92
|
+
|
93
|
+
@b.key("k3")
|
94
|
+
@b.start_object
|
95
|
+
@b.key("sub1")
|
96
|
+
@b.start_array
|
97
|
+
@b.value(12)
|
98
|
+
@b.end_array
|
99
|
+
@b.end_object
|
100
|
+
|
101
|
+
@b.key("k4")
|
102
|
+
@b.start_array
|
103
|
+
@b.value(1)
|
104
|
+
@b.start_object
|
105
|
+
@b.key("sub2")
|
106
|
+
@b.start_array
|
107
|
+
@b.value(nil)
|
108
|
+
@b.end_array
|
109
|
+
@b.end_object
|
110
|
+
@b.end_array
|
111
|
+
|
112
|
+
@b.key("k5")
|
113
|
+
@b.value("string value")
|
114
|
+
@b.end_object
|
115
|
+
@b.end_document
|
116
|
+
expected = {"k1"=>1,
|
117
|
+
"k2"=>{},
|
118
|
+
"k3"=>{"sub1"=>[12]},
|
119
|
+
"k4"=>[1, {"sub2"=>[nil]}],
|
120
|
+
"k5"=>"string value"}
|
121
|
+
assert_equal(expected, @b.result)
|
122
|
+
end
|
123
|
+
end
|
data/test/parser_test.rb
ADDED
@@ -0,0 +1,451 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'json/stream'
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
class ParserTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
# JSON documents must start with an array or object container
|
9
|
+
# and there must not be any extra data following that container.
|
10
|
+
def test_document
|
11
|
+
expected = [:error]
|
12
|
+
['a', 'null', 'false', 'true', '12', ' false '].each do |json|
|
13
|
+
assert_equal(expected, events(json))
|
14
|
+
end
|
15
|
+
|
16
|
+
expected = [:start_document, :start_array, :end_array, :end_document]
|
17
|
+
['[]', '[ ]', ' [] ', ' [ ] '].each do |json|
|
18
|
+
assert_equal(expected, events(json))
|
19
|
+
end
|
20
|
+
|
21
|
+
expected = [:start_document, :start_object, :end_object, :end_document]
|
22
|
+
['{}', '{ }', ' {} ', ' { } '].each do |json|
|
23
|
+
assert_equal(expected, events(json))
|
24
|
+
end
|
25
|
+
|
26
|
+
expected = [:start_document, :start_object, :end_object, :end_document, :error]
|
27
|
+
['{}a', '{ } 12', ' {} false', ' { }, {}'].each do |json|
|
28
|
+
assert_equal(expected, events(json))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Whitespace around tokens should be ignored. Whitespace whithin strings
|
33
|
+
# must be preserved.
|
34
|
+
def test_whitespace
|
35
|
+
json = %Q{
|
36
|
+
{ " key 1 " : \t [
|
37
|
+
1, 2, " my string ",
|
38
|
+
false, true, null ]
|
39
|
+
}
|
40
|
+
}
|
41
|
+
expected = [:start_document, :start_object,
|
42
|
+
[:key, " key 1 "],
|
43
|
+
:start_array,
|
44
|
+
[:value, 1],
|
45
|
+
[:value, 2],
|
46
|
+
[:value, " my string "],
|
47
|
+
[:value, false],
|
48
|
+
[:value, true],
|
49
|
+
[:value, nil],
|
50
|
+
:end_array, :end_object, :end_document]
|
51
|
+
assert_equal(expected, events(json))
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_keyword
|
55
|
+
expected = [:start_document, :start_array, :error]
|
56
|
+
['[tru]', '[fal]', '[nul,true]', '[fals1]'].each do |json|
|
57
|
+
assert_equal(expected, events(json))
|
58
|
+
end
|
59
|
+
|
60
|
+
expected = [:start_document, :start_array, [:value, true], :end_array, :end_document]
|
61
|
+
assert_equal(expected, events('[true]'))
|
62
|
+
|
63
|
+
expected = [:start_document, :start_array, [:value, true], [:value, nil], :end_array, :end_document]
|
64
|
+
assert_equal(expected, events('[true, null]'))
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_negative
|
68
|
+
expected = [:start_document, :start_array, :error]
|
69
|
+
assert_equal(expected, events('[-]'))
|
70
|
+
|
71
|
+
expected = [:start_document, :start_array, [:value, 1], :error]
|
72
|
+
assert_equal(expected, events('[1-0]'))
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_int_zero
|
76
|
+
expected = [:start_document, :start_array, [:value, 0], :end_array, :end_document]
|
77
|
+
assert_equal(expected, events('[0]'))
|
78
|
+
assert_equal(expected, events('[-0]'))
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_float_zero
|
82
|
+
expected = [:start_document, :start_array, [:value, 0.0], :end_array, :end_document]
|
83
|
+
assert_equal(expected, events('[0.0]'))
|
84
|
+
assert_equal(expected, events('[-0.0]'))
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_multi_zero
|
88
|
+
expected = [:start_document, :start_array, [:value, 0], :error]
|
89
|
+
assert_equal(expected, events('[00]'))
|
90
|
+
assert_equal(expected, events('[-00]'))
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_starts_with_zero
|
94
|
+
expected = [:start_document, :start_array, [:value, 0], :error]
|
95
|
+
assert_equal(expected, events('[01]'))
|
96
|
+
assert_equal(expected, events('[-01]'))
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_int
|
100
|
+
expected = [:start_document, :start_array, [:value, 1], :end_array, :end_document]
|
101
|
+
assert_equal(expected, events('[1]'))
|
102
|
+
|
103
|
+
expected = [:start_document, :start_array, [:value, -1], :end_array, :end_document]
|
104
|
+
assert_equal(expected, events('[-1]'))
|
105
|
+
|
106
|
+
expected = [:start_document, :start_array, [:value, 123], :end_array, :end_document]
|
107
|
+
assert_equal(expected, events('[123]'))
|
108
|
+
|
109
|
+
expected = [:start_document, :start_array, [:value, -123], :end_array, :end_document]
|
110
|
+
assert_equal(expected, events('[-123]'))
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_float
|
114
|
+
expected = [:start_document, :start_array, [:value, 1.0], :end_array, :end_document]
|
115
|
+
assert_equal(expected, events('[1.0]'))
|
116
|
+
assert_equal(expected, events('[1.00]'))
|
117
|
+
|
118
|
+
expected = [:start_document, :start_array, [:value, -1.0], :end_array, :end_document]
|
119
|
+
assert_equal(expected, events('[-1.0]'))
|
120
|
+
assert_equal(expected, events('[-1.00]'))
|
121
|
+
|
122
|
+
expected = [:start_document, :start_array, [:value, 123.012], :end_array, :end_document]
|
123
|
+
assert_equal(expected, events('[123.012]'))
|
124
|
+
assert_equal(expected, events('[123.0120]'))
|
125
|
+
|
126
|
+
expected = [:start_document, :start_array, [:value, -123.012], :end_array, :end_document]
|
127
|
+
assert_equal(expected, events('[-123.012]'))
|
128
|
+
assert_equal(expected, events('[-123.0120]'))
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_missing_leading_zero
|
132
|
+
expected = [:start_document, :start_array, :error]
|
133
|
+
assert_equal(expected, events('[.1]'))
|
134
|
+
assert_equal(expected, events('[-.1]'))
|
135
|
+
assert_equal(expected, events('[.01]'))
|
136
|
+
assert_equal(expected, events('[-.01]'))
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_missing_fraction
|
140
|
+
expected = [:start_document, :start_array, :error]
|
141
|
+
assert_equal(expected, events('[.]'))
|
142
|
+
assert_equal(expected, events('[..]'))
|
143
|
+
assert_equal(expected, events('[0.]'))
|
144
|
+
assert_equal(expected, events('[12.]'))
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_positive_exponent
|
148
|
+
expected = [:start_document, :start_array, [:value, 212], :end_array, :end_document]
|
149
|
+
assert_equal(expected, events('[2.12e2]'))
|
150
|
+
assert_equal(expected, events('[2.12e02]'))
|
151
|
+
assert_equal(expected, events('[2.12e+2]'))
|
152
|
+
assert_equal(expected, events('[2.12e+02]'))
|
153
|
+
|
154
|
+
expected = [:start_document, :start_array, [:value, 21.2], :end_array, :end_document]
|
155
|
+
assert_equal(expected, events('[2.12e1]'))
|
156
|
+
assert_equal(expected, events('[2.12e01]'))
|
157
|
+
assert_equal(expected, events('[2.12e+1]'))
|
158
|
+
assert_equal(expected, events('[2.12e+01]'))
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_negative_exponent
|
162
|
+
expected = [:start_document, :start_array, [:value, 0.0212], :end_array, :end_document]
|
163
|
+
assert_equal(expected, events('[2.12e-2]'))
|
164
|
+
assert_equal(expected, events('[2.12e-02]'))
|
165
|
+
assert_equal(expected, events('[2.12e-2]'))
|
166
|
+
assert_equal(expected, events('[2.12e-02]'))
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_zero_exponent
|
170
|
+
expected = [:start_document, :start_array, [:value, 2.12], :end_array, :end_document]
|
171
|
+
assert_equal(expected, events('[2.12e0]'))
|
172
|
+
assert_equal(expected, events('[2.12e00]'))
|
173
|
+
assert_equal(expected, events('[2.12e-0]'))
|
174
|
+
assert_equal(expected, events('[2.12e-00]'))
|
175
|
+
|
176
|
+
expected = [:start_document, :start_array, [:value, 2.0], :end_array, :end_document]
|
177
|
+
assert_equal(expected, events('[2e0]'))
|
178
|
+
assert_equal(expected, events('[2e00]'))
|
179
|
+
assert_equal(expected, events('[2e-0]'))
|
180
|
+
assert_equal(expected, events('[2e-00]'))
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_missing_exponent
|
184
|
+
expected = [:start_document, :start_array, :error]
|
185
|
+
assert_equal(expected, events('[e]'))
|
186
|
+
assert_equal(expected, events('[1e]'))
|
187
|
+
assert_equal(expected, events('[1e-]'))
|
188
|
+
assert_equal(expected, events('[1e--]'))
|
189
|
+
assert_equal(expected, events('[1e+]'))
|
190
|
+
assert_equal(expected, events('[1e++]'))
|
191
|
+
assert_equal(expected, events('[0.e]'))
|
192
|
+
assert_equal(expected, events('[10.e]'))
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_non_digit_end_char
|
196
|
+
expected = [:start_document, :start_array, [:value, 0.0], :error]
|
197
|
+
assert_equal(expected, events('[0.0q]'))
|
198
|
+
|
199
|
+
expected = [:start_document, :start_array, [:value, 1], :error]
|
200
|
+
assert_equal(expected, events('[1q]'))
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_string
|
204
|
+
expected = [:start_document, :start_array, :error]
|
205
|
+
assert_equal(expected, events(%q{ [" \\a "] }))
|
206
|
+
|
207
|
+
expected = [:start_document, :start_array, [:value, "\" \\ / \b \f \n \r \t"], :end_array, :end_document]
|
208
|
+
assert_equal(expected, events('["\" \\\ \/ \b \f \n \r \t"]'))
|
209
|
+
|
210
|
+
expected = [:start_document, :start_array, [:value, "\"\\/\b\f\n\r\t"], :end_array, :end_document]
|
211
|
+
assert_equal(expected, events('["\"\\\\/\b\f\n\r\t"]'))
|
212
|
+
|
213
|
+
expected = [:start_document, :start_array, [:value, "\"t\\b/f\bn\f/\nn\rr\t"], :end_array, :end_document]
|
214
|
+
assert_equal(expected, events('["\"t\\\b\/f\bn\f/\nn\rr\t"]'))
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_control_char
|
218
|
+
expected = [:start_document, :start_array, :error]
|
219
|
+
assert_equal(expected, events("[\" \u0000 \"]"))
|
220
|
+
|
221
|
+
expected = [:start_document, :start_object, :error]
|
222
|
+
assert_equal(expected, events("{\" \u0000 \":12}"))
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_unicode_escape
|
226
|
+
expected = [:start_document, :start_array, :error]
|
227
|
+
[%q{ [" \\u "] }, %q{ [" \\u2 "]}, %q{ [" \\u26 "]}, %q{ [" \\u260 "]}].each do |json|
|
228
|
+
assert_equal(expected, events(json))
|
229
|
+
end
|
230
|
+
|
231
|
+
expected = [:start_document, :start_array, [:value, "\u2603"], :end_array, :end_document]
|
232
|
+
assert_equal(expected, events(%q{ ["\\u2603"] }))
|
233
|
+
|
234
|
+
expected = [:start_document, :start_array, [:value, "snow\u2603 man"], :end_array, :end_document]
|
235
|
+
assert_equal(expected, events(%q{ ["snow\\u2603 man"] }))
|
236
|
+
|
237
|
+
expected = [:start_document, :start_array, [:value, "snow\u26033 man"], :end_array, :end_document]
|
238
|
+
assert_equal(expected, events(%q{ ["snow\\u26033 man"] }))
|
239
|
+
|
240
|
+
expected = [:start_document, :start_object, [:key, "snow\u26033 man"], [:value, 1], :end_object, :end_document]
|
241
|
+
assert_equal(expected, events(%q{ {"snow\\u26033 man": 1} }))
|
242
|
+
end
|
243
|
+
|
244
|
+
def test_unicode_escape_surrogate_pairs
|
245
|
+
expected = [:start_document, :start_array, :error]
|
246
|
+
assert_equal(expected, events(%q{ ["\uD834"] }))
|
247
|
+
assert_equal(expected, events(%q{ ["\uD834\uD834"] }))
|
248
|
+
assert_equal(expected, events(%q{ ["\uDD1E"] }))
|
249
|
+
assert_equal(expected, events(%q{ ["\uDD1E\uDD1E"] }))
|
250
|
+
|
251
|
+
expected = [:start_document, :start_object, [:key, "\u{1D11E}"],
|
252
|
+
[:value, "g\u{1D11E}clef"], :end_object, :end_document]
|
253
|
+
assert_equal(expected, events(%q{ {"\uD834\uDD1E": "g\uD834\uDD1Eclef"} }))
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_array_trailing_comma
|
257
|
+
expected = [:start_document, :start_array, [:value, 12], :error]
|
258
|
+
assert_equal(expected, events('[12, ]'))
|
259
|
+
end
|
260
|
+
|
261
|
+
def test_nested_array
|
262
|
+
expected = [:start_document, :start_array, :start_array, :end_array, :end_array, :end_document]
|
263
|
+
assert_equal(expected, events('[[]]'))
|
264
|
+
|
265
|
+
expected = [:start_document, :start_array, :start_array, [:value, 2.1], :end_array, :end_array, :end_document]
|
266
|
+
assert_equal(expected, events('[[ 2.10 ]]'))
|
267
|
+
end
|
268
|
+
|
269
|
+
def test_array
|
270
|
+
expected = [:start_document, :start_array, :error]
|
271
|
+
['[}', '[,]', '[, 12]'].each do |json|
|
272
|
+
assert_equal(expected, events(json))
|
273
|
+
end
|
274
|
+
|
275
|
+
expected = [:start_document, :start_array, :start_array, :error]
|
276
|
+
assert_equal(expected, events('[[}]'))
|
277
|
+
['[[}]', '[[,]]'].each do |json|
|
278
|
+
assert_equal(expected, events(json))
|
279
|
+
end
|
280
|
+
|
281
|
+
expected = [:start_document, :start_array, [:value, "test"], :error]
|
282
|
+
['["test"}', '["test",]', '["test" "test"]', '["test" 12]'].each do |json|
|
283
|
+
assert_equal(expected, events(json))
|
284
|
+
end
|
285
|
+
|
286
|
+
expected = [:start_document, :start_array, [:value, "test"], :end_array, :end_document]
|
287
|
+
assert_equal(expected, events('["test"]'))
|
288
|
+
|
289
|
+
expected = [:start_document, :start_array,
|
290
|
+
[:value, 1],
|
291
|
+
[:value, 2],
|
292
|
+
[:value, nil],
|
293
|
+
[:value, 12.1],
|
294
|
+
[:value, "test"],
|
295
|
+
:end_array, :end_document]
|
296
|
+
['[1,2, null, 12.1,"test"]'].each do |json|
|
297
|
+
assert_equal(expected, events(json))
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
def test_object
|
302
|
+
expected = [:start_document, :start_object, :error]
|
303
|
+
['{]', '{:}'].each do |json|
|
304
|
+
assert_equal(expected, events(json))
|
305
|
+
end
|
306
|
+
|
307
|
+
expected = [:start_document, :start_object, [:key, "key 1"], [:value, 12], :end_object, :end_document]
|
308
|
+
assert_equal(expected, events('{"key 1" : 12}'))
|
309
|
+
|
310
|
+
expected = [:start_document, :start_object,
|
311
|
+
[:key, "key 1"], [:value, 12],
|
312
|
+
[:key, "key 2"], [:value, "two"],
|
313
|
+
:end_object, :end_document]
|
314
|
+
assert_equal(expected, events('{"key 1" : 12, "key 2":"two"}'))
|
315
|
+
end
|
316
|
+
|
317
|
+
def test_object_key_with_no_value
|
318
|
+
expected = [:start_document, :start_object, [:key, "key"],
|
319
|
+
:start_array, [:value, nil], [:value, false],
|
320
|
+
[:value, true], :end_array,
|
321
|
+
[:key, "key 2"],
|
322
|
+
:error]
|
323
|
+
assert_equal(expected, events('{"key": [ null , false , true ] ,"key 2"}'))
|
324
|
+
end
|
325
|
+
|
326
|
+
def test_object_trailing_comma
|
327
|
+
expected = [:start_document, :start_object, [:key, "key 1"], [:value, 12], :error]
|
328
|
+
assert_equal(expected, events('{"key 1" : 12,}'))
|
329
|
+
end
|
330
|
+
|
331
|
+
def test_single_byte_utf8
|
332
|
+
expected = [:start_document, :start_array, [:value, "test"], :end_array, :end_document]
|
333
|
+
assert_equal(expected, events('["test"]'))
|
334
|
+
end
|
335
|
+
|
336
|
+
def test_full_two_byte_utf8
|
337
|
+
expected = [:start_document, :start_array, [:value, "résumé"],
|
338
|
+
[:value, "éé"], :end_array, :end_document]
|
339
|
+
assert_equal(expected, events("[\"résumé\", \"é\xC3\xA9\"]"))
|
340
|
+
end
|
341
|
+
|
342
|
+
# Parser should throw an error when only one byte of a two byte character
|
343
|
+
# is available. The \xC3 byte is the first byte of the é character.
|
344
|
+
def test_partial_two_byte_utf8
|
345
|
+
expected = [:start_document, :start_array, :error]
|
346
|
+
assert_equal(expected, events('["\xC3"]'))
|
347
|
+
|
348
|
+
expected = [:start_document, :start_array, [:value, 'é'], :end_array, :end_document]
|
349
|
+
assert_equal(expected, events("[\"\xC3\xA9\"]"))
|
350
|
+
end
|
351
|
+
|
352
|
+
def test_full_three_byte_utf8
|
353
|
+
expected = [:start_document, :start_array, [:value, "snow\u2603man"],
|
354
|
+
[:value, "\u2603\u2603"], :end_array, :end_document]
|
355
|
+
assert_equal(expected, events("[\"snow\u2603man\", \"\u2603\u2603\"]"))
|
356
|
+
end
|
357
|
+
|
358
|
+
def test_partial_three_byte_utf8
|
359
|
+
expected = [:start_document, :start_array, :error]
|
360
|
+
assert_equal(expected, events('["\xE2"]'))
|
361
|
+
|
362
|
+
expected = [:start_document, :start_array, :error]
|
363
|
+
assert_equal(expected, events('["\xE2\x98"]'))
|
364
|
+
|
365
|
+
expected = [:start_document, :start_array, [:value, "\u2603"], :end_array, :end_document]
|
366
|
+
assert_equal(expected, events("[\"\xE2\x98\x83\"]"))
|
367
|
+
end
|
368
|
+
|
369
|
+
def test_full_four_byte_utf8
|
370
|
+
expected = [:start_document, :start_array, [:value, "\u{10102} check mark"],
|
371
|
+
:end_array, :end_document]
|
372
|
+
assert_equal(expected, events("[\"\u{10102} check mark\"]"))
|
373
|
+
end
|
374
|
+
|
375
|
+
def test_partial_four_byte_utf8
|
376
|
+
expected = [:start_document, :start_array, :error]
|
377
|
+
assert_equal(expected, events('["\xF0"]'))
|
378
|
+
|
379
|
+
expected = [:start_document, :start_array, :error]
|
380
|
+
assert_equal(expected, events('["\xF0\x90"]'))
|
381
|
+
|
382
|
+
expected = [:start_document, :start_array, :error]
|
383
|
+
assert_equal(expected, events('["\xF0\x90\x84"]'))
|
384
|
+
|
385
|
+
expected = [:start_document, :start_array, [:value, "\u{10102}"], :end_array, :end_document]
|
386
|
+
assert_equal(expected, events("[\"\xF0\x90\x84\x82\"]"))
|
387
|
+
end
|
388
|
+
|
389
|
+
def test_parse
|
390
|
+
json = "[1,2,3]"
|
391
|
+
obj = JSON::Stream::Parser.parse(json)
|
392
|
+
assert_equal([1,2,3], obj)
|
393
|
+
end
|
394
|
+
|
395
|
+
def test_initializer_block
|
396
|
+
events = []
|
397
|
+
parser = JSON::Stream::Parser.new do
|
398
|
+
start_document { events << :start_document }
|
399
|
+
end_document { events << :end_document }
|
400
|
+
start_object { events << :start_object }
|
401
|
+
end_object { events << :end_object }
|
402
|
+
key {|k| events << [:key, k] }
|
403
|
+
value {|v| events << [:value, v] }
|
404
|
+
end
|
405
|
+
parser << '{"key":12}'
|
406
|
+
expected = [:start_document, :start_object, [:key, "key"], [:value, 12], :end_object, :end_document]
|
407
|
+
assert_equal(expected, events)
|
408
|
+
end
|
409
|
+
|
410
|
+
private
|
411
|
+
|
412
|
+
# Run a worst case, one character at a time, parse against the
|
413
|
+
# JSON string and return a list of events generated by the parser.
|
414
|
+
# A special :error event is included if the parser threw an exception.
|
415
|
+
def events(json)
|
416
|
+
parser = JSON::Stream::Parser.new
|
417
|
+
collector = Events.new(parser)
|
418
|
+
begin
|
419
|
+
json.each_char {|ch| parser << ch }
|
420
|
+
rescue JSON::Stream::ParserError => e
|
421
|
+
collector.error
|
422
|
+
end
|
423
|
+
collector.events
|
424
|
+
end
|
425
|
+
|
426
|
+
# Dynamically map methods in this class to parser callback methods
|
427
|
+
# so we can collect parser events for inspection by test cases.
|
428
|
+
class Events
|
429
|
+
METHODS = %w[start_document end_document start_object end_object start_array end_array key value]
|
430
|
+
|
431
|
+
attr_reader :events
|
432
|
+
|
433
|
+
def initialize(parser)
|
434
|
+
@events = []
|
435
|
+
METHODS.each do |name|
|
436
|
+
parser.send(name, &method(name))
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
METHODS.each do |name|
|
441
|
+
define_method(name) do |*args|
|
442
|
+
@events << (args.empty? ? name.to_sym : [name.to_sym, *args])
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
def error
|
447
|
+
@events << :error
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
end
|