// 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. // Formatting can break multitests, so don't format them. // dart format off import "package:expect/expect.dart"; const whiteSpace = const [ "", "\x09", "\x0a", "\x0b", "\x0c", "\x0d", "\x85", "\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); } // Test parsing source, optionally preceded and/or followed by whitespace. void testParse(String source, num result) { expectNumEquals(result, num.parse(source), "parse '$source'"); expectNumEquals(result, num.parse(" $source"), "parse ' $source'"); expectNumEquals(result, num.parse("$source "), "parse '$source '"); expectNumEquals(result, num.parse(" $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) { var object = new Object(); Expect.throwsFormatException(() { num.parse(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(0x20000000000000); // 2^53 testIntAround(0x40000000000000); // 2^54 // 0x7ffffffffffffffe on int-is-64-bit implementations, rounded up on // int-is-double implementations. testIntAround(0x7ffffffffffff000 + 0xffe); // 2^63 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); // //# 01: ok // 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"); }