Skip to content

Commit 4dcf60c

Browse files
drodriguezgwynne
authored andcommitted
[test] Fix FixedPointConversion tests (#23220)
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 <[email protected]>
1 parent 65d4199 commit 4dcf60c

File tree

3 files changed

+54
-60
lines changed

3 files changed

+54
-60
lines changed

test/stdlib/Inputs/FixedPointConversion.swift.gyb

Lines changed: 52 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
// FIXME(integers): add tests that perform the same checks in generic code
22

33
%{
4-
import gyb
4+
from SwiftIntTypes import all_integer_types, int_max, int_min
5+
from SwiftFloatingPointTypes import all_floating_point_types, getFtoIBounds
6+
7+
from decimal import Decimal
58
}%
69

710
import StdlibUnittest
@@ -34,22 +37,15 @@ func getTooLargeMessage() -> String {
3437
return ""
3538
}
3639

37-
%{
38-
39-
int_to_int_conversion_template = gyb.parse_template("int_to_int_conversion",
40-
"""
41-
%{
42-
from SwiftIntTypes import all_integer_types, int_max, int_min
43-
from SwiftFloatingPointTypes import all_floating_point_types
44-
45-
}%
40+
% word_bits = int(target_ptrsize)
4641
% for self_ty in all_integer_types(word_bits):
4742
% selfBits = self_ty.bits
4843
% selfSigned = self_ty.is_signed
4944
% selfMin = self_ty.min
5045
% selfMax = self_ty.max
5146
% Self = self_ty.stdlib_name
5247

48+
% # Test conversion behaviors for all integer types
5349
% for other_ty in all_integer_types(word_bits):
5450
% otherBits = other_ty.bits
5551
% otherSigned = other_ty.is_signed
@@ -60,9 +56,10 @@ from SwiftFloatingPointTypes import all_floating_point_types
6056
% for testValue in [selfMin, selfMax, selfMin - 1, selfMax + 1, otherMin, otherMax]:
6157

6258
% if testValue < otherMin or testValue > otherMax:
63-
% # Can't construct `other` value, do nothing and continue.
64-
59+
% # Can't construct `other` value, do nothing and continue.
60+
% pass
6561
% elif testValue >= selfMin and testValue <= selfMax:
62+
% # Test value can be represented by Self, test conversion succeeds
6663

6764
/// Always-safe conversion from ${Other}(${testValue}) to ${Self}.
6865
FixedPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValue}") {
@@ -75,18 +72,19 @@ FixedPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValue}")
7572
FixedPointConversionFailure.test("${Other}To${Self}FailableConversion/dest=${testValue}") {
7673
// Test that nothing interesting happens and we end up with a non-nil, identical result.
7774
let input = get${Other}(${testValue})
78-
var result = ${Self}(exactly: input)
75+
let result = ${Self}(exactly: input)
7976
expectEqual(${testValue}, result)
8077
}
8178

8279
% else:
80+
% # Test value is out of range of Self, test conversion fails
8381

8482
/// Always-failing conversion from ${Other}(${testValue}) to ${Self}.
8583
FixedPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValue}") {
8684
// Test that we check if we fail and crash when an integer would be truncated in conversion.
8785
let input = get${Other}(${testValue})
8886
expectCrashLater()
89-
var result = ${Self}(input)
87+
let result = ${Self}(input)
9088
_blackHole(result)
9189
}
9290

@@ -96,60 +94,78 @@ FixedPointConversionFailure.test("${Other}To${Self}Conversion/dest=${testValue}"
9694
let input = get${Other}(${testValue})
9795
expectNil(${Self}(exactly: input))
9896
}
99-
% end
10097

98+
% end
10199
% end # for testValue in ...
102100
% end # for in all_integer_types (Other)
103101

102+
% # Test conversion behaviors for all floating-point types
104103
% for other_type in all_floating_point_types():
105104
% Other = "Float" + str(other_type.bits)
106105
% otherMin = -int_max(bits=other_type.explicit_significand_bits, signed=False)
107106
% otherMax = int_max(bits=other_type.explicit_significand_bits, signed=False)
107+
% (selfFtoIMin, selfFtoIMax) = getFtoIBounds(other_type.bits, selfBits, selfSigned)
108108

109109
% if Other == 'Float80':
110110
#if !os(Windows) && (arch(i386) || arch(x86_64))
111111
% end
112112

113-
% 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]]:
113+
% testValues = [
114+
% Decimal(selfMin),
115+
% Decimal(selfMax),
116+
% Decimal(selfFtoIMin) - Decimal('0.1'),
117+
% Decimal(selfFtoIMax) + Decimal('0.1'),
118+
% Decimal(otherMin),
119+
% Decimal(otherMax),
120+
% Decimal('0.0'),
121+
% Decimal('-0.0'),
122+
% Decimal('0.1'),
123+
% Decimal('-0.1')
124+
% ]
125+
% for testValue in testValues:
126+
% testValueStr = str(testValue)
114127

115128
% if testValue < otherMin or testValue > otherMax:
116129
% # Can't construct `other` value to test from, do nothing and continue.
130+
% pass
131+
% elif testValue >= selfFtoIMin and testValue <= selfFtoIMax and (testValue % 1).is_zero():
132+
% # Test value can be represented exactly by Self, test two-way conversion
117133

118-
% elif testValue >= selfMin and testValue <= selfMax and testValue % 1 == 0 and testValue != -0.0:
119-
120-
FloatingPointConversionTruncations.test("${Other}To${Self}Conversion/dest=${testValue}") {
121-
let input = get${Other}(${testValue})
134+
FloatingPointConversionTruncations.test("${Other}To${Self}Conversion/dest=${testValueStr}") {
135+
let input = get${Other}(${testValueStr})
122136
let result = ${Self}(input)
123-
var resultConvertedBack = ${Other}(result)
124-
expectEqual(${testValue}, resultConvertedBack)
137+
let resultConvertedBack = ${Other}(result)
138+
expectEqual(${testValueStr}, resultConvertedBack)
125139
}
126140

127-
FloatingPointConversionFailures.test("${Other}To${Self}FailableConversion/dest=${testValue}") {
128-
let input = get${Other}(${testValue})
129-
expectNil(${Self}(exactly: input))
141+
FloatingPointConversionFailures.test("${Other}To${Self}FailableConversion/dest=${testValueStr}") {
142+
let input = get${Other}(${testValueStr})
143+
expectNotNil(${Self}(exactly: input))
130144
}
131145

132146
% else:
133-
134-
% if testValue > selfMax:
135-
FloatingPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValue}")
147+
% if testValue > selfFtoIMax:
148+
% # Test value exceeds maximum value of Self, test for too large message
149+
FloatingPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValueStr}")
136150
.crashOutputMatches(getTooLargeMessage()).code {
137151
expectCrashLater()
138-
% elif testValue < selfMin:
139-
FloatingPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValue}")
152+
% elif testValue < selfFtoIMin:
153+
% # Test value doesn't reach minimum value of Self, test for too small message
154+
FloatingPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValueStr}")
140155
.crashOutputMatches(getTooSmallMessage()).code {
141156
expectCrashLater()
142157
% else:
143-
FloatingPointConversionTruncations.test("${Other}To${Self}Conversion/dest=${testValue}") {
158+
% # Test value can be represented inexactly by Self, test for truncation
159+
FloatingPointConversionTruncations.test("${Other}To${Self}Conversion/dest=${testValueStr}") {
144160
% end
145-
let input = get${Other}(${testValue})
146-
var result = ${Self}(input)
147-
var resultConvertedBack = ${Other}(result)
161+
let input = get${Other}(${testValueStr})
162+
let result = ${Self}(input)
163+
let resultConvertedBack = ${Other}(result)
148164
expectNotEqual(input, resultConvertedBack)
149165
}
150166

151-
FloatingPointConversionFailures.test("${Other}To${Self}Conversion/dest=${testValue}") {
152-
let input = get${Other}(${testValue})
167+
FloatingPointConversionFailures.test("${Other}To${Self}Conversion/dest=${testValueStr}") {
168+
let input = get${Other}(${testValueStr})
153169
expectNil(${Self}(exactly: input))
154170
}
155171
% end
@@ -208,26 +224,4 @@ FloatingPointConversionFailures.test("${Self}/${Other}/NaN") {
208224
% end # for in all_floating_point_types (Other)
209225
% end # for in all_integer_types (Self)
210226

211-
""")
212-
213-
}%
214-
215-
#if arch(i386) || arch(arm)
216-
217-
${gyb.execute_template(
218-
int_to_int_conversion_template,
219-
word_bits=32)}
220-
221-
#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x)
222-
223-
${gyb.execute_template(
224-
int_to_int_conversion_template,
225-
word_bits=64)}
226-
227-
#else
228-
229-
_UnimplementedError()
230-
231-
#endif
232-
233227
runAllTests()

validation-test/stdlib/FixedPointConversion_Debug.test-sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %gyb %S/Inputs/FixedPointConversion.swift.gyb -o %t/FixedPointConversion.swift
2+
// RUN: %gyb %S/Inputs/FixedPointConversion.swift.gyb -Dtarget_ptrsize=%target-ptrsize -o %t/FixedPointConversion.swift
33
// RUN: %line-directive %t/FixedPointConversion.swift -- %target-build-swift %t/FixedPointConversion.swift -o %t/a.out_Debug -Onone
44
// RUN: %target-codesign %t/a.out_Debug
55
//

validation-test/stdlib/FixedPointConversion_Release.test-sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %gyb %S/Inputs/FixedPointConversion.swift.gyb -o %t/FixedPointConversion.swift
2+
// RUN: %gyb %S/Inputs/FixedPointConversion.swift.gyb -Dtarget_ptrsize=%target-ptrsize -o %t/FixedPointConversion.swift
33
// RUN: %line-directive %t/FixedPointConversion.swift -- %target-build-swift %t/FixedPointConversion.swift -o %t/a.out_Release -O
44
// RUN: %target-codesign %t/a.out_Release
55
//

0 commit comments

Comments
 (0)