mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Segregate out a couple of tests that verify changed behaviors in the standard library so we can omit them when testing against older runtimes.
196 lines
6.1 KiB
Swift
196 lines
6.1 KiB
Swift
//===--- NumericParsing.swift.gyb -----------------------------*- swift -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
// -*- swift -*-
|
|
// RUN: %empty-directory(%t)
|
|
// RUN: %gyb -DCMAKE_SIZEOF_VOID_P=%target-ptrsize %s -o %t/NumericParsing.swift
|
|
// RUN: %line-directive %t/NumericParsing.swift -- %target-build-swift %t/NumericParsing.swift -o %t/a.out
|
|
// RUN: %target-codesign %t/a.out
|
|
// RUN: %line-directive %t/NumericParsing.swift -- %target-run %t/a.out
|
|
// REQUIRES: executable_test
|
|
%{
|
|
from __future__ import division
|
|
from SwiftIntTypes import all_integer_types
|
|
|
|
word_bits = int(CMAKE_SIZEOF_VOID_P)
|
|
|
|
def maskOfWidth(n):
|
|
return (1 << n) - 1
|
|
|
|
def inRadix(radix, n, zero='0'):
|
|
"""
|
|
Represent the int n in the given radix.
|
|
Note: the third parameter, zero, is not for user consumption.
|
|
"""
|
|
if n < 0:
|
|
return '-' + inRadix(radix, -n, '')
|
|
elif n == 0:
|
|
return zero
|
|
else:
|
|
r = n % radix
|
|
digit = chr((ord('0') + r) if r < 10 else (ord('a') + r - 10))
|
|
return inRadix(radix, int(n // radix), '') + digit
|
|
|
|
# The maximal legal radix
|
|
max_radix = ord('z') - ord('a') + 1 + 10
|
|
|
|
# Test a few important radices
|
|
radices_to_test = [2, 8, 10, 16, max_radix]
|
|
|
|
# How many values to test in each radix? A nice prime number of course.
|
|
number_of_values = 23
|
|
}%
|
|
|
|
import StdlibUnittest
|
|
|
|
|
|
var tests = TestSuite("NumericParsing")
|
|
|
|
% for type in all_integer_types(word_bits):
|
|
% Self = type.stdlib_name
|
|
% maxValue = maskOfWidth((type.bits - 1) if type.is_signed else type.bits)
|
|
% minValue = -maxValue - 1 if type.is_signed else 0
|
|
% required_values = [minValue, 0, maxValue]
|
|
tests.test("${Self}/success") {
|
|
let isSigned = ${str(type.is_signed).lower()}
|
|
|
|
//===--- Important cases ------------------------------------------------===//
|
|
expectEqual(0, ${Self}("0")) // zero
|
|
expectEqual(17, ${Self}("17")) // non-zero with no radix
|
|
|
|
// Leading zeroes, with and without a radix
|
|
expectEqual(10, ${Self}("010"))
|
|
expectEqual(15, ${Self}("00F", radix: 16))
|
|
|
|
// Leading '+'
|
|
expectEqual(0, ${Self}("+0"))
|
|
expectEqual(10, ${Self}("+10"))
|
|
expectEqual(10, ${Self}("+010"))
|
|
expectEqual(15, ${Self}("+00F", radix: 16))
|
|
|
|
// Negative numbers
|
|
expectEqual(${-128 if type.is_signed else 'nil'}, ${Self}("-0080", radix: 16))
|
|
expectEqual(0, ${Self}("-0"))
|
|
expectEqual(0, ${Self}("-00", radix: 16))
|
|
|
|
// Maximum radix
|
|
expectEqual(${max_radix} - 1, ${Self}("z", radix: ${max_radix})!)
|
|
|
|
// Out-of-range values
|
|
expectEqual(nil, ${Self}("${maxValue + 1}"))
|
|
expectEqual(nil, ${Self}("${minValue - 1}"))
|
|
expectEqual(nil, ${Self}("\u{1D7FF}")) // MATHEMATICAL MONOSPACE DIGIT NINE
|
|
|
|
// Cases that should fail to parse
|
|
expectEqual(nil, ${Self}("--0")) // Zero w/ repeated plus
|
|
expectEqual(nil, ${Self}("-+5")) // Non-zero with -+
|
|
|
|
// Do more exhaustive testing
|
|
% for radix in radices_to_test:
|
|
% for n in required_values + list(range(
|
|
% minValue + 1, maxValue - 1,
|
|
% int((maxValue - minValue - 2) // (number_of_values - len(required_values))))):
|
|
% prefix = '+' if n > 0 and n % 2 == 0 else '' # leading '+'
|
|
% text = inRadix(radix, n)
|
|
expectEqual(${n}, ${Self}("${prefix + text}", radix: ${radix}))
|
|
% if text != text.upper():
|
|
expectEqual(${n}, ${Self}("${prefix + text.upper()}", radix: ${radix}))
|
|
% end
|
|
% end
|
|
% end
|
|
}
|
|
|
|
tests.test("${Self}/radixTooLow") {
|
|
${Self}("0", radix: 2)
|
|
expectCrashLater()
|
|
${Self}("0", radix: 1)
|
|
}
|
|
|
|
tests.test("${Self}/radixTooHigh") {
|
|
let maxRadix = ${ord('z') - ord('a') + 1 + 10}
|
|
${Self}("0", radix: maxRadix)
|
|
expectCrashLater()
|
|
let y = ${Self}("0", radix: maxRadix + 1)
|
|
}
|
|
|
|
% end
|
|
|
|
tests.test("FixedWidthInteger/maxUInt64") {
|
|
func f<T : FixedWidthInteger>(_ x: T) -> String {
|
|
return String(x, radix: 16)
|
|
}
|
|
let x = f(UInt64.max)
|
|
let y = String(UInt64.max, radix: 16)
|
|
expectEqual(x, y)
|
|
}
|
|
|
|
% for Self in 'Float', 'Double', 'Float80':
|
|
|
|
% if Self == 'Float80':
|
|
#if !os(Windows) && (arch(i386) || arch(x86_64))
|
|
% end
|
|
|
|
tests.test("${Self}/Basics") {
|
|
% if Self != 'Float80': # Inf/NaN are not defined for Float80
|
|
expectEqual(.infinity, ${Self}("inf"))
|
|
expectEqual(.infinity, ${Self}("Inf"))
|
|
expectEqual(-(.infinity), ${Self}("-inf"))
|
|
expectEqual(-(.infinity), ${Self}("-Inf"))
|
|
expectEqual(String(${Self}.nan), String(${Self}("nan")!))
|
|
expectEqual(String(${Self}.nan), String(${Self}("NaN")!))
|
|
|
|
// sNaN cannot be fully supported on i386.
|
|
#if !arch(i386)
|
|
expectTrue(${Self}("sNaN")!.isSignalingNaN)
|
|
expectTrue(${Self}("SNAN")!.isSignalingNaN)
|
|
expectTrue(${Self}("+snan")!.isSignalingNaN)
|
|
expectTrue(${Self}("-SnAn")!.isSignalingNaN)
|
|
#endif
|
|
% end
|
|
|
|
expectEqual(-0.0, ${Self}("-0"))
|
|
expectEqual(-0.0, ${Self}("-0.0"))
|
|
expectEqual(0.0, ${Self}("0"))
|
|
expectEqual(0.0, ${Self}("0.0"))
|
|
expectEqual(64206, ${Self}("0xFACE")) // Yes, strtoXXX supports hex.
|
|
|
|
// Check that we can round-trip the string representation of 2^100,
|
|
// which requires an exponent to express...
|
|
let large =
|
|
repeatElement(1024 as ${Self}, count: 10).reduce(1, *)
|
|
let largeText = String(large)
|
|
expectEqual(largeText, String(${Self}(largeText)!))
|
|
|
|
// ...ditto for its inverse.
|
|
let smallText = String(1 / large)
|
|
expectEqual(smallText, String(${Self}(smallText)!))
|
|
|
|
// Cases that should fail to parse
|
|
expectNil(${Self}("")) // EMPTY
|
|
expectNil(${Self}("0FACE")) // Hex characters without 0x
|
|
expectNil(${Self}("99x"))
|
|
expectNil(${Self}(" 0")) // Leading whitespace
|
|
expectNil(${Self}("0 ")) // Trailing whitespace
|
|
expectNil(${Self}("\u{1D7FF}")) // MATHEMATICAL MONOSPACE DIGIT NINE
|
|
|
|
// Values that are too large/small:
|
|
// * Early versions of Swift returned `nil` for e.g., 1e99999 or 1e-99999
|
|
// * After 5.3, large/small values return .infinity or zero, respectively
|
|
// These are tested in NumericParsing2.swift.gyb
|
|
}
|
|
|
|
% if Self == 'Float80':
|
|
#endif
|
|
% end
|
|
|
|
% end
|
|
runAllTests()
|