@@ -220,6 +220,43 @@ class MetricsExtensionsTests: XCTestCase {
220
220
" expected value to match "
221
221
)
222
222
}
223
+
224
+ #if compiler(>=6.0)
225
+ func testTimerMeasure( ) async throws {
226
+ // bootstrap with our test metrics
227
+ let metrics = TestMetrics ( )
228
+ MetricsSystem . bootstrapInternal ( metrics)
229
+ // run the test
230
+ let name = " timer- \( UUID ( ) . uuidString) "
231
+ let delay = Duration . milliseconds ( 5 )
232
+ let timer = Timer ( label: name)
233
+ try await timer. measure {
234
+ try await Task . sleep ( for: delay)
235
+ }
236
+
237
+ let expectedTimer = try metrics. expectTimer ( name)
238
+ XCTAssertEqual ( 1 , expectedTimer. values. count, " expected number of entries to match " )
239
+ XCTAssertGreaterThan ( expectedTimer. values [ 0 ] , delay. nanosecondsClamped, " expected delay to match " )
240
+ }
241
+
242
+ @MainActor
243
+ func testTimerMeasureFromMainActor( ) async throws {
244
+ // bootstrap with our test metrics
245
+ let metrics = TestMetrics ( )
246
+ MetricsSystem . bootstrapInternal ( metrics)
247
+ // run the test
248
+ let name = " timer- \( UUID ( ) . uuidString) "
249
+ let delay = Duration . milliseconds ( 5 )
250
+ let timer = Timer ( label: name)
251
+ try await timer. measure {
252
+ try await Task . sleep ( for: delay)
253
+ }
254
+
255
+ let expectedTimer = try metrics. expectTimer ( name)
256
+ XCTAssertEqual ( 1 , expectedTimer. values. count, " expected number of entries to match " )
257
+ XCTAssertGreaterThan ( expectedTimer. values [ 0 ] , delay. nanosecondsClamped, " expected delay to match " )
258
+ }
259
+ #endif
223
260
}
224
261
225
262
// https://bugs.swift.org/browse/SR-6310
@@ -251,3 +288,25 @@ extension DispatchTimeInterval {
251
288
}
252
289
}
253
290
}
291
+
292
+ #if swift(>=5.7)
293
+ @available ( macOS 13 , iOS 16 , tvOS 16 , watchOS 9 , * )
294
+ extension Swift . Duration {
295
+ fileprivate var nanosecondsClamped : Int64 {
296
+ let components = self . components
297
+
298
+ let secondsComponentNanos = components. seconds. multipliedReportingOverflow ( by: 1_000_000_000 )
299
+ let attosCompononentNanos = components. attoseconds / 1_000_000_000
300
+ let combinedNanos = secondsComponentNanos. partialValue. addingReportingOverflow ( attosCompononentNanos)
301
+
302
+ guard
303
+ !secondsComponentNanos. overflow,
304
+ !combinedNanos. overflow
305
+ else {
306
+ return . max
307
+ }
308
+
309
+ return combinedNanos. partialValue
310
+ }
311
+ }
312
+ #endif
0 commit comments