|
1 |
| -// FIXME(integers): add tests that perform the same checks in generic code |
2 |
| - |
3 |
| -%{ |
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 |
8 |
| -}% |
9 |
| - |
10 |
| -import StdlibUnittest |
11 |
| - |
12 |
| -var FixedPointConversionTraps = TestSuite("FixedPointToFixedPointConversionTraps") |
13 |
| -var FixedPointConversionFailure = TestSuite("FixedPointToFixedPointConversionFailures") |
14 |
| - |
15 |
| -var FloatingPointConversionTruncations = TestSuite("FloatingPointToFixedPointConversionTruncations") |
16 |
| -var FloatingPointConversionTraps = TestSuite("FloatingPointConversionTraps") |
17 |
| -var FloatingPointConversionFailures = TestSuite("FloatingPointToFixedPointConversionFailures") |
18 |
| - |
19 |
| -func getInfiniteOrNaNMessage() -> String { |
20 |
| - if _isDebugAssertConfiguration() { |
21 |
| - return "either infinite or NaN" |
22 |
| - } |
23 |
| - return "" |
24 |
| -} |
25 |
| - |
26 |
| -func getTooSmallMessage() -> String { |
27 |
| - if _isDebugAssertConfiguration() { |
28 |
| - return "would be less than" |
29 |
| - } |
30 |
| - return "" |
31 |
| -} |
32 |
| - |
33 |
| -func getTooLargeMessage() -> String { |
34 |
| - if _isDebugAssertConfiguration() { |
35 |
| - return "would be greater than" |
36 |
| - } |
37 |
| - return "" |
38 |
| -} |
39 |
| - |
| 1 | +% # FIXME(integers): add tests that perform the same checks in generic code. |
| 2 | +% |
| 3 | +% from SwiftIntTypes import all_integer_types, int_max |
| 4 | +% from SwiftFloatingPointTypes import all_floating_point_types |
| 5 | +% from decimal import Decimal |
| 6 | +% |
| 7 | +% test_suites = [] |
| 8 | +% |
40 | 9 | % word_bits = int(target_ptrsize)
|
41 | 10 | % for self_ty in all_integer_types(word_bits):
|
42 |
| -% selfBits = self_ty.bits |
43 |
| -% selfSigned = self_ty.is_signed |
44 |
| -% selfMin = self_ty.min |
45 |
| -% selfMax = self_ty.max |
46 | 11 | % Self = self_ty.stdlib_name
|
| 12 | +% selfMax = self_ty.max |
| 13 | +% selfMin = self_ty.min |
| 14 | +% |
| 15 | +% test_suite = 'FixedPointConversion_' + configuration + '_To' + Self |
| 16 | +% test_suites.append(test_suite) |
| 17 | +% |
| 18 | +//===----------------------------------------------------------------------===// |
| 19 | +// BEGIN ${test_suite}.swift |
| 20 | +//===----------------------------------------------------------------------===// |
47 | 21 |
|
48 |
| -% # Test conversion behaviors for all integer types |
49 |
| -% for other_ty in all_integer_types(word_bits): |
50 |
| -% otherBits = other_ty.bits |
51 |
| -% otherSigned = other_ty.is_signed |
52 |
| -% otherMin = other_ty.min |
53 |
| -% otherMax = other_ty.max |
54 |
| -% Other = other_ty.stdlib_name |
55 |
| - |
56 |
| -% for testValue in [selfMin, selfMax, selfMin - 1, selfMax + 1, otherMin, otherMax]: |
| 22 | +import StdlibUnittest |
57 | 23 |
|
58 |
| -% if testValue < otherMin or testValue > otherMax: |
59 |
| -% # Can't construct `other` value, do nothing and continue. |
60 |
| -% pass |
61 |
| -% elif testValue >= selfMin and testValue <= selfMax: |
62 |
| -% # Test value can be represented by Self, test conversion succeeds |
| 24 | +func register${test_suite}() { |
63 | 25 |
|
64 |
| -/// Always-safe conversion from ${Other}(${testValue}) to ${Self}. |
65 |
| -FixedPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValue}") { |
66 |
| - // Test that nothing interesting happens and we end up with the same result after converting. |
67 |
| - let input = get${Other}(${testValue}) |
68 |
| - expectEqual(${testValue}, ${Self}(input)) |
69 |
| -} |
| 26 | + let ${test_suite} = TestSuite("${test_suite}") |
70 | 27 |
|
71 |
| -/// Never-nil failable conversion from ${Other}(${testValue}) to ${Self}. |
72 |
| -FixedPointConversionFailure.test("${Other}To${Self}FailableConversion/dest=${testValue}") { |
73 |
| - // Test that nothing interesting happens and we end up with a non-nil, identical result. |
74 |
| - let input = get${Other}(${testValue}) |
75 |
| - let result = ${Self}(exactly: input) |
76 |
| - expectEqual(${testValue}, result) |
77 |
| -} |
| 28 | +% # Test conversion behaviors for all integer types. |
| 29 | +% for other_ty in all_integer_types(word_bits): |
| 30 | +% Other = other_ty.stdlib_name |
| 31 | +% otherMax = other_ty.max |
| 32 | +% otherMin = other_ty.min |
| 33 | +% |
| 34 | + //===--------------------------------------------------------------------===// |
| 35 | + // ${Other} |
| 36 | + //===--------------------------------------------------------------------===// |
78 | 37 |
|
79 |
| -% else: |
80 |
| -% # Test value is out of range of Self, test conversion fails |
| 38 | +% testValues = [ |
| 39 | +% selfMin, |
| 40 | +% selfMax, |
| 41 | +% selfMin - 1, |
| 42 | +% selfMax + 1, |
| 43 | +% otherMin, |
| 44 | +% otherMax |
| 45 | +% ] |
| 46 | +% for testValue in testValues: |
| 47 | +% testLiteralValue = str(testValue) |
| 48 | +% if otherMin <= testValue <= otherMax: |
| 49 | +% if selfMin <= testValue <= selfMax: |
| 50 | + ${test_suite}.test("From${Other}(${testLiteralValue})_NeverTraps") { |
| 51 | + let input = get${Other}(${testLiteralValue}) |
| 52 | + let actual = ${Self}(input) |
| 53 | + expectEqual(${testLiteralValue}, actual) |
| 54 | + } |
81 | 55 |
|
82 |
| -/// Always-failing conversion from ${Other}(${testValue}) to ${Self}. |
83 |
| -FixedPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValue}") { |
84 |
| - // Test that we check if we fail and crash when an integer would be truncated in conversion. |
85 |
| - let input = get${Other}(${testValue}) |
86 |
| - expectCrashLater() |
87 |
| - let result = ${Self}(input) |
88 |
| - _blackHole(result) |
89 |
| -} |
| 56 | + ${test_suite}.test("From${Other}(${testLiteralValue})_NeverFails") { |
| 57 | + let input = get${Other}(${testLiteralValue}) |
| 58 | + let actual = ${Self}(exactly: input) |
| 59 | + expectEqual(${testLiteralValue}, actual) |
| 60 | + } |
90 | 61 |
|
91 |
| -/// Always-nil failable conversion from ${Other}(${testValue}) to ${Self}. |
92 |
| -FixedPointConversionFailure.test("${Other}To${Self}Conversion/dest=${testValue}") { |
93 |
| - // Test that we check if we return nil when an integer would be truncated in conversion. |
94 |
| - let input = get${Other}(${testValue}) |
95 |
| - expectNil(${Self}(exactly: input)) |
96 |
| -} |
| 62 | +% else: |
| 63 | + ${test_suite}.test("From${Other}(${testLiteralValue})_AlwaysTraps") { |
| 64 | + let input = get${Other}(${testLiteralValue}) |
| 65 | + expectCrash { |
| 66 | + let actual = ${Self}(input) |
| 67 | + _blackHole(actual) |
| 68 | + } |
| 69 | + } |
97 | 70 |
|
98 |
| -% end |
99 |
| -% end # for testValue in ... |
100 |
| -% end # for in all_integer_types (Other) |
| 71 | + ${test_suite}.test("From${Other}(${testLiteralValue})_AlwaysFails") { |
| 72 | + let input = get${Other}(${testLiteralValue}) |
| 73 | + let actual = ${Self}(exactly: input) |
| 74 | + expectNil(actual) |
| 75 | + } |
101 | 76 |
|
102 |
| -% # Test conversion behaviors for all floating-point types |
| 77 | +% end # if |
| 78 | +% end # if |
| 79 | +% end # for |
| 80 | +% end # for |
| 81 | +% |
| 82 | +% # Test conversion behaviors for all floating-point types. |
103 | 83 | % for other_type in all_floating_point_types():
|
104 | 84 | % Other = "Float" + str(other_type.bits)
|
105 |
| -% otherMin = -int_max(bits=other_type.explicit_significand_bits, signed=False) |
106 | 85 | % otherMax = int_max(bits=other_type.explicit_significand_bits, signed=False)
|
107 |
| -% (selfFtoIMin, selfFtoIMax) = getFtoIBounds(other_type.bits, selfBits, selfSigned) |
| 86 | +% otherMin = -otherMax |
| 87 | +% |
| 88 | + //===--------------------------------------------------------------------===// |
| 89 | + // ${Other} |
| 90 | + //===--------------------------------------------------------------------===// |
108 | 91 |
|
109 | 92 | % if Other == 'Float16':
|
110 | 93 | #if !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64))
|
111 | 94 | if #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) {
|
| 95 | + |
112 | 96 | % elif Other == 'Float80':
|
113 | 97 | #if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64))
|
114 |
| -% end |
115 | 98 |
|
| 99 | +% end # if |
| 100 | +% |
116 | 101 | % testValues = [
|
117 | 102 | % Decimal(selfMin),
|
118 | 103 | % Decimal(selfMax),
|
119 |
| -% Decimal(selfFtoIMin) - Decimal('0.1'), |
120 |
| -% Decimal(selfFtoIMax) + Decimal('0.1'), |
| 104 | +% Decimal(selfMin - 1), |
| 105 | +% Decimal(selfMax + 1), |
121 | 106 | % Decimal(otherMin),
|
122 | 107 | % Decimal(otherMax),
|
123 | 108 | % Decimal('0.0'),
|
124 | 109 | % Decimal('-0.0'),
|
125 | 110 | % Decimal('0.1'),
|
126 |
| -% Decimal('-0.1') |
| 111 | +% Decimal('-0.1'), |
| 112 | +% Decimal('-123.45') |
127 | 113 | % ]
|
128 | 114 | % for testValue in testValues:
|
129 |
| -% testValueStr = str(testValue) |
130 |
| - |
131 |
| -% if testValue < otherMin or testValue > otherMax: |
132 |
| -% # Can't construct `other` value to test from, do nothing and continue. |
133 |
| -% pass |
134 |
| -% elif testValue >= selfFtoIMin and testValue <= selfFtoIMax and (testValue % 1).is_zero(): |
135 |
| -% # Test value can be represented exactly by Self, test two-way conversion |
136 |
| - |
137 |
| -FloatingPointConversionTruncations.test("${Other}To${Self}Conversion/dest=${testValueStr}") { |
138 |
| - let input = get${Other}(${testValueStr}) |
139 |
| - let result = ${Self}(input) |
140 |
| - let resultConvertedBack = ${Other}(result) |
141 |
| - expectEqual(${testValueStr}, resultConvertedBack) |
142 |
| -} |
143 |
| - |
144 |
| -FloatingPointConversionFailures.test("${Other}To${Self}FailableConversion/dest=${testValueStr}") { |
145 |
| - let input = get${Other}(${testValueStr}) |
146 |
| - expectNotNil(${Self}(exactly: input)) |
147 |
| -} |
| 115 | +% testLiteralValue = str(testValue) |
| 116 | +% if otherMin <= testValue <= otherMax: |
| 117 | +% if (selfMin - 1) < testValue < (selfMax + 1): |
| 118 | + ${test_suite}.test("From${Other}(${testLiteralValue})_NeverTraps") { |
| 119 | + let input = get${Other}(${testLiteralValue}) |
| 120 | + let actual = ${Self}(input) |
| 121 | + expectEqual(${str(int(testValue))}, actual) |
| 122 | + } |
148 | 123 |
|
149 |
| -% else: |
150 |
| -% if testValue > selfFtoIMax: |
151 |
| -% # Test value exceeds maximum value of Self, test for too large message |
152 |
| -FloatingPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValueStr}") |
153 |
| -.crashOutputMatches(getTooLargeMessage()).code { |
154 |
| - expectCrashLater() |
155 |
| -% elif testValue < selfFtoIMin: |
156 |
| -% # Test value doesn't reach minimum value of Self, test for too small message |
157 |
| -FloatingPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValueStr}") |
158 |
| -.crashOutputMatches(getTooSmallMessage()).code { |
159 |
| - expectCrashLater() |
160 | 124 | % else:
|
161 |
| -% # Test value can be represented inexactly by Self, test for truncation |
162 |
| -FloatingPointConversionTruncations.test("${Other}To${Self}Conversion/dest=${testValueStr}") { |
163 |
| -% end |
164 |
| - let input = get${Other}(${testValueStr}) |
165 |
| - let result = ${Self}(input) |
166 |
| - let resultConvertedBack = ${Other}(result) |
167 |
| - expectNotEqual(input, resultConvertedBack) |
168 |
| -} |
169 |
| - |
170 |
| -FloatingPointConversionFailures.test("${Other}To${Self}Conversion/dest=${testValueStr}") { |
171 |
| - let input = get${Other}(${testValueStr}) |
172 |
| - expectNil(${Self}(exactly: input)) |
173 |
| -} |
174 |
| -% end |
175 |
| -% end # for in testValues |
176 |
| - |
177 |
| -// Test Always-Trapping conversions. |
178 |
| - |
179 |
| -% if not selfSigned: |
180 |
| - |
181 |
| -FloatingPointConversionTraps.test("${Self}/${Other}/negative") |
182 |
| - .crashOutputMatches(getTooSmallMessage()).code { |
183 |
| - expectCrashLater() |
184 |
| - _blackHole(${Self}(get${Other}(-123.0))) |
185 |
| -} |
| 125 | + ${test_suite}.test("From${Other}(${testLiteralValue})_AlwaysTraps") { |
| 126 | + let input = get${Other}(${testLiteralValue}) |
| 127 | + expectCrash { |
| 128 | + let actual = ${Self}(input) |
| 129 | + _blackHole(actual) |
| 130 | + } |
| 131 | + } |
186 | 132 |
|
187 |
| -FloatingPointConversionFailures.test("${Self}/${Other}/negative") { |
188 |
| - expectNil(${Self}(exactly: get${Other}(-123.0))) |
189 |
| -} |
| 133 | +% end # if |
| 134 | +% |
| 135 | +% if (selfMin <= testValue <= selfMax) and (testValue % 1).is_zero(): |
| 136 | + ${test_suite}.test("From${Other}(${testLiteralValue})_NeverFails") { |
| 137 | + let input = get${Other}(${testLiteralValue}) |
| 138 | + let actual = ${Self}(exactly: input) |
| 139 | + expectEqual(${str(int(testValue))}, actual) |
| 140 | + } |
190 | 141 |
|
191 |
| -% end |
| 142 | +% else: |
| 143 | + ${test_suite}.test("From${Other}(${testLiteralValue})_AlwaysFails") { |
| 144 | + let input = get${Other}(${testLiteralValue}) |
| 145 | + let actual = ${Self}(exactly: input) |
| 146 | + expectNil(actual) |
| 147 | + } |
192 | 148 |
|
193 |
| -FloatingPointConversionTraps.test("${Self}/${Other}/+inf") |
194 |
| - .crashOutputMatches(getInfiniteOrNaNMessage()).code { |
195 |
| - expectCrashLater() |
196 |
| - _blackHole(${Self}(get${Other}(${Other}.infinity))) |
197 |
| -} |
| 149 | +% end # if |
| 150 | +% end # if |
| 151 | +% end # for |
| 152 | +% |
| 153 | +% for testExpression in ['-.infinity', '.infinity', '-.nan', '.nan']: |
| 154 | + ${test_suite}.test("From${Other}(${testExpression})_AlwaysTraps") { |
| 155 | + let input = get${Other}(${testExpression}) |
| 156 | + expectCrash { |
| 157 | + let actual = ${Self}(input) |
| 158 | + _blackHole(actual) |
| 159 | + } |
| 160 | + } |
198 | 161 |
|
199 |
| -FloatingPointConversionFailures.test("${Self}/${Other}/+inf") { |
200 |
| - expectNil(${Self}(exactly: get${Other}(${Other}.infinity))) |
201 |
| -} |
| 162 | + ${test_suite}.test("From${Other}(${testExpression})_AlwaysFails") { |
| 163 | + let input = get${Other}(${testExpression}) |
| 164 | + let actual = ${Self}(exactly: input) |
| 165 | + expectNil(actual) |
| 166 | + } |
202 | 167 |
|
203 |
| -FloatingPointConversionTraps.test("${Self}/${Other}/-inf") |
204 |
| - .crashOutputMatches(getInfiniteOrNaNMessage()).code { |
205 |
| - expectCrashLater() |
206 |
| - _blackHole(${Self}(get${Other}(-${Other}.infinity))) |
| 168 | +% end # for |
| 169 | +% |
| 170 | +% if Other == 'Float16': |
207 | 171 | }
|
| 172 | +#endif // Float16 |
208 | 173 |
|
209 |
| -FloatingPointConversionFailures.test("${Self}/${Other}/-inf") { |
210 |
| - expectNil(${Self}(exactly: get${Other}(-${Other}.infinity))) |
211 |
| -} |
| 174 | +% elif Other == 'Float80': |
| 175 | +#endif // Float80 |
212 | 176 |
|
213 |
| -FloatingPointConversionTraps.test("${Self}/${Other}/NaN") |
214 |
| - .crashOutputMatches(getInfiniteOrNaNMessage()).code { |
215 |
| - expectCrashLater() |
216 |
| - _blackHole(${Self}(get${Other}(${Other}.nan))) |
217 |
| -} |
| 177 | +% end # if |
| 178 | +% |
| 179 | +% end # for |
| 180 | +} // func |
218 | 181 |
|
219 |
| -FloatingPointConversionFailures.test("${Self}/${Other}/NaN") { |
220 |
| - expectNil(${Self}(exactly: get${Other}(${Other}.nan))) |
221 |
| -} |
| 182 | +% end # for |
| 183 | +% |
| 184 | +//===----------------------------------------------------------------------===// |
| 185 | +// BEGIN main.swift |
| 186 | +//===----------------------------------------------------------------------===// |
222 | 187 |
|
223 |
| -% if Other == 'Float16': |
224 |
| -} |
225 |
| -#endif |
226 |
| -% elif Other == 'Float80': |
227 |
| -#endif |
228 |
| -% end |
| 188 | +import StdlibUnittest |
229 | 189 |
|
230 |
| -% end # for in all_floating_point_types (Other) |
231 |
| -% end # for in all_integer_types (Self) |
| 190 | +% for test_suite in test_suites: |
| 191 | +register${test_suite}() |
| 192 | +% end # for |
232 | 193 |
|
233 | 194 | runAllTests()
|
0 commit comments