wankel 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.
- 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"
|