| // 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() |