From 14d89ec1c112e196feaaedc26d22d351ec802eb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodr=C3=ADguez=20Troiti=C3=B1o?= Date: Mon, 11 Mar 2019 14:11:27 -0700 Subject: [PATCH] [test] Fix FixedPointConversion tests Fix several problems with FixedPointConversion generation code. The first problem is that at some point `repr(value)` was being used, which turn the number into a string. That was great for printing the number, but make the test against the value of the number (like `testValue < otherMin` always false. There were a number of tests that were never performed, specifically the integer tests. The second problem was using doubles in the Python code. For Float32 and Float64 the tests were generated correctly, but in the case of Float80, the test adding or removing a quantity to the maximum/minimum were failing because of the lack of precission (Adding 0.1 to a very big/small number is the same as not adding anything). Switching to Decimal should keep enough precission for the tests. Finally the last problem was that the bounds of the conversions are not actually `selfMin` and `selfMax`, but the values returned by the utility function `getFtoIBounds`. For example for unsigned types, the lower bound is always -1, not zero (every value between -1 and zero is rounded to zero, and doesn't fail). Instead of using nested gyb templates, use lit.cfg %target-ptrsize, which should be faster, cleaner, and provides correct line-directive output. Remove a bunch of warnings in Swift when compiling the generated result of FixedPointConversion.swift.gyb. Co-authored-by: Gwynne Raskind --- .../Inputs/FixedPointConversion.swift.gyb | 110 +++++++++--------- .../stdlib/FixedPointConversion_Debug.test-sh | 2 +- .../FixedPointConversion_Release.test-sh | 2 +- 3 files changed, 54 insertions(+), 60 deletions(-) diff --git a/test/stdlib/Inputs/FixedPointConversion.swift.gyb b/test/stdlib/Inputs/FixedPointConversion.swift.gyb index bc1c35afcd569..65b98101cf3cb 100644 --- a/test/stdlib/Inputs/FixedPointConversion.swift.gyb +++ b/test/stdlib/Inputs/FixedPointConversion.swift.gyb @@ -1,7 +1,10 @@ // FIXME(integers): add tests that perform the same checks in generic code %{ -import gyb +from SwiftIntTypes import all_integer_types, int_max, int_min +from SwiftFloatingPointTypes import all_floating_point_types, getFtoIBounds + +from decimal import Decimal }% import StdlibUnittest @@ -34,15 +37,7 @@ func getTooLargeMessage() -> String { 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 - -}% +% word_bits = int(target_ptrsize) % for self_ty in all_integer_types(word_bits): % selfBits = self_ty.bits % selfSigned = self_ty.is_signed @@ -50,6 +45,7 @@ from SwiftFloatingPointTypes import all_floating_point_types % 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 @@ -60,9 +56,10 @@ from SwiftFloatingPointTypes import all_floating_point_types % 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. - +% # 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}") { @@ -75,18 +72,19 @@ FixedPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValue}") 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) + 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() - var result = ${Self}(input) + let result = ${Self}(input) _blackHole(result) } @@ -96,60 +94,78 @@ FixedPointConversionFailure.test("${Other}To${Self}Conversion/dest=${testValue}" let input = get${Other}(${testValue}) expectNil(${Self}(exactly: input)) } -% end +% 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 -% 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]]: +% 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 -% 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}) +FloatingPointConversionTruncations.test("${Other}To${Self}Conversion/dest=${testValueStr}") { + let input = get${Other}(${testValueStr}) let result = ${Self}(input) - var resultConvertedBack = ${Other}(result) - expectEqual(${testValue}, resultConvertedBack) + let resultConvertedBack = ${Other}(result) + expectEqual(${testValueStr}, resultConvertedBack) } -FloatingPointConversionFailures.test("${Other}To${Self}FailableConversion/dest=${testValue}") { - let input = get${Other}(${testValue}) - expectNil(${Self}(exactly: input)) +FloatingPointConversionFailures.test("${Other}To${Self}FailableConversion/dest=${testValueStr}") { + let input = get${Other}(${testValueStr}) + expectNotNil(${Self}(exactly: input)) } % else: - -% if testValue > selfMax: -FloatingPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValue}") +% 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 < selfMin: -FloatingPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValue}") +% 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: -FloatingPointConversionTruncations.test("${Other}To${Self}Conversion/dest=${testValue}") { +% # Test value can be represented inexactly by Self, test for truncation +FloatingPointConversionTruncations.test("${Other}To${Self}Conversion/dest=${testValueStr}") { % end - let input = get${Other}(${testValue}) - var result = ${Self}(input) - var resultConvertedBack = ${Other}(result) + let input = get${Other}(${testValueStr}) + let result = ${Self}(input) + let resultConvertedBack = ${Other}(result) expectNotEqual(input, resultConvertedBack) } -FloatingPointConversionFailures.test("${Other}To${Self}Conversion/dest=${testValue}") { - let input = get${Other}(${testValue}) +FloatingPointConversionFailures.test("${Other}To${Self}Conversion/dest=${testValueStr}") { + let input = get${Other}(${testValueStr}) expectNil(${Self}(exactly: input)) } % end @@ -208,26 +224,4 @@ FloatingPointConversionFailures.test("${Self}/${Other}/NaN") { % 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() diff --git a/validation-test/stdlib/FixedPointConversion_Debug.test-sh b/validation-test/stdlib/FixedPointConversion_Debug.test-sh index e38146bf38b40..8d47fb1b4d43d 100644 --- a/validation-test/stdlib/FixedPointConversion_Debug.test-sh +++ b/validation-test/stdlib/FixedPointConversion_Debug.test-sh @@ -1,5 +1,5 @@ // RUN: %empty-directory(%t) -// RUN: %gyb %S/Inputs/FixedPointConversion.swift.gyb -o %t/FixedPointConversion.swift +// RUN: %gyb %S/Inputs/FixedPointConversion.swift.gyb -Dtarget_ptrsize=%target-ptrsize -o %t/FixedPointConversion.swift // RUN: %line-directive %t/FixedPointConversion.swift -- %target-build-swift %t/FixedPointConversion.swift -o %t/a.out_Debug -Onone // RUN: %target-codesign %t/a.out_Debug // diff --git a/validation-test/stdlib/FixedPointConversion_Release.test-sh b/validation-test/stdlib/FixedPointConversion_Release.test-sh index 7ddcc4dd45537..c0fecf09fb7ff 100644 --- a/validation-test/stdlib/FixedPointConversion_Release.test-sh +++ b/validation-test/stdlib/FixedPointConversion_Release.test-sh @@ -1,5 +1,5 @@ // RUN: %empty-directory(%t) -// RUN: %gyb %S/Inputs/FixedPointConversion.swift.gyb -o %t/FixedPointConversion.swift +// RUN: %gyb %S/Inputs/FixedPointConversion.swift.gyb -Dtarget_ptrsize=%target-ptrsize -o %t/FixedPointConversion.swift // RUN: %line-directive %t/FixedPointConversion.swift -- %target-build-swift %t/FixedPointConversion.swift -o %t/a.out_Release -O // RUN: %target-codesign %t/a.out_Release //