From 0efaecac80d77d39f6d9598d109c01cd52db065d Mon Sep 17 00:00:00 2001 From: Jeremy Schonfeld Date: Wed, 11 Jun 2025 13:50:32 -0700 Subject: [PATCH 01/12] Convert buffer view tests to swift-testing --- .../BufferViewTests.swift | 193 +++++++++--------- 1 file changed, 95 insertions(+), 98 deletions(-) diff --git a/Tests/FoundationEssentialsTests/BufferViewTests.swift b/Tests/FoundationEssentialsTests/BufferViewTests.swift index 704ee470f..a644e13d1 100644 --- a/Tests/FoundationEssentialsTests/BufferViewTests.swift +++ b/Tests/FoundationEssentialsTests/BufferViewTests.swift @@ -10,33 +10,30 @@ // //===----------------------------------------------------------------------===// -#if canImport(TestSupport) -import TestSupport -#endif +import Testing #if canImport(FoundationEssentials) @testable import FoundationEssentials -#endif - -#if FOUNDATION_FRAMEWORK +#else @testable import Foundation #endif -final class BufferViewTests: XCTestCase { +@Suite("BufferView") +private struct BufferViewTests { - func testOptionalStorage() { - XCTAssertEqual( - MemoryLayout>.size, MemoryLayout?>.size + @Test func optionalStorage() { + #expect( + MemoryLayout>.size == MemoryLayout?>.size ) - XCTAssertEqual( - MemoryLayout>.stride, MemoryLayout?>.stride + #expect( + MemoryLayout>.stride == MemoryLayout?>.stride ) - XCTAssertEqual( - MemoryLayout>.alignment, MemoryLayout?>.alignment + #expect( + MemoryLayout>.alignment == MemoryLayout?>.alignment ) } - func testInitBufferViewOrdinaryElement() { + @Test func initBufferViewOrdinaryElement() { let capacity = 4 let s = (0..(start: nil, count: 0) @@ -58,17 +55,17 @@ final class BufferViewTests: XCTestCase { a.withUnsafeBytes { let b = BufferView(unsafeRawBufferPointer: $0)! - XCTAssertEqual(b.count, capacity) + #expect(b.count == capacity) let r = BufferView(unsafeRawBufferPointer: $0)! - XCTAssertEqual(r.count, capacity * MemoryLayout.stride) + #expect(r.count == capacity * MemoryLayout.stride) } let v = UnsafeRawBufferPointer(start: nil, count: 0) _ = BufferView(unsafeRawBufferPointer: v) } - func testIndex() { + @Test func index() { let count = 4 let strings = (1...count).map({ "This String is not BitwiseCopyable (\($0))." }) strings.withUnsafeBufferPointer { @@ -76,12 +73,12 @@ final class BufferViewTests: XCTestCase { let first = buffer.startIndex let second = first.advanced(by: 1) - XCTAssertLessThan(first, second) - XCTAssertEqual(1, first.distance(to: second)) + #expect(first < second) + #expect(1 == first.distance(to: second)) } } - func testIteratorOrdinaryElement() { + @Test func iteratorOrdinaryElement() { let capacity = 4 let s = (0...stride + offset var a = Array(repeating: UInt8.zero, count: bytes) - XCTAssertLessThan(offset, MemoryLayout.stride) + #expect(offset < MemoryLayout.stride) a.withUnsafeMutableBytes { for i in 0..<$0.count where i % 8 == offset { @@ -110,7 +107,7 @@ final class BufferViewTests: XCTestCase { } let orig = $0.loadUnaligned(as: Int64.self) - XCTAssertNotEqual(orig, 1) + #expect(orig != 1) // BufferView doesn't need to be aligned for accessing `BitwiseCopyable` types. let buffer = BufferView( @@ -121,14 +118,14 @@ final class BufferViewTests: XCTestCase { var iterator = buffer.makeIterator() var buffered = 0 while let value = iterator.next() { - XCTAssertEqual(value, 1) + #expect(value == 1) buffered += 1 } - XCTAssertEqual(buffered, count) + #expect(buffered == count) } } - func testBufferViewSequence() { + @Test func bufferViewSequence() { let capacity = 4 let a = Array(0...stride let s0 = view.load(as: String.self) - XCTAssertEqual(s0.contains("0"), true) + #expect(s0.contains("0")) let i1 = view.startIndex.advanced(by: stride / 2) let s1 = view.load(from: i1, as: String.self) - XCTAssertEqual(s1.contains("1"), true) + #expect(s1.contains("1")) let s2 = view.load(fromByteOffset: 2 * stride, as: String.self) - XCTAssertEqual(s2.contains("2"), true) + #expect(s2.contains("2")) } } - func testLoadUnaligned() { + @Test func loadUnaligned() { let capacity = 64 let a = Array(0..(unsafeRawBufferPointer: $0)! let u0 = view.dropFirst(1).loadUnaligned(as: UInt64.self) - XCTAssertEqual(u0 & 0xff, 2) - XCTAssertEqual(u0.byteSwapped & 0xff, 9) + #expect(u0 & 0xff == 2) + #expect(u0.byteSwapped & 0xff == 9) let i1 = view.startIndex.advanced(by: 3) let u1 = view.loadUnaligned(from: i1, as: UInt64.self) - XCTAssertEqual(u1 & 0xff, 6) + #expect(u1 & 0xff == 6) let u3 = view.loadUnaligned(fromByteOffset: 7, as: UInt32.self) - XCTAssertEqual(u3 & 0xff, 7) + #expect(u3 & 0xff == 7) } } - func testOffsetSubscript() { + @Test func offsetSubscript() { let capacity = 4 let a = Array(0.. Date: Wed, 11 Jun 2025 13:51:20 -0700 Subject: [PATCH 02/12] Convert BuiltInUnicodeScalarSet tests --- ...ift => BuiltInUnicodeScalarSetTests.swift} | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) rename Tests/FoundationEssentialsTests/{BuiltInUnicodeScalarSetTest.swift => BuiltInUnicodeScalarSetTests.swift} (85%) diff --git a/Tests/FoundationEssentialsTests/BuiltInUnicodeScalarSetTest.swift b/Tests/FoundationEssentialsTests/BuiltInUnicodeScalarSetTests.swift similarity index 85% rename from Tests/FoundationEssentialsTests/BuiltInUnicodeScalarSetTest.swift rename to Tests/FoundationEssentialsTests/BuiltInUnicodeScalarSetTests.swift index 3516d1706..63aee550d 100644 --- a/Tests/FoundationEssentialsTests/BuiltInUnicodeScalarSetTest.swift +++ b/Tests/FoundationEssentialsTests/BuiltInUnicodeScalarSetTests.swift @@ -10,22 +10,20 @@ // //===----------------------------------------------------------------------===// -#if canImport(TestSupport) -import TestSupport -#endif +import Testing -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#else +#if canImport(FoundationEssentials) @testable import FoundationEssentials -#endif // FOUNDATION_FRAMEWORK +#else +@testable import Foundation +#endif -final class BuiltInUnicodeScalarSetTest: XCTestCase { +@Suite("BuiltInUnicodeScalarSet") +private struct BuiltInUnicodeScalarSetTests { - func testMembership() { - func setContainsScalar(_ set: BuiltInUnicodeScalarSet, _ scalar: Unicode.Scalar, _ expect: Bool, file: StaticString = #filePath, line: UInt = #line) { - let actual = set.contains(scalar) - XCTAssertEqual(actual, expect, file: file, line: line) + @Test func membership() { + func setContainsScalar(_ set: BuiltInUnicodeScalarSet, _ scalar: Unicode.Scalar, _ expect: Bool, sourceLocation: SourceLocation = #_sourceLocation) { + #expect(set.contains(scalar) == expect, sourceLocation: sourceLocation) } setContainsScalar(.lowercaseLetters, "a", true) From 19dbba2f5d5cffadaceca3570d0a537038b85f85 Mon Sep 17 00:00:00 2001 From: Jeremy Schonfeld Date: Wed, 11 Jun 2025 14:00:00 -0700 Subject: [PATCH 03/12] Convert ErrorTests --- .../ErrorTests.swift | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/Tests/FoundationEssentialsTests/ErrorTests.swift b/Tests/FoundationEssentialsTests/ErrorTests.swift index f3cc6b3ce..dfce3c2c8 100644 --- a/Tests/FoundationEssentialsTests/ErrorTests.swift +++ b/Tests/FoundationEssentialsTests/ErrorTests.swift @@ -10,32 +10,25 @@ // //===----------------------------------------------------------------------===// -#if canImport(TestSupport) -import TestSupport -#endif +import Testing #if canImport(FoundationEssentials) -@testable import FoundationEssentials +import FoundationEssentials +#elseif FOUNDATION_FRAMEWORK +import Foundation #endif -final class ErrorTests : XCTestCase { +@Suite("Error") +private struct ErrorTests { func thisThrows() throws { throw CocoaError(CocoaError.Code(rawValue: 42), userInfo: ["hi" : "there"]) } - func test_throwCocoaError() { - let code: CocoaError.Code - do { + @Test func throwCocoaError() { + #expect { try thisThrows() - code = .featureUnsupported - } catch { - if let error = error as? CocoaError { - code = error.code - } else { - code = .featureUnsupported - } + } throws: { + ($0 as? CocoaError)?.code.rawValue == 42 } - - XCTAssertEqual(code.rawValue, 42) } } From 55238b47eff29139532b6351e3e0b81142b1cf79 Mon Sep 17 00:00:00 2001 From: Jeremy Schonfeld Date: Wed, 11 Jun 2025 14:00:09 -0700 Subject: [PATCH 04/12] Convert LockedStateTests --- .../LockedStateTests.swift | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/Tests/FoundationEssentialsTests/LockedStateTests.swift b/Tests/FoundationEssentialsTests/LockedStateTests.swift index 3b1d59c89..9eaea70b8 100644 --- a/Tests/FoundationEssentialsTests/LockedStateTests.swift +++ b/Tests/FoundationEssentialsTests/LockedStateTests.swift @@ -10,17 +10,16 @@ // //===----------------------------------------------------------------------===// -#if canImport(TestSupport) -import TestSupport -#endif +import Testing -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#else +#if canImport(FoundationEssentials) @testable import FoundationEssentials +#else +@testable import Foundation #endif -final class LockedStateTests : XCTestCase { +@Suite("LockedState") +private struct LockedStateTests { final class TestObject { var deinitBlock: () -> Void = {} @@ -31,7 +30,7 @@ final class LockedStateTests : XCTestCase { struct TestError: Error {} - func testWithLockDoesNotExtendLifetimeOfState() { + @Test func withLockDoesNotExtendLifetimeOfState() { weak var state: TestObject? let lockedState: LockedState @@ -43,23 +42,23 @@ final class LockedStateTests : XCTestCase { lockedState.withLock { state in weak var oldState = state state = TestObject() - XCTAssertNil(oldState, "State object lifetime was extended after reassignment within body") + #expect(oldState == nil, "State object lifetime was extended after reassignment within body") } - XCTAssertNil(state, "State object lifetime was extended beyond end of call") + #expect(state == nil, "State object lifetime was extended beyond end of call") } - func testWithLockExtendingLifetimeExtendsLifetimeOfStatePastReassignment() { + @Test func withLockExtendingLifetimeExtendsLifetimeOfStatePastReassignment() { let lockedState = LockedState(initialState: TestObject()) lockedState.withLockExtendingLifetimeOfState { state in weak var oldState = state state = TestObject() - XCTAssertNotNil(oldState, "State object lifetime was not extended after reassignment within body") + #expect(oldState != nil, "State object lifetime was not extended after reassignment within body") } } - func testWithLockExtendingLifetimeExtendsLifetimeOfStatePastEndOfLockedScope() { + @Test func withLockExtendingLifetimeExtendsLifetimeOfStatePastEndOfLockedScope() { let lockedState: LockedState = { let state = TestObject() let lockedState = LockedState(initialState: state) @@ -79,7 +78,7 @@ final class LockedStateTests : XCTestCase { } } - func testWithLockExtendingLifetimeDoesNotExtendLifetimeOfStatePastEndOfCall() { + @Test func withLockExtendingLifetimeDoesNotExtendLifetimeOfStatePastEndOfCall() { weak var state: TestObject? let lockedState: LockedState @@ -92,23 +91,22 @@ final class LockedStateTests : XCTestCase { state = TestObject() } - XCTAssertNil(state, "State object lifetime was extended beyond end of call") + #expect(state == nil, "State object lifetime was extended beyond end of call") } - func testWithLockExtendingLifetimeReleasesLockWhenBodyThrows() { + @Test func withLockExtendingLifetimeReleasesLockWhenBodyThrows() { let lockedState = LockedState(initialState: TestObject()) - XCTAssertThrowsError( + #expect(throws: TestError.self, "The body was expected to throw an error, but it did not.") { try lockedState.withLockExtendingLifetimeOfState { _ in throw TestError() - }, - "The body was expected to throw an error, but it did not." - ) + } + } assertLockNotHeld(lockedState, "Lock was not properly released by withLockExtendingLifetimeOfState()") } - func testWithLockExtendingLifespanDoesExtendLifetimeOfState() { + @Test func withLockExtendingLifespanDoesExtendLifetimeOfState() { weak var state: TestObject? let lockedState: LockedState @@ -120,10 +118,10 @@ final class LockedStateTests : XCTestCase { lockedState.withLockExtendingLifetimeOfState { state in weak var oldState = state state = TestObject() - XCTAssertNotNil(oldState, "State object lifetime was not extended after reassignment within body") + #expect(oldState != nil, "State object lifetime was not extended after reassignment within body") } - XCTAssertNil(state, "State object lifetime was extended beyond end of call") + #expect(state == nil, "State object lifetime was extended beyond end of call") } } From c97ac7752bf4e4d3bf221879d309a0e0053e97bf Mon Sep 17 00:00:00 2001 From: Jeremy Schonfeld Date: Wed, 11 Jun 2025 14:07:19 -0700 Subject: [PATCH 05/12] Move aside old XCTest-based equatable/hashable utilities and define new swift-testing utilities --- Sources/TestSupport/Utilities.swift | 291 ++++++++++++++++-- .../DateIntervalTests.swift | 2 +- .../IndexPathTests.swift | 2 +- .../FoundationEssentialsTests/UUIDTests.swift | 2 +- .../CalendarTests.swift | 4 +- 5 files changed, 270 insertions(+), 31 deletions(-) diff --git a/Sources/TestSupport/Utilities.swift b/Sources/TestSupport/Utilities.swift index 3ef31c5b0..3a8cb7587 100644 --- a/Sources/TestSupport/Utilities.swift +++ b/Sources/TestSupport/Utilities.swift @@ -170,7 +170,7 @@ func expectNoChanges(_ check: @autoclosure () -> T, by differe /// /// - Note: `oracle` is also checked for conformance to the /// laws. -public func checkEquatable( +public func XCTCheckEquatable( _ instances: Instances, oracle: (Instances.Index, Instances.Index) -> Bool, allowBrokenTransitivity: Bool = false, @@ -179,7 +179,7 @@ public func checkEquatable( line: UInt = #line ) where Instances.Element: Equatable { let indices = Array(instances.indices) - _checkEquatableImpl( + _XCTCheckEquatableImpl( Array(instances), oracle: { oracle(indices[$0], indices[$1]) }, allowBrokenTransitivity: allowBrokenTransitivity, @@ -188,15 +188,7 @@ public func checkEquatable( line: line) } -private class Box { - var value: T - - init(_ value: T) { - self.value = value - } -} - -internal func _checkEquatableImpl( +internal func _XCTCheckEquatableImpl( _ instances: [Instance], oracle: (Int, Int) -> Bool, allowBrokenTransitivity: Bool = false, @@ -271,23 +263,14 @@ internal func _checkEquatableImpl( } } -func hash(_ value: H, salt: Int? = nil) -> Int { - var hasher = Hasher() - if let salt = salt { - hasher.combine(salt) - } - hasher.combine(value) - return hasher.finalize() -} - -public func checkHashable( +public func XCTCheckHashable( _ instances: Instances, equalityOracle: (Instances.Index, Instances.Index) -> Bool, allowIncompleteHashing: Bool = false, _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line ) where Instances.Element: Hashable { - checkHashable( + XCTCheckHashable( instances, equalityOracle: equalityOracle, hashEqualityOracle: equalityOracle, @@ -298,7 +281,7 @@ public func checkHashable( } -public func checkHashable( +public func XCTCheckHashable( _ instances: Instances, equalityOracle: (Instances.Index, Instances.Index) -> Bool, hashEqualityOracle: (Instances.Index, Instances.Index) -> Bool, @@ -307,7 +290,7 @@ public func checkHashable( file: StaticString = #filePath, line: UInt = #line ) where Instances.Element: Hashable { - checkEquatable( + XCTCheckEquatable( instances, oracle: equalityOracle, message(), @@ -390,7 +373,7 @@ public func checkHashable( /// Test that the elements of `groups` consist of instances that satisfy the /// semantic requirements of `Hashable`, with each group defining a distinct /// equivalence class under `==`. -public func checkHashableGroups( +public func XCTCheckHashableGroups( _ groups: Groups, _ message: @autoclosure () -> String = "", allowIncompleteHashing: Bool = false, @@ -405,7 +388,7 @@ public func checkHashableGroups( func equalityOracle(_ lhs: Int, _ rhs: Int) -> Bool { return groupIndices[lhs] == groupIndices[rhs] } - checkHashable( + XCTCheckHashable( instances, equalityOracle: equalityOracle, hashEqualityOracle: equalityOracle, @@ -477,3 +460,259 @@ func testExpectedToFailWithCheck(check: (String) -> Bool, _ test: @escaping } } +// MARK: - swift-testing Helpers + +import Testing + +/// Test that the elements of `instances` satisfy the semantic +/// requirements of `Equatable`, using `oracle` to generate equality +/// expectations from pairs of positions in `instances`. +/// +/// - Note: `oracle` is also checked for conformance to the +/// laws. +func checkEquatable( + _ instances: Instances, + oracle: (Instances.Index, Instances.Index) -> Bool, + allowBrokenTransitivity: Bool = false, + _ message: @autoclosure () -> String = "", + sourceLocation: SourceLocation = #_sourceLocation +) where Instances.Element: Equatable { + let indices = Array(instances.indices) + _checkEquatable( + instances, + oracle: { oracle(indices[$0], indices[$1]) }, + allowBrokenTransitivity: allowBrokenTransitivity, + message(), + sourceLocation: sourceLocation + ) +} + +func _checkEquatable( + _ _instances: Instances, + oracle: (Int, Int) -> Bool, + allowBrokenTransitivity: Bool = false, + _ message: @autoclosure () -> String = "", + sourceLocation: SourceLocation = #_sourceLocation +) where Instances.Element: Equatable { + let instances = Array(_instances) + + // For each index (which corresponds to an instance being tested) track the + // set of equal instances. + var transitivityScoreboard: [Box>] = + instances.indices.map { _ in Box([]) } + + for i in instances.indices { + let x = instances[i] + #expect(oracle(i, i), "bad oracle: broken reflexivity at index \(i)") + + for j in instances.indices { + let y = instances[j] + + let predictedXY = oracle(i, j) + #expect( + predictedXY == oracle(j, i), + "bad oracle: broken symmetry between indices \(i), \(j)", + sourceLocation: sourceLocation + ) + + let isEqualXY = x == y + #expect( + predictedXY == isEqualXY, + """ + \((predictedXY + ? "expected equal, found not equal" + : "expected not equal, found equal")) + lhs (at index \(i)): \(String(reflecting: x)) + rhs (at index \(j)): \(String(reflecting: y)) + """, + sourceLocation: sourceLocation + ) + + // Not-equal is an inverse of equal. + #expect( + isEqualXY != (x != y), + """ + lhs (at index \(i)): \(String(reflecting: x)) + rhs (at index \(j)): \(String(reflecting: y)) + """, + sourceLocation: sourceLocation + ) + + if !allowBrokenTransitivity { + // Check transitivity of the predicate represented by the oracle. + // If we are adding the instance `j` into an equivalence set, check that + // it is equal to every other instance in the set. + if predictedXY && i < j && transitivityScoreboard[i].value.insert(j).inserted { + if transitivityScoreboard[i].value.count == 1 { + transitivityScoreboard[i].value.insert(i) + } + for k in transitivityScoreboard[i].value { + #expect( + oracle(j, k), + "bad oracle: broken transitivity at indices \(i), \(j), \(k)", + sourceLocation: sourceLocation + ) + // No need to check equality between actual values, we will check + // them with the checks above. + } + precondition(transitivityScoreboard[j].value.isEmpty) + transitivityScoreboard[j] = transitivityScoreboard[i] + } + } + } + } +} + +public func checkHashable( + _ instances: Instances, + equalityOracle: (Instances.Index, Instances.Index) -> Bool, + allowIncompleteHashing: Bool = false, + _ message: @autoclosure () -> String = "", + sourceLocation: SourceLocation = #_sourceLocation +) where Instances.Element: Hashable { + checkHashable( + instances, + equalityOracle: equalityOracle, + hashEqualityOracle: equalityOracle, + allowIncompleteHashing: allowIncompleteHashing, + message(), + sourceLocation: sourceLocation) +} + +func checkHashable( + _ instances: Instances, + equalityOracle: (Instances.Index, Instances.Index) -> Bool, + hashEqualityOracle: (Instances.Index, Instances.Index) -> Bool, + allowIncompleteHashing: Bool = false, + _ message: @autoclosure () -> String = "", + sourceLocation: SourceLocation = #_sourceLocation +) where Instances.Element: Hashable { + checkEquatable( + instances, + oracle: equalityOracle, + message(), + sourceLocation: sourceLocation + ) + + for i in instances.indices { + let x = instances[i] + for j in instances.indices { + let y = instances[j] + let predicted = hashEqualityOracle(i, j) + #expect( + predicted == hashEqualityOracle(j, i), + "bad hash oracle: broken symmetry between indices \(i), \(j)", + sourceLocation: sourceLocation + ) + if x == y { + #expect( + predicted, + """ + bad hash oracle: equality must imply hash equality + lhs (at index \(i)): \(x) + rhs (at index \(j)): \(y) + """, + sourceLocation: sourceLocation + ) + } + if predicted { + #expect( + hash(x) == hash(y), + """ + hash(into:) expected to match, found to differ + lhs (at index \(i)): \(x) + rhs (at index \(j)): \(y) + """, + sourceLocation: sourceLocation + ) + #expect( + x.hashValue == y.hashValue, + """ + hashValue expected to match, found to differ + lhs (at index \(i)): \(x) + rhs (at index \(j)): \(y) + """, + sourceLocation: sourceLocation + ) + #expect( + x._rawHashValue(seed: 0) == y._rawHashValue(seed: 0), + """ + _rawHashValue(seed:) expected to match, found to differ + lhs (at index \(i)): \(x) + rhs (at index \(j)): \(y) + """, + sourceLocation: sourceLocation + ) + } else if !allowIncompleteHashing { + // Try a few different seeds; at least one of them should discriminate + // between the hashes. It is extremely unlikely this check will fail + // all ten attempts, unless the type's hash encoding is not unique, + // or unless the hash equality oracle is wrong. + #expect( + (0..<10).contains { hash(x, salt: $0) != hash(y, salt: $0) }, + """ + hash(into:) expected to differ, found to match + lhs (at index \(i)): \(x) + rhs (at index \(j)): \(y) + """, + sourceLocation: sourceLocation + ) + #expect( + (0..<10).contains { i in + x._rawHashValue(seed: i) != y._rawHashValue(seed: i) + }, + """ + _rawHashValue(seed:) expected to differ, found to match + lhs (at index \(i)): \(x) + rhs (at index \(j)): \(y) + """, + sourceLocation: sourceLocation + ) + } + } + } +} + +/// Test that the elements of `groups` consist of instances that satisfy the +/// semantic requirements of `Hashable`, with each group defining a distinct +/// equivalence class under `==`. +public func checkHashableGroups( + _ groups: Groups, + _ message: @autoclosure () -> String = "", + allowIncompleteHashing: Bool = false, + sourceLocation: SourceLocation = #_sourceLocation +) where Groups.Element: Collection, Groups.Element.Element: Hashable { + let instances = groups.flatMap { $0 } + // groupIndices[i] is the index of the element in groups that contains + // instances[i]. + let groupIndices = + zip(0..., groups).flatMap { i, group in group.map { _ in i } } + func equalityOracle(_ lhs: Int, _ rhs: Int) -> Bool { + return groupIndices[lhs] == groupIndices[rhs] + } + checkHashable( + instances, + equalityOracle: equalityOracle, + hashEqualityOracle: equalityOracle, + allowIncompleteHashing: allowIncompleteHashing, + sourceLocation: sourceLocation) +} + +// MARK: - Private Types + +private class Box { + var value: T + + init(_ value: T) { + self.value = value + } +} + +private func hash(_ value: H, salt: Int? = nil) -> Int { + var hasher = Hasher() + if let salt = salt { + hasher.combine(salt) + } + hasher.combine(value) + return hasher.finalize() +} diff --git a/Tests/FoundationEssentialsTests/DateIntervalTests.swift b/Tests/FoundationEssentialsTests/DateIntervalTests.swift index 95d7773cd..25dd11351 100644 --- a/Tests/FoundationEssentialsTests/DateIntervalTests.swift +++ b/Tests/FoundationEssentialsTests/DateIntervalTests.swift @@ -77,7 +77,7 @@ final class DateIntervalTests : XCTestCase { DateInterval(start: start2b, duration: duration2), ], ] - checkHashableGroups(intervals) + XCTCheckHashableGroups(intervals) } func test_checkIntersection() { diff --git a/Tests/FoundationEssentialsTests/IndexPathTests.swift b/Tests/FoundationEssentialsTests/IndexPathTests.swift index 86e9e825a..365e2ddfd 100644 --- a/Tests/FoundationEssentialsTests/IndexPathTests.swift +++ b/Tests/FoundationEssentialsTests/IndexPathTests.swift @@ -239,7 +239,7 @@ class TestIndexPath: XCTestCase { [1, 1, 2], [Int.max, Int.max, Int.max], ] - checkHashable(samples, equalityOracle: { $0 == $1 }) + XCTCheckHashable(samples, equalityOracle: { $0 == $1 }) // this should not cause an overflow crash _ = IndexPath(indexes: [Int.max >> 8, 2, Int.max >> 36]).hashValue diff --git a/Tests/FoundationEssentialsTests/UUIDTests.swift b/Tests/FoundationEssentialsTests/UUIDTests.swift index a21707f55..873a8d7e6 100644 --- a/Tests/FoundationEssentialsTests/UUIDTests.swift +++ b/Tests/FoundationEssentialsTests/UUIDTests.swift @@ -67,7 +67,7 @@ final class UUIDTests : XCTestCase { UUID(uuidString: "a53baa1c-b4f5-48db-9467-9786b76b266c")!, UUID(uuidString: "a53baa1c-b4f5-48db-9467-9786b76b256d")!, ] - checkHashable(values, equalityOracle: { $0 == $1 }) + XCTCheckHashable(values, equalityOracle: { $0 == $1 }) } func test_AnyHashableContainingUUID() { diff --git a/Tests/FoundationInternationalizationTests/CalendarTests.swift b/Tests/FoundationInternationalizationTests/CalendarTests.swift index b04456ec6..19df971e5 100644 --- a/Tests/FoundationInternationalizationTests/CalendarTests.swift +++ b/Tests/FoundationInternationalizationTests/CalendarTests.swift @@ -161,7 +161,7 @@ final class CalendarTests : XCTestCase { Calendar(identifier: .islamic), Calendar(identifier: .iso8601), ] - checkHashable(calendars, equalityOracle: { $0 == $1 }) + XCTCheckHashable(calendars, equalityOracle: { $0 == $1 }) // autoupdating calendar isn't equal to the current, even though it's // likely to be the same. @@ -169,7 +169,7 @@ final class CalendarTests : XCTestCase { Calendar.autoupdatingCurrent, Calendar.current, ] - checkHashable(calendars2, equalityOracle: { $0 == $1 }) + XCTCheckHashable(calendars2, equalityOracle: { $0 == $1 }) } func test_AnyHashableContainingCalendar() { From f3dceef9151162292b00eeddbcf5aa1ad06318e7 Mon Sep 17 00:00:00 2001 From: Jeremy Schonfeld Date: Wed, 11 Jun 2025 14:13:05 -0700 Subject: [PATCH 06/12] Convert UUID tests --- .../FoundationEssentialsTests/UUIDTests.swift | 102 ++++++++++-------- 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/Tests/FoundationEssentialsTests/UUIDTests.swift b/Tests/FoundationEssentialsTests/UUIDTests.swift index 873a8d7e6..22ad824ce 100644 --- a/Tests/FoundationEssentialsTests/UUIDTests.swift +++ b/Tests/FoundationEssentialsTests/UUIDTests.swift @@ -10,42 +10,51 @@ // //===----------------------------------------------------------------------===// +import Testing + +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif FOUNDATION_FRAMEWORK +import Foundation +#endif + #if canImport(TestSupport) import TestSupport #endif -final class UUIDTests : XCTestCase { - func test_UUIDEquality() { +@Suite("UUID") +private struct UUIDTests { + @Test func equality() { let uuidA = UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F") let uuidB = UUID(uuidString: "e621e1f8-c36c-495a-93fc-0c247a3e6e5f") let uuidC = UUID(uuid: (0xe6,0x21,0xe1,0xf8,0xc3,0x6c,0x49,0x5a,0x93,0xfc,0x0c,0x24,0x7a,0x3e,0x6e,0x5f)) let uuidD = UUID() - XCTAssertEqual(uuidA, uuidB, "String case must not matter.") - XCTAssertEqual(uuidA, uuidC, "A UUID initialized with a string must be equal to the same UUID initialized with its UnsafePointer equivalent representation.") - XCTAssertNotEqual(uuidC, uuidD, "Two different UUIDs must not be equal.") + #expect(uuidA == uuidB, "String case must not matter.") + #expect(uuidA == uuidC, "A UUID initialized with a string must be equal to the same UUID initialized with its UnsafePointer equivalent representation.") + #expect(uuidC != uuidD, "Two different UUIDs must not be equal.") } - func test_UUIDInvalid() { + @Test func invalidString() { let invalid = UUID(uuidString: "Invalid UUID") - XCTAssertNil(invalid, "The convenience initializer `init?(uuidString string:)` must return nil for an invalid UUID string.") + #expect(invalid == nil, "The convenience initializer `init?(uuidString string:)` must return nil for an invalid UUID string.") } // `uuidString` should return an uppercase string // See: https://bugs.swift.org/browse/SR-865 - func test_UUIDuuidString() { + @Test func uuidString() { let uuid = UUID(uuid: (0xe6,0x21,0xe1,0xf8,0xc3,0x6c,0x49,0x5a,0x93,0xfc,0x0c,0x24,0x7a,0x3e,0x6e,0x5f)) - XCTAssertEqual(uuid.uuidString, "E621E1F8-C36C-495A-93FC-0C247A3E6E5F", "The uuidString representation must be uppercase.") + #expect(uuid.uuidString == "E621E1F8-C36C-495A-93FC-0C247A3E6E5F", "The uuidString representation must be uppercase.") } - func test_UUIDdescription() { + @Test func description() { let uuid = UUID() let description: String = uuid.description let uuidString: String = uuid.uuidString - XCTAssertEqual(description, uuidString, "The description must be the same as the uuidString.") + #expect(description == uuidString, "The description must be the same as the uuidString.") } - func test_hash() { + @Test func hash() { let values: [UUID] = [ // This list takes a UUID and tweaks every byte while // leaving the version/variant intact. @@ -67,52 +76,53 @@ final class UUIDTests : XCTestCase { UUID(uuidString: "a53baa1c-b4f5-48db-9467-9786b76b266c")!, UUID(uuidString: "a53baa1c-b4f5-48db-9467-9786b76b256d")!, ] - XCTCheckHashable(values, equalityOracle: { $0 == $1 }) + checkHashable(values, equalityOracle: { $0 == $1 }) } - func test_AnyHashableContainingUUID() { + @Test func anyHashableContainingUUID() { let values: [UUID] = [ UUID(uuidString: "e621e1f8-c36c-495a-93fc-0c247a3e6e5f")!, UUID(uuidString: "f81d4fae-7dec-11d0-a765-00a0c91e6bf6")!, UUID(uuidString: "f81d4fae-7dec-11d0-a765-00a0c91e6bf6")!, ] let anyHashables = values.map(AnyHashable.init) - expectEqual(UUID.self, type(of: anyHashables[0].base)) - expectEqual(UUID.self, type(of: anyHashables[1].base)) - expectEqual(UUID.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) + #expect(UUID.self == type(of: anyHashables[0].base)) + #expect(UUID.self == type(of: anyHashables[1].base)) + #expect(UUID.self == type(of: anyHashables[2].base)) + #expect(anyHashables[0] != anyHashables[1]) + #expect(anyHashables[1] == anyHashables[2]) } // rdar://71190003 (UUID has no customMirror) - func test_UUID_custom_mirror() { - let uuid = UUID(uuidString: "89E90DC6-5EBA-41A8-A64D-81D3576EE46E")! - XCTAssertEqual(String(reflecting: uuid), "89E90DC6-5EBA-41A8-A64D-81D3576EE46E") + @Test func customMirror() throws { + let uuid = try #require(UUID(uuidString: "89E90DC6-5EBA-41A8-A64D-81D3576EE46E")) + #expect(String(reflecting: uuid) == "89E90DC6-5EBA-41A8-A64D-81D3576EE46E") } - func test_UUID_Comparable() throws { - var uuid1 = try XCTUnwrap(UUID(uuidString: "00000000-0000-0000-0000-000000000001")) - var uuid2 = try XCTUnwrap(UUID(uuidString: "00000000-0000-0000-0000-000000000002")) - XCTAssertTrue(uuid1 < uuid2) - XCTAssertFalse(uuid2 < uuid1) - XCTAssertFalse(uuid2 == uuid1) - - uuid1 = try XCTUnwrap(UUID(uuidString: "9707CE8D-251F-4858-8BF9-C9EC3D690FCE")) - uuid2 = try XCTUnwrap(UUID(uuidString: "9807CE8D-251F-4858-8BF9-C9EC3D690FCE")) - XCTAssertTrue(uuid1 < uuid2) - XCTAssertFalse(uuid2 < uuid1) - XCTAssertFalse(uuid2 == uuid1) - - uuid1 = try XCTUnwrap(UUID(uuidString: "9707CE8D-261F-4858-8BF9-C9EC3D690FCE")) - uuid2 = try XCTUnwrap(UUID(uuidString: "9707CE8D-251F-4858-8BF9-C9EC3D690FCE")) - XCTAssertTrue(uuid1 > uuid2) - XCTAssertFalse(uuid2 > uuid1) - XCTAssertFalse(uuid2 == uuid1) - - uuid1 = try XCTUnwrap(UUID(uuidString: "9707CE8D-251F-4858-8BF9-C9EC3D690FCE")) - uuid2 = try XCTUnwrap(UUID(uuidString: "9707CE8D-251F-4858-8BF9-C9EC3D690FCE")) - XCTAssertFalse(uuid1 > uuid2) - XCTAssertFalse(uuid2 > uuid1) - XCTAssertTrue(uuid2 == uuid1) + @available(FoundationPreview 0.1, *) + @Test func comparable() throws { + var uuid1 = try #require(UUID(uuidString: "00000000-0000-0000-0000-000000000001")) + var uuid2 = try #require(UUID(uuidString: "00000000-0000-0000-0000-000000000002")) + #expect(uuid1 < uuid2) + #expect(uuid2 >= uuid1) + #expect(uuid2 != uuid1) + + uuid1 = try #require(UUID(uuidString: "9707CE8D-251F-4858-8BF9-C9EC3D690FCE")) + uuid2 = try #require(UUID(uuidString: "9807CE8D-251F-4858-8BF9-C9EC3D690FCE")) + #expect(uuid1 < uuid2) + #expect(uuid2 >= uuid1) + #expect(uuid2 != uuid1) + + uuid1 = try #require(UUID(uuidString: "9707CE8D-261F-4858-8BF9-C9EC3D690FCE")) + uuid2 = try #require(UUID(uuidString: "9707CE8D-251F-4858-8BF9-C9EC3D690FCE")) + #expect(uuid1 > uuid2) + #expect(uuid2 <= uuid1) + #expect(uuid2 != uuid1) + + uuid1 = try #require(UUID(uuidString: "9707CE8D-251F-4858-8BF9-C9EC3D690FCE")) + uuid2 = try #require(UUID(uuidString: "9707CE8D-251F-4858-8BF9-C9EC3D690FCE")) + #expect(uuid1 <= uuid2) + #expect(uuid2 <= uuid1) + #expect(uuid2 == uuid1) } } From 89d01594868d248ff0f4f06d30e5b91fd9da1664 Mon Sep 17 00:00:00 2001 From: Jeremy Schonfeld Date: Wed, 11 Jun 2025 14:26:32 -0700 Subject: [PATCH 07/12] Convert DateInterval tests --- .../DateIntervalTests.swift | 88 ++++++++++--------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/Tests/FoundationEssentialsTests/DateIntervalTests.swift b/Tests/FoundationEssentialsTests/DateIntervalTests.swift index 25dd11351..92fbadb1a 100644 --- a/Tests/FoundationEssentialsTests/DateIntervalTests.swift +++ b/Tests/FoundationEssentialsTests/DateIntervalTests.swift @@ -5,53 +5,58 @@ // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// -// -// RUN: %target-run-simple-swift -// REQUIRES: executable_test -// REQUIRES: objc_interop + +import Testing #if canImport(TestSupport) import TestSupport #endif -final class DateIntervalTests : XCTestCase { +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif FOUNDATION_FRAMEWORK +import Foundation +#endif + +@Suite("DateInterval") +private struct DateIntervalTests { - func test_compareDateIntervals() { + @Test func compareDateIntervals() { // dateWithString("2010-05-17 14:49:47 -0700") let start = Date(timeIntervalSinceReferenceDate: 295825787.0) let duration: TimeInterval = 10000000.0 let testInterval1 = DateInterval(start: start, duration: duration) let testInterval2 = DateInterval(start: start, duration: duration) - XCTAssertEqual(testInterval1, testInterval2) - XCTAssertEqual(testInterval2, testInterval1) - XCTAssertEqual(testInterval1.compare(testInterval2), ComparisonResult.orderedSame) + #expect(testInterval1 == testInterval2) + #expect(testInterval2 == testInterval1) + #expect(testInterval1.compare(testInterval2) == .orderedSame) let testInterval3 = DateInterval(start: start, duration: 10000000000.0) - XCTAssertTrue(testInterval1 < testInterval3) - XCTAssertTrue(testInterval3 > testInterval1) + #expect(testInterval1 < testInterval3) + #expect(testInterval3 > testInterval1) // dateWithString("2009-05-17 14:49:47 -0700") let earlierStart = Date(timeIntervalSinceReferenceDate: 264289787.0) let testInterval4 = DateInterval(start: earlierStart, duration: duration) - XCTAssertTrue(testInterval4 < testInterval1) - XCTAssertTrue(testInterval1 > testInterval4) + #expect(testInterval4 < testInterval1) + #expect(testInterval1 > testInterval4) } - func test_isEqualToDateInterval() { + @Test func isEqualToDateInterval() { // dateWithString("2010-05-17 14:49:47 -0700") let start = Date(timeIntervalSinceReferenceDate: 295825787.0) let duration = 10000000.0 let testInterval1 = DateInterval(start: start, duration: duration) let testInterval2 = DateInterval(start: start, duration: duration) - XCTAssertEqual(testInterval1, testInterval2) + #expect(testInterval1 == testInterval2) let testInterval3 = DateInterval(start: start, duration: 100.0) - XCTAssertNotEqual(testInterval1, testInterval3) + #expect(testInterval1 != testInterval3) } - func test_hashing() { + @Test func hashing() { // dateWithString("2019-04-04 17:09:23 -0700") let start1a = Date(timeIntervalSinceReferenceDate: 576115763.0) let start1b = Date(timeIntervalSinceReferenceDate: 576115763.0) @@ -77,10 +82,10 @@ final class DateIntervalTests : XCTestCase { DateInterval(start: start2b, duration: duration2), ], ] - XCTCheckHashableGroups(intervals) + checkHashableGroups(intervals) } - func test_checkIntersection() { + @Test func checkIntersection() { // dateWithString("2010-05-17 14:49:47 -0700") let start1 = Date(timeIntervalSinceReferenceDate: 295825787.0) // dateWithString("2010-08-17 14:49:47 -0700") @@ -95,7 +100,7 @@ final class DateIntervalTests : XCTestCase { let testInterval2 = DateInterval(start: start2, end: end2) - XCTAssertTrue(testInterval1.intersects(testInterval2)) + #expect(testInterval1.intersects(testInterval2)) // dateWithString("2010-10-17 14:49:47 -0700") let start3 = Date(timeIntervalSinceReferenceDate: 309044987.0) @@ -104,10 +109,10 @@ final class DateIntervalTests : XCTestCase { let testInterval3 = DateInterval(start: start3, end: end3) - XCTAssertFalse(testInterval1.intersects(testInterval3)) + #expect(!testInterval1.intersects(testInterval3)) } - func test_validIntersections() { + @Test func validIntersections() { // dateWithString("2010-05-17 14:49:47 -0700") let start1 = Date(timeIntervalSinceReferenceDate: 295825787.0) // dateWithString("2010-08-17 14:49:47 -0700") @@ -130,15 +135,13 @@ final class DateIntervalTests : XCTestCase { let testInterval3 = DateInterval(start: start3, end: end3) let intersection1 = testInterval2.intersection(with: testInterval1) - XCTAssertNotNil(intersection1) - XCTAssertEqual(testInterval3, intersection1) + #expect(testInterval3 == intersection1) let intersection2 = testInterval1.intersection(with: testInterval2) - XCTAssertNotNil(intersection2) - XCTAssertEqual(intersection1, intersection2) + #expect(intersection1 == intersection2) } - func test_containsDate() { + @Test func containsDate() { // dateWithString("2010-05-17 14:49:47 -0700") let start = Date(timeIntervalSinceReferenceDate: 295825787.0) let duration = 10000000.0 @@ -147,14 +150,14 @@ final class DateIntervalTests : XCTestCase { // dateWithString("2010-05-17 20:49:47 -0700") let containedDate = Date(timeIntervalSinceReferenceDate: 295847387.0) - XCTAssertTrue(testInterval.contains(containedDate)) + #expect(testInterval.contains(containedDate)) // dateWithString("2009-05-17 14:49:47 -0700") let earlierStart = Date(timeIntervalSinceReferenceDate: 264289787.0) - XCTAssertFalse(testInterval.contains(earlierStart)) + #expect(!testInterval.contains(earlierStart)) } - func test_AnyHashableContainingDateInterval() { + @Test func anyHashableContainingDateInterval() { // dateWithString("2010-05-17 14:49:47 -0700") let start = Date(timeIntervalSinceReferenceDate: 295825787.0) let duration = 10000000.0 @@ -164,18 +167,19 @@ final class DateIntervalTests : XCTestCase { DateInterval(start: start, duration: duration / 2), ] let anyHashables = values.map(AnyHashable.init) - expectEqual(DateInterval.self, type(of: anyHashables[0].base)) - expectEqual(DateInterval.self, type(of: anyHashables[1].base)) - expectEqual(DateInterval.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) + #expect(DateInterval.self == type(of: anyHashables[0].base)) + #expect(DateInterval.self == type(of: anyHashables[1].base)) + #expect(DateInterval.self == type(of: anyHashables[2].base)) + #expect(anyHashables[0] != anyHashables[1]) + #expect(anyHashables[1] == anyHashables[2]) } } // MARK: - Bridging Tests #if FOUNDATION_FRAMEWORK -extension DateIntervalTests { - func test_AnyHashableCreatedFromNSDateInterval() { +@Suite("DateInterval Bridging") +private struct DateIntervalBridgingTests { + @Test func anyHashableCreatedFromNSDateInterval() { // dateWithString("2010-05-17 14:49:47 -0700") let start = Date(timeIntervalSinceReferenceDate: 295825787.0) let duration = 10000000.0 @@ -185,11 +189,11 @@ extension DateIntervalTests { NSDateInterval(start: start, duration: duration / 2), ] let anyHashables = values.map(AnyHashable.init) - expectEqual(DateInterval.self, type(of: anyHashables[0].base)) - expectEqual(DateInterval.self, type(of: anyHashables[1].base)) - expectEqual(DateInterval.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) + #expect(DateInterval.self == type(of: anyHashables[0].base)) + #expect(DateInterval.self == type(of: anyHashables[1].base)) + #expect(DateInterval.self == type(of: anyHashables[2].base)) + #expect(anyHashables[0] != anyHashables[1]) + #expect(anyHashables[1] == anyHashables[2]) } } #endif From 4726a867650c5caa5f553e962857a1924c2c1310 Mon Sep 17 00:00:00 2001 From: Jeremy Schonfeld Date: Wed, 11 Jun 2025 14:26:44 -0700 Subject: [PATCH 08/12] Convert date tests --- .../FoundationEssentialsTests/DateTests.swift | 140 +++++++++--------- 1 file changed, 72 insertions(+), 68 deletions(-) diff --git a/Tests/FoundationEssentialsTests/DateTests.swift b/Tests/FoundationEssentialsTests/DateTests.swift index 9558f580f..c28cf4fdf 100644 --- a/Tests/FoundationEssentialsTests/DateTests.swift +++ b/Tests/FoundationEssentialsTests/DateTests.swift @@ -10,154 +10,158 @@ // //===----------------------------------------------------------------------===// -#if canImport(TestSupport) -import TestSupport -#endif +import Testing #if canImport(FoundationEssentials) -@testable import FoundationEssentials +import FoundationEssentials +#elseif FOUNDATION_FRAMEWORK +import Foundation #endif -final class DateTests : XCTestCase { +@Suite("Date") +private struct DateTests { - func testDateComparison() { + @Test func comparison() { let d1 = Date() let d2 = d1 + 1 - XCTAssertGreaterThan(d2, d1) - XCTAssertLessThan(d1, d2) + #expect(d2 > d1) + #expect(d1 < d2) let d3 = Date(timeIntervalSince1970: 12345) let d4 = Date(timeIntervalSince1970: 12345) - XCTAssertEqual(d3, d4) - XCTAssertLessThanOrEqual(d3, d4) - XCTAssertGreaterThanOrEqual(d4, d3) + #expect(d3 == d4) + #expect(d3 <= d4) + #expect(d4 >= d3) } - func testDateMutation() { + @Test func mutation() { let d0 = Date() var d1 = Date() d1 = d1 + 1.0 let d2 = Date(timeIntervalSinceNow: 10) - XCTAssertGreaterThan(d2, d1) - XCTAssertNotEqual(d1, d0) + #expect(d2 > d1) + #expect(d1 != d0) let d3 = d1 d1 += 10 - XCTAssertGreaterThan(d1, d3) + #expect(d1 > d3) } - func testDistantPast() { + @Test func distantPast() { let distantPast = Date.distantPast let currentDate = Date() - XCTAssertLessThan(distantPast, currentDate) - XCTAssertGreaterThan(currentDate, distantPast) - XCTAssertLessThan(distantPast.timeIntervalSince(currentDate), + #expect(distantPast < currentDate) + #expect(currentDate > distantPast) + #expect(distantPast.timeIntervalSince(currentDate) < 3600.0 * 24 * 365 * 100) /* ~1 century in seconds */ } - func testDistantFuture() { + @Test func distantFuture() { let distantFuture = Date.distantFuture let currentDate = Date() - XCTAssertLessThan(currentDate, distantFuture) - XCTAssertGreaterThan(distantFuture, currentDate) - XCTAssertGreaterThan(distantFuture.timeIntervalSince(currentDate), + #expect(currentDate < distantFuture) + #expect(distantFuture > currentDate) + #expect(distantFuture.timeIntervalSince(currentDate) > 3600.0 * 24 * 365 * 100) /* ~1 century in seconds */ } - func test_now() { + @Test func now() { let date1 : Date = .now let date2 : Date = .now - XCTAssertLessThanOrEqual(date1, date2) + #expect(date1 <= date2) } - func testDescriptionReferenceDate() { + @Test func descriptionReferenceDate() { let date = Date(timeIntervalSinceReferenceDate: TimeInterval(0)) - XCTAssertEqual("2001-01-01 00:00:00 +0000", date.description) + #expect("2001-01-01 00:00:00 +0000" == date.description) } - func testDescription1970() { + @Test func description1970() { let date = Date(timeIntervalSince1970: TimeInterval(0)) - XCTAssertEqual("1970-01-01 00:00:00 +0000", date.description) + #expect("1970-01-01 00:00:00 +0000" == date.description) } - func testDescriptionDistantPast() throws { -#if os(Windows) - throw XCTSkip("ucrt does not support distant past") -#else + #if os(Windows) + @Test(.disabled("ucrt does not support distant past")) + #else + @Test + #endif + func descriptionDistantPast() throws { #if FOUNDATION_FRAMEWORK - XCTAssertEqual("0001-01-01 00:00:00 +0000", Date.distantPast.description) + #expect("0001-01-01 00:00:00 +0000" == Date.distantPast.description) #else - XCTAssertEqual("0000-12-30 00:00:00 +0000", Date.distantPast.description) -#endif + #expect("0000-12-30 00:00:00 +0000" == Date.distantPast.description) #endif } - func testDescriptionDistantFuture() throws { -#if os(Windows) - throw XCTSkip("ucrt does not support distant future") -#else - XCTAssertEqual("4001-01-01 00:00:00 +0000", Date.distantFuture.description) -#endif + #if os(Windows) + @Test(.disabled("ucrt does not support distant past")) + #else + @Test + #endif + func descriptionDistantFuture() throws { + #expect("4001-01-01 00:00:00 +0000" == Date.distantFuture.description) } - func testDescriptionBeyondDistantPast() { + @Test func descriptionBeyondDistantPast() { let date = Date.distantPast.addingTimeInterval(TimeInterval(-1)) #if FOUNDATION_FRAMEWORK - XCTAssertEqual("0000-12-31 23:59:59 +0000", date.description) + #expect("0000-12-31 23:59:59 +0000" == date.description) #else - XCTAssertEqual("", date.description) + #expect("" == date.description) #endif } - func testDescriptionBeyondDistantFuture() { + @Test func descriptionBeyondDistantFuture() { let date = Date.distantFuture.addingTimeInterval(TimeInterval(1)) #if FOUNDATION_FRAMEWORK - XCTAssertEqual("4001-01-01 00:00:01 +0000", date.description) + #expect("4001-01-01 00:00:01 +0000" == date.description) #else - XCTAssertEqual("", date.description) + #expect("" == date.description) #endif } - func testNowIsAfterReasonableDate() { + @Test func nowIsAfterReasonableDate() { let date = Date.now - XCTAssert(date.timeIntervalSinceReferenceDate > 742100000.0) // "2024-07-08T02:53:20Z" - XCTAssert(date.timeIntervalSinceReferenceDate < 3896300000.0) // "2124-06-21T01:33:20Z" + #expect(date.timeIntervalSinceReferenceDate > 742100000.0) // "2024-07-08T02:53:20Z" + #expect(date.timeIntervalSinceReferenceDate < 3896300000.0) // "2124-06-21T01:33:20Z" } } // MARK: - Bridging #if FOUNDATION_FRAMEWORK -final class DateBridgingTests : XCTestCase { - func testCast() { +@Suite("Date Bridging") +private struct DateBridgingTests { + @Test func cast() { let d0 = NSDate() let d1 = d0 as Date - XCTAssertEqual(d0.timeIntervalSinceReferenceDate, d1.timeIntervalSinceReferenceDate) + #expect(d0.timeIntervalSinceReferenceDate == d1.timeIntervalSinceReferenceDate) } - func test_AnyHashableCreatedFromNSDate() { + @Test func anyHashableCreatedFromNSDate() { let values: [NSDate] = [ NSDate(timeIntervalSince1970: 1000000000), NSDate(timeIntervalSince1970: 1000000001), NSDate(timeIntervalSince1970: 1000000001), ] let anyHashables = values.map(AnyHashable.init) - expectEqual(Date.self, type(of: anyHashables[0].base)) - expectEqual(Date.self, type(of: anyHashables[1].base)) - expectEqual(Date.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) + #expect(Date.self == type(of: anyHashables[0].base)) + #expect(Date.self == type(of: anyHashables[1].base)) + #expect(Date.self == type(of: anyHashables[2].base)) + #expect(anyHashables[0] != anyHashables[1]) + #expect(anyHashables[1] == anyHashables[2]) } - func test_AnyHashableCreatedFromNSDateComponents() { + @Test func anyHashableCreatedFromNSDateComponents() { func makeNSDateComponents(year: Int) -> NSDateComponents { let result = NSDateComponents() result.year = year @@ -169,15 +173,15 @@ final class DateBridgingTests : XCTestCase { makeNSDateComponents(year: 1995), ] let anyHashables = values.map(AnyHashable.init) - expectEqual(DateComponents.self, type(of: anyHashables[0].base)) - expectEqual(DateComponents.self, type(of: anyHashables[1].base)) - expectEqual(DateComponents.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) + #expect(DateComponents.self == type(of: anyHashables[0].base)) + #expect(DateComponents.self == type(of: anyHashables[1].base)) + #expect(DateComponents.self == type(of: anyHashables[2].base)) + #expect(anyHashables[0] != anyHashables[1]) + #expect(anyHashables[1] == anyHashables[2]) } - func test_dateComponents_unconditionallyBridgeFromObjectiveC() { - XCTAssertEqual(DateComponents(), DateComponents._unconditionallyBridgeFromObjectiveC(nil)) + @Test func dateComponents_unconditionallyBridgeFromObjectiveC() { + #expect(DateComponents() == DateComponents._unconditionallyBridgeFromObjectiveC(nil)) } } #endif // FOUNDATION_FRAMEWORK From e0dfddce49455f45e92dff73dabcf2f50632408a Mon Sep 17 00:00:00 2001 From: Jeremy Schonfeld Date: Wed, 11 Jun 2025 14:34:00 -0700 Subject: [PATCH 09/12] Convert SortComparator tests --- .../SortComparatorTests.swift | 60 ++++++++----------- .../StringSortComparatorTests.swift | 47 ++++++++------- 2 files changed, 51 insertions(+), 56 deletions(-) diff --git a/Tests/FoundationEssentialsTests/SortComparatorTests.swift b/Tests/FoundationEssentialsTests/SortComparatorTests.swift index 36f2206bb..935f77c57 100644 --- a/Tests/FoundationEssentialsTests/SortComparatorTests.swift +++ b/Tests/FoundationEssentialsTests/SortComparatorTests.swift @@ -10,56 +10,46 @@ // //===----------------------------------------------------------------------===// -#if canImport(TestSupport) -import TestSupport -#endif -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#else +import Testing + +#if canImport(FoundationEssentials) @testable import FoundationEssentials -#endif // FOUNDATION_FRAMEWORK +#else +@testable import Foundation +#endif -class SortComparatorTests: XCTestCase { - func test_comparable_descriptors() { +@Suite("SortComparator") +private struct SortComparatorTests { + @Test func comparableDescriptors() { let intDesc: ComparableComparator = ComparableComparator() - XCTAssertEqual(intDesc.compare(0, 1), .orderedAscending) + #expect(intDesc.compare(0, 1) == .orderedAscending) let result = intDesc.compare(1000, -10) - XCTAssertEqual(result, .orderedDescending) + #expect(result == .orderedDescending) } - func test_order() { + @Test func order() { var intDesc: ComparableComparator = ComparableComparator(order: .reverse) - XCTAssertEqual(intDesc.compare(0, 1), .orderedDescending) - XCTAssertEqual(intDesc.compare(1000, -10), .orderedAscending) - XCTAssertEqual(intDesc.compare(100, 100), .orderedSame) + #expect(intDesc.compare(0, 1) == .orderedDescending) + #expect(intDesc.compare(1000, -10) == .orderedAscending) + #expect(intDesc.compare(100, 100) == .orderedSame) intDesc.order = .forward - XCTAssertEqual(intDesc.compare(0, 1), .orderedAscending) - XCTAssertEqual(intDesc.compare(1000, -10), .orderedDescending) - XCTAssertEqual(intDesc.compare(100, 100), .orderedSame) - } - - func test_compare_options_descriptor() { - let compareOptions = String.Comparator(options: [.numeric]) - XCTAssertEqual( - compareOptions.compare("ttestest005", "test2"), - "test005".compare("test2", options: [.numeric])) - XCTAssertEqual( - compareOptions.compare("test2", "test005"), - "test2".compare("test005", options: [.numeric])) + #expect(intDesc.compare(0, 1) == .orderedAscending) + #expect(intDesc.compare(1000, -10) == .orderedDescending) + #expect(intDesc.compare(100, 100) == .orderedSame) } - func testAnySortComparatorEquality() { + @Test func anySortComparatorEquality() { let a: ComparableComparator = ComparableComparator() let b: ComparableComparator = ComparableComparator(order: .reverse) let c: ComparableComparator = ComparableComparator() - XCTAssertEqual(AnySortComparator(a), AnySortComparator(a)) - XCTAssertEqual(AnySortComparator(b), AnySortComparator(b)) - XCTAssertEqual(AnySortComparator(c), AnySortComparator(c)) - XCTAssertNotEqual(AnySortComparator(a), AnySortComparator(b)) - XCTAssertNotEqual(AnySortComparator(b), AnySortComparator(c)) - XCTAssertNotEqual(AnySortComparator(a), AnySortComparator(c)) + #expect(AnySortComparator(a) == AnySortComparator(a)) + #expect(AnySortComparator(b) == AnySortComparator(b)) + #expect(AnySortComparator(c) == AnySortComparator(c)) + #expect(AnySortComparator(a) != AnySortComparator(b)) + #expect(AnySortComparator(b) != AnySortComparator(c)) + #expect(AnySortComparator(a) != AnySortComparator(c)) } } diff --git a/Tests/FoundationInternationalizationTests/StringSortComparatorTests.swift b/Tests/FoundationInternationalizationTests/StringSortComparatorTests.swift index cb6649531..1e14a94cb 100644 --- a/Tests/FoundationInternationalizationTests/StringSortComparatorTests.swift +++ b/Tests/FoundationInternationalizationTests/StringSortComparatorTests.swift @@ -10,43 +10,48 @@ // //===----------------------------------------------------------------------===// -#if canImport(TestSupport) -import TestSupport -#endif +import Testing -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#else +#if canImport(FoundationEssentials) @testable import FoundationEssentials @testable import FoundationInternationalization -#endif // FOUNDATION_FRAMEWORK +#else +@testable import Foundation +#endif -class StringSortComparatorTests: XCTestCase { +@Suite("String SortComparator") +private struct StringSortComparatorTests { + @Test func compareOptionsDescriptor() { + let compareOptions = String.Comparator(options: [.numeric]) + #expect( + compareOptions.compare("ttestest005", "test2") == + "test005".compare("test2", options: [.numeric])) + #expect( + compareOptions.compare("test2", "test005") == + "test2".compare("test005", options: [.numeric])) + } + #if FOUNDATION_FRAMEWORK // TODO: Until we support String.compare(_:options:locale:) in FoundationInternationalization, only support unlocalized comparisons // https://github.com/apple/swift-foundation/issues/284 - func test_locale() { + @Test func locale() { let swedishComparator = String.Comparator(options: [], locale: Locale(identifier: "sv")) - XCTAssertEqual(swedishComparator.compare("ă", "ã"), .orderedAscending) - XCTAssertEqual(swedishComparator.locale, Locale(identifier: "sv")) + #expect(swedishComparator.compare("ă", "ã") == .orderedAscending) + #expect(swedishComparator.locale, Locale(identifier: "sv")) } - func test_nil_locale() { + @Test func nilLocale() { let swedishComparator = String.Comparator(options: [], locale: nil) - XCTAssertEqual(swedishComparator.compare("ă", "ã"), .orderedDescending) + #expect(swedishComparator.compare("ă", "ã") == .orderedDescending) } - func test_standard_localized() throws { - // This test is only verified to work with en - guard Locale.current.language.languageCode == .english else { - throw XCTSkip("Test only verified to work with English as current language") - } - + @Test(.enabled(if: Locale.current.language.languageCode == .english, "Test only verified to work with English as current language")) + func standardLocalized() throws { let localizedStandard = String.StandardComparator.localizedStandard - XCTAssertEqual(localizedStandard.compare("ă", "ã"), .orderedAscending) + #expect(localizedStandard.compare("ă", "ã") == .orderedAscending) let unlocalizedStandard = String.StandardComparator.lexical - XCTAssertEqual(unlocalizedStandard.compare("ă", "ã"), .orderedDescending) + #expect(unlocalizedStandard.compare("ă", "ã") == .orderedDescending) } #endif } From fdbf6cac9dcb437125f46b8e55c857321fdf1981 Mon Sep 17 00:00:00 2001 From: Jeremy Schonfeld Date: Wed, 11 Jun 2025 14:44:55 -0700 Subject: [PATCH 10/12] Convert decimal tests --- .../DecimalTests.swift | 1285 ++++++++--------- 1 file changed, 564 insertions(+), 721 deletions(-) diff --git a/Tests/FoundationEssentialsTests/DecimalTests.swift b/Tests/FoundationEssentialsTests/DecimalTests.swift index 6f7d08ff3..a20d634b4 100644 --- a/Tests/FoundationEssentialsTests/DecimalTests.swift +++ b/Tests/FoundationEssentialsTests/DecimalTests.swift @@ -10,148 +10,147 @@ // //===----------------------------------------------------------------------===// -#if canImport(TestSupport) -import TestSupport -#endif // canImport(TestSupport) +import Testing + +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#elseif os(WASI) +import WASILibc +#elseif os(Windows) +import CRT +#endif -#if FOUNDATION_FRAMEWORK -@testable import Foundation -#else +#if canImport(FoundationEssentials) @_spi(SwiftCorelibsFoundation) @testable import FoundationEssentials +#else +@testable import Foundation #endif -final class DecimalTests : XCTestCase { +@Suite("Decimal") +private struct DecimalTests { #if !FOUNDATION_FRAMEWORK // These tests tests the stub implementations - func assertMantissaEquals(lhs: Decimal, rhs: Decimal.Mantissa) { - XCTAssertEqual(lhs[0], rhs.0, "Mantissa.0 does not equal: \(lhs[0]) vs \(rhs.0)") - XCTAssertEqual(lhs[1], rhs.1, "Mantissa.1 does not equal: \(lhs[1]) vs \(rhs.1)") - XCTAssertEqual(lhs[2], rhs.2, "Mantissa.2 does not equal: \(lhs[2]) vs \(rhs.2)") - XCTAssertEqual(lhs[3], rhs.3, "Mantissa.3 does not equal: \(lhs[3]) vs \(rhs.3)") - XCTAssertEqual(lhs[4], rhs.4, "Mantissa.4 does not equal: \(lhs[4]) vs \(rhs.4)") - XCTAssertEqual(lhs[5], rhs.5, "Mantissa.5 does not equal: \(lhs[5]) vs \(rhs.5)") - XCTAssertEqual(lhs[6], rhs.6, "Mantissa.6 does not equal: \(lhs[6]) vs \(rhs.6)") - XCTAssertEqual(lhs[7], rhs.7, "Mantissa.7 does not equal: \(lhs[7]) vs \(rhs.7)") + func assertMantissaEquals(lhs: Decimal, rhs: Decimal.Mantissa, sourceLocation: SourceLocation = #_sourceLocation) { + #expect(lhs[0] == rhs.0, "Mantissa.0 does not equal: \(lhs[0]) vs \(rhs.0)", sourceLocation: sourceLocation) + #expect(lhs[1] == rhs.1, "Mantissa.1 does not equal: \(lhs[1]) vs \(rhs.1)", sourceLocation: sourceLocation) + #expect(lhs[2] == rhs.2, "Mantissa.2 does not equal: \(lhs[2]) vs \(rhs.2)", sourceLocation: sourceLocation) + #expect(lhs[3] == rhs.3, "Mantissa.3 does not equal: \(lhs[3]) vs \(rhs.3)", sourceLocation: sourceLocation) + #expect(lhs[4] == rhs.4, "Mantissa.4 does not equal: \(lhs[4]) vs \(rhs.4)", sourceLocation: sourceLocation) + #expect(lhs[5] == rhs.5, "Mantissa.5 does not equal: \(lhs[5]) vs \(rhs.5)", sourceLocation: sourceLocation) + #expect(lhs[6] == rhs.6, "Mantissa.6 does not equal: \(lhs[6]) vs \(rhs.6)", sourceLocation: sourceLocation) + #expect(lhs[7] == rhs.7, "Mantissa.7 does not equal: \(lhs[7]) vs \(rhs.7)", sourceLocation: sourceLocation) } - func testDecimalRoundtripFuzzing() { - let iterations = 100 - for _ in 0 ..< iterations { - // Exponent is only 8 bits long - let exponent: CInt = CInt(Int8.random(in: Int8.min ..< Int8.max)) - // Length is only 4 bits long - var length: CUnsignedInt = .random(in: 0 ..< 0xF) - let isNegative: CUnsignedInt = .random(in: 0 ..< 1) - let isCompact: CUnsignedInt = .random(in: 0 ..< 1) - // Reserved is 18 bits long - let reserved: CUnsignedInt = .random(in: 0 ..< 0x3FFFF) - let mantissa: Decimal.Mantissa = ( - .random(in: 0 ..< UInt16.max), - .random(in: 0 ..< UInt16.max), - .random(in: 0 ..< UInt16.max), - .random(in: 0 ..< UInt16.max), - .random(in: 0 ..< UInt16.max), - .random(in: 0 ..< UInt16.max), - .random(in: 0 ..< UInt16.max), - .random(in: 0 ..< UInt16.max) - ) - - var decimal = Decimal( - _exponent: exponent, - _length: length, - _isNegative: isNegative, - _isCompact: isCompact, - _reserved: reserved, - _mantissa: mantissa - ) - - XCTAssertEqual(decimal._exponent, exponent) - XCTAssertEqual(decimal._length, length) - XCTAssertEqual(decimal._isNegative, isNegative) - XCTAssertEqual(decimal._isCompact, isCompact) - XCTAssertEqual(decimal._reserved, reserved) - assertMantissaEquals( - lhs: decimal, - rhs: mantissa - ) - - // Update invidividual values - length = .random(in: 0 ..< 0xF) - decimal._length = length - XCTAssertEqual(decimal._length, length) - } + @Test(arguments: 0 ..< 100) + func roundtripFuzzing(iteration: Int) { + // Exponent is only 8 bits long + let exponent: CInt = CInt(Int8.random(in: Int8.min ..< Int8.max)) + // Length is only 4 bits long + var length: CUnsignedInt = .random(in: 0 ..< 0xF) + let isNegative: CUnsignedInt = .random(in: 0 ..< 1) + let isCompact: CUnsignedInt = .random(in: 0 ..< 1) + // Reserved is 18 bits long + let reserved: CUnsignedInt = .random(in: 0 ..< 0x3FFFF) + let mantissa: Decimal.Mantissa = ( + .random(in: 0 ..< UInt16.max), + .random(in: 0 ..< UInt16.max), + .random(in: 0 ..< UInt16.max), + .random(in: 0 ..< UInt16.max), + .random(in: 0 ..< UInt16.max), + .random(in: 0 ..< UInt16.max), + .random(in: 0 ..< UInt16.max), + .random(in: 0 ..< UInt16.max) + ) + + var decimal = Decimal( + _exponent: exponent, + _length: length, + _isNegative: isNegative, + _isCompact: isCompact, + _reserved: reserved, + _mantissa: mantissa + ) + + #expect(decimal._exponent == exponent) + #expect(decimal._length == length) + #expect(decimal._isNegative == isNegative) + #expect(decimal._isCompact == isCompact) + #expect(decimal._reserved == reserved) + assertMantissaEquals( + lhs: decimal, + rhs: mantissa + ) + + // Update invidividual values + length = .random(in: 0 ..< 0xF) + decimal._length = length + #expect(decimal._length == length) } - #endif - func testAbusiveCompact() { + @Test func abusiveCompact() { var decimal = Decimal() decimal._exponent = 5 decimal._length = 5 decimal.compact() - XCTAssertEqual(Decimal.zero, decimal); - } - - func test_Description() { - XCTAssertEqual("0", Decimal().description) - XCTAssertEqual("0", Decimal(0).description) - XCTAssertEqual("10", Decimal(_exponent: 1, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (1, 0, 0, 0, 0, 0, 0, 0)).description) - XCTAssertEqual("10", Decimal(10).description) - XCTAssertEqual("123.458", Decimal(_exponent: -3, _length: 2, _isNegative: 0, _isCompact:1, _reserved: 0, _mantissa: (57922, 1, 0, 0, 0, 0, 0, 0)).description) - XCTAssertEqual("123.458", Decimal(123.458).description) - XCTAssertEqual("123", Decimal(UInt8(123)).description) - XCTAssertEqual("45", Decimal(Int8(45)).description) - XCTAssertEqual("3.14159265358979323846264338327950288419", Decimal.pi.description) - XCTAssertEqual("-30000000000", Decimal(sign: .minus, exponent: 10, significand: Decimal(3)).description) - XCTAssertEqual("300000", Decimal(sign: .plus, exponent: 5, significand: Decimal(3)).description) - XCTAssertEqual("5", Decimal(signOf: Decimal(3), magnitudeOf: Decimal(5)).description) - XCTAssertEqual("-5", Decimal(signOf: Decimal(-3), magnitudeOf: Decimal(5)).description) - XCTAssertEqual("5", Decimal(signOf: Decimal(3), magnitudeOf: Decimal(-5)).description) - XCTAssertEqual("-5", Decimal(signOf: Decimal(-3), magnitudeOf: Decimal(-5)).description) + #expect(Decimal.zero == decimal) } - func test_DescriptionWithLocale() { - let decimal = Decimal(string: "-123456.789")! - XCTAssertEqual(decimal._toString(withDecimalSeparator: "."), "-123456.789") - let en = decimal._toString(withDecimalSeparator: Locale(identifier: "en_GB").decimalSeparator!) - XCTAssertEqual(en, "-123456.789") - let fr = decimal._toString(withDecimalSeparator: Locale(identifier: "fr_FR").decimalSeparator!) - XCTAssertEqual(fr, "-123456,789") + @Test func description() { + #expect("0" == Decimal().description) + #expect("0" == Decimal(0).description) + #expect("10" == Decimal(_exponent: 1, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (1, 0, 0, 0, 0, 0, 0, 0)).description) + #expect("10" == Decimal(10).description) + #expect("123.458" == Decimal(_exponent: -3, _length: 2, _isNegative: 0, _isCompact:1, _reserved: 0, _mantissa: (57922, 1, 0, 0, 0, 0, 0, 0)).description) + #expect("123.458" == Decimal(123.458).description) + #expect("123" == Decimal(UInt8(123)).description) + #expect("45" == Decimal(Int8(45)).description) + #expect("3.14159265358979323846264338327950288419" == Decimal.pi.description) + #expect("-30000000000" == Decimal(sign: .minus, exponent: 10, significand: Decimal(3)).description) + #expect("300000" == Decimal(sign: .plus, exponent: 5, significand: Decimal(3)).description) + #expect("5" == Decimal(signOf: Decimal(3), magnitudeOf: Decimal(5)).description) + #expect("-5" == Decimal(signOf: Decimal(-3), magnitudeOf: Decimal(5)).description) + #expect("5" == Decimal(signOf: Decimal(3), magnitudeOf: Decimal(-5)).description) + #expect("-5" == Decimal(signOf: Decimal(-3), magnitudeOf: Decimal(-5)).description) } - func test_BasicConstruction() { + @Test func basicConstruction() { let zero = Decimal() - XCTAssertEqual(20, MemoryLayout.size) - XCTAssertEqual(0, zero._exponent) - XCTAssertEqual(0, zero._length) - XCTAssertEqual(0, zero._isNegative) - XCTAssertEqual(0, zero._isCompact) - XCTAssertEqual(0, zero._reserved) + #expect(20 == MemoryLayout.size) + #expect(0 == zero._exponent) + #expect(0 == zero._length) + #expect(0 == zero._isNegative) + #expect(0 == zero._isCompact) + #expect(0 == zero._reserved) let (m0, m1, m2, m3, m4, m5, m6, m7) = zero._mantissa - XCTAssertEqual(0, m0) - XCTAssertEqual(0, m1) - XCTAssertEqual(0, m2) - XCTAssertEqual(0, m3) - XCTAssertEqual(0, m4) - XCTAssertEqual(0, m5) - XCTAssertEqual(0, m6) - XCTAssertEqual(0, m7) - XCTAssertEqual(8, Decimal.maxSize) - XCTAssertEqual(32767, CShort.max) - XCTAssertFalse(zero.isNormal) - XCTAssertTrue(zero.isFinite) - XCTAssertTrue(zero.isZero) - XCTAssertFalse(zero.isSubnormal) - XCTAssertFalse(zero.isInfinite) - XCTAssertFalse(zero.isNaN) - XCTAssertFalse(zero.isSignaling) + #expect(0 == m0) + #expect(0 == m1) + #expect(0 == m2) + #expect(0 == m3) + #expect(0 == m4) + #expect(0 == m5) + #expect(0 == m6) + #expect(0 == m7) + #expect(8 == Decimal.maxSize) + #expect(32767 == CShort.max) + #expect(!zero.isNormal) + #expect(zero.isFinite) + #expect(zero.isZero) + #expect(!zero.isSubnormal) + #expect(!zero.isInfinite) + #expect(!zero.isNaN) + #expect(!zero.isSignaling) let d1 = Decimal(1234567890123456789 as UInt64) - XCTAssertEqual(d1._exponent, 0) - XCTAssertEqual(d1._length, 4) + #expect(d1._exponent == 0) + #expect(d1._length == 4) } - func test_ExplicitConstruction() { + @Test func explicitConstruction() { var explicit = Decimal( _exponent: 0x17f, _length: 0xff, @@ -160,50 +159,50 @@ final class DecimalTests : XCTestCase { _reserved: UInt32(1<<18 + 1<<17 + 1), _mantissa: (6, 7, 8, 9, 10, 11, 12, 13) ) - XCTAssertEqual(0x7f, explicit._exponent) - XCTAssertEqual(0x7f, explicit.exponent) - XCTAssertEqual(0x0f, explicit._length) - XCTAssertEqual(1, explicit._isNegative) - XCTAssertEqual(FloatingPointSign.minus, explicit.sign) - XCTAssertTrue(explicit.isSignMinus) - XCTAssertEqual(0, explicit._isCompact) - XCTAssertEqual(UInt32(1<<17 + 1), explicit._reserved) + #expect(0x7f == explicit._exponent) + #expect(0x7f == explicit.exponent) + #expect(0x0f == explicit._length) + #expect(1 == explicit._isNegative) + #expect(FloatingPointSign.minus == explicit.sign) + #expect(explicit.isSignMinus) + #expect(0 == explicit._isCompact) + #expect(UInt32(1<<17 + 1) == explicit._reserved) let (m0, m1, m2, m3, m4, m5, m6, m7) = explicit._mantissa - XCTAssertEqual(6, m0) - XCTAssertEqual(7, m1) - XCTAssertEqual(8, m2) - XCTAssertEqual(9, m3) - XCTAssertEqual(10, m4) - XCTAssertEqual(11, m5) - XCTAssertEqual(12, m6) - XCTAssertEqual(13, m7) + #expect(6 == m0) + #expect(7 == m1) + #expect(8 == m2) + #expect(9 == m3) + #expect(10 == m4) + #expect(11 == m5) + #expect(12 == m6) + #expect(13 == m7) explicit._isCompact = 5 explicit._isNegative = 6 - XCTAssertEqual(0, explicit._isNegative) - XCTAssertEqual(1, explicit._isCompact) - XCTAssertEqual(FloatingPointSign.plus, explicit.sign) - XCTAssertFalse(explicit.isSignMinus) - XCTAssertTrue(explicit.isNormal) + #expect(0 == explicit._isNegative) + #expect(1 == explicit._isCompact) + #expect(FloatingPointSign.plus == explicit.sign) + #expect(!explicit.isSignMinus) + #expect(explicit.isNormal) let significand = explicit.significand - XCTAssertEqual(0, significand._exponent) - XCTAssertEqual(0, significand.exponent) - XCTAssertEqual(0x0f, significand._length) - XCTAssertEqual(0, significand._isNegative) - XCTAssertEqual(1, significand._isCompact) - XCTAssertEqual(0, significand._reserved) + #expect(0 == significand._exponent) + #expect(0 == significand.exponent) + #expect(0x0f == significand._length) + #expect(0 == significand._isNegative) + #expect(1 == significand._isCompact) + #expect(0 == significand._reserved) let (sm0, sm1, sm2, sm3, sm4, sm5, sm6, sm7) = significand._mantissa - XCTAssertEqual(6, sm0) - XCTAssertEqual(7, sm1) - XCTAssertEqual(8, sm2) - XCTAssertEqual(9, sm3) - XCTAssertEqual(10, sm4) - XCTAssertEqual(11, sm5) - XCTAssertEqual(12, sm6) - XCTAssertEqual(13, sm7) + #expect(6 == sm0) + #expect(7 == sm1) + #expect(8 == sm2) + #expect(9 == sm3) + #expect(10 == sm4) + #expect(11 == sm5) + #expect(12 == sm6) + #expect(13 == sm7) } - func test_ScanDecimal() throws { + @Test func scanDecimal() throws { let testCases = [ // expected, value ( 123.456e78, "123.456e78", "123456000000000000000000000000000000000000000000000000000000000000000000000000000" ), @@ -218,181 +217,122 @@ final class DecimalTests : XCTestCase { ] for testCase in testCases { let (expected, string, _) = testCase - let decimal = Decimal(string:string)! + let decimal = try #require(Decimal(string: string)) let aboutOne = Decimal(expected) / decimal - let approximatelyRight = aboutOne >= Decimal(0.99999) && aboutOne <= Decimal(1.00001) - XCTAssertTrue(approximatelyRight, "\(expected) ~= \(decimal) : \(aboutOne) \(aboutOne >= Decimal(0.99999)) \(aboutOne <= Decimal(1.00001))" ) - } - guard let answer = Decimal(string:"12345679012345679012345679012345679012.3") else { - XCTFail("Unable to parse Decimal(string:'12345679012345679012345679012345679012.3')") - return - } - guard let ones = Decimal(string:"111111111111111111111111111111111111111") else { - XCTFail("Unable to parse Decimal(string:'111111111111111111111111111111111111111')") - return + #expect(aboutOne >= Decimal(0.99999) && aboutOne <= Decimal(1.00001), "\(expected) ~= \(decimal)") } + let answer = try #require(Decimal(string:"12345679012345679012345679012345679012.3")) + let ones = try #require(Decimal(string:"111111111111111111111111111111111111111")) let num = ones / Decimal(9) - XCTAssertEqual(answer,num,"\(ones) / 9 = \(answer) \(num)") + #expect(answer == num, "\(ones) / 9 = \(answer) \(num)") // Exponent overflow, returns nil - XCTAssertNil(Decimal(string: "1e200")) - XCTAssertNil(Decimal(string: "1e-200")) - XCTAssertNil(Decimal(string: "1e300")) - XCTAssertNil(Decimal(string: "1" + String(repeating: "0", count: 170))) - XCTAssertNil(Decimal(string: "0." + String(repeating: "0", count: 170) + "1")) - XCTAssertNil(Decimal(string: "0e200")) + #expect(Decimal(string: "1e200") == nil) + #expect(Decimal(string: "1e-200") == nil) + #expect(Decimal(string: "1e300") == nil) + #expect(Decimal(string: "1" + String(repeating: "0", count: 170)) == nil) + #expect(Decimal(string: "0." + String(repeating: "0", count: 170) + "1") == nil) + #expect(Decimal(string: "0e200") == nil) // Parsing zero in different forms - let zero1 = try XCTUnwrap(Decimal(string: "000.000e123")) - XCTAssertTrue(zero1.isZero) - XCTAssertEqual(zero1._isNegative, 0) - XCTAssertEqual(zero1._length, 0) - XCTAssertEqual(zero1.description, "0") - - let zero2 = try XCTUnwrap(Decimal(string: "+000.000e-123")) - XCTAssertTrue(zero2.isZero) - XCTAssertEqual(zero2._isNegative, 0) - XCTAssertEqual(zero2._length, 0) - XCTAssertEqual(zero2.description, "0") - - let zero3 = try XCTUnwrap(Decimal(string: "-0.0e1")) - XCTAssertTrue(zero3.isZero) - XCTAssertEqual(zero3._isNegative, 0) - XCTAssertEqual(zero3._length, 0) - XCTAssertEqual(zero3.description, "0") + let zero1 = try #require(Decimal(string: "000.000e123")) + #expect(zero1.isZero) + #expect(zero1._isNegative == 0) + #expect(zero1._length == 0) + #expect(zero1.description == "0") + + let zero2 = try #require(Decimal(string: "+000.000e-123")) + #expect(zero2.isZero) + #expect(zero2._isNegative == 0) + #expect(zero2._length == 0) + #expect(zero2.description == "0") + + let zero3 = try #require(Decimal(string: "-0.0e1")) + #expect(zero3.isZero) + #expect(zero3._isNegative == 0) + #expect(zero3._length == 0) + #expect(zero3.description == "0") // Bin compat: invalid strings starting with E should be parsed as 0 - var zeroE = try XCTUnwrap(Decimal(string: "en")) - XCTAssertTrue(zeroE.isZero) - zeroE = try XCTUnwrap(Decimal(string: "e")) - XCTAssertTrue(zeroE.isZero) + var zeroE = try #require(Decimal(string: "en")) + #expect(zeroE.isZero) + zeroE = try #require(Decimal(string: "e")) + #expect(zeroE.isZero) // Partitally valid strings ending with e shold be parsed - let notZero = try XCTUnwrap(Decimal(string: "123e")) - XCTAssertEqual(notZero, Decimal(123)) - } - - func test_stringWithLocale() { - - let en_US = Locale(identifier: "en_US") - let fr_FR = Locale(identifier: "fr_FR") - - XCTAssertEqual(Decimal(string: "1,234.56")! * 1000, Decimal(1000)) - XCTAssertEqual(Decimal(string: "1,234.56", locale: en_US)! * 1000, Decimal(1000)) - XCTAssertEqual(Decimal(string: "1,234.56", locale: fr_FR)! * 1000, Decimal(1234)) - XCTAssertEqual(Decimal(string: "1.234,56", locale: en_US)! * 1000, Decimal(1234)) - XCTAssertEqual(Decimal(string: "1.234,56", locale: fr_FR)! * 1000, Decimal(1000)) - - XCTAssertEqual(Decimal(string: "-1,234.56")! * 1000, Decimal(-1000)) - XCTAssertEqual(Decimal(string: "+1,234.56")! * 1000, Decimal(1000)) - XCTAssertEqual(Decimal(string: "+1234.56e3"), Decimal(1234560)) - XCTAssertEqual(Decimal(string: "+1234.56E3"), Decimal(1234560)) - XCTAssertEqual(Decimal(string: "+123456000E-3"), Decimal(123456)) - - XCTAssertNil(Decimal(string: "")) - XCTAssertNil(Decimal(string: "x")) - XCTAssertEqual(Decimal(string: "-x"), Decimal.zero) - XCTAssertEqual(Decimal(string: "+x"), Decimal.zero) - XCTAssertEqual(Decimal(string: "-"), Decimal.zero) - XCTAssertEqual(Decimal(string: "+"), Decimal.zero) - XCTAssertEqual(Decimal(string: "-."), Decimal.zero) - XCTAssertEqual(Decimal(string: "+."), Decimal.zero) - - XCTAssertEqual(Decimal(string: "-0"), Decimal.zero) - XCTAssertEqual(Decimal(string: "+0"), Decimal.zero) - XCTAssertEqual(Decimal(string: "-0."), Decimal.zero) - XCTAssertEqual(Decimal(string: "+0."), Decimal.zero) - XCTAssertEqual(Decimal(string: "e1"), Decimal.zero) - XCTAssertEqual(Decimal(string: "e-5"), Decimal.zero) - XCTAssertEqual(Decimal(string: ".3e1"), Decimal(3)) - - XCTAssertEqual(Decimal(string: "."), Decimal.zero) - XCTAssertEqual(Decimal(string: ".", locale: en_US), Decimal.zero) - XCTAssertNil(Decimal(string: ".", locale: fr_FR)) - - XCTAssertNil(Decimal(string: ",")) - XCTAssertEqual(Decimal(string: ",", locale: fr_FR), Decimal.zero) - XCTAssertNil(Decimal(string: ",", locale: en_US)) - - let s1 = "1234.5678" - XCTAssertEqual(Decimal(string: s1, locale: en_US)?.description, s1) - XCTAssertEqual(Decimal(string: s1, locale: fr_FR)?.description, "1234") - - let s2 = "1234,5678" - XCTAssertEqual(Decimal(string: s2, locale: en_US)?.description, "1234") - XCTAssertEqual(Decimal(string: s2, locale: fr_FR)?.description, s1) + let notZero = try #require(Decimal(string: "123e")) + #expect(notZero == Decimal(123)) } - func testStringPartialMatch() { + @Test func stringPartialMatch() throws { // This tests makes sure Decimal still has the // same behavior that it only requires the beginning // of the string to be valid number - let decimal = Decimal(string: "3.14notanumber") - XCTAssertNotNil(decimal) - XCTAssertEqual(decimal!.description, "3.14") + let decimal = try #require(Decimal(string: "3.14notanumber")) + #expect(decimal.description == "3.14") } - func testStringNoMatch() { + @Test func stringNoMatch() { // This test makes sure Decimal returns nil // if the does not start with a number var notDecimal = Decimal(string: "A Flamingo's head has to be upside down when it eats.") - XCTAssertNil(notDecimal) + #expect(notDecimal == nil) // Same if the number does not appear at the beginning notDecimal = Decimal(string: "Jump 22 Street") - XCTAssertNil(notDecimal) + #expect(notDecimal == nil) } - func testNormalize() throws { + @Test func normalize() throws { var one = Decimal(1) var ten = Decimal(-10) var lossPrecision = try Decimal._normalize(a: &one, b: &ten, roundingMode: .plain) - XCTAssertFalse(lossPrecision) - XCTAssertEqual(Decimal(1), one) - XCTAssertEqual(Decimal(-10), ten) - XCTAssertEqual(1, one._length) - XCTAssertEqual(1, ten._length) + #expect(!lossPrecision) + #expect(Decimal(1) == one) + #expect(Decimal(-10) == ten) + #expect(1 == one._length) + #expect(1 == ten._length) one = Decimal(1) ten = Decimal(10) lossPrecision = try Decimal._normalize(a: &one, b: &ten, roundingMode: .plain) - XCTAssertFalse(lossPrecision) - XCTAssertEqual(Decimal(1), one) - XCTAssertEqual(Decimal(10), ten) - XCTAssertEqual(1, one._length) - XCTAssertEqual(1, ten._length) + #expect(!lossPrecision) + #expect(Decimal(1) == one) + #expect(Decimal(10) == ten) + #expect(1 == one._length) + #expect(1 == ten._length) // Normalise with loss of precision - let a = try XCTUnwrap(Decimal(string: "498.7509045")) - let b = try XCTUnwrap(Decimal(string: "8.453441368210501065891847765109162027")) + let a = try #require(Decimal(string: "498.7509045")) + let b = try #require(Decimal(string: "8.453441368210501065891847765109162027")) var aNormalized = a var bNormalized = b lossPrecision = try Decimal._normalize( a: &aNormalized, b: &bNormalized, roundingMode: .plain) - XCTAssertTrue(lossPrecision) - - XCTAssertEqual(aNormalized.exponent, -31) - XCTAssertEqual(aNormalized._mantissa.0, 0) - XCTAssertEqual(aNormalized._mantissa.1, 21760) - XCTAssertEqual(aNormalized._mantissa.2, 45355) - XCTAssertEqual(aNormalized._mantissa.3, 11455) - XCTAssertEqual(aNormalized._mantissa.4, 62709) - XCTAssertEqual(aNormalized._mantissa.5, 14050) - XCTAssertEqual(aNormalized._mantissa.6, 62951) - XCTAssertEqual(aNormalized._mantissa.7, 0) - XCTAssertEqual(bNormalized.exponent, -31) - XCTAssertEqual(bNormalized._mantissa.0, 56467) - XCTAssertEqual(bNormalized._mantissa.1, 17616) - XCTAssertEqual(bNormalized._mantissa.2, 59987) - XCTAssertEqual(bNormalized._mantissa.3, 21635) - XCTAssertEqual(bNormalized._mantissa.4, 5988) - XCTAssertEqual(bNormalized._mantissa.5, 63852) - XCTAssertEqual(bNormalized._mantissa.6, 1066) - XCTAssertEqual(bNormalized._length, 7) - XCTAssertEqual(a, aNormalized) - XCTAssertNotEqual(b, bNormalized) // b had a loss Of Precision when normalising + #expect(lossPrecision) + + #expect(aNormalized.exponent == -31) + #expect(aNormalized._mantissa.0 == 0) + #expect(aNormalized._mantissa.1 == 21760) + #expect(aNormalized._mantissa.2 == 45355) + #expect(aNormalized._mantissa.3 == 11455) + #expect(aNormalized._mantissa.4 == 62709) + #expect(aNormalized._mantissa.5 == 14050) + #expect(aNormalized._mantissa.6 == 62951) + #expect(aNormalized._mantissa.7 == 0) + #expect(bNormalized.exponent == -31) + #expect(bNormalized._mantissa.0 == 56467) + #expect(bNormalized._mantissa.1 == 17616) + #expect(bNormalized._mantissa.2 == 59987) + #expect(bNormalized._mantissa.3 == 21635) + #expect(bNormalized._mantissa.4 == 5988) + #expect(bNormalized._mantissa.5 == 63852) + #expect(bNormalized._mantissa.6 == 1066) + #expect(bNormalized._length == 7) + #expect(a == aNormalized) + #expect(b != bNormalized) // b had a loss Of Precision when normalising } - func testAdditionWithNormalization() throws { + @Test func additionWithNormalization() throws { let one: Decimal = Decimal(1) var addend: Decimal = one // 2 digits @@ -404,7 +344,7 @@ final class DecimalTests : XCTestCase { expected._exponent = -1 expected._length = 1 expected._mantissa.0 = 11 - XCTAssertTrue(Decimal._compare(lhs: result, rhs: expected) == .orderedSame) + #expect(Decimal._compare(lhs: result, rhs: expected) == .orderedSame) // 38 digits addend._exponent = -37 expected._exponent = -37; @@ -418,7 +358,7 @@ final class DecimalTests : XCTestCase { expected._mantissa.6 = 0xee10; expected._mantissa.7 = 0x0785; (result, _) = try one._add(rhs: addend, roundingMode: .plain) - XCTAssertTrue(Decimal._compare(lhs: expected, rhs: result) == .orderedSame) + #expect(Decimal._compare(lhs: expected, rhs: result) == .orderedSame) // 39 Digits -- not guaranteed to work addend._exponent = -38 (result, lostPrecision) = try one._add(rhs: addend, roundingMode: .plain) @@ -433,19 +373,19 @@ final class DecimalTests : XCTestCase { expected._mantissa.5 = 0x5a86; expected._mantissa.6 = 0x4ca8; expected._mantissa.7 = 0x4b3b; - XCTAssertTrue(Decimal._compare(lhs: expected, rhs: result) == .orderedSame) + #expect(Decimal._compare(lhs: expected, rhs: result) == .orderedSame) } else { - XCTAssertTrue(Decimal._compare(lhs: one, rhs: result) == .orderedSame) + #expect(Decimal._compare(lhs: one, rhs: result) == .orderedSame) } // 40 Digits -- does NOT work, make sure we round addend._exponent = -39 (result, lostPrecision) = try one._add(rhs: addend, roundingMode: .plain) - XCTAssertTrue(lostPrecision) - XCTAssertEqual("1", result.description) - XCTAssertTrue(Decimal._compare(lhs: one, rhs: result) == .orderedSame) + #expect(lostPrecision) + #expect("1" == result.description) + #expect(Decimal._compare(lhs: one, rhs: result) == .orderedSame) } - func testSimpleMultiplication() throws { + @Test func simpleMultiplication() throws { var multiplicand = Decimal() multiplicand._isNegative = 0 multiplicand._isCompact = 0 @@ -469,12 +409,12 @@ final class DecimalTests : XCTestCase { let result = try multiplicand._multiply( by: multiplier, roundingMode: .plain ) - XCTAssertTrue(Decimal._compare(lhs: expected, rhs: result) == .orderedSame) + #expect(Decimal._compare(lhs: expected, rhs: result) == .orderedSame) } } } - func testNegativeAndZeroMultiplication() throws { + @Test func negativeAndZeroMultiplication() throws { let one = Decimal(1) let zero = Decimal(0) var negativeOne = one @@ -482,25 +422,25 @@ final class DecimalTests : XCTestCase { // 1 * 1 var result = try one._multiply(by: one, roundingMode: .plain) - XCTAssertTrue(Decimal._compare(lhs: one, rhs: result) == .orderedSame) + #expect(Decimal._compare(lhs: one, rhs: result) == .orderedSame) // 1 * -1 result = try one._multiply(by: negativeOne, roundingMode: .plain) - XCTAssertTrue(Decimal._compare(lhs: negativeOne, rhs: result) == .orderedSame) + #expect(Decimal._compare(lhs: negativeOne, rhs: result) == .orderedSame) // -1 * 1 result = try negativeOne._multiply(by: one, roundingMode: .plain) - XCTAssertTrue(Decimal._compare(lhs: negativeOne, rhs: result) == .orderedSame) + #expect(Decimal._compare(lhs: negativeOne, rhs: result) == .orderedSame) // -1 * -1 result = try negativeOne._multiply(by: negativeOne, roundingMode: .plain) - XCTAssertTrue(Decimal._compare(lhs: one, rhs: result) == .orderedSame) + #expect(Decimal._compare(lhs: one, rhs: result) == .orderedSame) // 1 * 0 result = try one._multiply(by: zero, roundingMode: .plain) - XCTAssertTrue(Decimal._compare(lhs: zero, rhs: result) == .orderedSame) + #expect(Decimal._compare(lhs: zero, rhs: result) == .orderedSame) // 0 * 1 result = try zero._multiply(by: negativeOne, roundingMode: .plain) - XCTAssertTrue(Decimal._compare(lhs: zero, rhs: result) == .orderedSame) + #expect(Decimal._compare(lhs: zero, rhs: result) == .orderedSame) } - func testMultiplicationOverflow() throws { + @Test func multiplicationOverflow() throws { let multiplicand = Decimal( _exponent: 0, _length: 8, @@ -523,70 +463,50 @@ final class DecimalTests : XCTestCase { // The following should throw .overlow multiplier._exponent = 0x7F - do { + #expect { // 2e127 * max_mantissa _ = try multiplicand._multiply( by: multiplier, roundingMode: .plain) - XCTFail("Expected _CalculationError.overflow to be thrown") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) + } throws: { + ($0 as? Decimal._CalculationError) == .overflow } - do { + #expect { // max_mantissa * 2e127 _ = try multiplier._multiply( by: multiplicand, roundingMode: .plain) - XCTFail("Expected _CalculationError.overflow to be thrown") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) + } throws: { + ($0 as? Decimal._CalculationError) == .overflow } } - func testMultiplyByPowerOfTen() throws { + @Test func multiplyByPowerOfTen() throws { let a = Decimal(1234) var result = try a._multiplyByPowerOfTen(power: 1, roundingMode: .plain) - XCTAssertEqual(result, Decimal(12340)) + #expect(result == Decimal(12340)) result = try a._multiplyByPowerOfTen(power: 2, roundingMode: .plain) - XCTAssertEqual(result, Decimal(123400)) + #expect(result == Decimal(123400)) result = try a._multiplyByPowerOfTen(power: 0, roundingMode: .plain) - XCTAssertEqual(result, Decimal(1234)) + #expect(result == Decimal(1234)) result = try a._multiplyByPowerOfTen(power: -2, roundingMode: .plain) - XCTAssertEqual(result, Decimal(12.34)) + #expect(result == Decimal(12.34)) // Overflow - do { + #expect { _ = try a._multiplyByPowerOfTen(power: 128, roundingMode: .plain) - XCTFail("Expected overflow to have been thrown") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) + } throws: { + ($0 as? Decimal._CalculationError) == .overflow } // Underflow - do { + #expect { _ = try Decimal(12.34)._multiplyByPowerOfTen(power: -128, roundingMode: .plain) - XCTFail("Expected underflow to have been thrown") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .underflow) + } throws: { + ($0 as? Decimal._CalculationError) == .underflow } } - func testRepeatingDivision() throws { + @Test func repeatingDivision() throws { let repeatingNumerator = Decimal(16) let repeatingDenominator = Decimal(9) let repeating = try repeatingNumerator._divide( @@ -610,12 +530,12 @@ final class DecimalTests : XCTestCase { expected._mantissa.5 = 55436 expected._mantissa.6 = 45186 expected._mantissa.7 = 10941 - XCTAssertTrue(Decimal._compare(lhs: expected, rhs: result) == .orderedSame) + #expect(Decimal._compare(lhs: expected, rhs: result) == .orderedSame) } #if _pointerBitWidth(_64) // This test require Int to be Int64 - func testCrashingDivision() throws { + @Test func crashingDivision() throws { // This test makes sure the following division // does not crash let first: Decimal = Decimal(1147858867) @@ -638,33 +558,33 @@ final class DecimalTests : XCTestCase { 5147 ) ) - XCTAssertEqual(result, expected) + #expect(result == expected) } #endif - func testPower() throws { + @Test func power() throws { var a = Decimal(1234) var result = try a._power(exponent: 0, roundingMode: .plain) - XCTAssert(Decimal._compare(lhs: result, rhs: Decimal(1)) == .orderedSame) + #expect(Decimal._compare(lhs: result, rhs: Decimal(1)) == .orderedSame) a = Decimal(8) result = try a._power(exponent: 2, roundingMode: .plain) - XCTAssert(Decimal._compare(lhs: result, rhs: Decimal(64)) == .orderedSame) + #expect(Decimal._compare(lhs: result, rhs: Decimal(64)) == .orderedSame) a = Decimal(-2) result = try a._power(exponent: 3, roundingMode: .plain) - XCTAssert(Decimal._compare(lhs: result, rhs: Decimal(-8)) == .orderedSame) + #expect(Decimal._compare(lhs: result, rhs: Decimal(-8)) == .orderedSame) result = try a._power(exponent: 0, roundingMode: .plain) - XCTAssert(Decimal._compare(lhs: result, rhs: Decimal(1)) == .orderedSame) + #expect(Decimal._compare(lhs: result, rhs: Decimal(1)) == .orderedSame) // Positive base let six = Decimal(6) for exponent in 1 ..< 10 { result = try six._power(exponent: exponent, roundingMode: .plain) - XCTAssertEqual(result.doubleValue, pow(6.0, Double(exponent))) + #expect(result.doubleValue == pow(6.0, Double(exponent))) } // Negative base let negativeSix = Decimal(-6) for exponent in 1 ..< 10 { result = try negativeSix._power(exponent: exponent, roundingMode: .plain) - XCTAssertEqual(result.doubleValue, pow(-6.0, Double(exponent))) + #expect(result.doubleValue == pow(-6.0, Double(exponent))) } for i in -2 ... 10 { for j in 0 ... 5 { @@ -673,169 +593,119 @@ final class DecimalTests : XCTestCase { exponent: j, roundingMode: .plain ) let expected = Decimal(pow(Double(i), Double(j))) - XCTAssertEqual(expected, result, "\(result) == \(i)^\(j)") + #expect(expected == result, "\(result) == \(i)^\(j)") } } } - func testNaNInput() throws { + @Test func nanInput() throws { let nan = Decimal.nan let one = Decimal(1) - do { + #expect { // NaN + 1 _ = try nan._add(rhs: one, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) + } throws: { + ($0 as? Decimal._CalculationError) == .overflow } - do { + #expect { // 1 + NaN _ = try one._add(rhs: nan, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) + } throws: { + ($0 as? Decimal._CalculationError) == .overflow } - do { + #expect { // NaN - 1 _ = try nan._subtract(rhs: one, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) + } throws: { + ($0 as? Decimal._CalculationError) == .overflow } - do { + #expect { // 1 - NaN _ = try one._subtract(rhs: nan, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) + } throws: { + ($0 as? Decimal._CalculationError) == .overflow } - do { + #expect { // NaN * 1 _ = try nan._multiply(by: one, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) + } throws: { + ($0 as? Decimal._CalculationError) == .overflow } - do { + #expect { // 1 * NaN _ = try one._multiply(by: nan, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) + } throws: { + ($0 as? Decimal._CalculationError) == .overflow } - do { + #expect { // NaN / 1 _ = try nan._divide(by: one, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) + } throws: { + ($0 as? Decimal._CalculationError) == .overflow } - do { + #expect { // 1 / NaN _ = try one._divide(by: nan, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) + } throws: { + ($0 as? Decimal._CalculationError) == .overflow } - do { + #expect { // NaN ^ 0 _ = try nan._power(exponent: 0, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) + } throws: { + ($0 as? Decimal._CalculationError) == .overflow } - do { + #expect { // NaN ^ 1 _ = try nan._power(exponent: 1, roundingMode: .plain) - XCTFail("Expected to throw error") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Wrong error thrown") - return - } - XCTAssertEqual(calculationError, .overflow) + } throws: { + ($0 as? Decimal._CalculationError) == .overflow } // Overflow doubles - XCTAssertTrue(Decimal(Double.leastNonzeroMagnitude).isNaN) - XCTAssertTrue(Decimal(Double.leastNormalMagnitude).isNaN) - XCTAssertTrue(Decimal(Double.greatestFiniteMagnitude).isNaN) - XCTAssertTrue(Decimal(Double("1e-129")!).isNaN) - XCTAssertTrue(Decimal(Double("0.1e-128")!).isNaN) + #expect(Decimal(Double.leastNonzeroMagnitude).isNaN) + #expect(Decimal(Double.leastNormalMagnitude).isNaN) + #expect(Decimal(Double.greatestFiniteMagnitude).isNaN) + #expect(Decimal(Double("1e-129")!).isNaN) + #expect(Decimal(Double("0.1e-128")!).isNaN) } - func testDecimalRoundBankers() throws { + @Test func roundBankers() throws { let onePointTwo = Decimal(1.2) var result = try onePointTwo._round(scale: 1, roundingMode: .bankers) - XCTAssertEqual(1.2, result.doubleValue, accuracy: 0.0001) + #expect((1.1009 ... 1.2001).contains(result.doubleValue)) let onePointTwoOne = Decimal(1.21) result = try onePointTwoOne._round(scale: 1, roundingMode: .bankers) - XCTAssertEqual(1.2, result.doubleValue, accuracy: 0.0001) + #expect((1.1009 ... 1.2001).contains(result.doubleValue)) let onePointTwoFive = Decimal(1.25) result = try onePointTwoFive._round(scale: 1, roundingMode: .bankers) - XCTAssertEqual(1.2, result.doubleValue, accuracy: 0.0001) + #expect((1.1009 ... 1.2001).contains(result.doubleValue)) let onePointThreeFive = Decimal(1.35) result = try onePointThreeFive._round(scale: 1, roundingMode: .bankers) - XCTAssertEqual(1.4, result.doubleValue, accuracy: 0.0001) + #expect((1.3009 ... 1.4001).contains(result.doubleValue)) let onePointTwoSeven = Decimal(1.27) result = try onePointTwoSeven._round(scale: 1, roundingMode: .bankers) - XCTAssertEqual(1.3, result.doubleValue, accuracy: 0.0001) + #expect((1.2009 ... 3.2001).contains(result.doubleValue)) let minusEightPointFourFive = Decimal(-8.45) result = try minusEightPointFourFive._round(scale: 1, roundingMode: .bankers) - XCTAssertEqual(-8.4, result.doubleValue, accuracy: 0.0001) + #expect((-8.4001 ... -8.3009).contains(result.doubleValue)) let minusFourPointNineEightFive = Decimal(-4.985) result = try minusFourPointNineEightFive._round(scale: 2, roundingMode: .bankers) - XCTAssertEqual(-4.98, result.doubleValue, accuracy: 0.0001) + #expect((-4.9801 ... -4.9709).contains(result.doubleValue)) } - func test_Round() throws { + @Test func round() throws { let testCases: [(Double, Double, Int, Decimal.RoundingMode)] = [ // expected, start, scale, round ( 0, 0.5, 0, .down ), @@ -862,16 +732,16 @@ final class DecimalTests : XCTestCase { let (expected, start, scale, mode) = testCase let num = Decimal(start) let actual = try num._round(scale: scale, roundingMode: mode) - XCTAssertEqual(Decimal(expected), actual, "Failed test case: \(testCase)") + #expect(Decimal(expected) == actual, "Failed test case: \(testCase)") } } - func test_Maths() { + @Test func maths() { for i in -2...10 { for j in 0...5 { - XCTAssertEqual(Decimal(i*j), Decimal(i) * Decimal(j), "\(Decimal(i*j)) == \(i) * \(j)") - XCTAssertEqual(Decimal(i+j), Decimal(i) + Decimal(j), "\(Decimal(i+j)) == \(i)+\(j)") - XCTAssertEqual(Decimal(i-j), Decimal(i) - Decimal(j), "\(Decimal(i-j)) == \(i)-\(j)") + #expect(Decimal(i*j) == Decimal(i) * Decimal(j), "\(Decimal(i*j)) == \(i) * \(j)") + #expect(Decimal(i+j) == Decimal(i) + Decimal(j), "\(Decimal(i+j)) == \(i)+\(j)") + #expect(Decimal(i-j) == Decimal(i) - Decimal(j), "\(Decimal(i-j)) == \(i)-\(j)") if j != 0 { let approximation = Decimal(Double(i)/Double(j)) let answer = Decimal(i) / Decimal(j) @@ -893,185 +763,175 @@ final class DecimalTests : XCTestCase { } count += 1 } - XCTAssertFalse(failed, "\(Decimal(i/j)) == \(i)/\(j)") + #expect(!failed, "\(Decimal(i/j)) == \(i)/\(j)") } } } - XCTAssertEqual(Decimal(186243 * 15673 as Int64), Decimal(186243) * Decimal(15673)) + #expect(Decimal(186243 * 15673 as Int64) == Decimal(186243) * Decimal(15673)) - XCTAssertEqual(Decimal(string: "5538")! + Decimal(string: "2880.4")!, Decimal(string: "8418.4")!) + #expect(Decimal(string: "5538")! + Decimal(string: "2880.4")! == Decimal(string: "8418.4")!) - XCTAssertEqual(Decimal(string: "5538.0")! - Decimal(string: "2880.4")!, Decimal(string: "2657.6")!) - XCTAssertEqual(Decimal(string: "2880.4")! - Decimal(5538), Decimal(string: "-2657.6")!) - XCTAssertEqual(Decimal(0x10000) - Decimal(0x1000), Decimal(0xf000)) + #expect(Decimal(string: "5538.0")! - Decimal(string: "2880.4")! == Decimal(string: "2657.6")!) + #expect(Decimal(string: "2880.4")! - Decimal(5538) == Decimal(string: "-2657.6")!) + #expect(Decimal(0x10000) - Decimal(0x1000) == Decimal(0xf000)) #if !os(watchOS) - XCTAssertEqual(Decimal(0x1_0000_0000) - Decimal(0x1000), Decimal(0xFFFFF000)) - XCTAssertEqual(Decimal(0x1_0000_0000_0000) - Decimal(0x1000), Decimal(0xFFFFFFFFF000)) + #expect(Decimal(0x1_0000_0000) - Decimal(0x1000) == Decimal(0xFFFFF000)) + #expect(Decimal(0x1_0000_0000_0000) - Decimal(0x1000) == Decimal(0xFFFFFFFFF000)) #endif - XCTAssertEqual(Decimal(1234_5678_9012_3456_7899 as UInt64) - Decimal(1234_5678_9012_3456_7890 as UInt64), Decimal(9)) - XCTAssertEqual(Decimal(0xffdd_bb00_8866_4422 as UInt64) - Decimal(0x7777_7777), Decimal(0xFFDD_BB00_10EE_CCAB as UInt64)) + #expect(Decimal(1234_5678_9012_3456_7899 as UInt64) - Decimal(1234_5678_9012_3456_7890 as UInt64) == Decimal(9)) + #expect(Decimal(0xffdd_bb00_8866_4422 as UInt64) - Decimal(0x7777_7777) == Decimal(0xFFDD_BB00_10EE_CCAB as UInt64)) let highBit = Decimal(_exponent: 0, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8000)) let otherBits = Decimal(_exponent: 0, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x7fff)) - XCTAssertEqual(highBit - otherBits, Decimal(1)) - XCTAssertEqual(otherBits + Decimal(1), highBit) + #expect(highBit - otherBits == Decimal(1)) + #expect(otherBits + Decimal(1) == highBit) } - func testMisc() throws { - XCTAssertEqual(Decimal(-5.2).sign, .minus) - XCTAssertEqual(Decimal(5.2).sign, .plus) + @Test func misc() throws { + #expect(Decimal(-5.2).sign == .minus) + #expect(Decimal(5.2).sign == .plus) var d = Decimal(5.2) - XCTAssertEqual(d.sign, .plus) + #expect(d.sign == .plus) d.negate() - XCTAssertEqual(d.sign, .minus) + #expect(d.sign == .minus) d.negate() - XCTAssertEqual(d.sign, .plus) + #expect(d.sign == .plus) var e = Decimal(0) e.negate() - XCTAssertEqual(e, Decimal(0)) - XCTAssertTrue(Decimal(3.5).isEqual(to: Decimal(3.5))) - XCTAssertTrue(Decimal.nan.isEqual(to: Decimal.nan)) - XCTAssertTrue(Decimal(1.28).isLess(than: Decimal(2.24))) - XCTAssertFalse(Decimal(2.28).isLess(than: Decimal(2.24))) - XCTAssertTrue(Decimal(1.28).isTotallyOrdered(belowOrEqualTo: Decimal(2.24))) - XCTAssertFalse(Decimal(2.28).isTotallyOrdered(belowOrEqualTo: Decimal(2.24))) - XCTAssertTrue(Decimal(1.2).isTotallyOrdered(belowOrEqualTo: Decimal(1.2))) - XCTAssertTrue(Decimal.nan.isEqual(to: Decimal.nan)) - XCTAssertTrue(Decimal.nan.isLess(than: Decimal(0))) - XCTAssertFalse(Decimal.nan.isLess(than: Decimal.nan)) - XCTAssertTrue(Decimal.nan.isLessThanOrEqualTo(Decimal(0))) - XCTAssertTrue(Decimal.nan.isLessThanOrEqualTo(Decimal.nan)) - XCTAssertFalse(Decimal.nan.isTotallyOrdered(belowOrEqualTo: Decimal.nan)) - XCTAssertFalse(Decimal.nan.isTotallyOrdered(belowOrEqualTo: Decimal(2.3))) - XCTAssertTrue(Decimal(2) < Decimal(3)) - XCTAssertTrue(Decimal(3) > Decimal(2)) - XCTAssertEqual(Decimal(-9), Decimal(1) - Decimal(10)) - XCTAssertEqual(Decimal(476), Decimal(1024).distance(to: Decimal(1500))) - XCTAssertEqual(Decimal(68040), Decimal(386).advanced(by: Decimal(67654))) - XCTAssertEqual(Decimal(1.234), abs(Decimal(1.234))) - XCTAssertEqual(Decimal(1.234), abs(Decimal(-1.234))) - XCTAssertTrue(Decimal.nan.magnitude.isNaN) - XCTAssertEqual(Decimal.leastFiniteMagnitude.magnitude, -Decimal.leastFiniteMagnitude) - - XCTAssertEqual(Decimal(-9), Decimal(1) - Decimal(10)) - XCTAssertEqual(Decimal(1.234), abs(Decimal(1.234))) - XCTAssertEqual(Decimal(1.234), abs(Decimal(-1.234))) - XCTAssertEqual((0 as Decimal).magnitude, 0 as Decimal) - XCTAssertEqual((1 as Decimal).magnitude, 1 as Decimal) - XCTAssertEqual((1 as Decimal).magnitude, abs(1 as Decimal)) - XCTAssertEqual((1 as Decimal).magnitude, abs(-1 as Decimal)) - XCTAssertEqual((-1 as Decimal).magnitude, abs(-1 as Decimal)) - XCTAssertEqual((-1 as Decimal).magnitude, abs(1 as Decimal)) - XCTAssertEqual(Decimal.greatestFiniteMagnitude.magnitude, Decimal.greatestFiniteMagnitude) + #expect(e == Decimal(0)) + #expect(Decimal(3.5).isEqual(to: Decimal(3.5))) + #expect(Decimal.nan.isEqual(to: Decimal.nan)) + #expect(Decimal(1.28).isLess(than: Decimal(2.24))) + #expect(!Decimal(2.28).isLess(than: Decimal(2.24))) + #expect(Decimal(1.28).isTotallyOrdered(belowOrEqualTo: Decimal(2.24))) + #expect(!Decimal(2.28).isTotallyOrdered(belowOrEqualTo: Decimal(2.24))) + #expect(Decimal(1.2).isTotallyOrdered(belowOrEqualTo: Decimal(1.2))) + #expect(Decimal.nan.isEqual(to: Decimal.nan)) + #expect(Decimal.nan.isLess(than: Decimal(0))) + #expect(!Decimal.nan.isLess(than: Decimal.nan)) + #expect(Decimal.nan.isLessThanOrEqualTo(Decimal(0))) + #expect(Decimal.nan.isLessThanOrEqualTo(Decimal.nan)) + #expect(!Decimal.nan.isTotallyOrdered(belowOrEqualTo: Decimal.nan)) + #expect(!Decimal.nan.isTotallyOrdered(belowOrEqualTo: Decimal(2.3))) + #expect(Decimal(2) < Decimal(3)) + #expect(Decimal(3) > Decimal(2)) + #expect(Decimal(-9) == Decimal(1) - Decimal(10)) + #expect(Decimal(476) == Decimal(1024).distance(to: Decimal(1500))) + #expect(Decimal(68040) == Decimal(386).advanced(by: Decimal(67654))) + #expect(Decimal(1.234) == abs(Decimal(1.234))) + #expect(Decimal(1.234) == abs(Decimal(-1.234))) + #expect(Decimal.nan.magnitude.isNaN) + #expect(Decimal.leastFiniteMagnitude.magnitude == -Decimal.leastFiniteMagnitude) + + #expect(Decimal(-9) == Decimal(1) - Decimal(10)) + #expect(Decimal(1.234) == abs(Decimal(1.234))) + #expect(Decimal(1.234) == abs(Decimal(-1.234))) + #expect((0 as Decimal).magnitude == 0 as Decimal) + #expect((1 as Decimal).magnitude == 1 as Decimal) + #expect((1 as Decimal).magnitude == abs(1 as Decimal)) + #expect((1 as Decimal).magnitude == abs(-1 as Decimal)) + #expect((-1 as Decimal).magnitude == abs(-1 as Decimal)) + #expect((-1 as Decimal).magnitude == abs(1 as Decimal)) + #expect(Decimal.greatestFiniteMagnitude.magnitude == Decimal.greatestFiniteMagnitude) var a = Decimal(1234) var result = try a._multiplyByPowerOfTen(power: 1, roundingMode: .plain) - XCTAssertEqual(Decimal(12340), result) + #expect(Decimal(12340) == result) a = Decimal(1234) result = try a._multiplyByPowerOfTen(power: 2, roundingMode: .plain) - XCTAssertEqual(Decimal(123400), result) + #expect(Decimal(123400) == result) a = result - do { + #expect { result = try a._multiplyByPowerOfTen(power: 128, roundingMode: .plain) - XCTFail("Expected to throw _CalcuationError.overflow") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Expected Decimal._CalculationError, got \(error)") - return - } - XCTAssertEqual(.overflow, calculationError) + } throws: { + ($0 as? Decimal._CalculationError) == .overflow } a = Decimal(1234) result = try a._multiplyByPowerOfTen(power: -2, roundingMode: .plain) - XCTAssertEqual(Decimal(12.34), result) + #expect(Decimal(12.34) == result) a = result - do { + #expect { result = try a._multiplyByPowerOfTen(power: -128, roundingMode: .plain) - XCTFail("Expected to throw _CalcuationError.underflow") - } catch { - guard let calculationError = error as? Decimal._CalculationError else { - XCTFail("Expected Decimal._CalculationError, got \(error)") - return - } - XCTAssertEqual(.underflow, calculationError) + } throws: { + ($0 as? Decimal._CalculationError) == .underflow } a = Decimal(1234) result = try a._power(exponent: 0, roundingMode: .plain) - XCTAssertEqual(Decimal(1), result) + #expect(Decimal(1) == result) a = Decimal(8) result = try a._power(exponent: 2, roundingMode: .plain) - XCTAssertEqual(Decimal(64), result) + #expect(Decimal(64) == result) a = Decimal(-2) result = try a._power(exponent: 3, roundingMode: .plain) - XCTAssertEqual(Decimal(-8), result) + #expect(Decimal(-8) == result) for i in -2...10 { for j in 0...5 { let power = Decimal(i) let actual = try power._power(exponent: j, roundingMode: .plain) let expected = Decimal(pow(Double(i), Double(j))) - XCTAssertEqual(expected, actual, "\(actual) == \(i)^\(j)") - XCTAssertEqual(expected, try power._power(exponent: j, roundingMode: .plain)) + #expect(expected == actual, "\(actual) == \(i)^\(j)") + #expect(try expected == power._power(exponent: j, roundingMode: .plain)) } } do { // SR-13015 - let a = try XCTUnwrap(Decimal(string: "119.993")) - let b = try XCTUnwrap(Decimal(string: "4.1565")) - let c = try XCTUnwrap(Decimal(string: "18.209")) - let d = try XCTUnwrap(Decimal(string: "258.469")) + let a = try #require(Decimal(string: "119.993")) + let b = try #require(Decimal(string: "4.1565")) + let c = try #require(Decimal(string: "18.209")) + let d = try #require(Decimal(string: "258.469")) let ab = a * b let aDivD = a / d let caDivD = c * aDivD - XCTAssertEqual(ab, try XCTUnwrap(Decimal(string: "498.7509045"))) - XCTAssertEqual(aDivD, try XCTUnwrap(Decimal(string: "0.46424522863476857959755328492004843907"))) - XCTAssertEqual(caDivD, try XCTUnwrap(Decimal(string: "8.453441368210501065891847765109162027"))) + #expect(try ab == #require(Decimal(string: "498.7509045"))) + #expect(try aDivD == #require(Decimal(string: "0.46424522863476857959755328492004843907"))) + #expect(try caDivD == #require(Decimal(string: "8.453441368210501065891847765109162027"))) let result = (a * b) + (c * (a / d)) - XCTAssertEqual(result, try XCTUnwrap(Decimal(string: "507.2043458682105010658918477651091"))) + #expect(try result == #require(Decimal(string: "507.2043458682105010658918477651091"))) } } - func test_Constants() { + @Test func constants() { let smallest = Decimal(_exponent: 127, _length: 8, _isNegative: 1, _isCompact: 1, _reserved: 0, _mantissa: (UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max)) - XCTAssertEqual(smallest, Decimal.leastFiniteMagnitude) + #expect(smallest == Decimal.leastFiniteMagnitude) let biggest = Decimal(_exponent: 127, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max)) - XCTAssertEqual(biggest, Decimal.greatestFiniteMagnitude) + #expect(biggest == Decimal.greatestFiniteMagnitude) let leastNormal = Decimal(_exponent: -127, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (1, 0, 0, 0, 0, 0, 0, 0)) - XCTAssertEqual(leastNormal, Decimal.leastNormalMagnitude) + #expect(leastNormal == Decimal.leastNormalMagnitude) let leastNonzero = Decimal(_exponent: -127, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (1, 0, 0, 0, 0, 0, 0, 0)) - XCTAssertEqual(leastNonzero, Decimal.leastNonzeroMagnitude) + #expect(leastNonzero == Decimal.leastNonzeroMagnitude) let pi = Decimal(_exponent: -38, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0x6623, 0x7d57, 0x16e7, 0xad0d, 0xaf52, 0x4641, 0xdfa7, 0xec58)) - XCTAssertEqual(pi, Decimal.pi) - XCTAssertEqual(10, Decimal.radix) - XCTAssertTrue(Decimal().isCanonical) - XCTAssertFalse(Decimal().isSignalingNaN) - XCTAssertFalse(Decimal.nan.isSignalingNaN) - XCTAssertTrue(Decimal.nan.isNaN) - XCTAssertEqual(.quietNaN, Decimal.nan.floatingPointClass) - XCTAssertEqual(.positiveZero, Decimal().floatingPointClass) - XCTAssertEqual(.negativeNormal, smallest.floatingPointClass) - XCTAssertEqual(.positiveNormal, biggest.floatingPointClass) - XCTAssertFalse(Double.nan.isFinite) - XCTAssertFalse(Double.nan.isInfinite) + #expect(pi == Decimal.pi) + #expect(10 == Decimal.radix) + #expect(Decimal().isCanonical) + #expect(!Decimal().isSignalingNaN) + #expect(!Decimal.nan.isSignalingNaN) + #expect(Decimal.nan.isNaN) + #expect(.quietNaN == Decimal.nan.floatingPointClass) + #expect(.positiveZero == Decimal().floatingPointClass) + #expect(.negativeNormal == smallest.floatingPointClass) + #expect(.positiveNormal == biggest.floatingPointClass) + #expect(!Double.nan.isFinite) + #expect(!Double.nan.isInfinite) } - func test_parseDouble() throws { - XCTAssertEqual(Decimal(Double(0.0)), Decimal(Int.zero)) - XCTAssertEqual(Decimal(Double(-0.0)), Decimal(Int.zero)) + @Test func parseDouble() throws { + #expect(Decimal(Double(0.0)) == Decimal(Int.zero)) + #expect(Decimal(Double(-0.0)) == Decimal(Int.zero)) // These values can only be represented as Decimal.nan - XCTAssertEqual(Decimal(Double.nan), Decimal.nan) - XCTAssertEqual(Decimal(Double.signalingNaN), Decimal.nan) + #expect(Decimal(Double.nan) == Decimal.nan) + #expect(Decimal(Double.signalingNaN) == Decimal.nan) // These values are out out range for Decimal - XCTAssertEqual(Decimal(-Double.leastNonzeroMagnitude), Decimal.nan) - XCTAssertEqual(Decimal(Double.leastNonzeroMagnitude), Decimal.nan) - XCTAssertEqual(Decimal(-Double.leastNormalMagnitude), Decimal.nan) - XCTAssertEqual(Decimal(Double.leastNormalMagnitude), Decimal.nan) - XCTAssertEqual(Decimal(-Double.greatestFiniteMagnitude), Decimal.nan) - XCTAssertEqual(Decimal(Double.greatestFiniteMagnitude), Decimal.nan) + #expect(Decimal(-Double.leastNonzeroMagnitude) == Decimal.nan) + #expect(Decimal(Double.leastNonzeroMagnitude) == Decimal.nan) + #expect(Decimal(-Double.leastNormalMagnitude) == Decimal.nan) + #expect(Decimal(Double.leastNormalMagnitude) == Decimal.nan) + #expect(Decimal(-Double.greatestFiniteMagnitude) == Decimal.nan) + #expect(Decimal(Double.greatestFiniteMagnitude) == Decimal.nan) // SR-13837 let testDoubles: [(Double, String)] = [ @@ -1098,124 +958,116 @@ final class DecimalTests : XCTestCase { ] for (d, s) in testDoubles { - XCTAssertEqual(Decimal(d), Decimal(string: s)) - XCTAssertEqual(Decimal(d).description, try XCTUnwrap(Decimal(string: s)).description) + #expect(Decimal(d) == Decimal(string: s)) + #expect(try Decimal(d).description == #require(Decimal(string: s)).description) } } - func test_initExactly() { + @Test func initExactly() throws { // This really requires some tests using a BinaryInteger of bitwidth > 128 to test failures. - let d1 = Decimal(exactly: UInt64.max) - XCTAssertNotNil(d1) - XCTAssertEqual(d1?.description, UInt64.max.description) - XCTAssertEqual(d1?._length, 4) - - let d2 = Decimal(exactly: Int64.min) - XCTAssertNotNil(d2) - XCTAssertEqual(d2?.description, Int64.min.description) - XCTAssertEqual(d2?._length, 4) - - let d3 = Decimal(exactly: Int64.max) - XCTAssertNotNil(d3) - XCTAssertEqual(d3?.description, Int64.max.description) - XCTAssertEqual(d3?._length, 4) - - let d4 = Decimal(exactly: Int32.min) - XCTAssertNotNil(d4) - XCTAssertEqual(d4?.description, Int32.min.description) - XCTAssertEqual(d4?._length, 2) - - let d5 = Decimal(exactly: Int32.max) - XCTAssertNotNil(d5) - XCTAssertEqual(d5?.description, Int32.max.description) - XCTAssertEqual(d5?._length, 2) - - let d6 = Decimal(exactly: 0) - XCTAssertNotNil(d6) - XCTAssertEqual(d6, Decimal.zero) - XCTAssertEqual(d6?.description, "0") - XCTAssertEqual(d6?._length, 0) - - let d7 = Decimal(exactly: 1) - XCTAssertNotNil(d7) - XCTAssertEqual(d7?.description, "1") - XCTAssertEqual(d7?._length, 1) - - let d8 = Decimal(exactly: -1) - XCTAssertNotNil(d8) - XCTAssertEqual(d8?.description, "-1") - XCTAssertEqual(d8?._length, 1) + let d1 = try #require(Decimal(exactly: UInt64.max)) + #expect(d1.description == UInt64.max.description) + #expect(d1._length == 4) + + let d2 = try #require(Decimal(exactly: Int64.min)) + #expect(d2.description == Int64.min.description) + #expect(d2._length == 4) + + let d3 = try #require(Decimal(exactly: Int64.max)) + #expect(d3.description == Int64.max.description) + #expect(d3._length == 4) + + let d4 = try #require(Decimal(exactly: Int32.min)) + #expect(d4.description == Int32.min.description) + #expect(d4._length == 2) + + let d5 = try #require(Decimal(exactly: Int32.max)) + #expect(d5.description == Int32.max.description) + #expect(d5._length == 2) + + let d6 = try #require(Decimal(exactly: 0)) + #expect(d6 == Decimal.zero) + #expect(d6.description == "0") + #expect(d6._length == 0) + + let d7 = try #require(Decimal(exactly: 1)) + #expect(d7.description == "1") + #expect(d7._length == 1) + + let d8 = try #require(Decimal(exactly: -1)) + #expect(d8.description == "-1") + #expect(d8._length == 1) } - func test_Strideable() { + @Test func strideable() { let x = 42 as Decimal - XCTAssertEqual(x.distance(to: 43), 1) - XCTAssertEqual(x.advanced(by: 1), 43) - XCTAssertEqual(x.distance(to: 41), -1) - XCTAssertEqual(x.advanced(by: -1), 41) + #expect(x.distance(to: 43) == 1) + #expect(x.advanced(by: 1) == 43) + #expect(x.distance(to: 41) == -1) + #expect(x.advanced(by: -1) == 41) } - func test_Significand() { + @Test func significand() { var x = -42 as Decimal - XCTAssertEqual(x.significand.sign, .plus) + #expect(x.significand.sign == .plus) var y = Decimal(sign: .plus, exponent: 0, significand: x) #if FOUNDATION_FRAMEWORK if Decimal.compatibility1 { - XCTAssertEqual(y, 42) + #expect(y == 42) y = Decimal(sign: .minus, exponent: 0, significand: x) - XCTAssertEqual(y, -42) + #expect(y == -42) } else { - XCTAssertEqual(y, -42) + #expect(y == -42) y = Decimal(sign: .minus, exponent: 0, significand: x) - XCTAssertEqual(y, 42) + #expect(y == 42) } #else - XCTAssertEqual(y, -42) + #expect(y == -42) y = Decimal(sign: .minus, exponent: 0, significand: x) - XCTAssertEqual(y, 42) + #expect(y == 42) #endif x = 42 as Decimal - XCTAssertEqual(x.significand.sign, .plus) + #expect(x.significand.sign == .plus) y = Decimal(sign: .plus, exponent: 0, significand: x) - XCTAssertEqual(y, 42) + #expect(y == 42) y = Decimal(sign: .minus, exponent: 0, significand: x) - XCTAssertEqual(y, -42) + #expect(y == -42) let a = Decimal.leastNonzeroMagnitude - XCTAssertEqual(Decimal(sign: .plus, exponent: -10, significand: a), 0) - XCTAssertEqual(Decimal(sign: .plus, exponent: .min, significand: a), 0) + #expect(Decimal(sign: .plus, exponent: -10, significand: a) == 0) + #expect(Decimal(sign: .plus, exponent: .min, significand: a) == 0) let b = Decimal.greatestFiniteMagnitude - XCTAssertTrue(Decimal(sign: .plus, exponent: 10, significand: b).isNaN) - XCTAssertTrue(Decimal(sign: .plus, exponent: .max, significand: b).isNaN) + #expect(Decimal(sign: .plus, exponent: 10, significand: b).isNaN) + #expect(Decimal(sign: .plus, exponent: .max, significand: b).isNaN) } - func test_ULP() { + @Test func ULP() { var x = 0.1 as Decimal - XCTAssertFalse(x.ulp > x) + #expect(!(x.ulp > x)) x = .nan - XCTAssertTrue(x.ulp.isNaN) - XCTAssertTrue(x.nextDown.isNaN) - XCTAssertTrue(x.nextUp.isNaN) + #expect(x.ulp.isNaN) + #expect(x.nextDown.isNaN) + #expect(x.nextUp.isNaN) x = .greatestFiniteMagnitude - XCTAssertEqual(x.ulp, Decimal(string: "1e127")!) - XCTAssertEqual(x.nextDown, x - Decimal(string: "1e127")!) - XCTAssertTrue(x.nextUp.isNaN) + #expect(x.ulp == Decimal(string: "1e127")!) + #expect(x.nextDown == x - Decimal(string: "1e127")!) + #expect(x.nextUp.isNaN) // '4' is an important value to test because the max supported // significand of this type is not 10 ** 38 - 1 but rather 2 ** 128 - 1, // for which reason '4.ulp' is not equal to '1.ulp' despite having the // same decimal exponent. x = 4 - XCTAssertEqual(x.ulp, Decimal(string: "1e-37")!) - XCTAssertEqual(x.nextDown, x - Decimal(string: "1e-37")!) - XCTAssertEqual(x.nextUp, x + Decimal(string: "1e-37")!) - XCTAssertEqual(x.nextDown.nextUp, x) - XCTAssertEqual(x.nextUp.nextDown, x) - XCTAssertNotEqual(x.nextDown, x) - XCTAssertNotEqual(x.nextUp, x) + #expect(x.ulp == Decimal(string: "1e-37")!) + #expect(x.nextDown == x - Decimal(string: "1e-37")!) + #expect(x.nextUp == x + Decimal(string: "1e-37")!) + #expect(x.nextDown.nextUp == x) + #expect(x.nextUp.nextDown == x) + #expect(x.nextDown != x) + #expect(x.nextUp != x) // For similar reasons, '3.40282366920938463463374607431768211455', // which has the same significand as 'Decimal.greatestFiniteMagnitude', @@ -1223,85 +1075,75 @@ final class DecimalTests : XCTestCase { // representable value is more than 'ulp' and instead requires // incrementing '_exponent'. x = Decimal(string: "3.40282366920938463463374607431768211455")! - XCTAssertEqual(x.ulp, Decimal(string: "0.00000000000000000000000000000000000001")!) - XCTAssertEqual(x.nextUp, Decimal(string: "3.4028236692093846346337460743176821146")!) + #expect(x.ulp == Decimal(string: "0.00000000000000000000000000000000000001")!) + #expect(x.nextUp == Decimal(string: "3.4028236692093846346337460743176821146")!) x = Decimal(string: "3.4028236692093846346337460743176821146")! - XCTAssertEqual(x.ulp, Decimal(string: "0.0000000000000000000000000000000000001")!) - XCTAssertEqual(x.nextDown, Decimal(string: "3.40282366920938463463374607431768211455")!) + #expect(x.ulp == Decimal(string: "0.0000000000000000000000000000000000001")!) + #expect(x.nextDown == Decimal(string: "3.40282366920938463463374607431768211455")!) x = 1 - XCTAssertEqual(x.ulp, Decimal(string: "1e-38")!) - XCTAssertEqual(x.nextDown, x - Decimal(string: "1e-38")!) - XCTAssertEqual(x.nextUp, x + Decimal(string: "1e-38")!) - XCTAssertEqual(x.nextDown.nextUp, x) - XCTAssertEqual(x.nextUp.nextDown, x) - XCTAssertNotEqual(x.nextDown, x) - XCTAssertNotEqual(x.nextUp, x) + #expect(x.ulp == Decimal(string: "1e-38")!) + #expect(x.nextDown == x - Decimal(string: "1e-38")!) + #expect(x.nextUp == x + Decimal(string: "1e-38")!) + #expect(x.nextDown.nextUp == x) + #expect(x.nextUp.nextDown == x) + #expect(x.nextDown != x) + #expect(x.nextUp != x) x = 0 - XCTAssertEqual(x.ulp, Decimal(string: "1e-128")!) - XCTAssertEqual(x.nextDown, -Decimal(string: "1e-128")!) - XCTAssertEqual(x.nextUp, Decimal(string: "1e-128")!) - XCTAssertEqual(x.nextDown.nextUp, x) - XCTAssertEqual(x.nextUp.nextDown, x) - XCTAssertNotEqual(x.nextDown, x) - XCTAssertNotEqual(x.nextUp, x) + #expect(x.ulp == Decimal(string: "1e-128")!) + #expect(x.nextDown == -Decimal(string: "1e-128")!) + #expect(x.nextUp == Decimal(string: "1e-128")!) + #expect(x.nextDown.nextUp == x) + #expect(x.nextUp.nextDown == x) + #expect(x.nextDown != x) + #expect(x.nextUp != x) x = -1 - XCTAssertEqual(x.ulp, Decimal(string: "1e-38")!) - XCTAssertEqual(x.nextDown, x - Decimal(string: "1e-38")!) - XCTAssertEqual(x.nextUp, x + Decimal(string: "1e-38")!) + #expect(x.ulp == Decimal(string: "1e-38")!) + #expect(x.nextDown == x - Decimal(string: "1e-38")!) + #expect(x.nextUp == x + Decimal(string: "1e-38")!) let y = x - x.ulp + x.ulp - XCTAssertEqual(x, y) - XCTAssertEqual(x.nextDown.nextUp, x) - XCTAssertEqual(x.nextUp.nextDown, x) - XCTAssertNotEqual(x.nextDown, x) - XCTAssertNotEqual(x.nextUp, x) - } - - #if FOUNDATION_FRAMEWORK - #else - func test_toString() { - let decimal = Decimal(string: "-123456.789")! - XCTAssertEqual(decimal._toString(withDecimalSeparator: "."), "-123456.789") - let en = decimal._toString(withDecimalSeparator: Locale(identifier: "en_GB").decimalSeparator!) - XCTAssertEqual(en, "-123456.789") - let fr = decimal._toString(withDecimalSeparator: Locale(identifier: "fr_FR").decimalSeparator!) - XCTAssertEqual(fr, "-123456,789") + #expect(x == y) + #expect(x.nextDown.nextUp == x) + #expect(x.nextUp.nextDown == x) + #expect(x.nextDown != x) + #expect(x.nextUp != x) } - func test_int64Value() { - XCTAssertEqual(Decimal(-1).int64Value, -1) - XCTAssertEqual(Decimal(0).int64Value, 0) - XCTAssertEqual(Decimal(1).int64Value, 1) - XCTAssertEqual(Decimal.nan.int64Value, 0) - XCTAssertEqual(Decimal(1e50).int64Value, 0) - XCTAssertEqual(Decimal(1e-50).int64Value, 0) + #if !FOUNDATION_FRAMEWORK + @Test func int64Value() { + #expect(Decimal(-1).int64Value == -1) + #expect(Decimal(0).int64Value == 0) + #expect(Decimal(1).int64Value == 1) + #expect(Decimal.nan.int64Value == 0) + #expect(Decimal(1e50).int64Value == 0) + #expect(Decimal(1e-50).int64Value == 0) - XCTAssertEqual(Decimal(UInt64.max).uint64Value, UInt64.max) - XCTAssertEqual((Decimal(UInt64.max) + 1).uint64Value, 0) - XCTAssertEqual(Decimal(Int64.max).int64Value, Int64.max) - XCTAssertEqual((Decimal(Int64.max) + 1 ).int64Value, Int64.min) - XCTAssertEqual((Decimal(Int64.max) + 1 ).uint64Value, UInt64(Int64.max) + 1) - XCTAssertEqual(Decimal(Int64.min).int64Value, Int64.min) + #expect(Decimal(UInt64.max).uint64Value == UInt64.max) + #expect((Decimal(UInt64.max) + 1).uint64Value == 0) + #expect(Decimal(Int64.max).int64Value == Int64.max) + #expect((Decimal(Int64.max) + 1 ).int64Value == Int64.min) + #expect((Decimal(Int64.max) + 1 ).uint64Value == UInt64(Int64.max) + 1) + #expect(Decimal(Int64.min).int64Value == Int64.min) - XCTAssertEqual(Decimal(Int.min).int64Value, Int64(Int.min)) + #expect(Decimal(Int.min).int64Value == Int64(Int.min)) let div3 = Decimal(10) / 3 - XCTAssertEqual(div3.int64Value, 3) + #expect(div3.int64Value == 3) let pi = Decimal(Double.pi) - XCTAssertEqual(pi.int64Value, 3) + #expect(pi.int64Value == 3) } - func test_doubleValue() { - XCTAssertEqual(Decimal(0).doubleValue, 0) - XCTAssertEqual(Decimal(1).doubleValue, 1) - XCTAssertEqual(Decimal(-1).doubleValue, -1) - XCTAssertTrue(Decimal.nan.doubleValue.isNaN) - XCTAssertEqual(Decimal(UInt64.max).doubleValue, Double(1.8446744073709552e+19)) + @Test func doubleValue() { + #expect(Decimal(0).doubleValue == 0) + #expect(Decimal(1).doubleValue == 1) + #expect(Decimal(-1).doubleValue == -1) + #expect(Decimal.nan.doubleValue.isNaN) + #expect(Decimal(UInt64.max).doubleValue == Double(1.8446744073709552e+19)) } - func test_decimalFromString() { + @Test func decimalFromString() { let string = "x123x" let scanLocation = 1 @@ -1309,41 +1151,42 @@ final class DecimalTests : XCTestCase { let substring = string[start.. Date: Wed, 11 Jun 2025 14:53:04 -0700 Subject: [PATCH 11/12] Convert IndexPath tests --- .../IndexPathTests.swift | 707 +++++++++--------- 1 file changed, 353 insertions(+), 354 deletions(-) diff --git a/Tests/FoundationEssentialsTests/IndexPathTests.swift b/Tests/FoundationEssentialsTests/IndexPathTests.swift index 365e2ddfd..0c6475a1c 100644 --- a/Tests/FoundationEssentialsTests/IndexPathTests.swift +++ b/Tests/FoundationEssentialsTests/IndexPathTests.swift @@ -7,224 +7,229 @@ //===----------------------------------------------------------------------===// // +import Testing + #if canImport(TestSupport) import TestSupport #endif #if canImport(FoundationEssentials) -@testable import FoundationEssentials +import FoundationEssentials +#else +import Foundation #endif -class TestIndexPath: XCTestCase { - func testEmpty() { +@Suite("IndexPath") +private struct TestIndexPath { + @Test func empty() { let ip = IndexPath() - XCTAssertEqual(ip.count, 0) + #expect(ip.count == 0) #if FOUNDATION_FRAMEWORK // Darwin allows nil if length is 0 let nsip = NSIndexPath(indexes: nil, length: 0) - XCTAssertEqual(nsip.length, 0) + #expect(nsip.length == 0) let newIp = nsip.adding(1) - XCTAssertEqual(newIp.count, 1) + #expect(newIp.count == 1) #endif } - func testSingleIndex() { + @Test func singleIndex() { let ip = IndexPath(index: 1) - XCTAssertEqual(ip.count, 1) - XCTAssertEqual(ip[0], 1) + #expect(ip.count == 1) + #expect(ip[0] == 1) let highValueIp = IndexPath(index: .max) - XCTAssertEqual(highValueIp.count, 1) - XCTAssertEqual(highValueIp[0], .max) + #expect(highValueIp.count == 1) + #expect(highValueIp[0] == .max) let lowValueIp = IndexPath(index: .min) - XCTAssertEqual(lowValueIp.count, 1) - XCTAssertEqual(lowValueIp[0], .min) + #expect(lowValueIp.count == 1) + #expect(lowValueIp[0] == .min) } - func testTwoIndexes() { + @Test func twoIndexes() { let ip = IndexPath(indexes: [0, 1]) - XCTAssertEqual(ip.count, 2) - XCTAssertEqual(ip[0], 0) - XCTAssertEqual(ip[1], 1) + #expect(ip.count == 2) + #expect(ip[0] == 0) + #expect(ip[1] == 1) } - func testManyIndexes() { + @Test func manyIndexes() { let ip = IndexPath(indexes: [0, 1, 2, 3, 4]) - XCTAssertEqual(ip.count, 5) - XCTAssertEqual(ip[0], 0) - XCTAssertEqual(ip[1], 1) - XCTAssertEqual(ip[2], 2) - XCTAssertEqual(ip[3], 3) - XCTAssertEqual(ip[4], 4) + #expect(ip.count == 5) + #expect(ip[0] == 0) + #expect(ip[1] == 1) + #expect(ip[2] == 2) + #expect(ip[3] == 3) + #expect(ip[4] == 4) } - func testCreateFromSequence() { + @Test func createFromSequence() { let seq = repeatElement(5, count: 3) let ip = IndexPath(indexes: seq) - XCTAssertEqual(ip.count, 3) - XCTAssertEqual(ip[0], 5) - XCTAssertEqual(ip[1], 5) - XCTAssertEqual(ip[2], 5) + #expect(ip.count == 3) + #expect(ip[0] == 5) + #expect(ip[1] == 5) + #expect(ip[2] == 5) } - func testCreateFromLiteral() { + @Test func createFromLiteral() { let ip: IndexPath = [1, 2, 3, 4] - XCTAssertEqual(ip.count, 4) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[1], 2) - XCTAssertEqual(ip[2], 3) - XCTAssertEqual(ip[3], 4) + #expect(ip.count == 4) + #expect(ip[0] == 1) + #expect(ip[1] == 2) + #expect(ip[2] == 3) + #expect(ip[3] == 4) } - func testDropLast() { + @Test func dropLast() { let ip: IndexPath = [1, 2, 3, 4] let ip2 = ip.dropLast() - XCTAssertEqual(ip2.count, 3) - XCTAssertEqual(ip2[0], 1) - XCTAssertEqual(ip2[1], 2) - XCTAssertEqual(ip2[2], 3) + #expect(ip2.count == 3) + #expect(ip2[0] == 1) + #expect(ip2[1] == 2) + #expect(ip2[2] == 3) } - func testDropLastFromEmpty() { + @Test func dropLastFromEmpty() { let ip: IndexPath = [] let ip2 = ip.dropLast() - XCTAssertEqual(ip2.count, 0) + #expect(ip2.count == 0) } - func testDropLastFromSingle() { + @Test func dropLastFromSingle() { let ip: IndexPath = [1] let ip2 = ip.dropLast() - XCTAssertEqual(ip2.count, 0) + #expect(ip2.count == 0) } - func testDropLastFromPair() { + @Test func dropLastFromPair() { let ip: IndexPath = [1, 2] let ip2 = ip.dropLast() - XCTAssertEqual(ip2.count, 1) - XCTAssertEqual(ip2[0], 1) + #expect(ip2.count == 1) + #expect(ip2[0] == 1) } - func testDropLastFromTriple() { + @Test func dropLastFromTriple() { let ip: IndexPath = [1, 2, 3] let ip2 = ip.dropLast() - XCTAssertEqual(ip2.count, 2) - XCTAssertEqual(ip2[0], 1) - XCTAssertEqual(ip2[1], 2) + #expect(ip2.count == 2) + #expect(ip2[0] == 1) + #expect(ip2[1] == 2) } - func testStartEndIndex() { + @Test func startEndIndex() { let ip: IndexPath = [1, 2, 3, 4] - XCTAssertEqual(ip.startIndex, 0) - XCTAssertEqual(ip.endIndex, ip.count) + #expect(ip.startIndex == 0) + #expect(ip.endIndex == ip.count) } - func testIterator() { + @Test func iterator() { let ip: IndexPath = [1, 2, 3, 4] var iter = ip.makeIterator() var sum = 0 while let index = iter.next() { sum += index } - XCTAssertEqual(sum, 1 + 2 + 3 + 4) + #expect(sum == 1 + 2 + 3 + 4) } - func testIndexing() { + @Test func indexing() { let ip: IndexPath = [1, 2, 3, 4] - XCTAssertEqual(ip.index(before: 1), 0) - XCTAssertEqual(ip.index(before: 0), -1) // beyond range! - XCTAssertEqual(ip.index(after: 1), 2) - XCTAssertEqual(ip.index(after: 4), 5) // beyond range! + #expect(ip.index(before: 1) == 0) + #expect(ip.index(before: 0) == -1) // beyond range! + #expect(ip.index(after: 1) == 2) + #expect(ip.index(after: 4) == 5) // beyond range! } - func testCompare() { + @Test func compare() { let ip1: IndexPath = [1, 2] let ip2: IndexPath = [3, 4] let ip3: IndexPath = [5, 1] let ip4: IndexPath = [1, 1, 1] let ip5: IndexPath = [1, 1, 9] - XCTAssertEqual(ip1.compare(ip1), ComparisonResult.orderedSame) - XCTAssertEqual(ip1 < ip1, false) - XCTAssertEqual(ip1 <= ip1, true) - XCTAssertEqual(ip1 == ip1, true) - XCTAssertEqual(ip1 >= ip1, true) - XCTAssertEqual(ip1 > ip1, false) - - XCTAssertEqual(ip1.compare(ip2), ComparisonResult.orderedAscending) - XCTAssertEqual(ip1 < ip2, true) - XCTAssertEqual(ip1 <= ip2, true) - XCTAssertEqual(ip1 == ip2, false) - XCTAssertEqual(ip1 >= ip2, false) - XCTAssertEqual(ip1 > ip2, false) - - XCTAssertEqual(ip1.compare(ip3), ComparisonResult.orderedAscending) - XCTAssertEqual(ip1 < ip3, true) - XCTAssertEqual(ip1 <= ip3, true) - XCTAssertEqual(ip1 == ip3, false) - XCTAssertEqual(ip1 >= ip3, false) - XCTAssertEqual(ip1 > ip3, false) - - XCTAssertEqual(ip1.compare(ip4), ComparisonResult.orderedDescending) - XCTAssertEqual(ip1 < ip4, false) - XCTAssertEqual(ip1 <= ip4, false) - XCTAssertEqual(ip1 == ip4, false) - XCTAssertEqual(ip1 >= ip4, true) - XCTAssertEqual(ip1 > ip4, true) - - XCTAssertEqual(ip1.compare(ip5), ComparisonResult.orderedDescending) - XCTAssertEqual(ip1 < ip5, false) - XCTAssertEqual(ip1 <= ip5, false) - XCTAssertEqual(ip1 == ip5, false) - XCTAssertEqual(ip1 >= ip5, true) - XCTAssertEqual(ip1 > ip5, true) - - XCTAssertEqual(ip2.compare(ip1), ComparisonResult.orderedDescending) - XCTAssertEqual(ip2 < ip1, false) - XCTAssertEqual(ip2 <= ip1, false) - XCTAssertEqual(ip2 == ip1, false) - XCTAssertEqual(ip2 >= ip1, true) - XCTAssertEqual(ip2 > ip1, true) - - XCTAssertEqual(ip2.compare(ip2), ComparisonResult.orderedSame) - XCTAssertEqual(ip2 < ip2, false) - XCTAssertEqual(ip2 <= ip2, true) - XCTAssertEqual(ip2 == ip2, true) - XCTAssertEqual(ip2 >= ip2, true) - XCTAssertEqual(ip2 > ip2, false) - - XCTAssertEqual(ip2.compare(ip3), ComparisonResult.orderedAscending) - XCTAssertEqual(ip2 < ip3, true) - XCTAssertEqual(ip2 <= ip3, true) - XCTAssertEqual(ip2 == ip3, false) - XCTAssertEqual(ip2 >= ip3, false) - XCTAssertEqual(ip2 > ip3, false) - - XCTAssertEqual(ip2.compare(ip4), ComparisonResult.orderedDescending) - XCTAssertEqual(ip2.compare(ip5), ComparisonResult.orderedDescending) - XCTAssertEqual(ip3.compare(ip1), ComparisonResult.orderedDescending) - XCTAssertEqual(ip3.compare(ip2), ComparisonResult.orderedDescending) - XCTAssertEqual(ip3.compare(ip3), ComparisonResult.orderedSame) - XCTAssertEqual(ip3.compare(ip4), ComparisonResult.orderedDescending) - XCTAssertEqual(ip3.compare(ip5), ComparisonResult.orderedDescending) - XCTAssertEqual(ip4.compare(ip1), ComparisonResult.orderedAscending) - XCTAssertEqual(ip4.compare(ip2), ComparisonResult.orderedAscending) - XCTAssertEqual(ip4.compare(ip3), ComparisonResult.orderedAscending) - XCTAssertEqual(ip4.compare(ip4), ComparisonResult.orderedSame) - XCTAssertEqual(ip4.compare(ip5), ComparisonResult.orderedAscending) - XCTAssertEqual(ip5.compare(ip1), ComparisonResult.orderedAscending) - XCTAssertEqual(ip5.compare(ip2), ComparisonResult.orderedAscending) - XCTAssertEqual(ip5.compare(ip3), ComparisonResult.orderedAscending) - XCTAssertEqual(ip5.compare(ip4), ComparisonResult.orderedDescending) - XCTAssertEqual(ip5.compare(ip5), ComparisonResult.orderedSame) + #expect(ip1.compare(ip1) == .orderedSame) + #expect(!(ip1 < ip1)) + #expect(ip1 <= ip1) + #expect(ip1 == ip1) + #expect(ip1 >= ip1) + #expect(!(ip1 > ip1)) + + #expect(ip1.compare(ip2) == .orderedAscending) + #expect(ip1 < ip2) + #expect(ip1 <= ip2) + #expect(!(ip1 == ip2)) + #expect(!(ip1 >= ip2)) + #expect(!(ip1 > ip2)) + + #expect(ip1.compare(ip3) == .orderedAscending) + #expect(ip1 < ip3) + #expect(ip1 <= ip3) + #expect(!(ip1 == ip3)) + #expect(!(ip1 >= ip3)) + #expect(!(ip1 > ip3)) + + #expect(ip1.compare(ip4) == .orderedDescending) + #expect(!(ip1 < ip4)) + #expect(!(ip1 <= ip4)) + #expect(!(ip1 == ip4)) + #expect(ip1 >= ip4) + #expect(ip1 > ip4) + + #expect(ip1.compare(ip5) == .orderedDescending) + #expect(!(ip1 < ip5)) + #expect(!(ip1 <= ip5)) + #expect(!(ip1 == ip5)) + #expect(ip1 >= ip5) + #expect(ip1 > ip5) + + #expect(ip2.compare(ip1) == .orderedDescending) + #expect(!(ip2 < ip1)) + #expect(!(ip2 <= ip1)) + #expect(!(ip2 == ip1)) + #expect(ip2 >= ip1) + #expect(ip2 > ip1) + + #expect(ip2.compare(ip2) == .orderedSame) + #expect(!(ip2 < ip2)) + #expect(ip2 <= ip2) + #expect(ip2 == ip2) + #expect(ip2 >= ip2) + #expect(!(ip2 > ip2)) + + #expect(ip2.compare(ip3) == .orderedAscending) + #expect(ip2 < ip3) + #expect(ip2 <= ip3) + #expect(!(ip2 == ip3)) + #expect(!(ip2 >= ip3)) + #expect(!(ip2 > ip3)) + + #expect(ip2.compare(ip4) == .orderedDescending) + #expect(ip2.compare(ip5) == .orderedDescending) + #expect(ip3.compare(ip1) == .orderedDescending) + #expect(ip3.compare(ip2) == .orderedDescending) + #expect(ip3.compare(ip3) == .orderedSame) + #expect(ip3.compare(ip4) == .orderedDescending) + #expect(ip3.compare(ip5) == .orderedDescending) + #expect(ip4.compare(ip1) == .orderedAscending) + #expect(ip4.compare(ip2) == .orderedAscending) + #expect(ip4.compare(ip3) == .orderedAscending) + #expect(ip4.compare(ip4) == .orderedSame) + #expect(ip4.compare(ip5) == .orderedAscending) + #expect(ip5.compare(ip1) == .orderedAscending) + #expect(ip5.compare(ip2) == .orderedAscending) + #expect(ip5.compare(ip3) == .orderedAscending) + #expect(ip5.compare(ip4) == .orderedDescending) + #expect(ip5.compare(ip5) == .orderedSame) let ip6: IndexPath = [1, 1] - XCTAssertEqual(ip6.compare(ip5), ComparisonResult.orderedAscending) - XCTAssertEqual(ip5.compare(ip6), ComparisonResult.orderedDescending) + #expect(ip6.compare(ip5) == .orderedAscending) + #expect(ip5.compare(ip6) == .orderedDescending) } - func testHashing() { + @Test func hashing() { let samples: [IndexPath] = [ [], [1], @@ -239,320 +244,320 @@ class TestIndexPath: XCTestCase { [1, 1, 2], [Int.max, Int.max, Int.max], ] - XCTCheckHashable(samples, equalityOracle: { $0 == $1 }) + checkHashable(samples, equalityOracle: { $0 == $1 }) // this should not cause an overflow crash _ = IndexPath(indexes: [Int.max >> 8, 2, Int.max >> 36]).hashValue } - func testEquality() { + @Test func equality() { let ip1: IndexPath = [1, 1] let ip2: IndexPath = [1, 1] let ip3: IndexPath = [1, 1, 1] let ip4: IndexPath = [] let ip5: IndexPath = [1] - XCTAssertTrue(ip1 == ip2) - XCTAssertFalse(ip1 == ip3) - XCTAssertFalse(ip1 == ip4) - XCTAssertFalse(ip4 == ip1) - XCTAssertFalse(ip5 == ip1) - XCTAssertFalse(ip5 == ip4) - XCTAssertTrue(ip4 == ip4) - XCTAssertTrue(ip5 == ip5) + #expect(ip1 == ip2) + #expect(ip1 != ip3) + #expect(ip1 != ip4) + #expect(ip4 != ip1) + #expect(ip5 != ip1) + #expect(ip5 != ip4) + #expect(ip4 == ip4) + #expect(ip5 == ip5) } - func testSubscripting() { + @Test func subscripting() { var ip1: IndexPath = [1] var ip2: IndexPath = [1, 2] var ip3: IndexPath = [1, 2, 3] - XCTAssertEqual(ip1[0], 1) + #expect(ip1[0] == 1) - XCTAssertEqual(ip2[0], 1) - XCTAssertEqual(ip2[1], 2) + #expect(ip2[0] == 1) + #expect(ip2[1] == 2) - XCTAssertEqual(ip3[0], 1) - XCTAssertEqual(ip3[1], 2) - XCTAssertEqual(ip3[2], 3) + #expect(ip3[0] == 1) + #expect(ip3[1] == 2) + #expect(ip3[2] == 3) ip1[0] = 2 - XCTAssertEqual(ip1[0], 2) + #expect(ip1[0] == 2) ip2[0] = 2 ip2[1] = 3 - XCTAssertEqual(ip2[0], 2) - XCTAssertEqual(ip2[1], 3) + #expect(ip2[0] == 2) + #expect(ip2[1] == 3) ip3[0] = 2 ip3[1] = 3 ip3[2] = 4 - XCTAssertEqual(ip3[0], 2) - XCTAssertEqual(ip3[1], 3) - XCTAssertEqual(ip3[2], 4) + #expect(ip3[0] == 2) + #expect(ip3[1] == 3) + #expect(ip3[2] == 4) let ip4 = ip3[0..<2] - XCTAssertEqual(ip4.count, 2) - XCTAssertEqual(ip4[0], 2) - XCTAssertEqual(ip4[1], 3) + #expect(ip4.count == 2) + #expect(ip4[0] == 2) + #expect(ip4[1] == 3) let ip5 = ip3[1...] - XCTAssertEqual(ip5.count, 2) - XCTAssertEqual(ip5[0], 3) - XCTAssertEqual(ip5[1], 4) + #expect(ip5.count == 2) + #expect(ip5[0] == 3) + #expect(ip5[1] == 4) let ip6 = ip3[2...] - XCTAssertEqual(ip6.count, 1) - XCTAssertEqual(ip6[0], 4) + #expect(ip6.count == 1) + #expect(ip6[0] == 4) } - func testAppending() { + @Test func appending() { var ip : IndexPath = [1, 2, 3, 4] let ip2 = IndexPath(indexes: [5, 6, 7]) ip.append(ip2) - XCTAssertEqual(ip.count, 7) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[6], 7) + #expect(ip.count == 7) + #expect(ip[0] == 1) + #expect(ip[6] == 7) let ip3 = ip.appending(IndexPath(indexes: [8, 9])) - XCTAssertEqual(ip3.count, 9) - XCTAssertEqual(ip3[7], 8) - XCTAssertEqual(ip3[8], 9) + #expect(ip3.count == 9) + #expect(ip3[7] == 8) + #expect(ip3[8] == 9) let ip4 = ip3.appending([10, 11]) - XCTAssertEqual(ip4.count, 11) - XCTAssertEqual(ip4[9], 10) - XCTAssertEqual(ip4[10], 11) + #expect(ip4.count == 11) + #expect(ip4[9] == 10) + #expect(ip4[10] == 11) let ip5 = ip.appending(8) - XCTAssertEqual(ip5.count, 8) - XCTAssertEqual(ip5[7], 8) + #expect(ip5.count == 8) + #expect(ip5[7] == 8) } - func testAppendEmpty() { + @Test func appendEmpty() { var ip: IndexPath = [] ip.append(1) - XCTAssertEqual(ip.count, 1) - XCTAssertEqual(ip[0], 1) + #expect(ip.count == 1) + #expect(ip[0] == 1) ip.append(2) - XCTAssertEqual(ip.count, 2) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[1], 2) + #expect(ip.count == 2) + #expect(ip[0] == 1) + #expect(ip[1] == 2) ip.append(3) - XCTAssertEqual(ip.count, 3) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[1], 2) - XCTAssertEqual(ip[2], 3) + #expect(ip.count == 3) + #expect(ip[0] == 1) + #expect(ip[1] == 2) + #expect(ip[2] == 3) ip.append(4) - XCTAssertEqual(ip.count, 4) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[1], 2) - XCTAssertEqual(ip[2], 3) - XCTAssertEqual(ip[3], 4) + #expect(ip.count == 4) + #expect(ip[0] == 1) + #expect(ip[1] == 2) + #expect(ip[2] == 3) + #expect(ip[3] == 4) } - func testAppendEmptyIndexPath() { + @Test func appendEmptyIndexPath() { var ip: IndexPath = [] ip.append(IndexPath(indexes: [])) - XCTAssertEqual(ip.count, 0) + #expect(ip.count == 0) } - func testAppendManyIndexPath() { + @Test func appendManyIndexPath() { var ip: IndexPath = [] ip.append(IndexPath(indexes: [1, 2, 3])) - XCTAssertEqual(ip.count, 3) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[1], 2) - XCTAssertEqual(ip[2], 3) + #expect(ip.count == 3) + #expect(ip[0] == 1) + #expect(ip[1] == 2) + #expect(ip[2] == 3) } - func testAppendEmptyIndexPathToSingle() { + @Test func appendEmptyIndexPathToSingle() { var ip: IndexPath = [1] ip.append(IndexPath(indexes: [])) - XCTAssertEqual(ip.count, 1) - XCTAssertEqual(ip[0], 1) + #expect(ip.count == 1) + #expect(ip[0] == 1) } - func testAppendSingleIndexPath() { + @Test func appendSingleIndexPath() { var ip: IndexPath = [] ip.append(IndexPath(indexes: [1])) - XCTAssertEqual(ip.count, 1) - XCTAssertEqual(ip[0], 1) + #expect(ip.count == 1) + #expect(ip[0] == 1) } - func testAppendSingleIndexPathToSingle() { + @Test func appendSingleIndexPathToSingle() { var ip: IndexPath = [1] ip.append(IndexPath(indexes: [1])) - XCTAssertEqual(ip.count, 2) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[1], 1) + #expect(ip.count == 2) + #expect(ip[0] == 1) + #expect(ip[1] == 1) } - func testAppendPairIndexPath() { + @Test func appendPairIndexPath() { var ip: IndexPath = [] ip.append(IndexPath(indexes: [1, 2])) - XCTAssertEqual(ip.count, 2) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[1], 2) + #expect(ip.count == 2) + #expect(ip[0] == 1) + #expect(ip[1] == 2) } - func testAppendManyIndexPathToEmpty() { + @Test func appendManyIndexPathToEmpty() { var ip: IndexPath = [] ip.append(IndexPath(indexes: [1, 2, 3])) - XCTAssertEqual(ip.count, 3) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[1], 2) - XCTAssertEqual(ip[2], 3) + #expect(ip.count == 3) + #expect(ip[0] == 1) + #expect(ip[1] == 2) + #expect(ip[2] == 3) } - func testAppendByOperator() { + @Test func appendByOperator() { let ip1: IndexPath = [] let ip2: IndexPath = [] let ip3 = ip1 + ip2 - XCTAssertEqual(ip3.count, 0) + #expect(ip3.count == 0) let ip4: IndexPath = [1] let ip5: IndexPath = [2] let ip6 = ip4 + ip5 - XCTAssertEqual(ip6.count, 2) - XCTAssertEqual(ip6[0], 1) - XCTAssertEqual(ip6[1], 2) + #expect(ip6.count == 2) + #expect(ip6[0] == 1) + #expect(ip6[1] == 2) var ip7: IndexPath = [] ip7 += ip6 - XCTAssertEqual(ip7.count, 2) - XCTAssertEqual(ip7[0], 1) - XCTAssertEqual(ip7[1], 2) + #expect(ip7.count == 2) + #expect(ip7[0] == 1) + #expect(ip7[1] == 2) } - func testAppendArray() { + @Test func appendArray() { var ip: IndexPath = [1, 2, 3, 4] let indexes = [5, 6, 7] ip.append(indexes) - XCTAssertEqual(ip.count, 7) - XCTAssertEqual(ip[0], 1) - XCTAssertEqual(ip[6], 7) + #expect(ip.count == 7) + #expect(ip[0] == 1) + #expect(ip[6] == 7) } - func testRanges() { + @Test func ranges() { let ip1 = IndexPath(indexes: [1, 2, 3]) let ip2 = IndexPath(indexes: [6, 7, 8]) // Replace the whole range var mutateMe = ip1 mutateMe[0..<3] = ip2 - XCTAssertEqual(mutateMe, ip2) + #expect(mutateMe == ip2) // Insert at the beginning mutateMe = ip1 mutateMe[0..<0] = ip2 - XCTAssertEqual(mutateMe, IndexPath(indexes: [6, 7, 8, 1, 2, 3])) + #expect(mutateMe == IndexPath(indexes: [6, 7, 8, 1, 2, 3])) // Insert at the end mutateMe = ip1 mutateMe[3..<3] = ip2 - XCTAssertEqual(mutateMe, IndexPath(indexes: [1, 2, 3, 6, 7, 8])) + #expect(mutateMe == IndexPath(indexes: [1, 2, 3, 6, 7, 8])) // Insert in middle mutateMe = ip1 mutateMe[2..<2] = ip2 - XCTAssertEqual(mutateMe, IndexPath(indexes: [1, 2, 6, 7, 8, 3])) + #expect(mutateMe == IndexPath(indexes: [1, 2, 6, 7, 8, 3])) } - func testRangeFromEmpty() { + @Test func rangeFromEmpty() { let ip1 = IndexPath() let ip2 = ip1[0..<0] - XCTAssertEqual(ip2.count, 0) + #expect(ip2.count == 0) } - func testRangeFromSingle() { + @Test func rangeFromSingle() { let ip1 = IndexPath(indexes: [1]) let ip2 = ip1[0..<0] - XCTAssertEqual(ip2.count, 0) + #expect(ip2.count == 0) let ip3 = ip1[0..<1] - XCTAssertEqual(ip3.count, 1) - XCTAssertEqual(ip3[0], 1) + #expect(ip3.count == 1) + #expect(ip3[0] == 1) } - func testRangeFromPair() { + @Test func rangeFromPair() { let ip1 = IndexPath(indexes: [1, 2]) let ip2 = ip1[0..<0] - XCTAssertEqual(ip2.count, 0) + #expect(ip2.count == 0) let ip3 = ip1[0..<1] - XCTAssertEqual(ip3.count, 1) - XCTAssertEqual(ip3[0], 1) + #expect(ip3.count == 1) + #expect(ip3[0] == 1) let ip4 = ip1[1..<1] - XCTAssertEqual(ip4.count, 0) + #expect(ip4.count == 0) let ip5 = ip1[0..<2] - XCTAssertEqual(ip5.count, 2) - XCTAssertEqual(ip5[0], 1) - XCTAssertEqual(ip5[1], 2) + #expect(ip5.count == 2) + #expect(ip5[0] == 1) + #expect(ip5[1] == 2) let ip6 = ip1[1..<2] - XCTAssertEqual(ip6.count, 1) - XCTAssertEqual(ip6[0], 2) + #expect(ip6.count == 1) + #expect(ip6[0] == 2) let ip7 = ip1[2..<2] - XCTAssertEqual(ip7.count, 0) + #expect(ip7.count == 0) } - func testRangeFromMany() { + @Test func rangeFromMany() { let ip1 = IndexPath(indexes: [1, 2, 3]) let ip2 = ip1[0..<0] - XCTAssertEqual(ip2.count, 0) + #expect(ip2.count == 0) let ip3 = ip1[0..<1] - XCTAssertEqual(ip3.count, 1) + #expect(ip3.count == 1) let ip4 = ip1[0..<2] - XCTAssertEqual(ip4.count, 2) + #expect(ip4.count == 2) let ip5 = ip1[0..<3] - XCTAssertEqual(ip5.count, 3) + #expect(ip5.count == 3) } - func testRangeReplacementSingle() { + @Test func rangeReplacementSingle() { var ip1 = IndexPath(indexes: [1]) ip1[0..<1] = IndexPath(indexes: [2]) - XCTAssertEqual(ip1[0], 2) + #expect(ip1[0] == 2) ip1[0..<1] = IndexPath(indexes: []) - XCTAssertEqual(ip1.count, 0) + #expect(ip1.count == 0) } - func testRangeReplacementPair() { + @Test func rangeReplacementPair() { var ip1 = IndexPath(indexes: [1, 2]) ip1[0..<1] = IndexPath(indexes: [2, 3]) - XCTAssertEqual(ip1.count, 3) - XCTAssertEqual(ip1[0], 2) - XCTAssertEqual(ip1[1], 3) - XCTAssertEqual(ip1[2], 2) + #expect(ip1.count == 3) + #expect(ip1[0] == 2) + #expect(ip1[1] == 3) + #expect(ip1[2] == 2) ip1[0..<1] = IndexPath(indexes: []) - XCTAssertEqual(ip1.count, 2) + #expect(ip1.count == 2) } - func testMoreRanges() { + @Test func moreRanges() { var ip = IndexPath(indexes: [1, 2, 3]) let ip2 = IndexPath(indexes: [5, 6, 7, 8, 9, 10]) ip[1..<2] = ip2 - XCTAssertEqual(ip, IndexPath(indexes: [1, 5, 6, 7, 8, 9, 10, 3])) + #expect(ip == IndexPath(indexes: [1, 5, 6, 7, 8, 9, 10, 3])) } - func testIteration() { + @Test func iteration() { let ip = IndexPath(indexes: [1, 2, 3]) var count = 0 @@ -560,50 +565,50 @@ class TestIndexPath: XCTestCase { count += 1 } - XCTAssertEqual(3, count) + #expect(3 == count) } - func testDescription() { + @Test func description() { let ip1: IndexPath = [] let ip2: IndexPath = [1] let ip3: IndexPath = [1, 2] let ip4: IndexPath = [1, 2, 3] - XCTAssertEqual(ip1.description, "[]") - XCTAssertEqual(ip2.description, "[1]") - XCTAssertEqual(ip3.description, "[1, 2]") - XCTAssertEqual(ip4.description, "[1, 2, 3]") + #expect(ip1.description == "[]") + #expect(ip2.description == "[1]") + #expect(ip3.description == "[1, 2]") + #expect(ip4.description == "[1, 2, 3]") - XCTAssertEqual(ip1.debugDescription, ip1.description) - XCTAssertEqual(ip2.debugDescription, ip2.description) - XCTAssertEqual(ip3.debugDescription, ip3.description) - XCTAssertEqual(ip4.debugDescription, ip4.description) + #expect(ip1.debugDescription == ip1.description) + #expect(ip2.debugDescription == ip2.description) + #expect(ip3.debugDescription == ip3.description) + #expect(ip4.debugDescription == ip4.description) } - func test_AnyHashableContainingIndexPath() { + @Test func anyHashableContainingIndexPath() { let values: [IndexPath] = [ IndexPath(indexes: [1, 2]), IndexPath(indexes: [1, 2, 3]), IndexPath(indexes: [1, 2, 3]), ] let anyHashables = values.map(AnyHashable.init) - expectEqual(IndexPath.self, type(of: anyHashables[0].base)) - expectEqual(IndexPath.self, type(of: anyHashables[1].base)) - expectEqual(IndexPath.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) + #expect(IndexPath.self == type(of: anyHashables[0].base)) + #expect(IndexPath.self == type(of: anyHashables[1].base)) + #expect(IndexPath.self == type(of: anyHashables[2].base)) + #expect(anyHashables[0] != anyHashables[1]) + #expect(anyHashables[1] == anyHashables[2]) } - func test_slice_1ary() { + @Test func slice_1ary() { let indexPath: IndexPath = [0] let res = indexPath.dropFirst() - XCTAssertEqual(0, res.count) + #expect(0 == res.count) let slice = indexPath[1..<1] - XCTAssertEqual(0, slice.count) + #expect(0 == slice.count) } - func test_dropFirst() { + @Test func dropFirst() { var pth = IndexPath(indexes:[1,2,3,4]) while !pth.isEmpty { // this should not crash @@ -614,8 +619,9 @@ class TestIndexPath: XCTestCase { #if FOUNDATION_FRAMEWORK -class TestIndexPathBridging: XCTestCase { - func testBridgeToObjC() { +@Suite("IndexPath Bridging") +private struct IndexPathBridgingTests { + @Test func bridgeToObjC() { let ip1: IndexPath = [] let ip2: IndexPath = [1] let ip3: IndexPath = [1, 2] @@ -626,13 +632,13 @@ class TestIndexPathBridging: XCTestCase { let nsip3 = ip3 as NSIndexPath let nsip4 = ip4 as NSIndexPath - XCTAssertEqual(nsip1.length, 0) - XCTAssertEqual(nsip2.length, 1) - XCTAssertEqual(nsip3.length, 2) - XCTAssertEqual(nsip4.length, 3) + #expect(nsip1.length == 0) + #expect(nsip2.length == 1) + #expect(nsip3.length == 2) + #expect(nsip4.length == 3) } - func testForceBridgeFromObjC() { + @Test func forceBridgeFromObjC() { let nsip1 = NSIndexPath() let nsip2 = NSIndexPath(index: 1) let nsip3 = [1, 2].withUnsafeBufferPointer { (buffer: UnsafeBufferPointer) -> NSIndexPath in @@ -644,32 +650,28 @@ class TestIndexPathBridging: XCTestCase { var ip1: IndexPath? = IndexPath() IndexPath._forceBridgeFromObjectiveC(nsip1, result: &ip1) - XCTAssertNotNil(ip1) - XCTAssertEqual(ip1!.count, 0) + #expect(ip1?.count == 0) var ip2: IndexPath? = IndexPath() IndexPath._forceBridgeFromObjectiveC(nsip2, result: &ip2) - XCTAssertNotNil(ip2) - XCTAssertEqual(ip2!.count, 1) - XCTAssertEqual(ip2![0], 1) + #expect(ip2?.count == 1) + #expect(ip2?[0] == 1) var ip3: IndexPath? = IndexPath() IndexPath._forceBridgeFromObjectiveC(nsip3, result: &ip3) - XCTAssertNotNil(ip3) - XCTAssertEqual(ip3!.count, 2) - XCTAssertEqual(ip3![0], 1) - XCTAssertEqual(ip3![1], 2) + #expect(ip3?.count == 2) + #expect(ip3?[0] == 1) + #expect(ip3?[1] == 2) var ip4: IndexPath? = IndexPath() IndexPath._forceBridgeFromObjectiveC(nsip4, result: &ip4) - XCTAssertNotNil(ip4) - XCTAssertEqual(ip4!.count, 3) - XCTAssertEqual(ip4![0], 1) - XCTAssertEqual(ip4![1], 2) - XCTAssertEqual(ip4![2], 3) + #expect(ip4?.count == 3) + #expect(ip4?[0] == 1) + #expect(ip4?[1] == 2) + #expect(ip4?[2] == 3) } - func testConditionalBridgeFromObjC() { + @Test func conditionalBridgeFromObjC() { let nsip1 = NSIndexPath() let nsip2 = NSIndexPath(index: 1) let nsip3 = [1, 2].withUnsafeBufferPointer { (buffer: UnsafeBufferPointer) -> NSIndexPath in @@ -680,33 +682,29 @@ class TestIndexPathBridging: XCTestCase { } var ip1: IndexPath? = IndexPath() - XCTAssertTrue(IndexPath._conditionallyBridgeFromObjectiveC(nsip1, result: &ip1)) - XCTAssertNotNil(ip1) - XCTAssertEqual(ip1!.count, 0) + #expect(IndexPath._conditionallyBridgeFromObjectiveC(nsip1, result: &ip1)) + #expect(ip1?.count == 0) var ip2: IndexPath? = IndexPath() - XCTAssertTrue(IndexPath._conditionallyBridgeFromObjectiveC(nsip2, result: &ip2)) - XCTAssertNotNil(ip2) - XCTAssertEqual(ip2!.count, 1) - XCTAssertEqual(ip2![0], 1) + #expect(IndexPath._conditionallyBridgeFromObjectiveC(nsip2, result: &ip2)) + #expect(ip2?.count == 1) + #expect(ip2?[0] == 1) var ip3: IndexPath? = IndexPath() - XCTAssertTrue(IndexPath._conditionallyBridgeFromObjectiveC(nsip3, result: &ip3)) - XCTAssertNotNil(ip3) - XCTAssertEqual(ip3!.count, 2) - XCTAssertEqual(ip3![0], 1) - XCTAssertEqual(ip3![1], 2) + #expect(IndexPath._conditionallyBridgeFromObjectiveC(nsip3, result: &ip3)) + #expect(ip3?.count == 2) + #expect(ip3?[0] == 1) + #expect(ip3?[1] == 2) var ip4: IndexPath? = IndexPath() - XCTAssertTrue(IndexPath._conditionallyBridgeFromObjectiveC(nsip4, result: &ip4)) - XCTAssertNotNil(ip4) - XCTAssertEqual(ip4!.count, 3) - XCTAssertEqual(ip4![0], 1) - XCTAssertEqual(ip4![1], 2) - XCTAssertEqual(ip4![2], 3) + #expect(IndexPath._conditionallyBridgeFromObjectiveC(nsip4, result: &ip4)) + #expect(ip4?.count == 3) + #expect(ip4?[0] == 1) + #expect(ip4?[1] == 2) + #expect(ip4?[2] == 3) } - func testUnconditionalBridgeFromObjC() { + @Test func unconditionalBridgeFromObjC() { let nsip1 = NSIndexPath() let nsip2 = NSIndexPath(index: 1) let nsip3 = [1, 2].withUnsafeBufferPointer { (buffer: UnsafeBufferPointer) -> NSIndexPath in @@ -717,44 +715,45 @@ class TestIndexPathBridging: XCTestCase { } let ip1: IndexPath = IndexPath._unconditionallyBridgeFromObjectiveC(nsip1) - XCTAssertEqual(ip1.count, 0) + #expect(ip1.count == 0) let ip2: IndexPath = IndexPath._unconditionallyBridgeFromObjectiveC(nsip2) - XCTAssertEqual(ip2.count, 1) - XCTAssertEqual(ip2[0], 1) + #expect(ip2.count == 1) + #expect(ip2[0] == 1) let ip3: IndexPath = IndexPath._unconditionallyBridgeFromObjectiveC(nsip3) - XCTAssertEqual(ip3.count, 2) - XCTAssertEqual(ip3[0], 1) - XCTAssertEqual(ip3[1], 2) + #expect(ip3.count == 2) + #expect(ip3[0] == 1) + #expect(ip3[1] == 2) let ip4: IndexPath = IndexPath._unconditionallyBridgeFromObjectiveC(nsip4) - XCTAssertEqual(ip4.count, 3) - XCTAssertEqual(ip4[0], 1) - XCTAssertEqual(ip4[1], 2) - XCTAssertEqual(ip4[2], 3) + #expect(ip4.count == 3) + #expect(ip4[0] == 1) + #expect(ip4[1] == 2) + #expect(ip4[2] == 3) } - func testObjcBridgeType() { - XCTAssertTrue(IndexPath._getObjectiveCType() == NSIndexPath.self) + @Test func objcBridgeType() { + let typeIsExpected = IndexPath._getObjectiveCType() == NSIndexPath.self + #expect(typeIsExpected) } - func test_AnyHashableCreatedFromNSIndexPath() { + @Test func anyHashableCreatedFromNSIndexPath() { let values: [NSIndexPath] = [ NSIndexPath(index: 1), NSIndexPath(index: 2), NSIndexPath(index: 2), ] let anyHashables = values.map(AnyHashable.init) - expectEqual(IndexPath.self, type(of: anyHashables[0].base)) - expectEqual(IndexPath.self, type(of: anyHashables[1].base)) - expectEqual(IndexPath.self, type(of: anyHashables[2].base)) - XCTAssertNotEqual(anyHashables[0], anyHashables[1]) - XCTAssertEqual(anyHashables[1], anyHashables[2]) + #expect(IndexPath.self == type(of: anyHashables[0].base)) + #expect(IndexPath.self == type(of: anyHashables[1].base)) + #expect(IndexPath.self == type(of: anyHashables[2].base)) + #expect(anyHashables[0] != anyHashables[1]) + #expect(anyHashables[1] == anyHashables[2]) } - func test_unconditionallyBridgeFromObjectiveC() { - XCTAssertEqual(IndexPath(), IndexPath._unconditionallyBridgeFromObjectiveC(nil)) + @Test func unconditionallyBridgeFromObjectiveC() { + #expect(IndexPath() == IndexPath._unconditionallyBridgeFromObjectiveC(nil)) } } From 5bb3bd69fa55f27e39401e9572e7d680c8c2c500 Mon Sep 17 00:00:00 2001 From: Jeremy Schonfeld Date: Thu, 12 Jun 2025 13:18:49 -0700 Subject: [PATCH 12/12] Fix build failures --- Tests/FoundationEssentialsTests/StringTests.swift | 2 +- .../FoundationInternationalizationTests/DateTests+Locale.swift | 2 +- .../StringSortComparatorTests.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/FoundationEssentialsTests/StringTests.swift b/Tests/FoundationEssentialsTests/StringTests.swift index 39b5d3672..50a81618d 100644 --- a/Tests/FoundationEssentialsTests/StringTests.swift +++ b/Tests/FoundationEssentialsTests/StringTests.swift @@ -1463,7 +1463,7 @@ final class StringTestsStdlib: XCTestCase { .ascii, .utf8, ] - checkHashable(instances, equalityOracle: { $0 == $1 }) + XCTCheckHashable(instances, equalityOracle: { $0 == $1 }) } func test_localizedStringWithFormat() { diff --git a/Tests/FoundationInternationalizationTests/DateTests+Locale.swift b/Tests/FoundationInternationalizationTests/DateTests+Locale.swift index 609e47476..df2c58181 100644 --- a/Tests/FoundationInternationalizationTests/DateTests+Locale.swift +++ b/Tests/FoundationInternationalizationTests/DateTests+Locale.swift @@ -71,7 +71,7 @@ final class DateLocaleTests : XCTestCase { dateWithString("2010-05-17 14:50:47 -0700"), dateWithString("2010-05-17 14:49:48 -0700"), ] - checkHashable(values, equalityOracle: { $0 == $1 }) + XCTCheckHashable(values, equalityOracle: { $0 == $1 }) } func test_AnyHashableContainingDate() { diff --git a/Tests/FoundationInternationalizationTests/StringSortComparatorTests.swift b/Tests/FoundationInternationalizationTests/StringSortComparatorTests.swift index 1e14a94cb..a4bf70d11 100644 --- a/Tests/FoundationInternationalizationTests/StringSortComparatorTests.swift +++ b/Tests/FoundationInternationalizationTests/StringSortComparatorTests.swift @@ -37,7 +37,7 @@ private struct StringSortComparatorTests { @Test func locale() { let swedishComparator = String.Comparator(options: [], locale: Locale(identifier: "sv")) #expect(swedishComparator.compare("ă", "ã") == .orderedAscending) - #expect(swedishComparator.locale, Locale(identifier: "sv")) + #expect(swedishComparator.locale == Locale(identifier: "sv")) } @Test func nilLocale() {