| // Copyright (c) 2013, 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. | |
| import "package:expect/expect.dart"; | |
| const whiteSpace = const [ | |
| "", | |
| "\x09", | |
| "\x0a", | |
| "\x0b", | |
| "\x0c", | |
| "\x0d", | |
| "\xa0", | |
| "\u1680", | |
| "\u2000", | |
| "\u2001", | |
| "\u2002", | |
| "\u2003", | |
| "\u2004", | |
| "\u2005", | |
| "\u2006", | |
| "\u2007", | |
| "\u2008", | |
| "\u2009", | |
| "\u200a", | |
| "\u2028", | |
| "\u2029", | |
| "\u202f", | |
| "\u205f", | |
| "\u3000", | |
| "\uFEFF", | |
| ]; | |
| void expectNumEquals(num expect, num? actual, String message) { | |
| if (expect is double && expect.isNaN) { | |
| Expect.isTrue(actual is double && actual.isNaN, "isNaN: $message"); | |
| } else { | |
| Expect.identical(expect, actual, message); | |
| } | |
| } | |
| // Test source surrounded by any combination of whitespace. | |
| void testParseAllWhitespace(String source, num result) { | |
| for (String ws1 in whiteSpace) { | |
| for (String ws2 in whiteSpace) { | |
| String padded = "$ws1$source$ws2"; | |
| // Use Expect.identical because it also handles NaN and 0.0/-0.0. | |
| // Except on dart2js: http://dartbug.com/11551 | |
| expectNumEquals(result, num.parse(padded), "parse '$padded'"); | |
| padded = "$ws1$ws2$source"; | |
| expectNumEquals(result, num.parse(padded), "parse '$padded'"); | |
| padded = "$source$ws1$ws2"; | |
| expectNumEquals(result, num.parse(padded), "parse '$padded'"); | |
| } | |
| } | |
| } | |
| // Test source and -source surrounded by any combination of whitespace. | |
| void testParseWhitespace(String source, num result) { | |
| assert(result >= 0); | |
| testParseAllWhitespace(source, result); | |
| testParseAllWhitespace("-$source", -result); | |
| } | |
| void testParse(String source, num result) { | |
| expectNumEquals(result, num.tryParse(source), "parse '$source'"); | |
| expectNumEquals(result, num.tryParse(" $source"), "parse ' $source'"); | |
| expectNumEquals(result, num.tryParse("$source "), "parse '$source '"); | |
| expectNumEquals(result, num.tryParse(" $source "), "parse ' $source '"); | |
| } | |
| // Test parsing an integer in decimal or hex format, with or without signs. | |
| void testInt(int value) { | |
| testParse("$value", value); | |
| testParse("+$value", value); | |
| testParse("-$value", -value); | |
| var hex = "0x${value.toRadixString(16)}"; | |
| var lchex = hex.toLowerCase(); | |
| testParse(lchex, value); | |
| testParse("+$lchex", value); | |
| testParse("-$lchex", -value); | |
| var uchex = hex.toUpperCase(); | |
| testParse(uchex, value); | |
| testParse("+$uchex", value); | |
| testParse("-$uchex", -value); | |
| } | |
| // Test parsing an integer, and the integers just around it. | |
| void testIntAround(int value) { | |
| testInt(value - 1); | |
| testInt(value); | |
| testInt(value + 1); | |
| } | |
| void testDouble(double value) { | |
| testParse("$value", value); | |
| testParse("+$value", value); | |
| testParse("-$value", -value); | |
| if (value.isFinite) { | |
| String exp = value.toStringAsExponential(); | |
| String lcexp = exp.toLowerCase(); | |
| testParse(lcexp, value); | |
| testParse("+$lcexp", value); | |
| testParse("-$lcexp", -value); | |
| String ucexp = exp.toUpperCase(); | |
| testParse(ucexp, value); | |
| testParse("+$ucexp", value); | |
| testParse("-$ucexp", -value); | |
| } | |
| } | |
| void testFail(String source) { | |
| Expect.isNull(num.tryParse(source)); | |
| } | |
| void main() { | |
| testInt(0); | |
| testInt(1); | |
| testInt(9); | |
| testInt(10); | |
| testInt(99); | |
| testInt(100); | |
| testIntAround(256); | |
| testIntAround(0x80000000); // 2^31 | |
| testIntAround(0x100000000); // 2^32 | |
| testIntAround(0x10000000000000); // 2^52 | |
| testIntAround(0x1FFFFFFFFFFFFF); // 2^53 - 1 | |
| testDouble(0.0); | |
| testDouble(5e-324); | |
| testDouble(2.225073858507201e-308); | |
| testDouble(2.2250738585072014e-308); | |
| testDouble(0.49999999999999994); | |
| testDouble(0.5); | |
| testDouble(0.50000000000000006); | |
| testDouble(0.9999999999999999); | |
| testDouble(1.0); | |
| testDouble(1.0000000000000002); | |
| testDouble(4294967295.0); | |
| testDouble(4294967296.0); | |
| testDouble(4503599627370495.5); | |
| testDouble(4503599627370497.0); | |
| testDouble(9007199254740991.0); | |
| testDouble(9007199254740992.0); | |
| testDouble(1.7976931348623157e+308); | |
| testDouble(double.infinity); | |
| testDouble(double.nan); | |
| // Strings that cannot occur from toString of a number. | |
| testParse("000000000000", 0); | |
| testParse("000000000001", 1); | |
| testParse("000000000000.0000000000000", 0.0); | |
| testParse("000000000001.0000000000000", 1.0); | |
| testParse("0x0000000000", 0); | |
| testParse("0e0", 0.0); | |
| testParse("0e+0", 0.0); | |
| testParse("0e-0", 0.0); | |
| testParse("-0e0", -0.0); | |
| testParse("-0e+0", -0.0); | |
| testParse("-0e-0", -0.0); | |
| testParse("1e0", 1.0); | |
| testParse("1e+0", 1.0); | |
| testParse("1e-0", 1.0); | |
| testParse("-1e0", -1.0); | |
| testParse("-1e+0", -1.0); | |
| testParse("-1e-0", -1.0); | |
| testParse("1.", 1.0); | |
| testParse(".1", 0.1); | |
| testParse("1.e1", 10.0); | |
| testParse(".1e1", 1.0); | |
| testParseWhitespace("0x1", 1); | |
| testParseWhitespace("1", 1); | |
| testParseWhitespace("1.0", 1.0); | |
| testParseWhitespace("1e1", 10.0); | |
| testParseWhitespace(".1e1", 1.0); | |
| testParseWhitespace("1.e1", 10.0); | |
| testParseWhitespace("1e+1", 10.0); | |
| testParseWhitespace("1e-1", 0.1); | |
| // Negative tests - things not to allow. | |
| // Spaces inside the numeral. | |
| testFail("- 1"); | |
| testFail("+ 1"); | |
| testFail("2 2"); | |
| testFail("0x 42"); | |
| testFail("1 ."); | |
| testFail(". 1"); | |
| testFail("1e 2"); | |
| testFail("1 e2"); | |
| // Invalid characters. | |
| testFail("0x1H"); | |
| testFail("12H"); | |
| testFail("1x2"); | |
| testFail("00x2"); | |
| testFail("0x2.2"); | |
| // Empty hex number. | |
| testFail("0x"); | |
| testFail("-0x"); | |
| testFail("+0x"); | |
| // Double exponent without value. | |
| testFail(".e1"); | |
| testFail("e1"); | |
| testFail("e+1"); | |
| testFail("e-1"); | |
| testFail("-e1"); | |
| testFail("-e+1"); | |
| testFail("-e-1"); | |
| // Incorrect ways to write NaN/Infinity. | |
| testFail("infinity"); | |
| testFail("INFINITY"); | |
| testFail("1.#INF"); | |
| testFail("inf"); | |
| testFail("nan"); | |
| testFail("NAN"); | |
| testFail("1.#IND"); | |
| testFail("indef"); | |
| testFail("qnan"); | |
| testFail("snan"); | |
| } |