Skip to content

Commit c51784e

Browse files
authored
Adopt swift-testing for Timeout tests (grpc#2051)
Motivation: swift-testing has a number of advantages over XCTest (parameterisation, organisation, failure messages etc.), we should start using it instead of XCTest. Modifications: - Convert the Timeout tests Results: Better tests
1 parent b036fb7 commit c51784e

File tree

1 file changed

+64
-185
lines changed

1 file changed

+64
-185
lines changed

Tests/GRPCCoreTests/TimeoutTests.swift

Lines changed: 64 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -13,193 +13,72 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
import XCTest
1716

18-
@testable import GRPCCore
19-
20-
@available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)
21-
final class TimeoutTests: XCTestCase {
22-
func testDecodeInvalidTimeout_Empty() {
23-
let timeoutHeader = ""
24-
XCTAssertNil(Timeout(decoding: timeoutHeader))
25-
}
26-
27-
func testDecodeInvalidTimeout_NoAmount() {
28-
let timeoutHeader = "H"
29-
XCTAssertNil(Timeout(decoding: timeoutHeader))
30-
}
31-
32-
func testDecodeInvalidTimeout_NoUnit() {
33-
let timeoutHeader = "123"
34-
XCTAssertNil(Timeout(decoding: timeoutHeader))
35-
}
36-
37-
func testDecodeInvalidTimeout_TooLongAmount() {
38-
let timeoutHeader = "100000000S"
39-
XCTAssertNil(Timeout(decoding: timeoutHeader))
40-
}
41-
42-
func testDecodeInvalidTimeout_InvalidUnit() {
43-
let timeoutHeader = "123j"
44-
XCTAssertNil(Timeout(decoding: timeoutHeader))
45-
}
46-
47-
func testDecodeValidTimeout_Hours() throws {
48-
let timeoutHeader = "123H"
49-
let timeout = Timeout(decoding: timeoutHeader)
50-
let unwrappedTimeout = try XCTUnwrap(timeout)
51-
XCTAssertEqual(unwrappedTimeout.duration, Duration.hours(123))
52-
XCTAssertEqual(unwrappedTimeout.wireEncoding, timeoutHeader)
53-
}
54-
55-
func testDecodeValidTimeout_Minutes() throws {
56-
let timeoutHeader = "123M"
57-
let timeout = Timeout(decoding: timeoutHeader)
58-
let unwrappedTimeout = try XCTUnwrap(timeout)
59-
XCTAssertEqual(unwrappedTimeout.duration, Duration.minutes(123))
60-
XCTAssertEqual(unwrappedTimeout.wireEncoding, timeoutHeader)
61-
}
62-
63-
func testDecodeValidTimeout_Seconds() throws {
64-
let timeoutHeader = "123S"
65-
let timeout = Timeout(decoding: timeoutHeader)
66-
let unwrappedTimeout = try XCTUnwrap(timeout)
67-
XCTAssertEqual(unwrappedTimeout.duration, Duration.seconds(123))
68-
XCTAssertEqual(unwrappedTimeout.wireEncoding, timeoutHeader)
69-
}
70-
71-
func testDecodeValidTimeout_Milliseconds() throws {
72-
let timeoutHeader = "123m"
73-
let timeout = Timeout(decoding: timeoutHeader)
74-
let unwrappedTimeout = try XCTUnwrap(timeout)
75-
XCTAssertEqual(unwrappedTimeout.duration, Duration.milliseconds(123))
76-
XCTAssertEqual(unwrappedTimeout.wireEncoding, timeoutHeader)
77-
}
78-
79-
func testDecodeValidTimeout_Microseconds() throws {
80-
let timeoutHeader = "123u"
81-
let timeout = Timeout(decoding: timeoutHeader)
82-
let unwrappedTimeout = try XCTUnwrap(timeout)
83-
XCTAssertEqual(unwrappedTimeout.duration, Duration.microseconds(123))
84-
XCTAssertEqual(unwrappedTimeout.wireEncoding, timeoutHeader)
85-
}
86-
87-
func testDecodeValidTimeout_Nanoseconds() throws {
88-
let timeoutHeader = "123n"
89-
let timeout = Timeout(decoding: timeoutHeader)
90-
let unwrappedTimeout = try XCTUnwrap(timeout)
91-
XCTAssertEqual(unwrappedTimeout.duration, Duration.nanoseconds(123))
92-
XCTAssertEqual(unwrappedTimeout.wireEncoding, timeoutHeader)
93-
}
17+
import Testing
9418

95-
func testEncodeValidTimeout_Hours() {
96-
let duration = Duration.hours(123)
97-
let timeout = Timeout(duration: duration)
98-
XCTAssertEqual(timeout.duration.components.seconds, duration.components.seconds)
99-
XCTAssertEqual(timeout.duration.components.attoseconds, duration.components.attoseconds)
100-
}
101-
102-
func testEncodeValidTimeout_Minutes() {
103-
let duration = Duration.minutes(43)
104-
let timeout = Timeout(duration: duration)
105-
XCTAssertEqual(timeout.duration.components.seconds, duration.components.seconds)
106-
XCTAssertEqual(timeout.duration.components.attoseconds, duration.components.attoseconds)
107-
}
108-
109-
func testEncodeValidTimeout_Seconds() {
110-
let duration = Duration.seconds(12345)
111-
let timeout = Timeout(duration: duration)
112-
XCTAssertEqual(timeout.duration.components.seconds, duration.components.seconds)
113-
XCTAssertEqual(timeout.duration.components.attoseconds, duration.components.attoseconds)
114-
}
115-
116-
func testEncodeValidTimeout_Seconds_TooLong_Minutes() {
117-
let duration = Duration.seconds(111_111_111)
118-
let timeout = Timeout(duration: duration)
119-
// The conversion from seconds to minutes results in a loss of precision.
120-
// 111,111,111 seconds / 60 = 1,851,851.85 minutes -rounding up-> 1,851,852 minutes * 60 = 111,111,120 seconds
121-
let expectedRoundedDuration = Duration.minutes(1_851_852)
122-
XCTAssertEqual(timeout.duration.components.seconds, expectedRoundedDuration.components.seconds)
123-
XCTAssertEqual(
124-
timeout.duration.components.attoseconds,
125-
expectedRoundedDuration.components.attoseconds
126-
)
127-
}
128-
129-
func testEncodeValidTimeout_Seconds_TooLong_Hours() {
130-
let duration = Duration.seconds(9_999_999_999 as Int64)
131-
let timeout = Timeout(duration: duration)
132-
// The conversion from seconds to hours results in a loss of precision.
133-
// 9,999,999,999 seconds / 60 = 166,666,666.65 minutes -rounding up->
134-
// 166,666,667 minutes / 60 = 2,777,777.78 hours -rounding up->
135-
// 2,777,778 hours * 60 -> 166,666,680 minutes * 60 = 10,000,000,800 seconds
136-
let expectedRoundedDuration = Duration.hours(2_777_778)
137-
XCTAssertEqual(timeout.duration.components.seconds, expectedRoundedDuration.components.seconds)
138-
XCTAssertEqual(
139-
timeout.duration.components.attoseconds,
140-
expectedRoundedDuration.components.attoseconds
141-
)
142-
}
143-
144-
func testEncodeValidTimeout_Seconds_TooLong_MaxAmount() {
145-
let duration = Duration.seconds(999_999_999_999 as Int64)
146-
let timeout = Timeout(duration: duration)
147-
// The conversion from seconds to hours results in a number that still has
148-
// more than the maximum allowed 8 digits, so we must clamp it.
149-
// Make sure that `Timeout.maxAmount` is the amount used for the resulting timeout.
150-
let expectedRoundedDuration = Duration.hours(Timeout.maxAmount)
151-
XCTAssertEqual(timeout.duration.components.seconds, expectedRoundedDuration.components.seconds)
152-
XCTAssertEqual(
153-
timeout.duration.components.attoseconds,
154-
expectedRoundedDuration.components.attoseconds
155-
)
156-
}
157-
158-
func testEncodeValidTimeout_SecondsAndMilliseconds() {
159-
let duration = Duration(secondsComponent: 100, attosecondsComponent: Int64(1e+17))
160-
let timeout = Timeout(duration: duration)
161-
XCTAssertEqual(timeout.duration.components.seconds, duration.components.seconds)
162-
XCTAssertEqual(timeout.duration.components.attoseconds, duration.components.attoseconds)
163-
}
164-
165-
func testEncodeValidTimeout_SecondsAndMicroseconds() {
166-
let duration = Duration(secondsComponent: 1, attosecondsComponent: Int64(1e+14))
167-
let timeout = Timeout(duration: duration)
168-
XCTAssertEqual(timeout.duration.components.seconds, duration.components.seconds)
169-
XCTAssertEqual(timeout.duration.components.attoseconds, duration.components.attoseconds)
170-
}
171-
172-
func testEncodeValidTimeout_SecondsAndNanoseconds() {
173-
let duration = Duration(secondsComponent: 1, attosecondsComponent: Int64(1e+11))
174-
let timeout = Timeout(duration: duration)
175-
// We can't convert seconds to nanoseconds because that would require at least
176-
// 9 digits, and the maximum allowed is 8: we expect to simply drop the nanoseconds.
177-
let expectedRoundedDuration = Duration.seconds(1)
178-
XCTAssertEqual(timeout.duration.components.seconds, expectedRoundedDuration.components.seconds)
179-
XCTAssertEqual(
180-
timeout.duration.components.attoseconds,
181-
expectedRoundedDuration.components.attoseconds
182-
)
183-
}
184-
185-
func testEncodeValidTimeout_Milliseconds() {
186-
let duration = Duration.milliseconds(100)
187-
let timeout = Timeout(duration: duration)
188-
XCTAssertEqual(timeout.duration.components.seconds, duration.components.seconds)
189-
XCTAssertEqual(timeout.duration.components.attoseconds, duration.components.attoseconds)
190-
}
191-
192-
func testEncodeValidTimeout_Microseconds() {
193-
let duration = Duration.microseconds(100)
194-
let timeout = Timeout(duration: duration)
195-
XCTAssertEqual(timeout.duration.components.seconds, duration.components.seconds)
196-
XCTAssertEqual(timeout.duration.components.attoseconds, duration.components.attoseconds)
197-
}
19+
@testable import GRPCCore
19820

199-
func testEncodeValidTimeout_Nanoseconds() {
200-
let duration = Duration.nanoseconds(100)
201-
let timeout = Timeout(duration: duration)
202-
XCTAssertEqual(timeout.duration.components.seconds, duration.components.seconds)
203-
XCTAssertEqual(timeout.duration.components.attoseconds, duration.components.attoseconds)
21+
struct TimeoutTests {
22+
@Test("Initialize from invalid String value", arguments: ["", "H", "123", "100000000S", "123j"])
23+
func initFromStringWithInvalidValue(_ value: String) throws {
24+
#expect(Timeout(decoding: value) == nil)
25+
}
26+
27+
@Test(
28+
"Initialize from String",
29+
arguments: [
30+
("123H", .hours(123)),
31+
("123M", .minutes(123)),
32+
("123S", .seconds(123)),
33+
("123m", .milliseconds(123)),
34+
("123u", .microseconds(123)),
35+
("123n", .nanoseconds(123)),
36+
] as [(String, Duration)]
37+
)
38+
func initFromString(_ value: String, expected: Duration) throws {
39+
let timeout = try #require(Timeout(decoding: value))
40+
#expect(timeout.duration == expected)
41+
}
42+
43+
@Test(
44+
"Initialize from Duration",
45+
arguments: [
46+
.hours(123),
47+
.minutes(43),
48+
.seconds(12345),
49+
.milliseconds(100),
50+
.microseconds(100),
51+
.nanoseconds(100),
52+
] as [Duration]
53+
)
54+
func initFromDuration(_ value: Duration) {
55+
let timeout = Timeout(duration: value)
56+
#expect(timeout.duration == value)
57+
}
58+
59+
@Test(
60+
"Initialize from Duration with loss of precision",
61+
arguments: [
62+
// 111,111,111 seconds / 60 = 1,851,851.85 minutes -rounding up-> 1,851,852 minutes * 60 = 111,111,120 seconds
63+
(.seconds(111_111_111), .minutes(1_851_852)),
64+
65+
// 9,999,999,999 seconds / 60 = 166,666,666.65 minutes -rounding up->
66+
// 166,666,667 minutes / 60 = 2,777,777.78 hours -rounding up->
67+
// 2,777,778 hours * 60 -> 166,666,680 minutes * 60 = 10,000,000,800 seconds
68+
(.seconds(9_999_999_999 as Int64), .hours(2_777_778)),
69+
70+
// The conversion from seconds to hours results in a number that still has
71+
// more than the maximum allowed 8 digits, so we must clamp it.
72+
// Make sure that `Timeout.maxAmount` is the amount used for the resulting timeout.
73+
(.seconds(999_999_999_999 as Int64), .hours(Timeout.maxAmount)),
74+
75+
// We can't convert seconds to nanoseconds because that would require at least
76+
// 9 digits, and the maximum allowed is 8: we expect to simply drop the nanoseconds.
77+
(Duration(secondsComponent: 1, attosecondsComponent: Int64(1e11)), .seconds(1)),
78+
] as [(Duration, Duration)]
79+
)
80+
func initFromDurationWithLossOfPrecision(original: Duration, rounded: Duration) {
81+
let timeout = Timeout(duration: original)
82+
#expect(timeout.duration == rounded)
20483
}
20584
}

0 commit comments

Comments
 (0)