wankel 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/LICENSE +20 -0
- data/README.md +43 -0
- data/Rakefile +63 -0
- data/benchmark/subjects/item.json +1 -0
- data/benchmark/subjects/ohai.json +1216 -0
- data/benchmark/subjects/twitter_search.json +1 -0
- data/benchmark/subjects/twitter_stream.json +430 -0
- data/ext/wankel/extconf.rb +15 -0
- data/ext/wankel/wankel.c +50 -0
- data/ext/wankel/wankel.h +17 -0
- data/ext/wankel/wankel_encoder.c +232 -0
- data/ext/wankel/wankel_encoder.h +13 -0
- data/ext/wankel/wankel_parser.c +345 -0
- data/ext/wankel/wankel_parser.h +26 -0
- data/ext/wankel/wankel_sax_encoder.c +290 -0
- data/ext/wankel/wankel_sax_encoder.h +13 -0
- data/ext/wankel/wankel_sax_parser.c +232 -0
- data/ext/wankel/wankel_sax_parser.h +23 -0
- data/ext/wankel/yajl_helpers.c +124 -0
- data/ext/wankel/yajl_helpers.h +22 -0
- data/lib/wankel/ex_sax_parser.rb +75 -0
- data/lib/wankel.rb +19 -0
- data/logo.png +0 -0
- data/test/encoding/encoding_test.rb +230 -0
- data/test/encoding/sax_encoder_test.rb +89 -0
- data/test/parsing/active_support_test.rb +66 -0
- data/test/parsing/fixtures/fail.15.json +1 -0
- data/test/parsing/fixtures/fail.16.json +1 -0
- data/test/parsing/fixtures/fail.17.json +1 -0
- data/test/parsing/fixtures/fail.26.json +1 -0
- data/test/parsing/fixtures/fail11.json +1 -0
- data/test/parsing/fixtures/fail12.json +1 -0
- data/test/parsing/fixtures/fail13.json +1 -0
- data/test/parsing/fixtures/fail14.json +1 -0
- data/test/parsing/fixtures/fail19.json +1 -0
- data/test/parsing/fixtures/fail20.json +1 -0
- data/test/parsing/fixtures/fail21.json +1 -0
- data/test/parsing/fixtures/fail22.json +1 -0
- data/test/parsing/fixtures/fail23.json +1 -0
- data/test/parsing/fixtures/fail24.json +1 -0
- data/test/parsing/fixtures/fail25.json +1 -0
- data/test/parsing/fixtures/fail27.json +2 -0
- data/test/parsing/fixtures/fail28.json +2 -0
- data/test/parsing/fixtures/fail3.json +1 -0
- data/test/parsing/fixtures/fail4.json +1 -0
- data/test/parsing/fixtures/fail5.json +1 -0
- data/test/parsing/fixtures/fail6.json +1 -0
- data/test/parsing/fixtures/fail9.json +1 -0
- data/test/parsing/fixtures/pass.array.json +6 -0
- data/test/parsing/fixtures/pass.codepoints_from_unicode_org.json +1 -0
- data/test/parsing/fixtures/pass.contacts.json +1 -0
- data/test/parsing/fixtures/pass.db100.xml.json +1 -0
- data/test/parsing/fixtures/pass.db1000.xml.json +1 -0
- data/test/parsing/fixtures/pass.dc_simple_with_comments.json +11 -0
- data/test/parsing/fixtures/pass.deep_arrays.json +1 -0
- data/test/parsing/fixtures/pass.difficult_json_c_test_case.json +1 -0
- data/test/parsing/fixtures/pass.difficult_json_c_test_case_with_comments.json +1 -0
- data/test/parsing/fixtures/pass.doubles.json +1 -0
- data/test/parsing/fixtures/pass.empty_array.json +1 -0
- data/test/parsing/fixtures/pass.empty_string.json +1 -0
- data/test/parsing/fixtures/pass.escaped_bulgarian.json +4 -0
- data/test/parsing/fixtures/pass.escaped_foobar.json +1 -0
- data/test/parsing/fixtures/pass.item.json +1 -0
- data/test/parsing/fixtures/pass.json-org-sample1.json +23 -0
- data/test/parsing/fixtures/pass.json-org-sample2.json +11 -0
- data/test/parsing/fixtures/pass.json-org-sample3.json +26 -0
- data/test/parsing/fixtures/pass.json-org-sample4-nows.json +88 -0
- data/test/parsing/fixtures/pass.json-org-sample4.json +89 -0
- data/test/parsing/fixtures/pass.json-org-sample5.json +27 -0
- data/test/parsing/fixtures/pass.map-spain.xml.json +1 -0
- data/test/parsing/fixtures/pass.ns-invoice100.xml.json +1 -0
- data/test/parsing/fixtures/pass.ns-soap.xml.json +1 -0
- data/test/parsing/fixtures/pass.numbers-fp-4k.json +6 -0
- data/test/parsing/fixtures/pass.numbers-fp-64k.json +61 -0
- data/test/parsing/fixtures/pass.numbers-int-4k.json +11 -0
- data/test/parsing/fixtures/pass.numbers-int-64k.json +154 -0
- data/test/parsing/fixtures/pass.twitter-search.json +1 -0
- data/test/parsing/fixtures/pass.twitter-search2.json +1 -0
- data/test/parsing/fixtures/pass.unicode.json +3315 -0
- data/test/parsing/fixtures/pass.yelp.json +1 -0
- data/test/parsing/fixtures/pass1.json +56 -0
- data/test/parsing/fixtures/pass2.json +1 -0
- data/test/parsing/fixtures/pass3.json +6 -0
- data/test/parsing/fixtures_test.rb +43 -0
- data/test/parsing/multiple_values_test.rb +100 -0
- data/test/parsing/one_off_test.rb +65 -0
- data/test/parsing/sax_parser_test.rb +125 -0
- data/test/performance.rb +135 -0
- data/test/test_helper.rb +36 -0
- data/test/wankel_test.rb +53 -0
- data/wankel.gemspec +23 -0
- metadata +259 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
#ifndef YAJL_HELPERS
|
2
|
+
#define YAJL_HELPERS
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
#include <yajl/yajl_common.h>
|
6
|
+
#include <yajl/yajl_parse.h>
|
7
|
+
#include <yajl/yajl_gen.h>
|
8
|
+
|
9
|
+
// Yajl Helpers ==============================================================
|
10
|
+
void yajl_helper_check_status(yajl_handle handle, yajl_status status, int verbose, const unsigned char * jsonText, size_t jsonTextLength);
|
11
|
+
void yajl_helper_check_gen_status(yajl_gen_status status);
|
12
|
+
|
13
|
+
// Memory funcs
|
14
|
+
void* yajl_helper_malloc(void *ctx, size_t);
|
15
|
+
void* yajl_helper_realloc(void *ctx, void *ptr, size_t size);
|
16
|
+
void yajl_helper_free(void *ctx, void *ptr);
|
17
|
+
// static yajl_alloc_funcs* yajl_helper_alloc_funcs();
|
18
|
+
|
19
|
+
void yajl_configure(yajl_handle handle, VALUE options);
|
20
|
+
void yajl_gen_configure(yajl_gen g, VALUE options);
|
21
|
+
|
22
|
+
#endif
|
@@ -0,0 +1,75 @@
|
|
1
|
+
class Wankel::SaxParser
|
2
|
+
|
3
|
+
def on_map_start
|
4
|
+
puts 'start map'
|
5
|
+
end
|
6
|
+
|
7
|
+
def on_map_end
|
8
|
+
puts 'end map'
|
9
|
+
end
|
10
|
+
|
11
|
+
def on_map_key(key)
|
12
|
+
puts 'key'
|
13
|
+
end
|
14
|
+
|
15
|
+
def on_null
|
16
|
+
puts "null"
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_boolean(value)
|
20
|
+
puts value
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_integer(i)
|
24
|
+
puts "integer"
|
25
|
+
end
|
26
|
+
|
27
|
+
def on_double(d)
|
28
|
+
puts "double"
|
29
|
+
end
|
30
|
+
|
31
|
+
def on_string(s)
|
32
|
+
puts "string"
|
33
|
+
end
|
34
|
+
|
35
|
+
def on_array_start
|
36
|
+
puts "start array"
|
37
|
+
end
|
38
|
+
|
39
|
+
def on_array_end
|
40
|
+
puts "end array"
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
class Wankel::SaxEncoder
|
47
|
+
|
48
|
+
def number
|
49
|
+
end
|
50
|
+
|
51
|
+
def string
|
52
|
+
end
|
53
|
+
|
54
|
+
def null
|
55
|
+
end
|
56
|
+
|
57
|
+
def bool
|
58
|
+
end
|
59
|
+
|
60
|
+
def map_open
|
61
|
+
end
|
62
|
+
|
63
|
+
def map_close
|
64
|
+
end
|
65
|
+
|
66
|
+
def array_open
|
67
|
+
end
|
68
|
+
|
69
|
+
def array_close
|
70
|
+
end
|
71
|
+
|
72
|
+
def complete
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
data/lib/wankel.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'wankel/wankel'
|
2
|
+
|
3
|
+
class Wankel
|
4
|
+
DEFAULTS = {
|
5
|
+
:read_buffer_size => 8092,
|
6
|
+
:symbolize_keys => false,
|
7
|
+
:allow_comments => false,
|
8
|
+
:validate_strings => false,
|
9
|
+
:allow_trailing_garbage => false,
|
10
|
+
:multiple_values => false,
|
11
|
+
:allow_partial_values => false,
|
12
|
+
|
13
|
+
:write_buffer_size => 8092,
|
14
|
+
:beautify => false,
|
15
|
+
:indent_string => ' ',
|
16
|
+
:validate_utf8 => false,
|
17
|
+
:escape_solidus => false
|
18
|
+
}
|
19
|
+
end
|
data/logo.png
ADDED
Binary file
|
@@ -0,0 +1,230 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'tmpdir'
|
3
|
+
require 'zlib'
|
4
|
+
|
5
|
+
class Dummy2
|
6
|
+
def to_json
|
7
|
+
"{\"hawtness\":true}"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class TheMindKiller
|
12
|
+
def to_json
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class TheMindKillerDuce
|
18
|
+
def to_s
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Wankel::EncoderTest < ::Test::Unit::TestCase
|
24
|
+
FILES = Dir[File.dirname(__FILE__)+'/../../benchmark/subjects/*.json']
|
25
|
+
|
26
|
+
FILES.each do |file|
|
27
|
+
if File.basename(file) != 'twitter_stream.json'
|
28
|
+
test "should encode #{File.basename(file)} to an StringIO" do
|
29
|
+
input = File.new(File.expand_path(file), 'r')
|
30
|
+
io = StringIO.new
|
31
|
+
encoder = Wankel::Encoder.new
|
32
|
+
hash = Wankel.parse(input)
|
33
|
+
encoder.encode(hash, io)
|
34
|
+
io.rewind
|
35
|
+
hash2 = Wankel.parse(io)
|
36
|
+
io.close
|
37
|
+
input.close
|
38
|
+
assert_equal(hash2, hash)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
FILES.each do |file|
|
44
|
+
test "should encode #{File.basename(file)} to a Zlib::GzipWriter" do
|
45
|
+
# we don't care about testing the stream subject as it has multiple JSON strings in it
|
46
|
+
if File.basename(file) != 'twitter_stream.json'
|
47
|
+
hash = File.open(File.expand_path(file), 'r') do |input|
|
48
|
+
Wankel.parse(input)
|
49
|
+
end
|
50
|
+
hash2 = Dir.mktmpdir do |tmp_dir|
|
51
|
+
output_filename = File.join(tmp_dir, 'output.json')
|
52
|
+
Zlib::GzipWriter.open(output_filename) do |writer|
|
53
|
+
Wankel.encode(hash, writer)
|
54
|
+
end
|
55
|
+
Zlib::GzipReader.open(output_filename) do |reader|
|
56
|
+
Wankel.parse(reader.read)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
assert_equal(hash2, hash)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
FILES.each do |file|
|
65
|
+
test "should encode #{File.basename(file)} and return a String" do
|
66
|
+
# we don't care about testing the stream subject as it has multiple JSON strings in it
|
67
|
+
if File.basename(file) != 'twitter_stream.json'
|
68
|
+
input = File.new(File.expand_path(file), 'r')
|
69
|
+
encoder = Wankel::Encoder.new
|
70
|
+
hash = Wankel.parse(input)
|
71
|
+
output = encoder.encode(hash)
|
72
|
+
hash2 = Wankel.parse(output)
|
73
|
+
input.close
|
74
|
+
assert_equal(hash2, hash)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
test "should encode with :beautify turned on and a single space indent, to an IO" do
|
80
|
+
output = "{\n \"foo\": 1234\n}\n"
|
81
|
+
obj = {:foo => 1234}
|
82
|
+
io = StringIO.new
|
83
|
+
encoder = Wankel::Encoder.new(:beautify => true, :indent_string => ' ')
|
84
|
+
encoder.encode(obj, io)
|
85
|
+
io.rewind
|
86
|
+
assert_equal(output, io.read)
|
87
|
+
end
|
88
|
+
|
89
|
+
test "should encode with :beautify turned on and a single space indent, and return a String" do
|
90
|
+
output = "{\n \"foo\": 1234\n}\n"
|
91
|
+
obj = {:foo => 1234}
|
92
|
+
encoder = Wankel::Encoder.new(:beautify => true, :indent_string => ' ')
|
93
|
+
result = encoder.encode(obj)
|
94
|
+
assert_equal(output, result)
|
95
|
+
end
|
96
|
+
|
97
|
+
test "should encode with :beautify turned on and a tab character indent, to an IO" do
|
98
|
+
output = "{\n\t\"foo\": 1234\n}\n"
|
99
|
+
obj = {:foo => 1234}
|
100
|
+
io = StringIO.new
|
101
|
+
encoder = Wankel::Encoder.new(:beautify => true, :indent_string => "\t")
|
102
|
+
encoder.encode(obj, io)
|
103
|
+
io.rewind
|
104
|
+
assert_equal(output, io.read)
|
105
|
+
end
|
106
|
+
|
107
|
+
test "should encode with :beautify turned on and a tab character indent, and return a String" do
|
108
|
+
output = "{\n\t\"foo\": 1234\n}\n"
|
109
|
+
obj = {:foo => 1234}
|
110
|
+
encoder = Wankel::Encoder.new(:beautify => true, :indent_string => "\t")
|
111
|
+
result = encoder.encode(obj)
|
112
|
+
assert_equal(output, result)
|
113
|
+
end
|
114
|
+
|
115
|
+
test "should encode with it's class method with :beautify and a tab character indent options set, to an IO" do
|
116
|
+
output = "{\n\t\"foo\": 1234\n}\n"
|
117
|
+
obj = {:foo => 1234}
|
118
|
+
io = StringIO.new
|
119
|
+
Wankel.encode(obj, io, :beautify => true, :indent_string => "\t")
|
120
|
+
io.rewind
|
121
|
+
assert_equal(output, io.read)
|
122
|
+
end
|
123
|
+
|
124
|
+
test "should encode with it's class method with :beautify and a tab character indent options set, and return a String" do
|
125
|
+
output = "{\n\t\"foo\": 1234\n}\n"
|
126
|
+
obj = {:foo => 1234}
|
127
|
+
result = Wankel.encode(obj, :beautify => true, :indent_string => "\t")
|
128
|
+
assert_equal(output, result)
|
129
|
+
end
|
130
|
+
|
131
|
+
test "should encode multiple objects into a single stream, to an IO" do
|
132
|
+
io = StringIO.new
|
133
|
+
obj = {:foo => 1234}
|
134
|
+
encoder = Wankel::Encoder.new
|
135
|
+
5.times do
|
136
|
+
encoder.encode(obj, io)
|
137
|
+
end
|
138
|
+
io.rewind
|
139
|
+
output = "{\"foo\":1234}{\"foo\":1234}{\"foo\":1234}{\"foo\":1234}{\"foo\":1234}"
|
140
|
+
assert_equal(output, io.read)
|
141
|
+
end
|
142
|
+
|
143
|
+
test "should encode multiple objects into a single stream, and return a String" do
|
144
|
+
obj = {:foo => 1234}
|
145
|
+
encoder = Wankel::Encoder.new
|
146
|
+
json_output = ''
|
147
|
+
5.times do
|
148
|
+
json_output << encoder.encode(obj)
|
149
|
+
end
|
150
|
+
output = "{\"foo\":1234}{\"foo\":1234}{\"foo\":1234}{\"foo\":1234}{\"foo\":1234}"
|
151
|
+
assert_equal(output, json_output)
|
152
|
+
end
|
153
|
+
|
154
|
+
test "should encode all map keys as strings" do
|
155
|
+
assert_equal("{\"1\":1}", Wankel.encode({1=>1}))
|
156
|
+
end
|
157
|
+
|
158
|
+
test "should check for and call #to_json if it exists on custom objects" do
|
159
|
+
d = Dummy2.new
|
160
|
+
assert_equal('{"foo":{"hawtness":true}}', Wankel.encode({:foo => d}))
|
161
|
+
end
|
162
|
+
|
163
|
+
test "should encode a hash where the key and value can be symbols" do
|
164
|
+
assert_equal('{"foo":"bar"}', Wankel.encode({:foo => :bar}))
|
165
|
+
end
|
166
|
+
|
167
|
+
test "should not encode NaN" do
|
168
|
+
assert_raises Wankel::EncodeError do
|
169
|
+
Wankel.encode(0.0/0.0)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
test "should not encode Infinity or -Infinity" do
|
174
|
+
assert_raises Wankel::EncodeError do
|
175
|
+
Wankel.encode(1.0/0.0)
|
176
|
+
end
|
177
|
+
assert_raises Wankel::EncodeError do
|
178
|
+
Wankel.encode(-1.0/0.0)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
test "should encode with unicode chars in the key" do
|
183
|
+
hash = {"浅草" => "<- those are unicode"}
|
184
|
+
assert_equal("{\"浅草\":\"<- those are unicode\"}", Wankel.encode(hash))
|
185
|
+
end
|
186
|
+
|
187
|
+
test "should return a string encoded in utf-8 if Encoding.default_internal is nil" do
|
188
|
+
Encoding.default_internal = nil
|
189
|
+
hash = {"浅草" => "<- those are unicode"}
|
190
|
+
assert_equal(Encoding.find('utf-8'), Wankel.encode(hash).encoding)
|
191
|
+
end
|
192
|
+
|
193
|
+
test "should return a string encoded in utf-8 even if Encoding.default_internal *is* set" do
|
194
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
195
|
+
hash = {"浅草" => "<- those are unicode"}
|
196
|
+
assert_equal(Encoding.default_internal, Wankel.encode(hash).encoding)
|
197
|
+
|
198
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
199
|
+
hash = {"浅草" => "<- those are unicode"}
|
200
|
+
assert_equal(Encoding.find('utf-8'), Wankel.encode(hash).encoding)
|
201
|
+
end
|
202
|
+
|
203
|
+
test "should default to *not* escaping / characters" do
|
204
|
+
unsafe_encoder = Wankel::Encoder.new
|
205
|
+
assert_equal("\"</script>\"", unsafe_encoder.encode("</script>"))
|
206
|
+
end
|
207
|
+
|
208
|
+
test "return value of #to_json must be a string" do
|
209
|
+
assert_raises TypeError do
|
210
|
+
Wankel.encode(TheMindKiller.new)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
test "return value of #to_s must be a string" do
|
215
|
+
assert_raises TypeError do
|
216
|
+
if TheMindKillerDuce.send(:method_defined?, :to_json)
|
217
|
+
TheMindKillerDuce.send(:undef_method, :to_json)
|
218
|
+
end
|
219
|
+
Wankel.encode(TheMindKillerDuce.new)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
test "output must be a an IO" do
|
224
|
+
assert_raises Wankel::EncodeError, "output must be a an IO" do
|
225
|
+
output = ""
|
226
|
+
Wankel.encode(TheMindKillerDuce.new, "")
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
class Wankel::SaxEncoderTest < ::Test::Unit::TestCase
|
4
|
+
|
5
|
+
test 'default inherited from Wankel' do
|
6
|
+
encoder = Wankel::SaxEncoder.new(StringIO.new)
|
7
|
+
assert_equal(Wankel::DEFAULTS, encoder.instance_variable_get("@options"))
|
8
|
+
end
|
9
|
+
|
10
|
+
test 'default options merged with options inherited from Wankel && Class' do
|
11
|
+
encoder = Wankel::SaxEncoder.new(StringIO.new, :hello => true, :metoo => false)
|
12
|
+
assert_equal(Wankel::DEFAULTS.merge({:hello => true, :metoo => false}), encoder.instance_variable_get("@options"))
|
13
|
+
end
|
14
|
+
|
15
|
+
test "number" do
|
16
|
+
output = StringIO.new
|
17
|
+
encoder = Wankel::SaxEncoder.new(output)
|
18
|
+
encoder.number(1234)
|
19
|
+
encoder.complete
|
20
|
+
assert_equal("1234", output.string)
|
21
|
+
end
|
22
|
+
|
23
|
+
test "string" do
|
24
|
+
output = StringIO.new
|
25
|
+
encoder = Wankel::SaxEncoder.new(output)
|
26
|
+
encoder.string("hello world")
|
27
|
+
encoder.complete
|
28
|
+
assert_equal('"hello world"', output.string)
|
29
|
+
end
|
30
|
+
|
31
|
+
test "null" do
|
32
|
+
output = StringIO.new
|
33
|
+
encoder = Wankel::SaxEncoder.new(output)
|
34
|
+
encoder.null
|
35
|
+
encoder.complete
|
36
|
+
assert_equal("null", output.string)
|
37
|
+
end
|
38
|
+
|
39
|
+
test "bool(false)" do
|
40
|
+
output = StringIO.new
|
41
|
+
encoder = Wankel::SaxEncoder.new(output)
|
42
|
+
encoder.bool(false)
|
43
|
+
encoder.complete
|
44
|
+
assert_equal("false", output.string)
|
45
|
+
end
|
46
|
+
|
47
|
+
test "bool(true)" do
|
48
|
+
output = StringIO.new
|
49
|
+
encoder = Wankel::SaxEncoder.new(output)
|
50
|
+
encoder.bool(true)
|
51
|
+
encoder.complete
|
52
|
+
assert_equal("true", output.string)
|
53
|
+
end
|
54
|
+
|
55
|
+
test "map_open" do
|
56
|
+
output = StringIO.new
|
57
|
+
encoder = Wankel::SaxEncoder.new(output)
|
58
|
+
encoder.map_open
|
59
|
+
encoder.complete
|
60
|
+
assert_equal("{", output.string)
|
61
|
+
end
|
62
|
+
|
63
|
+
test "map_close" do
|
64
|
+
output = StringIO.new
|
65
|
+
encoder = Wankel::SaxEncoder.new(output)
|
66
|
+
encoder.map_open
|
67
|
+
encoder.map_close
|
68
|
+
encoder.complete
|
69
|
+
assert_equal("{}", output.string)
|
70
|
+
end
|
71
|
+
|
72
|
+
test "array_open" do
|
73
|
+
output = StringIO.new
|
74
|
+
encoder = Wankel::SaxEncoder.new(output)
|
75
|
+
encoder.array_open
|
76
|
+
encoder.complete
|
77
|
+
assert_equal("[", output.string)
|
78
|
+
end
|
79
|
+
|
80
|
+
test "array_close" do
|
81
|
+
output = StringIO.new
|
82
|
+
encoder = Wankel::SaxEncoder.new(output)
|
83
|
+
encoder.array_open
|
84
|
+
encoder.array_close
|
85
|
+
encoder.complete
|
86
|
+
assert_equal("[]", output.string)
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
class Wankel::ActiveSupportTest < ::Test::Unit::TestCase
|
5
|
+
|
6
|
+
TESTS = {
|
7
|
+
%q({"returnTo":{"\/categories":"\/"}}) => {"returnTo" => {"/categories" => "/"}},
|
8
|
+
%q({"return\\"To\\":":{"\/categories":"\/"}}) => {"return\"To\":" => {"/categories" => "/"}},
|
9
|
+
%q({"returnTo":{"\/categories":1}}) => {"returnTo" => {"/categories" => 1}},
|
10
|
+
%({"returnTo":[1,"a"]}) => {"returnTo" => [1, "a"]},
|
11
|
+
%({"returnTo":[1,"\\"a\\",", "b"]}) => {"returnTo" => [1, "\"a\",", "b"]},
|
12
|
+
%({"a": "'", "b": "5,000"}) => {"a" => "'", "b" => "5,000"},
|
13
|
+
%({"a": "a's, b's and c's", "b": "5,000"}) => {"a" => "a's, b's and c's", "b" => "5,000"},
|
14
|
+
# multibyte
|
15
|
+
%({"matzue": "松江", "asakusa": "浅草"}) => {"matzue" => "松江", "asakusa" => "浅草"},
|
16
|
+
%({"a": "2007-01-01"}) => {'a' => "2007-01-01"},
|
17
|
+
%({"a": "2007-01-01 01:12:34 Z"}) => {'a' => "2007-01-01 01:12:34 Z"},
|
18
|
+
# no time zone
|
19
|
+
%({"a": "2007-01-01 01:12:34"}) => {'a' => "2007-01-01 01:12:34"},
|
20
|
+
# needs to be *exact*
|
21
|
+
%({"a": " 2007-01-01 01:12:34 Z "}) => {'a' => " 2007-01-01 01:12:34 Z "},
|
22
|
+
%({"a": "2007-01-01 : it's your birthday"}) => {'a' => "2007-01-01 : it's your birthday"},
|
23
|
+
%([]) => [],
|
24
|
+
%({}) => {},
|
25
|
+
%({"a":1}) => {"a" => 1},
|
26
|
+
%({"a": ""}) => {"a" => ""},
|
27
|
+
%({"a":"\\""}) => {"a" => "\""},
|
28
|
+
%({"a": null}) => {"a" => nil},
|
29
|
+
%({"a": true}) => {"a" => true},
|
30
|
+
%({"a": false}) => {"a" => false},
|
31
|
+
%q({"a": "http:\/\/test.host\/posts\/1"}) => {"a" => "http://test.host/posts/1"},
|
32
|
+
%q({"a": "\u003cunicode\u0020escape\u003e"}) => {"a" => "<unicode escape>"},
|
33
|
+
%q({"a": "\\\\u0020skip double backslashes"}) => {"a" => "\\u0020skip double backslashes"},
|
34
|
+
%q({"a": "\u003cbr /\u003e"}) => {'a' => "<br />"},
|
35
|
+
%q({"b":["\u003ci\u003e","\u003cb\u003e","\u003cu\u003e"]}) => {'b' => ["<i>","<b>","<u>"]}
|
36
|
+
}
|
37
|
+
|
38
|
+
TESTS.each do |json, expected|
|
39
|
+
test "should be able to parse #{json} as an IO" do
|
40
|
+
assert_nothing_raised Wankel::ParseError do
|
41
|
+
Wankel.parse(StringIO.new(json))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
TESTS.each do |json, expected|
|
47
|
+
test "should be able to parse #{json} as a string" do
|
48
|
+
assert_nothing_raised Wankel::ParseError do
|
49
|
+
Wankel.parse(json)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
test "should fail parsing {: 1} as an IO" do
|
55
|
+
assert_raise Wankel::ParseError do
|
56
|
+
Wankel.parse(StringIO.new("{: 1}"))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
test "should fail parsing {: 1} as a string" do
|
61
|
+
assert_raise Wankel::ParseError do
|
62
|
+
Wankel.parse("{: 1}")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
["Illegal backslash escape: \x15"]
|
@@ -0,0 +1 @@
|
|
1
|
+
["Illegal backslash escape: \'"]
|
@@ -0,0 +1 @@
|
|
1
|
+
["Illegal backslash escape: \017"]
|
@@ -0,0 +1 @@
|
|
1
|
+
["tab\ character\ in\ string\ "]
|
@@ -0,0 +1 @@
|
|
1
|
+
{"Illegal expression": 1 + 2}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"Illegal invocation": alert()}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"Numbers cannot have leading zeroes": 013}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"Numbers cannot be hex": 0x14}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"Missing colon" null}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"Double colon":: null}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"Comma instead of colon", null}
|
@@ -0,0 +1 @@
|
|
1
|
+
["Colon instead of comma": false]
|
@@ -0,0 +1 @@
|
|
1
|
+
["Bad value", truth]
|
@@ -0,0 +1 @@
|
|
1
|
+
['single quote']
|
@@ -0,0 +1 @@
|
|
1
|
+
["tab character in string "]
|
@@ -0,0 +1 @@
|
|
1
|
+
{unquoted_key: "keys must be quoted"}
|
@@ -0,0 +1 @@
|
|
1
|
+
["extra comma",]
|
@@ -0,0 +1 @@
|
|
1
|
+
["double extra comma",,]
|
@@ -0,0 +1 @@
|
|
1
|
+
[ , "<-- missing value"]
|
@@ -0,0 +1 @@
|
|
1
|
+
{"Extra comma": true,}
|
@@ -0,0 +1 @@
|
|
1
|
+
"\u004d\u0430\u4e8c\ud800\udf02"
|