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

Unified Diff: test/codegen/lib/convert/json_test.dart

Issue 1965563003: Update dart:convert and dart:core Uri. (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: test/codegen/lib/convert/json_test.dart
diff --git a/test/codegen/lib/convert/json_test.dart b/test/codegen/lib/convert/json_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..ef7b077d4c8c622a5f59044de9fd3b9c8073236f
--- /dev/null
+++ b/test/codegen/lib/convert/json_test.dart
@@ -0,0 +1,328 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Disable background compilation so that the Issue 24908 can be reproduced.
+// VMOptions=--no-background-compilation
+
+library json_test;
+
+import "package:expect/expect.dart";
+import "dart:convert";
+
+bool badFormat(e) => e is FormatException;
+
+void testJson(json, expected) {
+ compare(expected, actual, path) {
+ if (expected is List) {
+ Expect.isTrue(actual is List);
+ Expect.equals(expected.length, actual.length, "$path: List length");
+ for (int i = 0; i < expected.length; i++) {
+ compare(expected[i], actual[i], "$path[$i]");
+ }
+ } else if (expected is Map) {
+ Expect.isTrue(actual is Map);
+ Expect.equals(expected.length, actual.length, "$path: Map size");
+ expected.forEach((key, value) {
+ Expect.isTrue(actual.containsKey(key));
+ compare(value, actual[key], "$path[$key]");
+ });
+ } else if (expected is num) {
+ Expect.equals(expected is int, actual is int, "$path: same number type");
+ Expect.isTrue(expected.compareTo(actual) == 0,
+ "$path: Expected: $expected, was: $actual");
+ } else {
+ // String, bool, null.
+ Expect.equals(expected, actual, path);
+ }
+ }
+ for (var reviver in [null, (k, v) => v]) {
+ for (var split in [0, 1, 2, 3]) {
+ var name = (reviver == null) ? "" : "reviver:";
+ var sink = new ChunkedConversionSink.withCallback((values) {
+ var value = values[0];
+ compare(expected, value, "$name$value");
+ });
+ var decoderSink = JSON.decoder.startChunkedConversion(sink);
+ switch (split) {
+ case 0:
+ // Split after first char.
+ decoderSink.add(json.substring(0, 1));
+ decoderSink.add(json.substring(1));
+ decoderSink.close();
+ break;
+ case 1:
+ // Split before last char.
+ int length = json.length;
+ decoderSink.add(json.substring(0, length - 1));
+ decoderSink.add(json.substring(length - 1));
+ decoderSink.close();
+ break;
+ case 2:
+ // Split in middle.
+ int half = json.length ~/ 2;
+ decoderSink.add(json.substring(0, half));
+ decoderSink.add(json.substring(half));
+ decoderSink.close();
+ break;
+ case 3:
+ // Split in three chunks.
+ int length = json.length;
+ int third = length ~/ 3;
+ decoderSink.add(json.substring(0, third));
+ decoderSink.add(json.substring(third, 2 * third));
+ decoderSink.add(json.substring(2 * third));
+ decoderSink.close();
+ break;
+ }
+ }
+ }
+}
+
+String escape(String s) {
+ var sb = new StringBuffer();
+ for (int i = 0; i < s.length; i++) {
+ int code = s.codeUnitAt(i);
+ if (code == '\\'.codeUnitAt(0)) sb.write(r'\\');
+ else if (code == '\"'.codeUnitAt(0)) sb.write(r'\"');
+ else if (code >= 32 && code < 127) sb.writeCharCode(code);
+ else {
+ String hex = '000${code.toRadixString(16)}';
+ sb.write(r'\u' '${hex.substring(hex.length - 4)}');
+ }
+ }
+ return '$sb';
+}
+
+void testThrows(json) {
+ Expect.throws(() => JSON.decode(json), badFormat, "json = '${escape(json)}'");
+}
+
+testNumbers() {
+ // Positive tests for number formats.
+ var integerList = ["0","9","9999"];
+ var signList = ["", "-"];
+ var fractionList = ["", ".0", ".1", ".99999"];
+ var exponentList = [""];
+ for (var exphead in ["e", "E", "e-", "E-", "e+", "E+"]) {
+ for (var expval in ["0", "1", "200"]) {
+ exponentList.add("$exphead$expval");
+ }
+ }
+
+ for (var integer in integerList) {
+ for (var sign in signList) {
+ for (var fraction in fractionList) {
+ for (var exp in exponentList) {
+ for (var ws in ["", " ", "\t"]) {
+ var literal = "$ws$sign$integer$fraction$exp$ws";
+ var expectedValue = num.parse(literal);
+ testJson(literal, expectedValue);
+ }
+ }
+ }
+ }
+ }
+
+ // Negative tests (syntax error).
+ // testError thoroughly tests the given parts with a lot of valid
+ // values for the other parts.
+ testError({signs, integers, fractions, exponents}) {
+ def(value, defaultValue) {
+ if (value == null) return defaultValue;
+ if (value is List) return value;
+ return [value];
+ }
+ signs = def(signs, signList);
+ integers = def(integers, integerList);
+ fractions = def(fractions, fractionList);
+ exponents = def(exponents, exponentList);
+ for (var integer in integers) {
+ for (var sign in signs) {
+ for (var fraction in fractions) {
+ for (var exponent in exponents) {
+ var literal = "$sign$integer$fraction$exponent";
+ testThrows(literal);
+ }
+ }
+ }
+ }
+ }
+ // Doubles overflow to Infinity.
+ testJson("1e+400", double.INFINITY);
+ // (Integers do not, but we don't have those on dart2js).
+
+ // Integer part cannot be omitted:
+ testError(integers: "");
+
+ // Test for "Initial zero only allowed for zero integer part" moved to
+ // json_strict_test.dart because IE's JSON.decode accepts additional initial
+ // zeros.
+
+ // Only minus allowed as sign.
+ testError(signs: "+");
+ // Requires digits after decimal point.
+ testError(fractions: ".");
+ // Requires exponent digts, and only digits.
+ testError(exponents: ["e", "e+", "e-", "e.0"]);
+
+ // No whitespace inside numbers.
+ // Additional case "- 2.2e+2" in json_strict_test.dart.
+ testThrows("-2 .2e+2");
+ testThrows("-2. 2e+2");
+ testThrows("-2.2 e+2");
+ testThrows("-2.2e +2");
+ testThrows("-2.2e+ 2");
+
+ testThrows("[2.,2]");
+ testThrows("{2.:2}");
+
+ testThrows("NaN");
+ testThrows("Infinity");
+ testThrows("-Infinity");
+ Expect.throws(() => JSON.encode(double.NAN));
+ Expect.throws(() => JSON.encode(double.INFINITY));
+ Expect.throws(() => JSON.encode(double.NEGATIVE_INFINITY));
+}
+
+testStrings() {
+ // String parser accepts and understands escapes.
+ var input = r'"\u0000\uffff\n\r\f\t\b\/\\\"' '\x20\ufffd\uffff"';
+ var expected = "\u0000\uffff\n\r\f\t\b\/\\\"\x20\ufffd\uffff";
+ testJson(input, expected);
+ // Empty string.
+ testJson(r'""', "");
+ // Escape first.
+ var escapes = {
+ "f": "\f",
+ "b": "\b",
+ "n": "\n",
+ "r": "\r",
+ "t": "\t",
+ r"\": r"\",
+ '"': '"',
+ "/": "/",
+ };
+ escapes.forEach((esc, lit) {
+ testJson('"\\$esc........"', "$lit........");
+ // Escape last.
+ testJson('"........\\$esc"', "........$lit");
+ // Escape middle.
+ testJson('"....\\$esc...."', "....$lit....");
+ });
+
+ // Does not accept single quotes.
+ testThrows(r"''");
+ // Throws on unterminated strings.
+ testThrows(r'"......\"');
+ // Throws on unterminated escapes.
+ testThrows(r'"\'); // ' is not escaped.
+ testThrows(r'"\a"');
+ testThrows(r'"\u"');
+ testThrows(r'"\u1"');
+ testThrows(r'"\u12"');
+ testThrows(r'"\u123"');
+ testThrows(r'"\ux"');
+ testThrows(r'"\u1x"');
+ testThrows(r'"\u12x"');
+ testThrows(r'"\u123x"');
+ // Throws on bad escapes.
+ testThrows(r'"\a"');
+ testThrows(r'"\x00"');
+ testThrows(r'"\c2"');
+ testThrows(r'"\000"');
+ testThrows(r'"\u{0}"');
+ testThrows(r'"\%"');
+ testThrows('"\\\x00"'); // Not raw string!
+ // Throws on control characters.
+ for (int i = 0; i < 32; i++) {
+ var string = new String.fromCharCodes([0x22,i,0x22]); // '"\x00"' etc.
+ testThrows(string);
+ }
+}
+
+
+testObjects() {
+ testJson(r'{}', {});
+ testJson(r'{"x":42}', {"x":42});
+ testJson(r'{"x":{"x":{"x":42}}}', {"x": {"x": {"x": 42}}});
+ testJson(r'{"x":10,"x":42}', {"x": 42});
+ testJson(r'{"":42}', {"": 42});
+
+ // Keys must be strings.
+ testThrows(r'{x:10}');
+ testThrows(r'{true:10}');
+ testThrows(r'{false:10}');
+ testThrows(r'{null:10}');
+ testThrows(r'{42:10}');
+ testThrows(r'{42e1:10}');
+ testThrows(r'{-42:10}');
+ testThrows(r'{["text"]:10}');
+ testThrows(r'{:10}');
+}
+
+testArrays() {
+ testJson(r'[]', []);
+ testJson(r'[1.1e1,"string",true,false,null,{}]',
+ [1.1e1, "string", true, false, null, {}]);
+ testJson(r'[[[[[[]]]],[[[]]],[[]]]]', [[[[[[]]]],[[[]]],[[]]]]);
+ testJson(r'[{},[{}],{"x":[]}]', [{},[{}],{"x":[]}]);
+
+ testThrows(r'[1,,2]');
+ testThrows(r'[1,2,]');
+ testThrows(r'[,2]');
+}
+
+testWords() {
+ testJson(r'true', true);
+ testJson(r'false', false);
+ testJson(r'null', null);
+ testJson(r'[true]', [true]);
+ testJson(r'{"true":true}', {"true": true});
+
+ testThrows(r'truefalse');
+ testThrows(r'trues');
+ testThrows(r'nulll');
+ testThrows(r'full');
+ testThrows(r'nul');
+ testThrows(r'tru');
+ testThrows(r'fals');
+ testThrows(r'\null');
+ testThrows(r't\rue');
+ testThrows(r't\rue');
+}
+
+testWhitespace() {
+ // Valid white-space characters.
+ var v = '\t\r\n\ ';
+ // Invalid white-space and non-recognized characters.
+ var invalids = ['\x00', '\f', '\x08', '\\', '\xa0','\u2028', '\u2029'];
+
+ // Valid whitespace accepted "everywhere".
+ testJson('$v[${v}-2.2e2$v,$v{$v"key"$v:${v}true$v}$v,$v"ab"$v]$v',
+ [-2.2e2, {"key": true}, "ab"]);
+
+ // IE9 accepts invalid characters at the end, so some of these tests have been
+ // moved to json_strict_test.dart.
+ for (var i in invalids) {
+ testThrows('${i}"s"');
+ testThrows('42${i}');
+ testThrows('$i[]');
+ testThrows('[$i]');
+ testThrows('[$i"s"]');
+ testThrows('["s"$i]');
+ testThrows('$i{"k":"v"}');
+ testThrows('{$i"k":"v"}');
+ testThrows('{"k"$i:"v"}');
+ testThrows('{"k":$i"v"}');
+ testThrows('{"k":"v"$i}');
+ }
+}
+
+main() {
+ testNumbers();
+ testStrings();
+ testWords();
+ testObjects();
+ testArrays();
+ testWhitespace();
+}

Powered by Google App Engine
This is Rietveld 408576698