wankel 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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"