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.
Files changed (94) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/LICENSE +20 -0
  4. data/README.md +43 -0
  5. data/Rakefile +63 -0
  6. data/benchmark/subjects/item.json +1 -0
  7. data/benchmark/subjects/ohai.json +1216 -0
  8. data/benchmark/subjects/twitter_search.json +1 -0
  9. data/benchmark/subjects/twitter_stream.json +430 -0
  10. data/ext/wankel/extconf.rb +15 -0
  11. data/ext/wankel/wankel.c +50 -0
  12. data/ext/wankel/wankel.h +17 -0
  13. data/ext/wankel/wankel_encoder.c +232 -0
  14. data/ext/wankel/wankel_encoder.h +13 -0
  15. data/ext/wankel/wankel_parser.c +345 -0
  16. data/ext/wankel/wankel_parser.h +26 -0
  17. data/ext/wankel/wankel_sax_encoder.c +290 -0
  18. data/ext/wankel/wankel_sax_encoder.h +13 -0
  19. data/ext/wankel/wankel_sax_parser.c +232 -0
  20. data/ext/wankel/wankel_sax_parser.h +23 -0
  21. data/ext/wankel/yajl_helpers.c +124 -0
  22. data/ext/wankel/yajl_helpers.h +22 -0
  23. data/lib/wankel/ex_sax_parser.rb +75 -0
  24. data/lib/wankel.rb +19 -0
  25. data/logo.png +0 -0
  26. data/test/encoding/encoding_test.rb +230 -0
  27. data/test/encoding/sax_encoder_test.rb +89 -0
  28. data/test/parsing/active_support_test.rb +66 -0
  29. data/test/parsing/fixtures/fail.15.json +1 -0
  30. data/test/parsing/fixtures/fail.16.json +1 -0
  31. data/test/parsing/fixtures/fail.17.json +1 -0
  32. data/test/parsing/fixtures/fail.26.json +1 -0
  33. data/test/parsing/fixtures/fail11.json +1 -0
  34. data/test/parsing/fixtures/fail12.json +1 -0
  35. data/test/parsing/fixtures/fail13.json +1 -0
  36. data/test/parsing/fixtures/fail14.json +1 -0
  37. data/test/parsing/fixtures/fail19.json +1 -0
  38. data/test/parsing/fixtures/fail20.json +1 -0
  39. data/test/parsing/fixtures/fail21.json +1 -0
  40. data/test/parsing/fixtures/fail22.json +1 -0
  41. data/test/parsing/fixtures/fail23.json +1 -0
  42. data/test/parsing/fixtures/fail24.json +1 -0
  43. data/test/parsing/fixtures/fail25.json +1 -0
  44. data/test/parsing/fixtures/fail27.json +2 -0
  45. data/test/parsing/fixtures/fail28.json +2 -0
  46. data/test/parsing/fixtures/fail3.json +1 -0
  47. data/test/parsing/fixtures/fail4.json +1 -0
  48. data/test/parsing/fixtures/fail5.json +1 -0
  49. data/test/parsing/fixtures/fail6.json +1 -0
  50. data/test/parsing/fixtures/fail9.json +1 -0
  51. data/test/parsing/fixtures/pass.array.json +6 -0
  52. data/test/parsing/fixtures/pass.codepoints_from_unicode_org.json +1 -0
  53. data/test/parsing/fixtures/pass.contacts.json +1 -0
  54. data/test/parsing/fixtures/pass.db100.xml.json +1 -0
  55. data/test/parsing/fixtures/pass.db1000.xml.json +1 -0
  56. data/test/parsing/fixtures/pass.dc_simple_with_comments.json +11 -0
  57. data/test/parsing/fixtures/pass.deep_arrays.json +1 -0
  58. data/test/parsing/fixtures/pass.difficult_json_c_test_case.json +1 -0
  59. data/test/parsing/fixtures/pass.difficult_json_c_test_case_with_comments.json +1 -0
  60. data/test/parsing/fixtures/pass.doubles.json +1 -0
  61. data/test/parsing/fixtures/pass.empty_array.json +1 -0
  62. data/test/parsing/fixtures/pass.empty_string.json +1 -0
  63. data/test/parsing/fixtures/pass.escaped_bulgarian.json +4 -0
  64. data/test/parsing/fixtures/pass.escaped_foobar.json +1 -0
  65. data/test/parsing/fixtures/pass.item.json +1 -0
  66. data/test/parsing/fixtures/pass.json-org-sample1.json +23 -0
  67. data/test/parsing/fixtures/pass.json-org-sample2.json +11 -0
  68. data/test/parsing/fixtures/pass.json-org-sample3.json +26 -0
  69. data/test/parsing/fixtures/pass.json-org-sample4-nows.json +88 -0
  70. data/test/parsing/fixtures/pass.json-org-sample4.json +89 -0
  71. data/test/parsing/fixtures/pass.json-org-sample5.json +27 -0
  72. data/test/parsing/fixtures/pass.map-spain.xml.json +1 -0
  73. data/test/parsing/fixtures/pass.ns-invoice100.xml.json +1 -0
  74. data/test/parsing/fixtures/pass.ns-soap.xml.json +1 -0
  75. data/test/parsing/fixtures/pass.numbers-fp-4k.json +6 -0
  76. data/test/parsing/fixtures/pass.numbers-fp-64k.json +61 -0
  77. data/test/parsing/fixtures/pass.numbers-int-4k.json +11 -0
  78. data/test/parsing/fixtures/pass.numbers-int-64k.json +154 -0
  79. data/test/parsing/fixtures/pass.twitter-search.json +1 -0
  80. data/test/parsing/fixtures/pass.twitter-search2.json +1 -0
  81. data/test/parsing/fixtures/pass.unicode.json +3315 -0
  82. data/test/parsing/fixtures/pass.yelp.json +1 -0
  83. data/test/parsing/fixtures/pass1.json +56 -0
  84. data/test/parsing/fixtures/pass2.json +1 -0
  85. data/test/parsing/fixtures/pass3.json +6 -0
  86. data/test/parsing/fixtures_test.rb +43 -0
  87. data/test/parsing/multiple_values_test.rb +100 -0
  88. data/test/parsing/one_off_test.rb +65 -0
  89. data/test/parsing/sax_parser_test.rb +125 -0
  90. data/test/performance.rb +135 -0
  91. data/test/test_helper.rb +36 -0
  92. data/test/wankel_test.rb +53 -0
  93. data/wankel.gemspec +23 -0
  94. 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,2 @@
1
+ ["line
2
+ break"]
@@ -0,0 +1,2 @@
1
+ ["line\
2
+ break"]
@@ -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,6 @@
1
+ ["foo",
2
+ "bar", "baz",
3
+ true,false,null,{"key":"value"},
4
+ [null,null,null,[]],
5
+ "\n\r\\"
6
+ ]
@@ -0,0 +1 @@
1
+ "\u004d\u0430\u4e8c\ud800\udf02"