Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: tests/corelib/json_test.dart

Issue 136373002: Fix JSON encoder accepting NaN and Infinity. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sdk/lib/convert/json.dart ('k') | tests/lib/convert/json_lib_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library json_test;
6
7 import "package:expect/expect.dart";
8 import "dart:convert";
9
10 bool badFormat(e) => e is FormatException;
11
12 void testJson(json, expected) {
13 var value = JSON.decode(json);
14 compare(expected, actual, path) {
15 if (expected is List) {
16 Expect.isTrue(actual is List);
17 Expect.equals(expected.length, actual.length, "$path: List length");
18 for (int i = 0; i < expected.length; i++) {
19 compare(expected[i], actual[i], "$path[$i]");
20 }
21 } else if (expected is Map) {
22 Expect.isTrue(actual is Map);
23 Expect.equals(expected.length, actual.length, "$path: Map size");
24 expected.forEach((key, value) {
25 Expect.isTrue(actual.containsKey(key));
26 compare(value, actual[key], "$path[$key]");
27 });
28 } else if (expected is num) {
29 Expect.equals(expected is int, actual is int, "$path: same number type");
30 Expect.isTrue(expected.compareTo(actual) == 0,
31 "$path: $expected vs. $actual");
32 } else {
33 // String, bool, null.
34 Expect.equals(expected, actual, path);
35 }
36 }
37 compare(expected, value, "value");
38 }
39
40 String escape(String s) {
41 var sb = new StringBuffer();
42 for (int i = 0; i < s.length; i++) {
43 int code = s.codeUnitAt(i);
44 if (code == '\\'.codeUnitAt(0)) sb.write(r'\\');
45 else if (code == '\"'.codeUnitAt(0)) sb.write(r'\"');
46 else if (code >= 32 && code < 127) sb.writeCharCode(code);
47 else {
48 String hex = '000${code.toRadixString(16)}';
49 sb.write(r'\u' '${hex.substring(hex.length - 4)}');
50 }
51 }
52 return '$sb';
53 }
54
55 void testThrows(json) {
56 Expect.throws(() => JSON.decode(json), badFormat, "json = '${escape(json)}'");
57 }
58
59 testNumbers() {
60 // Positive tests for number formats.
61 var integerList = ["0","9","9999"];
62 var signList = ["", "-"];
63 var fractionList = ["", ".0", ".1", ".99999"];
64 var exponentList = [""];
65 for (var exphead in ["e", "E", "e-", "E-", "e+", "E+"]) {
66 for (var expval in ["0", "1", "200"]) {
67 exponentList.add("$exphead$expval");
68 }
69 }
70
71 for (var integer in integerList) {
72 for (var sign in signList) {
73 for (var fraction in fractionList) {
74 for (var exp in exponentList) {
75 var literal = "$sign$integer$fraction$exp";
76 var parseNumber =
77 ((fraction == "" && exp == "") ? (String x) => int.parse(x)
78 : (String x) => double.parse(x));
79 var expectedValue = parseNumber(literal);
80 testJson(literal, expectedValue);
81 }
82 }
83 }
84 }
85
86 // Negative tests (syntax error).
87 // testError thoroughly tests the given parts with a lot of valid
88 // values for the other parts.
89 testError({signs, integers, fractions, exponents}) {
90 def(value, defaultValue) {
91 if (value == null) return defaultValue;
92 if (value is List) return value;
93 return [value];
94 }
95 signs = def(signs, signList);
96 integers = def(integers, integerList);
97 fractions = def(fractions, fractionList);
98 exponents = def(exponents, exponentList);
99 for (var integer in integers) {
100 for (var sign in signs) {
101 for (var fraction in fractions) {
102 for (var exponent in exponents) {
103 var literal = "$sign$integer$fraction$exponent";
104 testThrows(literal);
105 }
106 }
107 }
108 }
109 }
110 // Doubles overflow to Infinity.
111 testJson("1e+400", double.INFINITY);
112 // (Integers do not, but we don't have those on dart2js).
113
114 // Integer part cannot be omitted:
115 testError(integers: "");
116
117 // Test for "Initial zero only allowed for zero integer part" moved to
118 // json_strict_test.dart because IE's JSON.decode accepts additional initial
119 // zeros.
120
121 // Only minus allowed as sign.
122 testError(signs: "+");
123 // Requires digits after decimal point.
124 testError(fractions: ".");
125 // Requires exponent digts, and only digits.
126 testError(exponents: ["e", "e+", "e-", "e.0"]);
127
128 // No whitespace inside numbers.
129 // Additional case "- 2.2e+2" in json_strict_test.dart.
130 testThrows("-2 .2e+2");
131 testThrows("-2. 2e+2");
132 testThrows("-2.2 e+2");
133 testThrows("-2.2e +2");
134 testThrows("-2.2e+ 2");
135
136 testThrows("[2.,2]");
137 testThrows("{2.:2}");
138 }
139
140 testStrings() {
141 // String parser accepts and understands escapes.
142 var input = r'"\u0000\uffff\n\r\f\t\b\/\\\"' '\x20\ufffd\uffff"';
143 var expected = "\u0000\uffff\n\r\f\t\b\/\\\"\x20\ufffd\uffff";
144 testJson(input, expected);
145 // Empty string.
146 testJson(r'""', "");
147 // Escape first.
148 testJson(r'"\"........"', "\"........");
149 // Escape last.
150 testJson(r'"........\""', "........\"");
151 // Escape middle.
152 testJson(r'"....\"...."', "....\"....");
153
154 // Does not accept single quotes.
155 testThrows(r"''");
156 // Throws on unterminated strings.
157 testThrows(r'"......\"');
158 // Throws on unterminated escapes.
159 testThrows(r'"\'); // ' is not escaped.
160 testThrows(r'"\a"');
161 testThrows(r'"\u"');
162 testThrows(r'"\u1"');
163 testThrows(r'"\u12"');
164 testThrows(r'"\u123"');
165 testThrows(r'"\ux"');
166 testThrows(r'"\u1x"');
167 testThrows(r'"\u12x"');
168 testThrows(r'"\u123x"');
169 // Throws on bad escapes.
170 testThrows(r'"\a"');
171 testThrows(r'"\x00"');
172 testThrows(r'"\c2"');
173 testThrows(r'"\000"');
174 testThrows(r'"\u{0}"');
175 testThrows(r'"\%"');
176 testThrows('"\\\x00"'); // Not raw string!
177 // Throws on control characters.
178 for (int i = 0; i < 32; i++) {
179 var string = new String.fromCharCodes([0x22,i,0x22]); // '"\x00"' etc.
180 testThrows(string);
181 }
182 }
183
184
185 testObjects() {
186 testJson(r'{}', {});
187 testJson(r'{"x":42}', {"x":42});
188 testJson(r'{"x":{"x":{"x":42}}}', {"x": {"x": {"x": 42}}});
189 testJson(r'{"x":10,"x":42}', {"x": 42});
190 testJson(r'{"":42}', {"": 42});
191
192 // Keys must be strings.
193 testThrows(r'{x:10}');
194 testThrows(r'{true:10}');
195 testThrows(r'{false:10}');
196 testThrows(r'{null:10}');
197 testThrows(r'{42:10}');
198 testThrows(r'{42e1:10}');
199 testThrows(r'{-42:10}');
200 testThrows(r'{["text"]:10}');
201 testThrows(r'{:10}');
202 }
203
204 testArrays() {
205 testJson(r'[]', []);
206 testJson(r'[1.1e1,"string",true,false,null,{}]',
207 [1.1e1, "string", true, false, null, {}]);
208 testJson(r'[[[[[[]]]],[[[]]],[[]]]]', [[[[[[]]]],[[[]]],[[]]]]);
209 testJson(r'[{},[{}],{"x":[]}]', [{},[{}],{"x":[]}]);
210
211 testThrows(r'[1,,2]');
212 testThrows(r'[1,2,]');
213 testThrows(r'[,2]');
214 }
215
216 testWords() {
217 testJson(r'true', true);
218 testJson(r'false', false);
219 testJson(r'null', null);
220 testJson(r'[true]', [true]);
221 testJson(r'{"true":true}', {"true": true});
222
223 testThrows(r'truefalse');
224 testThrows(r'trues');
225 testThrows(r'nulll');
226 testThrows(r'full');
227 testThrows(r'nul');
228 testThrows(r'tru');
229 testThrows(r'fals');
230 testThrows(r'\null');
231 testThrows(r't\rue');
232 testThrows(r't\rue');
233 }
234
235 testWhitespace() {
236 // Valid white-space characters.
237 var v = '\t\r\n\ ';
238 // Invalid white-space and non-recognized characters.
239 var invalids = ['\x00', '\f', '\x08', '\\', '\xa0','\u2028', '\u2029'];
240
241 // Valid whitespace accepted "everywhere".
242 testJson('$v[${v}-2.2e2$v,$v{$v"key"$v:${v}true$v}$v,$v"ab"$v]$v',
243 [-2.2e2, {"key": true}, "ab"]);
244
245 // IE9 accepts invalid characters at the end, so some of these tests have been
246 // moved to json_strict_test.dart.
247 for (var i in invalids) {
248 testThrows('${i}"s"');
249 testThrows('42${i}');
250 testThrows('$i[]');
251 testThrows('[$i]');
252 testThrows('[$i"s"]');
253 testThrows('["s"$i]');
254 testThrows('$i{"k":"v"}');
255 testThrows('{$i"k":"v"}');
256 testThrows('{"k"$i:"v"}');
257 testThrows('{"k":$i"v"}');
258 testThrows('{"k":"v"$i}');
259 }
260 }
261
262 main() {
263 testNumbers();
264 testStrings();
265 testWords();
266 testObjects();
267 testArrays();
268 testWhitespace();
269 }
OLDNEW
« no previous file with comments | « sdk/lib/convert/json.dart ('k') | tests/lib/convert/json_lib_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698