blob: 65b98101cf3cbe4dbc8d6e998ce5e08765341149 [file] [log] [blame]
// FIXME(integers): add tests that perform the same checks in generic code
%{
from SwiftIntTypes import all_integer_types, int_max, int_min
from SwiftFloatingPointTypes import all_floating_point_types, getFtoIBounds
from decimal import Decimal
}%
import StdlibUnittest
var FixedPointConversionTraps = TestSuite("FixedPointToFixedPointConversionTraps")
var FixedPointConversionFailure = TestSuite("FixedPointToFixedPointConversionFailures")
var FloatingPointConversionTruncations = TestSuite("FloatingPointToFixedPointConversionTruncations")
var FloatingPointConversionTraps = TestSuite("FloatingPointConversionTraps")
var FloatingPointConversionFailures = TestSuite("FloatingPointToFixedPointConversionFailures")
func getInfiniteOrNaNMessage() -> String {
if _isDebugAssertConfiguration() {
return "either infinite or NaN"
}
return ""
}
func getTooSmallMessage() -> String {
if _isDebugAssertConfiguration() {
return "would be less than"
}
return ""
}
func getTooLargeMessage() -> String {
if _isDebugAssertConfiguration() {
return "would be greater than"
}
return ""
}
% word_bits = int(target_ptrsize)
% for self_ty in all_integer_types(word_bits):
% selfBits = self_ty.bits
% selfSigned = self_ty.is_signed
% selfMin = self_ty.min
% selfMax = self_ty.max
% Self = self_ty.stdlib_name
% # Test conversion behaviors for all integer types
% for other_ty in all_integer_types(word_bits):
% otherBits = other_ty.bits
% otherSigned = other_ty.is_signed
% otherMin = other_ty.min
% otherMax = other_ty.max
% Other = other_ty.stdlib_name
% for testValue in [selfMin, selfMax, selfMin - 1, selfMax + 1, otherMin, otherMax]:
% if testValue < otherMin or testValue > otherMax:
% # Can't construct `other` value, do nothing and continue.
% pass
% elif testValue >= selfMin and testValue <= selfMax:
% # Test value can be represented by Self, test conversion succeeds
/// Always-safe conversion from ${Other}(${testValue}) to ${Self}.
FixedPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValue}") {
// Test that nothing interesting happens and we end up with the same result after converting.
let input = get${Other}(${testValue})
expectEqual(${testValue}, ${Self}(input))
}
/// Never-nil failable conversion from ${Other}(${testValue}) to ${Self}.
FixedPointConversionFailure.test("${Other}To${Self}FailableConversion/dest=${testValue}") {
// Test that nothing interesting happens and we end up with a non-nil, identical result.
let input = get${Other}(${testValue})
let result = ${Self}(exactly: input)
expectEqual(${testValue}, result)
}
% else:
% # Test value is out of range of Self, test conversion fails
/// Always-failing conversion from ${Other}(${testValue}) to ${Self}.
FixedPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValue}") {
// Test that we check if we fail and crash when an integer would be truncated in conversion.
let input = get${Other}(${testValue})
expectCrashLater()
let result = ${Self}(input)
_blackHole(result)
}
/// Always-nil failable conversion from ${Other}(${testValue}) to ${Self}.
FixedPointConversionFailure.test("${Other}To${Self}Conversion/dest=${testValue}") {
// Test that we check if we return nil when an integer would be truncated in conversion.
let input = get${Other}(${testValue})
expectNil(${Self}(exactly: input))
}
% end
% end # for testValue in ...
% end # for in all_integer_types (Other)
% # Test conversion behaviors for all floating-point types
% for other_type in all_floating_point_types():
% Other = "Float" + str(other_type.bits)
% otherMin = -int_max(bits=other_type.explicit_significand_bits, signed=False)
% otherMax = int_max(bits=other_type.explicit_significand_bits, signed=False)
% (selfFtoIMin, selfFtoIMax) = getFtoIBounds(other_type.bits, selfBits, selfSigned)
% if Other == 'Float80':
#if !os(Windows) && (arch(i386) || arch(x86_64))
% end
% testValues = [
% Decimal(selfMin),
% Decimal(selfMax),
% Decimal(selfFtoIMin) - Decimal('0.1'),
% Decimal(selfFtoIMax) + Decimal('0.1'),
% Decimal(otherMin),
% Decimal(otherMax),
% Decimal('0.0'),
% Decimal('-0.0'),
% Decimal('0.1'),
% Decimal('-0.1')
% ]
% for testValue in testValues:
% testValueStr = str(testValue)
% if testValue < otherMin or testValue > otherMax:
% # Can't construct `other` value to test from, do nothing and continue.
% pass
% elif testValue >= selfFtoIMin and testValue <= selfFtoIMax and (testValue % 1).is_zero():
% # Test value can be represented exactly by Self, test two-way conversion
FloatingPointConversionTruncations.test("${Other}To${Self}Conversion/dest=${testValueStr}") {
let input = get${Other}(${testValueStr})
let result = ${Self}(input)
let resultConvertedBack = ${Other}(result)
expectEqual(${testValueStr}, resultConvertedBack)
}
FloatingPointConversionFailures.test("${Other}To${Self}FailableConversion/dest=${testValueStr}") {
let input = get${Other}(${testValueStr})
expectNotNil(${Self}(exactly: input))
}
% else:
% if testValue > selfFtoIMax:
% # Test value exceeds maximum value of Self, test for too large message
FloatingPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValueStr}")
.crashOutputMatches(getTooLargeMessage()).code {
expectCrashLater()
% elif testValue < selfFtoIMin:
% # Test value doesn't reach minimum value of Self, test for too small message
FloatingPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValueStr}")
.crashOutputMatches(getTooSmallMessage()).code {
expectCrashLater()
% else:
% # Test value can be represented inexactly by Self, test for truncation
FloatingPointConversionTruncations.test("${Other}To${Self}Conversion/dest=${testValueStr}") {
% end
let input = get${Other}(${testValueStr})
let result = ${Self}(input)
let resultConvertedBack = ${Other}(result)
expectNotEqual(input, resultConvertedBack)
}
FloatingPointConversionFailures.test("${Other}To${Self}Conversion/dest=${testValueStr}") {
let input = get${Other}(${testValueStr})
expectNil(${Self}(exactly: input))
}
% end
% end # for in testValues
// Test Always-Trapping conversions.
% if not selfSigned:
FloatingPointConversionTraps.test("${Self}/${Other}/negative")
.crashOutputMatches(getTooSmallMessage()).code {
expectCrashLater()
_blackHole(${Self}(get${Other}(-123.0)))
}
FloatingPointConversionFailures.test("${Self}/${Other}/negative") {
expectNil(${Self}(exactly: get${Other}(-123.0)))
}
% end
FloatingPointConversionTraps.test("${Self}/${Other}/+inf")
.crashOutputMatches(getInfiniteOrNaNMessage()).code {
expectCrashLater()
_blackHole(${Self}(get${Other}(${Other}.infinity)))
}
FloatingPointConversionFailures.test("${Self}/${Other}/+inf") {
expectNil(${Self}(exactly: get${Other}(${Other}.infinity)))
}
FloatingPointConversionTraps.test("${Self}/${Other}/-inf")
.crashOutputMatches(getInfiniteOrNaNMessage()).code {
expectCrashLater()
_blackHole(${Self}(get${Other}(-${Other}.infinity)))
}
FloatingPointConversionFailures.test("${Self}/${Other}/-inf") {
expectNil(${Self}(exactly: get${Other}(-${Other}.infinity)))
}
FloatingPointConversionTraps.test("${Self}/${Other}/NaN")
.crashOutputMatches(getInfiniteOrNaNMessage()).code {
expectCrashLater()
_blackHole(${Self}(get${Other}(${Other}.nan)))
}
FloatingPointConversionFailures.test("${Self}/${Other}/NaN") {
expectNil(${Self}(exactly: get${Other}(${Other}.nan)))
}
% if Other == 'Float80':
#endif
% end
% end # for in all_floating_point_types (Other)
% end # for in all_integer_types (Self)
runAllTests()