1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
//===--- 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 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
}
#if !os(WASI)
// Trap tests aren't available on WASI.
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)
}
#endif
% 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()
|