// RUN: %empty-directory(%t) // RUN: %S/../../utils/gyb %s -o %t/FixedPointConversion.swift // RUN: %S/../../utils/line-directive %t/FixedPointConversion.swift -- %target-build-swift %t/FixedPointConversion.swift -o %t/a.out_Debug -Onone // RUN: %S/../../utils/line-directive %t/FixedPointConversion.swift -- %target-build-swift %t/FixedPointConversion.swift -o %t/a.out_Release -O // // RUN: %S/../../utils/line-directive %t/FixedPointConversion.swift -- %target-run %t/a.out_Debug // RUN: %S/../../utils/line-directive %t/FixedPointConversion.swift -- %target-run %t/a.out_Release // REQUIRES: executable_test // FIXME(integers): add tests that perform the same checks in generic code %{ import gyb }% 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 "" } %{ int_to_int_conversion_template = gyb.parse_template("int_to_int_conversion", """ %{ from SwiftIntTypes import all_integer_types, int_max, int_min from SwiftFloatingPointTypes import all_floating_point_types }% % 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 % 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. % elif testValue >= selfMin and testValue <= selfMax: /// 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}) var result = ${Self}(exactly: input) expectEqual(${testValue}, result) } % else: /// 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() var 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) % 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) % if Other == 'Float80': #if !os(Windows) && (arch(i386) || arch(x86_64)) % end % for testValue in [repr(value) for value in [selfMin, selfMax, selfMin - 0.1, selfMax + 0.1, otherMin, otherMax, 0.0, -0.0, 0.1, -0.1]]: % if testValue < otherMin or testValue > otherMax: % # Can't construct `other` value to test from, do nothing and continue. % elif testValue >= selfMin and testValue <= selfMax and testValue % 1 == 0 and testValue != -0.0: FloatingPointConversionTruncations.test("${Other}To${Self}Conversion/dest=${testValue}") { let input = get${Other}(${testValue}) let result = ${Self}(input) var resultConvertedBack = ${Other}(result) expectEqual(${testValue}, resultConvertedBack) } FloatingPointConversionFailures.test("${Other}To${Self}FailableConversion/dest=${testValue}") { let input = get${Other}(${testValue}) expectNil(${Self}(exactly: input)) } % else: % if testValue > selfMax: FloatingPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValue}") .crashOutputMatches(getTooLargeMessage()).code { expectCrashLater() % elif testValue < selfMin: FloatingPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValue}") .crashOutputMatches(getTooSmallMessage()).code { expectCrashLater() % else: FloatingPointConversionTruncations.test("${Other}To${Self}Conversion/dest=${testValue}") { % end let input = get${Other}(${testValue}) var result = ${Self}(input) var resultConvertedBack = ${Other}(result) expectNotEqual(input, resultConvertedBack) } FloatingPointConversionFailures.test("${Other}To${Self}Conversion/dest=${testValue}") { let input = get${Other}(${testValue}) 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) """) }% #if arch(i386) || arch(arm) ${gyb.execute_template( int_to_int_conversion_template, word_bits=32)} #elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x) ${gyb.execute_template( int_to_int_conversion_template, word_bits=64)} #else _UnimplementedError() #endif runAllTests()