diff --git a/Package.resolved b/Package.resolved index 4244270..ddb1781 100644 --- a/Package.resolved +++ b/Package.resolved @@ -194,8 +194,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/vapor/vapor.git", "state" : { - "revision" : "8589cb562feab069f2563bdcdeb8f9608a07a2c7", - "version" : "4.112.0" + "revision" : "fc2d0c6db94150d6ea528c9492d72c3c9c2197d7", + "version" : "4.112.2" } }, { diff --git a/Package.swift b/Package.swift index 390eb95..e58614a 100644 --- a/Package.swift +++ b/Package.swift @@ -113,7 +113,10 @@ import PackageDescription ), .testTarget( name: "HaystackServerVaporTests", - dependencies: ["HaystackServerVapor", .product(name: "XCTVapor", package: "vapor")] + dependencies: [ + "HaystackServerVapor", + .product(name: "VaporTesting", package: "vapor"), + ] ), ] ) @@ -204,7 +207,10 @@ import PackageDescription ), .testTarget( name: "HaystackServerVaporTests", - dependencies: ["HaystackServerVapor", .product(name: "XCTVapor", package: "vapor")] + dependencies: [ + "HaystackServerVapor", + .product(name: "VaporTesting", package: "vapor"), + ] ), ] ) diff --git a/Tests/HaystackClientDarwinIntegrationTests/HaystackClientDarwinIntegrationTests.swift b/Tests/HaystackClientDarwinIntegrationTests/HaystackClientDarwinIntegrationTests.swift index 9959056..93955eb 100644 --- a/Tests/HaystackClientDarwinIntegrationTests/HaystackClientDarwinIntegrationTests.swift +++ b/Tests/HaystackClientDarwinIntegrationTests/HaystackClientDarwinIntegrationTests.swift @@ -1,70 +1,63 @@ +import Foundation import Haystack import HaystackClientDarwin -import XCTest +import Testing /// To use these tests, run a [Haxall](https://github.com/haxall/haxall) server and set the username and password /// in the `HAYSTACK_USER` and `HAYSTACK_PASSWORD` environment variables -final class HaystackClientDarwinIntegrationTests: XCTestCase { +struct HaystackClientDarwinIntegration { var client: Client = try! Client( baseUrl: "http://localhost:8080/api/", username: ProcessInfo.processInfo.environment["HAYSTACK_USER"] ?? "su", password: ProcessInfo.processInfo.environment["HAYSTACK_PASSWORD"] ?? "su" ) - override func setUp() async throws { - try await client.open() - } - - override func tearDown() async throws { - try await client.close() - } - - func testCloseAndOpen() async throws { + @Test func closeAndOpen() async throws { try print(await client.close()) try print(await client.open()) } - func testAbout() async throws { + @Test func about() async throws { try print(await client.about().toZinc()) } - func testDefs() async throws { + @Test func defs() async throws { try print(await client.defs().toZinc()) try print(await client.defs(filter: "lib==^lib:phIoT").toZinc()) try print(await client.defs(limit: Number(1)).toZinc()) try print(await client.defs(filter: "lib==^lib:phIoT", limit: Number(1)).toZinc()) } - func testLibs() async throws { + @Test func libs() async throws { try print(await client.libs().toZinc()) try print(await client.libs(filter: "lib==^lib:phIoT").toZinc()) try print(await client.libs(limit: Number(1)).toZinc()) try print(await client.libs(filter: "lib==^lib:phIoT", limit: Number(1)).toZinc()) } - func testOps() async throws { + @Test func ops() async throws { try print(await client.ops().toZinc()) try print(await client.ops(filter: "lib==^lib:phIoT").toZinc()) try print(await client.ops(limit: Number(1)).toZinc()) try print(await client.ops(filter: "lib==^lib:phIoT", limit: Number(1)).toZinc()) } - func testFiletypes() async throws { + @Test func filetypes() async throws { try print(await client.filetypes().toZinc()) try print(await client.filetypes(filter: "lib==^lib:phIoT").toZinc()) try print(await client.filetypes(limit: Number(1)).toZinc()) try print(await client.filetypes(filter: "lib==^lib:phIoT", limit: Number(1)).toZinc()) } - func testRead() async throws { + @Test func read() async throws { try print(await client.read(ids: [Ref("28e7fb47-d67ab19a")]).toZinc()) } - func testReadAll() async throws { + @Test func readAll() async throws { try print(await client.read(filter: "site").toZinc()) } - func testHisRead() async throws { + @Test func hisRead() async throws { try print(await client.hisRead(id: Ref("28e7fb7d-e20316e0"), range: .today).toZinc()) try print(await client.hisRead(id: Ref("28e7fb7d-e20316e0"), range: .yesterday).toZinc()) try print(await client.hisRead(id: Ref("28e7fb7d-e20316e0"), range: .date(Date("2022-01-01"))).toZinc()) @@ -73,7 +66,7 @@ final class HaystackClientDarwinIntegrationTests: XCTestCase { try print(await client.hisRead(id: Ref("28e7fb7d-e20316e0"), range: .after(DateTime("2022-01-01T00:00:00Z"))).toZinc()) } - func testHisWrite() async throws { + @Test func hisWrite() async throws { try print(await client.hisWrite( id: Ref("28e7fb7d-e20316e0"), items: [ @@ -82,11 +75,11 @@ final class HaystackClientDarwinIntegrationTests: XCTestCase { ).toZinc()) } - func testEval() async throws { + @Test func eval() async throws { try print(await client.eval(expression: "readAll(site)").toZinc()) } - func testWatchUnsub() async throws { + @Test func watchUnsub() async throws { try print(await client.watchUnsubRemove(watchId: "id", ids: [Ref("28e7fb47-d67ab19a")])) } } diff --git a/Tests/HaystackClientNIOIntegrationTests/HaystackClientNIOIntegrationTests.swift b/Tests/HaystackClientNIOIntegrationTests/HaystackClientNIOIntegrationTests.swift index 49615f9..1ece6c4 100644 --- a/Tests/HaystackClientNIOIntegrationTests/HaystackClientNIOIntegrationTests.swift +++ b/Tests/HaystackClientNIOIntegrationTests/HaystackClientNIOIntegrationTests.swift @@ -1,100 +1,122 @@ import AsyncHTTPClient +import Foundation import Haystack import HaystackClientNIO import NIO -import XCTest +import Testing /// To use these tests, run a [Haxall](https://github.com/haxall/haxall) server and set the username and password /// in the `HAYSTACK_USER` and `HAYSTACK_PASSWORD` environment variables -final class HaystackClientNIOIntegrationTests: XCTestCase { - let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) - var httpClient: HTTPClient! - var client: Client! - - override func setUp() async throws { - httpClient = HTTPClient(eventLoopGroupProvider: .shared(eventLoopGroup)) - client = try Client( +struct HaystackClientNIOIntegrationTests { + private func withClient(_ block: (Client) async throws -> Void) async throws { + let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) + let httpClient = HTTPClient(eventLoopGroupProvider: .shared(eventLoopGroup)) + let client = try Client( baseUrl: "http://localhost:8080/api/", username: ProcessInfo.processInfo.environment["HAYSTACK_USER"] ?? "su", password: ProcessInfo.processInfo.environment["HAYSTACK_PASSWORD"] ?? "su", httpClient: httpClient ) try await client.open() - } - override func tearDown() async throws { + try await block(client) + try await client.close() try await httpClient.shutdown() } - func testCloseAndOpen() async throws { - try print(await client.close()) - try print(await client.open()) + @Test func closeAndOpen() async throws { + try await withClient { client in + try print(await client.close()) + try print(await client.open()) + } } - func testAbout() async throws { - try print(await client.about().toZinc()) + @Test func about() async throws { + try await withClient { client in + try print(await client.about().toZinc()) + } } - func testDefs() async throws { - try print(await client.defs().toZinc()) - try print(await client.defs(filter: "lib==^lib:phIoT").toZinc()) - try print(await client.defs(limit: Number(1)).toZinc()) - try print(await client.defs(filter: "lib==^lib:phIoT", limit: Number(1)).toZinc()) + @Test func defs() async throws { + try await withClient { client in + try print(await client.defs().toZinc()) + try print(await client.defs(filter: "lib==^lib:phIoT").toZinc()) + try print(await client.defs(limit: Number(1)).toZinc()) + try print(await client.defs(filter: "lib==^lib:phIoT", limit: Number(1)).toZinc()) + } } - func testLibs() async throws { - try print(await client.libs().toZinc()) - try print(await client.libs(filter: "lib==^lib:phIoT").toZinc()) - try print(await client.libs(limit: Number(1)).toZinc()) - try print(await client.libs(filter: "lib==^lib:phIoT", limit: Number(1)).toZinc()) + @Test func libs() async throws { + try await withClient { client in + try print(await client.libs().toZinc()) + try print(await client.libs(filter: "lib==^lib:phIoT").toZinc()) + try print(await client.libs(limit: Number(1)).toZinc()) + try print(await client.libs(filter: "lib==^lib:phIoT", limit: Number(1)).toZinc()) + } } - func testOps() async throws { - try print(await client.ops().toZinc()) - try print(await client.ops(filter: "lib==^lib:phIoT").toZinc()) - try print(await client.ops(limit: Number(1)).toZinc()) - try print(await client.ops(filter: "lib==^lib:phIoT", limit: Number(1)).toZinc()) + @Test func ops() async throws { + try await withClient { client in + try print(await client.ops().toZinc()) + try print(await client.ops(filter: "lib==^lib:phIoT").toZinc()) + try print(await client.ops(limit: Number(1)).toZinc()) + try print(await client.ops(filter: "lib==^lib:phIoT", limit: Number(1)).toZinc()) + } } - func testFiletypes() async throws { - try print(await client.filetypes().toZinc()) - try print(await client.filetypes(filter: "lib==^lib:phIoT").toZinc()) - try print(await client.filetypes(limit: Number(1)).toZinc()) - try print(await client.filetypes(filter: "lib==^lib:phIoT", limit: Number(1)).toZinc()) + @Test func filetypes() async throws { + try await withClient { client in + try print(await client.filetypes().toZinc()) + try print(await client.filetypes(filter: "lib==^lib:phIoT").toZinc()) + try print(await client.filetypes(limit: Number(1)).toZinc()) + try print(await client.filetypes(filter: "lib==^lib:phIoT", limit: Number(1)).toZinc()) + } } - func testRead() async throws { - try print(await client.read(ids: [Ref("28e7fb47-d67ab19a")]).toZinc()) + @Test func read() async throws { + try await withClient { client in + try print(await client.read(ids: [Ref("28e7fb47-d67ab19a")]).toZinc()) + } } - func testReadAll() async throws { - try print(await client.read(filter: "site").toZinc()) + @Test func readAll() async throws { + try await withClient { client in + try print(await client.read(filter: "site").toZinc()) + } } - func testHisRead() async throws { - try print(await client.hisRead(id: Ref("28e7fb7d-e20316e0"), range: .today).toZinc()) - try print(await client.hisRead(id: Ref("28e7fb7d-e20316e0"), range: .yesterday).toZinc()) - try print(await client.hisRead(id: Ref("28e7fb7d-e20316e0"), range: .date(Date("2022-01-01"))).toZinc()) - try print(await client.hisRead(id: Ref("28e7fb7d-e20316e0"), range: .dateRange(from: Date("2022-01-01"), to: Date("2022-02-01"))).toZinc()) - try print(await client.hisRead(id: Ref("28e7fb7d-e20316e0"), range: .dateTimeRange(from: DateTime("2022-01-01T00:00:00Z"), to: DateTime("2022-02-01T00:00:00Z"))).toZinc()) - try print(await client.hisRead(id: Ref("28e7fb7d-e20316e0"), range: .after(DateTime("2022-01-01T00:00:00Z"))).toZinc()) + @Test func hisRead() async throws { + try await withClient { client in + try print(await client.hisRead(id: Ref("28e7fb7d-e20316e0"), range: .today).toZinc()) + try print(await client.hisRead(id: Ref("28e7fb7d-e20316e0"), range: .yesterday).toZinc()) + try print(await client.hisRead(id: Ref("28e7fb7d-e20316e0"), range: .date(Date("2022-01-01"))).toZinc()) + try print(await client.hisRead(id: Ref("28e7fb7d-e20316e0"), range: .dateRange(from: Date("2022-01-01"), to: Date("2022-02-01"))).toZinc()) + try print(await client.hisRead(id: Ref("28e7fb7d-e20316e0"), range: .dateTimeRange(from: DateTime("2022-01-01T00:00:00Z"), to: DateTime("2022-02-01T00:00:00Z"))).toZinc()) + try print(await client.hisRead(id: Ref("28e7fb7d-e20316e0"), range: .after(DateTime("2022-01-01T00:00:00Z"))).toZinc()) + } } - func testHisWrite() async throws { - try print(await client.hisWrite( - id: Ref("28e7fb7d-e20316e0"), - items: [ - HisItem(ts: DateTime("2022-01-01T00:00:00-07:00 Denver"), val: Number(14)), - ] - ).toZinc()) + @Test func hisWrite() async throws { + try await withClient { client in + try print(await client.hisWrite( + id: Ref("28e7fb7d-e20316e0"), + items: [ + HisItem(ts: DateTime("2022-01-01T00:00:00-07:00 Denver"), val: Number(14)), + ] + ).toZinc()) + } } - func testEval() async throws { - try print(await client.eval(expression: "readAll(site)").toZinc()) + @Test func eval() async throws { + try await withClient { client in + try print(await client.eval(expression: "readAll(site)").toZinc()) + } } - func testWatchUnsub() async throws { - try print(await client.watchUnsubRemove(watchId: "id", ids: [Ref("28e7fb47-d67ab19a")])) + @Test func watchUnsub() async throws { + try await withClient { client in + try print(await client.watchUnsubRemove(watchId: "id", ids: [Ref("28e7fb47-d67ab19a")])) + } } } diff --git a/Tests/HaystackClientTests/SCRAMTests.swift b/Tests/HaystackClientTests/SCRAMTests.swift index 4c52cf5..f2afddd 100644 --- a/Tests/HaystackClientTests/SCRAMTests.swift +++ b/Tests/HaystackClientTests/SCRAMTests.swift @@ -1,8 +1,8 @@ import Crypto @testable import HaystackClient -import XCTest +import Testing -final class SCRAMTests: XCTestCase { +struct SCRAMTests { let scram = ScramClient( hash: Insecure.SHA1.self, username: "user", @@ -11,92 +11,81 @@ final class SCRAMTests: XCTestCase { ) /// Tests example from [RFC-5802's SCRAM Authentication Exchange section](https://www.rfc-editor.org/rfc/rfc5802#section-5) - func testClientExample() async throws { - XCTAssertEqual( - scram.clientFirstMessage(), - "n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL" - ) + @Test func clientExample() async throws { + #expect(scram.clientFirstMessage() == "n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL") - XCTAssertEqual( + #expect( try scram.clientFinalMessage( serverFirstMessage: "r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096" - ), - "c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,p=v0X8v3Bz2T0CJGbJQyF0X+HI4Ts=" + ) == "c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,p=v0X8v3Bz2T0CJGbJQyF0X+HI4Ts=" ) - XCTAssertNoThrow( + #expect(throws: Never.self) { try scram.validate(serverFinalMessage: "v=rmF9pqV8S7suAoZWja4dJRkFsKQ=") - ) + } } - func testServerFirstMessageResponseErrors() async throws { - XCTAssertEqual( - scram.clientFirstMessage(), - "n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL" - ) + @Test func serverFirstMessageResponseErrors() async throws { + #expect(scram.clientFirstMessage() == "n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL") // Server first message has no nonce attribute - XCTAssertThrowsError( + #expect(throws: (any Error).self) { try scram.clientFinalMessage( serverFirstMessage: "s=QSXCR+Q6sek8bf92,i=4096" ) - ) + } // Server first message has no salt attribute - XCTAssertThrowsError( + #expect(throws: (any Error).self) { try scram.clientFinalMessage( serverFirstMessage: "r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,i=4096" ) - ) + } // Server first message has no iteration attribute - XCTAssertThrowsError( + #expect(throws: (any Error).self) { try scram.clientFinalMessage( serverFirstMessage: "r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92" ) - ) + } // Server first message iteration is not integer - XCTAssertThrowsError( + #expect(throws: (any Error).self) { try scram.clientFinalMessage( serverFirstMessage: "r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=BAD" ) - ) + } // Server nonce isn't prefixed with client nonce - XCTAssertThrowsError( + #expect(throws: (any Error).self) { try scram.clientFinalMessage( serverFirstMessage: "r=BAD_fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096" ) - ) + } } - func testServerFinalMessageValidateErrors() async throws { - XCTAssertEqual( - scram.clientFirstMessage(), - "n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL" - ) + @Test func serverFinalMessageValidateErrors() async throws { + #expect(scram.clientFirstMessage() == "n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL") - XCTAssertEqual( + #expect( try scram.clientFinalMessage( serverFirstMessage: "r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096" - ), - "c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,p=v0X8v3Bz2T0CJGbJQyF0X+HI4Ts=" + ) == "c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,p=v0X8v3Bz2T0CJGbJQyF0X+HI4Ts=" ) // Throws if server final message is unexpected - XCTAssertThrowsError( + #expect(throws: (any Error).self) { try scram.validate(serverFinalMessage: "v=BAD_rmF9pqV8S7suAoZWja4dJRkFsKQ=") - ) + } // Throws if server final message has error attribute - XCTAssertThrowsError( + #expect(throws: (any Error).self) { try scram.validate(serverFinalMessage: "e=No way Jose,v=rmF9pqV8S7suAoZWja4dJRkFsKQ=") - ) + } // Throws if server final message has no server key attribute - XCTAssertThrowsError( + #expect(throws: (any Error).self) { try scram.validate(serverFinalMessage: "n=user") - ) + } } } diff --git a/Tests/HaystackClientTests/UrlSafeBase64Tests.swift b/Tests/HaystackClientTests/UrlSafeBase64Tests.swift index 6a6e293..e6b6c60 100644 --- a/Tests/HaystackClientTests/UrlSafeBase64Tests.swift +++ b/Tests/HaystackClientTests/UrlSafeBase64Tests.swift @@ -1,32 +1,20 @@ @testable import HaystackClient -import XCTest +import Testing -final class UrlSafeBase64Tests: XCTestCase { - func testEncodeStandard() throws { - XCTAssertEqual( - "user".encodeBase64Standard(), - "dXNlcg==" - ) +struct UrlSafeBase64Tests { + @Test func encodeStandard() throws { + #expect("user".encodeBase64Standard() == "dXNlcg==") } - func testEncodeUrlSafe() throws { - XCTAssertEqual( - "user".encodeBase64UrlSafe(), - "dXNlcg" - ) + @Test func encodeUrlSafe() throws { + #expect("user".encodeBase64UrlSafe() == "dXNlcg") } - func testDecodeStandard() throws { - XCTAssertEqual( - "dXNlcg==".decodeBase64Standard(), - "user" - ) + @Test func decodeStandard() throws { + #expect("dXNlcg==".decodeBase64Standard() == "user") } - func testDecodeUrlSafe() throws { - XCTAssertEqual( - "dXNlcg".decodeBase64UrlSafe(), - "user" - ) + @Test func decodeUrlSafe() throws { + #expect("dXNlcg".decodeBase64UrlSafe() == "user") } } diff --git a/Tests/HaystackServerTests/HaystackServerTests.swift b/Tests/HaystackServerTests/HaystackServerTests.swift index da4a126..9b51d94 100644 --- a/Tests/HaystackServerTests/HaystackServerTests.swift +++ b/Tests/HaystackServerTests/HaystackServerTests.swift @@ -1,29 +1,29 @@ import Foundation import Haystack import HaystackServer -import XCTest +import Testing -final class HaystackServerTests: XCTestCase { - func testAbout() async throws { +struct HaystackServerTests { + @Test func about() async throws { let server = HaystackServer( recordStore: InMemoryRecordStore(), historyStore: InMemoryHistoryStore(), watchStore: InMemoryWatchStore() ) let response = try await server.about() - let about = try XCTUnwrap(response.first) - XCTAssertNotNil(about["haystackVersion"] as? String) - XCTAssertNotNil(about["tz"] as? String) - XCTAssertNotNil(about["serverTime"] as? DateTime) - XCTAssertNotNil(about["serverBootTime"] as? DateTime) - XCTAssertEqual(about["productName"] as? String, "swift-haystack") - XCTAssertEqual(about["productUri"] as? Uri, Uri("https://github.com/NeedleInAJayStack/swift-haystack")) - XCTAssertNotNil(about["productVersion"] as? String) - XCTAssertEqual(about["vendorName"] as? String, "NeedleInAJayStack") - XCTAssertEqual(about["vendorUri"] as? Uri, Uri("https://github.com/NeedleInAJayStack")) + let about = try #require(response.first) + #expect(about["haystackVersion"] as? String != nil) + #expect(about["tz"] as? String != nil) + #expect(about["serverTime"] as? DateTime != nil) + #expect(about["serverBootTime"] as? DateTime != nil) + #expect(about["productName"] as? String == "swift-haystack") + #expect(about["productUri"] as? Uri == Uri("https://github.com/NeedleInAJayStack/swift-haystack")) + #expect(about["productVersion"] as? String != nil) + #expect(about["vendorName"] as? String == "NeedleInAJayStack") + #expect(about["vendorUri"] as? Uri == Uri("https://github.com/NeedleInAJayStack")) } - func testDefs() async throws { + @Test func defs() async throws { let server = try HaystackServer( recordStore: InMemoryRecordStore([ Ref("a"): ["id": Ref("a"), "def": Marker.val], @@ -36,31 +36,22 @@ final class HaystackServerTests: XCTestCase { // Test no filter var grid = try await server.defs(filter: nil, limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }.sorted(), - ["a", "b"] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val }.sorted() == ["a", "b"]) // Test filter grid = try await server.defs(filter: "foo", limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }, - ["b"] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val } == ["b"]) // Test bad filter grid = try await server.defs(filter: "none", limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }, - [] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val } == []) // Test limit grid = try await server.defs(filter: nil, limit: Number(0)) - XCTAssertEqual(grid.count, 0) + #expect(grid.count == 0) } - func testLibs() async throws { + @Test func libs() async throws { let server = try HaystackServer( recordStore: InMemoryRecordStore([ Ref("a"): ["id": Ref("a"), "lib": Marker.val], @@ -73,31 +64,22 @@ final class HaystackServerTests: XCTestCase { // Test no filter var grid = try await server.libs(filter: nil, limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }.sorted(), - ["a", "b"] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val }.sorted() == ["a", "b"]) // Test filter grid = try await server.libs(filter: "foo", limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }, - ["b"] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val } == ["b"]) // Test bad filter grid = try await server.libs(filter: "none", limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }, - [] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val } == []) // Test limit grid = try await server.libs(filter: nil, limit: Number(0)) - XCTAssertEqual(grid.count, 0) + #expect(grid.count == 0) } - func testOps() async throws { + @Test func ops() async throws { let server = try HaystackServer( recordStore: InMemoryRecordStore([ Ref("a"): ["id": Ref("a"), "def": Marker.val, "op": Marker.val], @@ -110,31 +92,22 @@ final class HaystackServerTests: XCTestCase { // Test no filter var grid = try await server.ops(filter: nil, limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }.sorted(), - ["a", "b"] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val }.sorted() == ["a", "b"]) // Test filter grid = try await server.ops(filter: "foo", limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }, - ["b"] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val } == ["b"]) // Test bad filter grid = try await server.ops(filter: "none", limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }, - [] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val } == []) // Test limit grid = try await server.ops(filter: nil, limit: Number(0)) - XCTAssertEqual(grid.count, 0) + #expect(grid.count == 0) } - func testFiletypes() async throws { + @Test func filetypes() async throws { let server = try HaystackServer( recordStore: InMemoryRecordStore([ Ref("a"): ["id": Ref("a"), "def": Marker.val, "filetype": Marker.val], @@ -147,31 +120,22 @@ final class HaystackServerTests: XCTestCase { // Test no filter var grid = try await server.filetypes(filter: nil, limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }.sorted(), - ["a", "b"] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val }.sorted() == ["a", "b"]) // Test filter grid = try await server.filetypes(filter: "foo", limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }, - ["b"] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val } == ["b"]) // Test bad filter grid = try await server.filetypes(filter: "none", limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }, - [] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val } == []) // Test limit grid = try await server.filetypes(filter: nil, limit: Number(0)) - XCTAssertEqual(grid.count, 0) + #expect(grid.count == 0) } - func testReadIds() async throws { + @Test func readIds() async throws { let server = try HaystackServer( recordStore: InMemoryRecordStore([ Ref("a"): ["id": Ref("a"), "def": Marker.val, "filetype": Marker.val], @@ -183,13 +147,10 @@ final class HaystackServerTests: XCTestCase { ) let grid = try await server.read(ids: [Ref("a"), Ref("b")]) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }.sorted(), - ["a", "b"] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val }.sorted() == ["a", "b"]) } - func testReadFilter() async throws { + @Test func readFilter() async throws { let server = try HaystackServer( recordStore: InMemoryRecordStore([ Ref("ahu"): ["id": Ref("ahu"), "equip": Marker.val, "ahu": Marker.val], @@ -203,45 +164,30 @@ final class HaystackServerTests: XCTestCase { // Test normal var grid = try await server.read(filter: "equip", limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }.sorted(), - ["ahu", "vav"] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val }.sorted() == ["ahu", "vav"]) // Test limit grid = try await server.read(filter: "equip", limit: Number(1)) - XCTAssertEqual(grid.count, 1) + #expect(grid.count == 1) // Test and grid = try await server.read(filter: "equip and ahu", limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }.sorted(), - ["ahu"] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val }.sorted() == ["ahu"]) // Test or grid = try await server.read(filter: "ahu or vav", limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }.sorted(), - ["ahu", "vav"] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val }.sorted() == ["ahu", "vav"]) // Test path grid = try await server.read(filter: "point and equipRef->ahu", limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }.sorted(), - ["supply-air-temp"] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val }.sorted() == ["supply-air-temp"]) // Test ref equality grid = try await server.read(filter: "equipRef == @ahu", limit: nil) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }.sorted(), - ["supply-air-temp"] - ) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val }.sorted() == ["supply-air-temp"]) } - func testNav() async throws { + @Test func nav() async throws { let server = try HaystackServer( recordStore: InMemoryRecordStore([ Ref("site"): ["id": Ref("site"), "site": Marker.val], @@ -254,20 +200,14 @@ final class HaystackServerTests: XCTestCase { var grid = try await server.nav(navId: Ref("site")) // TODO: Implement nav -// XCTAssertEqual( -// grid.compactMap { ($0["id"] as? Ref)?.val }.sorted(), -// ["equip"] -// ) +// #expect(grid.compactMap { ($0["id"] as? Ref)?.val }.sorted() == ["equip"]) grid = try await server.nav(navId: Ref("equip")) // TODO: Implement nav -// XCTAssertEqual( -// grid.compactMap { ($0["id"] as? Ref)?.val }.sorted(), -// ["point"] -// ) +// #expect(grid.compactMap { ($0["id"] as? Ref)?.val }.sorted() == ["point"]) } - func testHisRead() async throws { + @Test func hisRead() async throws { // Test absolute time ranges let absoluteServer = try HaystackServer( @@ -287,9 +227,8 @@ final class HaystackServerTests: XCTestCase { // After var grid = try await absoluteServer.hisRead(id: Ref("point"), range: .after(DateTime("2025-05-09T17:00:00-07:00"))) - try XCTAssertEqual( - grid.rows, - [ + #expect( + try grid.rows == [ ["ts": DateTime("2025-05-10T00:00:00-07:00"), "val": Number(2)], ["ts": DateTime("2025-05-10T12:00:00-07:00"), "val": Number(3)], ["ts": DateTime("2025-05-11T00:00:00-07:00"), "val": Number(4)], @@ -298,9 +237,8 @@ final class HaystackServerTests: XCTestCase { // Date grid = try await absoluteServer.hisRead(id: Ref("point"), range: .date(Date("2025-05-10"))) - try XCTAssertEqual( - grid.rows, - [ + #expect( + try grid.rows == [ ["ts": DateTime("2025-05-10T00:00:00-07:00"), "val": Number(2)], ["ts": DateTime("2025-05-10T12:00:00-07:00"), "val": Number(3)], ] @@ -308,9 +246,8 @@ final class HaystackServerTests: XCTestCase { // Date Range grid = try await absoluteServer.hisRead(id: Ref("point"), range: .dateRange(from: Date("2025-05-10"), to: Date("2025-05-11"))) - try XCTAssertEqual( - grid.rows, - [ + #expect( + try grid.rows == [ ["ts": DateTime("2025-05-10T00:00:00-07:00"), "val": Number(2)], ["ts": DateTime("2025-05-10T12:00:00-07:00"), "val": Number(3)], ["ts": DateTime("2025-05-11T00:00:00-07:00"), "val": Number(4)], @@ -319,9 +256,8 @@ final class HaystackServerTests: XCTestCase { // DateTime Range grid = try await absoluteServer.hisRead(id: Ref("point"), range: .dateTimeRange(from: DateTime("2025-05-10T00:00:00-07:00"), to: DateTime("2025-05-11T00:00:00-07:00"))) - try XCTAssertEqual( - grid.rows, - [ + #expect( + try grid.rows == [ ["ts": DateTime("2025-05-10T00:00:00-07:00"), "val": Number(2)], ["ts": DateTime("2025-05-10T12:00:00-07:00"), "val": Number(3)], ] @@ -350,32 +286,30 @@ final class HaystackServerTests: XCTestCase { ) grid = try await relativeServer.hisRead(id: Ref("point"), range: .today) - XCTAssertEqual( - grid.rows, - [ + #expect( + grid.rows == [ ["ts": DateTime(date: now), "val": Number(3)], ] ) grid = try await relativeServer.hisRead(id: Ref("point"), range: .yesterday) - XCTAssertEqual( - grid.rows, - [ + #expect( + grid.rows == [ ["ts": DateTime(date: yesterday), "val": Number(2)], ] ) } - func testPointWrite() async throws { + @Test func pointWrite() async throws { // TODO: Implement } - func testPointWriteStatus() async throws { + @Test func pointWriteStatus() async throws { // TODO: Implement } // Test all watch methods together to avoid state complexities - func testWatch() async throws { + @Test func watch() async throws { let idA = try Ref("a") let idB = try Ref("b") let idC = try Ref("c") @@ -395,12 +329,9 @@ final class HaystackServerTests: XCTestCase { // Create the watch and validate A and B are returned var grid = try await server.watchSubCreate(watchDis: "ab", lease: nil, ids: [idA, idB]) - let watchId = try XCTUnwrap(grid.meta["watchId"] as? String) - XCTAssertEqual(grid.meta, ["watchId": watchId, "lease": null]) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }.sorted(), - ["a", "b"] - ) + let watchId = try #require(grid.meta["watchId"] as? String) + #expect(grid.meta == ["watchId": watchId, "lease": null]) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val }.sorted() == ["a", "b"]) // Change B to increment "mod" var newB = recB @@ -411,18 +342,15 @@ final class HaystackServerTests: XCTestCase { // Check that subsequent poll picks up B grid = try await server.watchPoll(watchId: watchId, refresh: false) - XCTAssertEqual(grid.meta, ["watchId": watchId]) - XCTAssertEqual(grid.count, 1) - XCTAssertEqual(grid.first?["id"] as? Ref, idB) - XCTAssertNotNil(grid.first?["new"]) + #expect(grid.meta == ["watchId": watchId]) + #expect(grid.count == 1) + #expect(grid.first?["id"] as? Ref == idB) + #expect(grid.first?["new"] != nil) // Add C to the watch and validate C is returned grid = try await server.watchSubAdd(watchId: watchId, lease: nil, ids: [idC]) - XCTAssertEqual(grid.meta, ["watchId": watchId, "lease": null]) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }.sorted(), - ["c"] - ) + #expect(grid.meta == ["watchId": watchId, "lease": null]) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val }.sorted() == ["c"]) // Change C to increment "mod" var newC = recC @@ -433,14 +361,14 @@ final class HaystackServerTests: XCTestCase { // Validate poll picks up C grid = try await server.watchPoll(watchId: watchId, refresh: false) - XCTAssertEqual(grid.meta, ["watchId": watchId]) - XCTAssertEqual(grid.count, 1) - XCTAssertEqual(grid.first?["id"] as? Ref, idC) - XCTAssertNotNil(grid.first?["new"]) + #expect(grid.meta == ["watchId": watchId]) + #expect(grid.count == 1) + #expect(grid.first?["id"] as? Ref == idC) + #expect(grid.first?["new"] != nil) // Remove A from watch grid = try await server.watchUnsubRemove(watchId: watchId, ids: [Ref("a")]) - XCTAssertTrue(grid.isEmpty) + #expect(grid.isEmpty) // Change A to increment "mod" var newA = recA @@ -451,19 +379,16 @@ final class HaystackServerTests: XCTestCase { // Validate poll does not pick up A grid = try await server.watchPoll(watchId: watchId, refresh: false) - XCTAssertEqual(grid.meta, ["watchId": watchId]) - XCTAssertEqual(grid.count, 0) + #expect(grid.meta == ["watchId": watchId]) + #expect(grid.count == 0) // Test that poll with refresh gives B and C grid = try await server.watchPoll(watchId: watchId, refresh: true) - XCTAssertEqual(grid.meta, ["watchId": watchId]) - XCTAssertEqual( - grid.compactMap { ($0["id"] as? Ref)?.val }.sorted(), - ["b", "c"] - ) + #expect(grid.meta == ["watchId": watchId]) + #expect(grid.compactMap { ($0["id"] as? Ref)?.val }.sorted() == ["b", "c"]) } - func testInvokeAction() async throws { + @Test func invokeAction() async throws { let server = HaystackServer( recordStore: InMemoryRecordStore(), historyStore: InMemoryHistoryStore(), @@ -475,12 +400,12 @@ final class HaystackServerTests: XCTestCase { } ) let grid = try await server.invokeAction(id: Ref("1"), action: "a", args: ["foo": "bar"]) - try XCTAssertEqual(grid[0]["id"] as? Ref, Ref("1")) - XCTAssertEqual(grid[0]["action"] as? String, "a") - XCTAssertEqual(grid[0]["args"] as? Dict, Dict(["foo": "bar"])) + #expect(try grid[0]["id"] as? Ref == Ref("1")) + #expect(grid[0]["action"] as? String == "a") + #expect(grid[0]["args"] as? Dict == Dict(["foo": "bar"])) } - func testEval() async throws { + @Test func eval() async throws { let server = HaystackServer( recordStore: InMemoryRecordStore(), historyStore: InMemoryHistoryStore(), @@ -492,12 +417,7 @@ final class HaystackServerTests: XCTestCase { } ) let grid = try await server.eval(expression: "anything") - XCTAssertEqual( - grid, - [ - ["foo": "bar"], - ] - ) + #expect(grid == [["foo": "bar"]]) } } diff --git a/Tests/HaystackServerVaporTests/HaystackServerVaporTests.swift b/Tests/HaystackServerVaporTests/HaystackServerVaporTests.swift index bde2fb2..a6423e7 100644 --- a/Tests/HaystackServerVaporTests/HaystackServerVaporTests.swift +++ b/Tests/HaystackServerVaporTests/HaystackServerVaporTests.swift @@ -1,161 +1,150 @@ import Haystack import HaystackServerVapor -import XCTest -import XCTVapor - -final class HaystackServerVaporTests: XCTestCase { - func testGet() throws { - let app = Application(.testing) - app.haystack = HaystackAPIMock() - try app.register(collection: HaystackRouteCollection()) - defer { app.shutdown() } - - let responseGrid = try GridBuilder() - .addCols(names: ["id", "foo"]) - .addRow([Haystack.Ref("a"), Marker.val]) - .addRow([Haystack.Ref("b"), Marker.val]) - .toGrid() - - // Test zinc encoding - try app.test( - .GET, - "/read?id=[@a,@b]", - headers: [ - HTTPHeaders.Name.accept.description: HTTPMediaType.zinc.description, - ] - ) { res in - XCTAssertEqual(res.status, .ok) - XCTAssertEqual(res.headers.contentType, .zinc) - XCTAssertEqual( - res.body.string, - responseGrid.toZinc() - ) +import Testing +import VaporTesting + +struct HaystackServerVaporTests { + private func withApp(_ test: (Application) async throws -> Void) async throws { + let app = try await Application.make(.testing) + do { + app.haystack = HaystackAPIMock() + try app.register(collection: HaystackRouteCollection()) + try await test(app) + } catch { + try await app.asyncShutdown() + throw error } + try await app.asyncShutdown() + } + + @Test func get() async throws { + try await withApp { app in + let responseGrid = try GridBuilder() + .addCols(names: ["id", "foo"]) + .addRow([Haystack.Ref("a"), Marker.val]) + .addRow([Haystack.Ref("b"), Marker.val]) + .toGrid() + + // Test zinc encoding + try await app.test( + .GET, + "/read?id=[@a,@b]", + headers: [ + HTTPHeaders.Name.accept.description: HTTPMediaType.zinc.description, + ] + ) { res in + #expect(res.status == .ok) + #expect(res.headers.contentType == .zinc) + #expect(res.body.string == responseGrid.toZinc()) + } - // Test JSON encoding - try app.test( - .GET, - "/read?id=[@a,@b]", - headers: [ - HTTPHeaders.Name.accept.description: HTTPMediaType.json.description, - ] - ) { res in - XCTAssertEqual(res.status, .ok) - XCTAssertEqual(res.headers.contentType, .json) - try XCTAssertEqual( - res.content.decode(Grid.self), - responseGrid - ) + // Test JSON encoding + try await app.test( + .GET, + "/read?id=[@a,@b]", + headers: [ + HTTPHeaders.Name.accept.description: HTTPMediaType.json.description, + ] + ) { res in + #expect(res.status == .ok) + #expect(res.headers.contentType == .json) + try #expect(res.content.decode(Grid.self) == responseGrid) + } } } - func testGetBadQuery() throws { - let app = Application(.testing) - app.haystack = HaystackAPIMock() - try app.register(collection: HaystackRouteCollection()) - defer { app.shutdown() } - - try app.test( - .GET, - "/read?id=[a,b]" // Invalid because expecting Ref, not String - ) { res in - XCTAssertEqual(res.status, .badRequest) + @Test func getBadQuery() async throws { + try await withApp { app in + try await app.test( + .GET, + "/read?id=[a,b]" // Invalid because expecting Ref, not String + ) { res in + #expect(res.status == .badRequest) + } } } - func testPost() throws { - let app = Application(.testing) - app.haystack = HaystackAPIMock() - try app.register(collection: HaystackRouteCollection()) - defer { app.shutdown() } - - let requestGrid = try GridBuilder() - .addCol(name: "id") - .addRow([Haystack.Ref("a")]) - .addRow([Haystack.Ref("b")]) - .toGrid() - - let responseGrid = try GridBuilder() - .addCols(names: ["id", "foo"]) - .addRow([Haystack.Ref("a"), Marker.val]) - .addRow([Haystack.Ref("b"), Marker.val]) - .toGrid() - - // Test zinc encoding - try app.test( - .POST, - "/read", - headers: [ - HTTPHeaders.Name.accept.description: HTTPMediaType.zinc.description, - ], - body: .init(string: requestGrid.toZinc()), - beforeRequest: { req in - req.headers.contentType = .zinc + @Test func post() async throws { + try await withApp { app in + let requestGrid = try GridBuilder() + .addCol(name: "id") + .addRow([Haystack.Ref("a")]) + .addRow([Haystack.Ref("b")]) + .toGrid() + + let responseGrid = try GridBuilder() + .addCols(names: ["id", "foo"]) + .addRow([Haystack.Ref("a"), Marker.val]) + .addRow([Haystack.Ref("b"), Marker.val]) + .toGrid() + + // Test zinc encoding + try await app.test( + .POST, + "/read", + headers: [ + HTTPHeaders.Name.accept.description: HTTPMediaType.zinc.description, + ], + body: .init(string: requestGrid.toZinc()), + beforeRequest: { req in + req.headers.contentType = .zinc + } + ) { res in + #expect(res.status == .ok) + #expect(res.headers.contentType == .zinc) + #expect(res.body.string == responseGrid.toZinc()) } - ) { res in - XCTAssertEqual(res.status, .ok) - XCTAssertEqual(res.headers.contentType, .zinc) - XCTAssertEqual( - res.body.string, - responseGrid.toZinc() - ) - } - // Test JSON encoding - try app.test( - .POST, - "/read", - headers: [ - HTTPHeaders.Name.accept.description: HTTPMediaType.json.description, - ], - beforeRequest: { req in - req.headers.contentType = .json - try req.content.encode(requestGrid) + // Test JSON encoding + try await app.test( + .POST, + "/read", + headers: [ + HTTPHeaders.Name.accept.description: HTTPMediaType.json.description, + ], + beforeRequest: { req in + req.headers.contentType = .json + try req.content.encode(requestGrid) + } + ) { res in + #expect(res.status == .ok) + #expect(res.headers.contentType == .json) + try #expect(res.content.decode(Grid.self) == responseGrid) } - ) { res in - XCTAssertEqual(res.status, .ok) - XCTAssertEqual(res.headers.contentType, .json) - try XCTAssertEqual( - res.content.decode(Grid.self), - responseGrid - ) } } - func testPostBadQuery() throws { - let app = Application(.testing) - app.haystack = HaystackAPIMock() - try app.register(collection: HaystackRouteCollection()) - defer { app.shutdown() } - - let requestGrid = try GridBuilder() - .addCol(name: "id") - .addRow(["a"]) // Invalid because expecting Ref, not String - .addRow(["b"]) - .toGrid() - - // Test zinc encoding - try app.test( - .POST, - "/read", - body: .init(string: requestGrid.toZinc()), - beforeRequest: { req in - req.headers.contentType = .zinc + @Test func postBadQuery() async throws { + try await withApp { app in + let requestGrid = try GridBuilder() + .addCol(name: "id") + .addRow(["a"]) // Invalid because expecting Ref, not String + .addRow(["b"]) + .toGrid() + + // Test zinc encoding + try await app.test( + .POST, + "/read", + body: .init(string: requestGrid.toZinc()), + beforeRequest: { req in + req.headers.contentType = .zinc + } + ) { res in + #expect(res.status == .badRequest) } - ) { res in - XCTAssertEqual(res.status, .badRequest) - } - // Test JSON encoding - try app.test( - .POST, - "/read", - beforeRequest: { req in - req.headers.contentType = .json - try req.content.encode(requestGrid) + // Test JSON encoding + try await app.test( + .POST, + "/read", + beforeRequest: { req in + req.headers.contentType = .json + try req.content.encode(requestGrid) + } + ) { res in + #expect(res.status == .badRequest) } - ) { res in - XCTAssertEqual(res.status, .badRequest) } } } diff --git a/Tests/HaystackTests/BoolTests.swift b/Tests/HaystackTests/BoolTests.swift index a66a87c..e1d317e 100644 --- a/Tests/HaystackTests/BoolTests.swift +++ b/Tests/HaystackTests/BoolTests.swift @@ -1,33 +1,28 @@ +import Foundation import Haystack -import XCTest +import Testing -final class BoolTests: XCTestCase { - func testJsonCoding() throws { +struct BoolTests { + @Test func jsonCoding() throws { let value = true let jsonString = #"true"# let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - String(data: encodedData, encoding: .utf8), - jsonString - ) + #expect(String(data: encodedData, encoding: .utf8) == jsonString) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Bool.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Bool.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual(false.toZinc(), "F") - XCTAssertEqual(true.toZinc(), "T") + @Test func toZinc() throws { + #expect(false.toZinc() == "F") + #expect(true.toZinc() == "T") } - func testComparable() throws { - XCTAssertFalse(false < false) - XCTAssertTrue(false < true) - XCTAssertFalse(true < false) - XCTAssertFalse(true < true) + @Test func comparable() throws { + #expect((false < false) == false) + #expect(false < true) + #expect((true < false) == false) + #expect((true < true) == false) } } diff --git a/Tests/HaystackTests/CoordTests.swift b/Tests/HaystackTests/CoordTests.swift index 2d1dbb7..dfcc4fe 100644 --- a/Tests/HaystackTests/CoordTests.swift +++ b/Tests/HaystackTests/CoordTests.swift @@ -1,36 +1,28 @@ +import Foundation import Haystack -import XCTest +import Testing -final class CoordTests: XCTestCase { - func testInit() throws { - try XCTAssertThrowsError(Coord(latitude: -91, longitude: 0)) - try XCTAssertThrowsError(Coord(latitude: 91, longitude: 0)) - try XCTAssertThrowsError(Coord(latitude: 0, longitude: -181)) - try XCTAssertThrowsError(Coord(latitude: 0, longitude: 181)) +struct CoordTests { + @Test func testInit() throws { + #expect(throws: CoordError.self) { try Coord(latitude: -91, longitude: 0) } + #expect(throws: CoordError.self) { try Coord(latitude: 91, longitude: 0) } + #expect(throws: CoordError.self) { try Coord(latitude: 0, longitude: -181) } + #expect(throws: CoordError.self) { try Coord(latitude: 0, longitude: 181) } } - func testJsonCoding() throws { + @Test func jsonCoding() throws { let value = try Coord(latitude: 40, longitude: -111.84) let jsonString = #"{"_kind":"coord","lat":40,"lng":-111.84}"# // Must encode/decode b/c JSON ordering is not deterministic let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - try JSONDecoder().decode(Coord.self, from: encodedData), - value - ) + #expect(try JSONDecoder().decode(Coord.self, from: encodedData) == value) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Coord.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Coord.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual( - try Coord(latitude: 40, longitude: -111.84).toZinc(), - "C(40.0,-111.84)" - ) + @Test func toZinc() throws { + #expect(try Coord(latitude: 40, longitude: -111.84).toZinc() == "C(40.0,-111.84)") } } diff --git a/Tests/HaystackTests/DateTests.swift b/Tests/HaystackTests/DateTests.swift index efd4303..7f5b319 100644 --- a/Tests/HaystackTests/DateTests.swift +++ b/Tests/HaystackTests/DateTests.swift @@ -1,8 +1,9 @@ +import Foundation import Haystack -import XCTest +import Testing -final class DateTests: XCTestCase { - func testJsonCoding() throws { +struct DateTests { + @Test func jsonCoding() throws { let value = try Date( year: 1991, month: 6, @@ -12,26 +13,19 @@ final class DateTests: XCTestCase { // Must encode/decode b/c JSON ordering is not deterministic let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - try JSONDecoder().decode(Date.self, from: encodedData), - value - ) + #expect(try JSONDecoder().decode(Date.self, from: encodedData) == value) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Haystack.Date.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Haystack.Date.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual( + @Test func toZinc() throws { + #expect( try Date( year: 1991, month: 6, day: 7 - ).toZinc(), - "1991-06-07" + ).toZinc() == "1991-06-07" ) } } diff --git a/Tests/HaystackTests/DateTimeTests.swift b/Tests/HaystackTests/DateTimeTests.swift index f349b15..ccf0f37 100644 --- a/Tests/HaystackTests/DateTimeTests.swift +++ b/Tests/HaystackTests/DateTimeTests.swift @@ -1,8 +1,9 @@ +import Foundation import Haystack -import XCTest +import Testing -final class DateTimeTests: XCTestCase { - func testJsonCoding() throws { +struct DateTimeTests { + @Test func jsonCoding() throws { let value = try DateTime( year: 1988, month: 4, @@ -18,19 +19,13 @@ final class DateTimeTests: XCTestCase { // Must encode/decode b/c JSON ordering is not deterministic let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - try JSONDecoder().decode(DateTime.self, from: encodedData), - value - ) + #expect(try JSONDecoder().decode(DateTime.self, from: encodedData) == value) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(DateTime.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(DateTime.self, from: decodedData) == value) } - func testJsonCoding_noMilliseconds() throws { + @Test func jsonCoding_noMilliseconds() throws { let value = try DateTime( year: 1988, month: 4, @@ -45,20 +40,14 @@ final class DateTimeTests: XCTestCase { // Must encode/decode b/c JSON ordering is not deterministic let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - try JSONDecoder().decode(DateTime.self, from: encodedData), - value - ) + #expect(try JSONDecoder().decode(DateTime.self, from: encodedData) == value) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(DateTime.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(DateTime.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual( + @Test func toZinc() throws { + #expect( try DateTime( year: 1988, month: 4, @@ -68,11 +57,10 @@ final class DateTimeTests: XCTestCase { second: 43, gmtOffset: 0, timezone: DateTime.utcName - ).toZinc(), - "1988-04-01T10:05:43Z" + ).toZinc() == "1988-04-01T10:05:43Z" ) - XCTAssertEqual( + #expect( try DateTime( year: 1988, month: 4, @@ -82,8 +70,7 @@ final class DateTimeTests: XCTestCase { second: 43, gmtOffset: -5 * 60 * 60, timezone: "New_York" - ).toZinc(), - "1988-04-01T10:05:43-05:00 New_York" + ).toZinc() == "1988-04-01T10:05:43-05:00 New_York" ) } } diff --git a/Tests/HaystackTests/DictTests.swift b/Tests/HaystackTests/DictTests.swift index fae93c5..0958180 100644 --- a/Tests/HaystackTests/DictTests.swift +++ b/Tests/HaystackTests/DictTests.swift @@ -1,8 +1,9 @@ +import Foundation import Haystack -import XCTest +import Testing -final class DictTests: XCTestCase { - func testJsonCoding() throws { +struct DictTests { + @Test func jsonCoding() throws { let value: Dict = [ "bool": true, "str": "abc", @@ -17,20 +18,14 @@ final class DictTests: XCTestCase { // Must encode/decode b/c JSON ordering is not deterministic let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - try JSONDecoder().decode(Dict.self, from: encodedData), - value - ) + #expect(try JSONDecoder().decode(Dict.self, from: encodedData) == value) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Dict.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Dict.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual( + @Test func toZinc() throws { + #expect( Dict([ "bool": true, "str": "abc", @@ -39,57 +34,48 @@ final class DictTests: XCTestCase { "bool": false, "str": "xyz", ]), - ]).toZinc(), - // Keys are sorted alphabetically. - #"{bool:T dict:{bool:F str:"xyz"} number:42furloghs str:"abc"}"# + ]).toZinc() == + // Keys are sorted alphabetically. + #"{bool:T dict:{bool:F str:"xyz"} number:42furloghs str:"abc"}"# ) } - func testEquatable() { + @Test func equatable() { // Test basic - XCTAssertEqual( - Dict(["a": "b"]), - Dict(["a": "b"]) - ) - XCTAssertNotEqual( - Dict(["a": "a"]), - Dict(["a": "b"]) - ) + #expect(Dict(["a": "b"]) == Dict(["a": "b"])) + #expect(Dict(["a": "a"]) != Dict(["a": "b"])) // Test element count matters - XCTAssertNotEqual( + #expect( Dict([ "a": "a", "b": "b", - ]), - Dict([ + ]) != Dict([ "a": "a", ]) ) - XCTAssertNotEqual( + #expect( Dict([ "a": "a", - ]), - Dict([ + ]) != Dict([ "a": "a", "b": "b", ]) ) // Test order does not matter - XCTAssertEqual( + #expect( Dict([ "a": "a", "b": "b", - ]), - Dict([ + ]) == Dict([ "b": "b", "a": "a", ]) ) // Test nested - XCTAssertEqual( + #expect( Dict([ "bool": true, "str": "abc", @@ -98,8 +84,7 @@ final class DictTests: XCTestCase { "bool": false, "str": "xyz", ]), - ]), - Dict([ + ]) == Dict([ "bool": true, "str": "abc", "number": Number(42, unit: "furloghs"), @@ -109,7 +94,7 @@ final class DictTests: XCTestCase { ]), ]) ) - XCTAssertNotEqual( + #expect( Dict([ "bool": true, "str": "abc", @@ -118,8 +103,7 @@ final class DictTests: XCTestCase { "bool": false, "str": "xyz", ]), - ]), - Dict([ + ]) != Dict([ "bool": true, "str": "abc", "number": Number(42, unit: "furloghs"), @@ -131,27 +115,27 @@ final class DictTests: XCTestCase { ) } - func testTrap() { + @Test func trap() throws { let dict: Dict = ["a": "abc", "b": null] - try XCTAssertNoThrow(dict.trap("a")) - try XCTAssertEqual(dict.trap("a", as: String.self), "abc") - try XCTAssertThrowsError(dict.trap("a", as: Number.self)) - try XCTAssertThrowsError(dict.trap("b")) - try XCTAssertThrowsError(dict.trap("c")) + #expect(throws: Never.self) { try dict.trap("a") } + try #expect(dict.trap("a", as: String.self) == "abc") + #expect(throws: (any Error).self) { try dict.trap("a", as: Number.self) } + #expect(throws: (any Error).self) { try dict.trap("b") } + #expect(throws: (any Error).self) { try dict.trap("c") } } - func testGet() { + @Test func get() throws { let dict: Dict = ["a": "abc", "b": null] - try XCTAssertNotNil(dict.get("a")) - try XCTAssertEqual(dict.get("a", as: String.self), "abc") - try XCTAssertThrowsError(dict.get("a", as: Number.self)) - try XCTAssertNil(dict.get("b")) - try XCTAssertNil(dict.get("c")) + try #expect(dict.get("a") != nil) + try #expect(dict.get("a", as: String.self) == "abc") + #expect(throws: ValError.self) { try dict.get("a", as: Number.self) } + try #expect(dict.get("b") == nil) + try #expect(dict.get("c") == nil) } - func testCollection() { + @Test func collection() { let dict: Dict = [ "bool": true, "str": "abc", @@ -163,18 +147,18 @@ final class DictTests: XCTestCase { ] // Test index access - XCTAssertEqual(dict["bool"] as? Bool, true) - XCTAssertEqual(dict["str"] as? String, "abc") - XCTAssertEqual(dict["number"] as? Number, Number(42, unit: "furloghs")) - XCTAssertEqual(dict["dict"] as? Dict, ["bool": true, "str": "xyz"]) + #expect(dict["bool"] as? Bool == true) + #expect(dict["str"] as? String == "abc") + #expect(dict["number"] as? Number == Number(42, unit: "furloghs")) + #expect(dict["dict"] as? Dict == ["bool": true, "str": "xyz"]) // Test loop for (key, value) in dict { switch key { - case "bool": XCTAssertEqual(value as? Bool, true) - case "str": XCTAssertEqual(value as? String, "abc") - case "number": XCTAssertEqual((value as? Number), Number(42, unit: "furloghs")) - case "dict": XCTAssertEqual((value as? Dict), ["bool": true, "str": "xyz"]) + case "bool": #expect(value as? Bool == true) + case "str": #expect(value as? String == "abc") + case "number": #expect((value as? Number) == Number(42, unit: "furloghs")) + case "dict": #expect((value as? Dict) == ["bool": true, "str": "xyz"]) default: break } } diff --git a/Tests/HaystackTests/FilterTests.swift b/Tests/HaystackTests/FilterTests.swift index 92c897b..ce42c9e 100644 --- a/Tests/HaystackTests/FilterTests.swift +++ b/Tests/HaystackTests/FilterTests.swift @@ -1,13 +1,13 @@ import Haystack -import XCTest +import Testing -final class FilterTests: XCTestCase { - func testIdentity() throws { - try XCTAssertTrue(FilterFactory.has("a").equals(FilterFactory.has("a"))) - try XCTAssertFalse(FilterFactory.has("a").equals(FilterFactory.has("b"))) +struct FilterTests { + @Test func identity() throws { + try #expect(FilterFactory.has("a").equals(FilterFactory.has("a"))) + try #expect(!FilterFactory.has("a").equals(FilterFactory.has("b"))) } - func testBasics() throws { + @Test func basics() throws { try verifyParse("x", FilterFactory.has("x")) try verifyParse("foo", FilterFactory.has("foo")) try verifyParse("fooBar", FilterFactory.has("fooBar")) @@ -17,35 +17,35 @@ final class FilterTests: XCTestCase { try verifyParse("not foo", FilterFactory.missing("foo")) } - func testZincOnlyLiteralsDontWork() throws { - try XCTAssertThrowsError(FilterFactory.make("x==T")) - try XCTAssertThrowsError(FilterFactory.make("x==F")) - try XCTAssertThrowsError(FilterFactory.make("x==F")) + @Test func zincOnlyLiteralsDontWork() throws { + #expect(throws: (any Error).self) { try FilterFactory.make("x==T") } + #expect(throws: (any Error).self) { try FilterFactory.make("x==F") } + #expect(throws: (any Error).self) { try FilterFactory.make("x==F") } } - func testBool() throws { + @Test func bool() throws { try verifyParse("x->y==true", FilterFactory.eq("x->y", true)) try verifyParse("x->y!=false", FilterFactory.ne("x->y", false)) } - func testStr() throws { + @Test func str() throws { try verifyParse("x==\"hi\"", FilterFactory.eq("x", "hi")) try verifyParse("x!=\"\\\"hi\\\"\"", FilterFactory.ne("x", "\"hi\"")) try verifyParse("x==\"_\\uabcd_\\n_\"", FilterFactory.eq("x", "_\u{abcd}_\n_")) } - func testUri() throws { + @Test func uri() throws { try verifyParse("ref==`http://foo/?bar`", FilterFactory.eq("ref", Uri("http://foo/?bar"))) try verifyParse("ref->x==`file name`", FilterFactory.eq("ref->x", Uri("file name"))) try verifyParse("ref == `foo bar`", FilterFactory.eq("ref", Uri("foo bar"))) } - func testInt() throws { + @Test func int() throws { try verifyParse("num < 4", FilterFactory.lt("num", Number(4))) try verifyParse("num <= -99", FilterFactory.le("num", Number(-99))) } - func testFloat() throws { + @Test func float() throws { try verifyParse("num < 4.0", FilterFactory.lt("num", Number(4.0))) try verifyParse("num <= -9.6", FilterFactory.le("num", Number(-9.6))) try verifyParse("num > 400000", FilterFactory.gt("num", Number(4e5))) @@ -53,42 +53,42 @@ final class FilterTests: XCTestCase { try verifyParse("num >= 2.16", FilterFactory.ge("num", Number(2.16))) } - func testUnit() throws { + @Test func unit() throws { try verifyParse("dur < 5ns", FilterFactory.lt("dur", Number(5, unit: "ns"))) try verifyParse("dur < 10kg", FilterFactory.lt("dur", Number(10, unit: "kg"))) try verifyParse("dur < -9sec", FilterFactory.lt("dur", Number(-9, unit: "sec"))) try verifyParse("dur < 2.5hr", FilterFactory.lt("dur", Number(2.5, unit: "hr"))) } - func testDateTime() throws { + @Test func dateTime() throws { try verifyParse("foo < 2009-10-30", FilterFactory.lt("foo", Date("2009-10-30"))) try verifyParse("foo < 08:30:00", FilterFactory.lt("foo", Time("08:30:00"))) try verifyParse("foo < 13:00:00", FilterFactory.lt("foo", Time("13:00:00"))) } - func testRef() throws { + @Test func ref() throws { try verifyParse("author == @xyz", FilterFactory.eq("author", Ref("xyz"))) try verifyParse("author==@xyz:foo.bar", FilterFactory.eq("author", Ref("xyz:foo.bar"))) } - func testAnd() throws { + @Test func and() throws { try verifyParse("a and b", FilterFactory.has("a").and(FilterFactory.has("b"))) try verifyParse("a and b and c == 3", FilterFactory.has("a").and(FilterFactory.has("b").and(FilterFactory.eq("c", Number(3))))) } - func testOr() throws { + @Test func or() throws { try verifyParse("a or b", FilterFactory.has("a").or(FilterFactory.has("b"))) try verifyParse("a or b or c == 3", FilterFactory.has("a").or(FilterFactory.has("b").or(FilterFactory.eq("c", Number(3))))) } - func testParens() throws { + @Test func parens() throws { try verifyParse("(a)", FilterFactory.has("a")) try verifyParse("(a) and (b)", FilterFactory.has("a").and(FilterFactory.has("b"))) try verifyParse("( a ) and ( b ) ", FilterFactory.has("a").and(FilterFactory.has("b"))) try verifyParse("(a or b) or (c == 3)", FilterFactory.has("a").or(FilterFactory.has("b")).or(FilterFactory.eq("c", Number(3)))) } - func testCombo() throws { + @Test func combo() throws { let isA = try FilterFactory.has("a") let isB = try FilterFactory.has("b") let isC = try FilterFactory.has("c") @@ -102,10 +102,10 @@ final class FilterTests: XCTestCase { func verifyParse(_ s: String, _ expected: any Filter) throws { let actual = try FilterFactory.make(s) - XCTAssertTrue(actual.equals(expected)) + #expect(actual.equals(expected)) } - func testInclude() throws { + @Test func include() throws { let a: Dict = try [ "dis": "a", "num": Number(10), @@ -234,32 +234,32 @@ final class FilterTests: XCTestCase { actual += id } } - XCTAssertEqual(actual, expected) + #expect(actual == expected) } - func testPath() throws { + @Test func path() throws { // single name var path = try Path.make(path: "foo") - XCTAssertEqual(path.count, 1) - XCTAssertEqual(path[0], "foo") - XCTAssertEqual(path.description, "foo") - try XCTAssertEqual(path, Path.make(path: "foo")) + #expect(path.count == 1) + #expect(path[0] == "foo") + #expect(path.description == "foo") + #expect(try path == Path.make(path: "foo")) // two names path = try Path.make(path: "foo->bar") - XCTAssertEqual(path.count, 2) - XCTAssertEqual(path[0], "foo") - XCTAssertEqual(path[1], "bar") - XCTAssertEqual(path.description, "foo->bar") - try XCTAssertEqual(path, Path.make(path: "foo->bar")) + #expect(path.count == 2) + #expect(path[0] == "foo") + #expect(path[1] == "bar") + #expect(path.description == "foo->bar") + #expect(try path == Path.make(path: "foo->bar")) // three names path = try Path.make(path: "x->y->z") - XCTAssertEqual(path.count, 3) - XCTAssertEqual(path[0], "x") - XCTAssertEqual(path[1], "y") - XCTAssertEqual(path[2], "z") - XCTAssertEqual(path.description, "x->y->z") - try XCTAssertEqual(path, Path.make(path: "x->y->z")) + #expect(path.count == 3) + #expect(path[0] == "x") + #expect(path[1] == "y") + #expect(path[2] == "z") + #expect(path.description == "x->y->z") + #expect(try path == Path.make(path: "x->y->z")) } } diff --git a/Tests/HaystackTests/GridTests.swift b/Tests/HaystackTests/GridTests.swift index 6f81807..35242e7 100644 --- a/Tests/HaystackTests/GridTests.swift +++ b/Tests/HaystackTests/GridTests.swift @@ -1,8 +1,9 @@ +import Foundation import Haystack -import XCTest +import Testing -final class GridTests: XCTestCase { - func testJsonCoding() throws { +struct GridTests { + @Test func jsonCoding() throws { let value = try GridBuilder() .setMeta(["foo": "bar"]) .addCol(name: "dis", meta: ["dis": "Equip Name"]) @@ -16,38 +17,26 @@ final class GridTests: XCTestCase { // Must encode/decode b/c JSON ordering is not deterministic let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - try JSONDecoder().decode(Grid.self, from: encodedData), - value - ) + #expect(try JSONDecoder().decode(Grid.self, from: encodedData) == value) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Grid.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Grid.self, from: decodedData) == value) } - func testJsonCoding_empty() throws { + @Test func jsonCoding_empty() throws { let value = GridBuilder().toGrid() let jsonString = #"{"_kind":"grid","meta":{"ver":"3.0"},"cols":[{"name":"empty"}],"rows":[]}"# // Must encode/decode b/c JSON ordering is not deterministic let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - try JSONDecoder().decode(Grid.self, from: encodedData), - value - ) + #expect(try JSONDecoder().decode(Grid.self, from: encodedData) == value) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Grid.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Grid.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual( + @Test func toZinc() throws { + #expect( try GridBuilder() .setMeta(["foo": "bar"]) .addCol(name: "dis", meta: ["dis": "Equip Name"]) @@ -57,29 +46,31 @@ final class GridTests: XCTestCase { .addRow(["dis": "RTU-1", "equip": marker, "siteRef": Ref("153c-699a", dis: "HQ"), "installed": Date(year: 2005, month: 6, day: 1)]) .addRow(["dis": "RTU-2", "equip": marker, "siteRef": Ref("153c-699b", dis: "Library"), "installed": Date(year: 1997, month: 7, day: 12)]) .toGrid() - .toZinc(), - """ - ver:"3.0" foo:"bar" - dis dis:"Equip Name", equip, siteRef, installed - "RTU-1", M, @153c-699a HQ, 2005-06-01 - "RTU-2", M, @153c-699b Library, 1997-07-12 - """ + .toZinc() + == + """ + ver:"3.0" foo:"bar" + dis dis:"Equip Name", equip, siteRef, installed + "RTU-1", M, @153c-699a HQ, 2005-06-01 + "RTU-2", M, @153c-699b Library, 1997-07-12 + """ ) // Test empty grid - XCTAssertEqual( + #expect( GridBuilder() .toGrid() - .toZinc(), - """ - ver:"3.0" - empty + .toZinc() + == + """ + ver:"3.0" + empty - """ + """ ) } - func testEquatable() throws { + @Test func equatable() throws { let builder1 = try GridBuilder() .setMeta(["ver": "3.0", "foo": "bar"]) .addCol(name: "dis", meta: ["dis": "Equip Name"]) @@ -99,17 +90,11 @@ final class GridTests: XCTestCase { .addRow(["dis": "RTU-2", "equip": marker, "siteRef": Ref("153c-699b", dis: "Library"), "managed": false]) // Test basic - XCTAssertEqual( - builder1.toGrid(), - builder1.toGrid() - ) - XCTAssertNotEqual( - builder1.toGrid(), - builder2.toGrid() - ) + #expect(builder1.toGrid() == builder1.toGrid()) + #expect(builder1.toGrid() != builder2.toGrid()) } - func testCollection() throws { + @Test func collection() throws { let grid = try GridBuilder() .setMeta(["ver": "3.0", "foo": "bar"]) .addCol(name: "dis", meta: ["dis": "Equip Name"]) @@ -121,15 +106,15 @@ final class GridTests: XCTestCase { .toGrid() // Test index access - try XCTAssertEqual(grid[0], ["dis": "RTU-1", "equip": marker, "siteRef": Ref("153c-699a", dis: "HQ"), "managed": true]) - try XCTAssertEqual(grid[1], ["dis": "RTU-2", "equip": marker, "siteRef": Ref("153c-699b", dis: "Library"), "managed": false]) - XCTAssertEqual(grid[0]["dis"] as? String, "RTU-1") + #expect(try grid[0] == ["dis": "RTU-1", "equip": marker, "siteRef": Ref("153c-699a", dis: "HQ"), "managed": true]) + #expect(try grid[1] == ["dis": "RTU-2", "equip": marker, "siteRef": Ref("153c-699b", dis: "Library"), "managed": false]) + #expect(grid[0]["dis"] as? String == "RTU-1") // Test loop for (i, row) in grid.enumerated() { switch i { - case 0: try XCTAssertEqual(row, ["dis": "RTU-1", "equip": marker, "siteRef": Ref("153c-699a", dis: "HQ"), "managed": true]) - case 1: try XCTAssertEqual(row, ["dis": "RTU-2", "equip": marker, "siteRef": Ref("153c-699b", dis: "Library"), "managed": false]) + case 0: #expect(try row == ["dis": "RTU-1", "equip": marker, "siteRef": Ref("153c-699a", dis: "HQ"), "managed": true]) + case 1: #expect(try row == ["dis": "RTU-2", "equip": marker, "siteRef": Ref("153c-699b", dis: "Library"), "managed": false]) default: break } } diff --git a/Tests/HaystackTests/IO/ZincReaderTests.swift b/Tests/HaystackTests/IO/ZincReaderTests.swift index 439549b..09e2a34 100644 --- a/Tests/HaystackTests/IO/ZincReaderTests.swift +++ b/Tests/HaystackTests/IO/ZincReaderTests.swift @@ -1,9 +1,9 @@ import Haystack -import XCTest +import Testing -final class ZincReaderTests: XCTestCase { - func testNullGridMetaAndColMeta() throws { - try XCTAssertEqualZincGrid( +struct ZincReaderTests { + @Test func nullGridMetaAndColMeta() throws { + try expectEqualZincGrid( zinc: """ ver:"3.0" tag:N a nullmetatag:N, b markermetatag @@ -15,8 +15,8 @@ final class ZincReaderTests: XCTestCase { ) } - func testGridWithSymbols() throws { - try XCTAssertEqualZincGrid( + @Test func gridWithSymbols() throws { + try expectEqualZincGrid( zinc: """ ver:"3.0" a,b @@ -30,8 +30,8 @@ final class ZincReaderTests: XCTestCase { ) } - func test() throws { - try XCTAssertEqualZincGrid( + @Test func test() throws { + try expectEqualZincGrid( zinc: """ ver:"3.0" fooBar33 @@ -42,7 +42,7 @@ final class ZincReaderTests: XCTestCase { rows: [] ) - try XCTAssertEqualZincGrid( + try expectEqualZincGrid( zinc: """ ver:"3.0" tag foo:"bar" xyz @@ -55,7 +55,7 @@ final class ZincReaderTests: XCTestCase { ] ) - try XCTAssertEqualZincGrid( + try expectEqualZincGrid( zinc: """ ver:"3.0" val @@ -70,7 +70,7 @@ final class ZincReaderTests: XCTestCase { ] ) - try XCTAssertEqualZincGrid( + try expectEqualZincGrid( zinc: """ ver:"3.0" a,b @@ -85,7 +85,7 @@ final class ZincReaderTests: XCTestCase { ] ) - try XCTAssertEqualZincGrid( + try expectEqualZincGrid( zinc: """ ver:"3.0" a, b, c, d @@ -112,7 +112,7 @@ final class ZincReaderTests: XCTestCase { ] ) - try XCTAssertEqualZincGrid( + try expectEqualZincGrid( zinc: """ ver:"3.0" foo @@ -131,7 +131,7 @@ final class ZincReaderTests: XCTestCase { ] ) - try XCTAssertEqualZincGrid( + try expectEqualZincGrid( zinc: """ ver:"3.0" a,b @@ -150,7 +150,7 @@ final class ZincReaderTests: XCTestCase { ] ) - try XCTAssertEqualZincGrid( + try expectEqualZincGrid( zinc: """ ver:"3.0" a, b, c @@ -173,7 +173,7 @@ final class ZincReaderTests: XCTestCase { ] ) - try XCTAssertEqualZincGrid( + try expectEqualZincGrid( zinc: """ ver:"3.0" a,b @@ -189,7 +189,7 @@ final class ZincReaderTests: XCTestCase { ] ) - try XCTAssertEqualZincGrid( + try expectEqualZincGrid( zinc: """ ver:"3.0" a: 2009-02-03T04:05:06Z foo b: 2010-02-03T04:05:06Z UTC bar c: 2009-12-03T04:05:06Z London baz a @@ -228,7 +228,7 @@ final class ZincReaderTests: XCTestCase { ) } - private func XCTAssertEqualZincGrid( + private func expectEqualZincGrid( zinc: String, meta: [String: any Val], cols: [(String, [String: any Val]?)], @@ -248,9 +248,8 @@ final class ZincReaderTests: XCTestCase { } let expected = builder.toGrid() - XCTAssertEqual( - actual, - expected, + #expect( + actual == expected, """ \(actual.toZinc()) is not equal to diff --git a/Tests/HaystackTests/IO/ZincTokenizerTests.swift b/Tests/HaystackTests/IO/ZincTokenizerTests.swift index def38df..d05e35b 100644 --- a/Tests/HaystackTests/IO/ZincTokenizerTests.swift +++ b/Tests/HaystackTests/IO/ZincTokenizerTests.swift @@ -1,113 +1,113 @@ @testable import Haystack -import XCTest +import Testing -final class ZincTokenizerTests: XCTestCase { - func testEmpty() throws { - try XCTAssertEqualTokensAndVals(zinc: "", expected: []) +struct ZincTokenizerTests { + @Test func empty() throws { + try expectEqualTokensAndVals(zinc: "", expected: []) } - func testId() throws { - try XCTAssertEqualTokensAndVals(zinc: "x", expected: [(.id, "x")]) - try XCTAssertEqualTokensAndVals(zinc: "fooBar", expected: [(.id, "fooBar")]) - try XCTAssertEqualTokensAndVals(zinc: "fooBar1999x", expected: [(.id, "fooBar1999x")]) - try XCTAssertEqualTokensAndVals(zinc: "foo_23", expected: [(.id, "foo_23")]) - try XCTAssertEqualTokensAndVals(zinc: "Foo", expected: [(.id, "Foo")]) + @Test func id() throws { + try expectEqualTokensAndVals(zinc: "x", expected: [(.id, "x")]) + try expectEqualTokensAndVals(zinc: "fooBar", expected: [(.id, "fooBar")]) + try expectEqualTokensAndVals(zinc: "fooBar1999x", expected: [(.id, "fooBar1999x")]) + try expectEqualTokensAndVals(zinc: "foo_23", expected: [(.id, "foo_23")]) + try expectEqualTokensAndVals(zinc: "Foo", expected: [(.id, "Foo")]) } - func testNum() throws { - try XCTAssertEqualTokensAndVals(zinc: "5", expected: [(.num, Number(5))]) - try XCTAssertEqualTokensAndVals(zinc: "0x1234_abcd", expected: [(.num, Number(0x1234_ABCD))]) + @Test func num() throws { + try expectEqualTokensAndVals(zinc: "5", expected: [(.num, Number(5))]) + try expectEqualTokensAndVals(zinc: "0x1234_abcd", expected: [(.num, Number(0x1234_ABCD))]) } - func testFloats() throws { - try XCTAssertEqualTokensAndVals(zinc: "5.0", expected: [(.num, Number(5))]) - try XCTAssertEqualTokensAndVals(zinc: "5.42", expected: [(.num, Number(5.42))]) - try XCTAssertEqualTokensAndVals(zinc: "123.2e32", expected: [(.num, Number(123.2e32))]) - try XCTAssertEqualTokensAndVals(zinc: "123.2e+32", expected: [(.num, Number(123.2e+32))]) - try XCTAssertEqualTokensAndVals(zinc: "2_123.2e+32", expected: [(.num, Number(2123.2e+32))]) - try XCTAssertEqualTokensAndVals(zinc: "4.2e-7", expected: [(.num, Number(4.2e-7))]) + @Test func floats() throws { + try expectEqualTokensAndVals(zinc: "5.0", expected: [(.num, Number(5))]) + try expectEqualTokensAndVals(zinc: "5.42", expected: [(.num, Number(5.42))]) + try expectEqualTokensAndVals(zinc: "123.2e32", expected: [(.num, Number(123.2e32))]) + try expectEqualTokensAndVals(zinc: "123.2e+32", expected: [(.num, Number(123.2e+32))]) + try expectEqualTokensAndVals(zinc: "2_123.2e+32", expected: [(.num, Number(2123.2e+32))]) + try expectEqualTokensAndVals(zinc: "4.2e-7", expected: [(.num, Number(4.2e-7))]) } - func testNumberWithUnits() throws { - try XCTAssertEqualTokensAndVals(zinc: "-40ms", expected: [(.num, Number(-40, unit: "ms"))]) - try XCTAssertEqualTokensAndVals(zinc: "1sec", expected: [(.num, Number(1, unit: "sec"))]) - try XCTAssertEqualTokensAndVals(zinc: "5hr", expected: [(.num, Number(5, unit: "hr"))]) - try XCTAssertEqualTokensAndVals(zinc: "2.5day", expected: [(.num, Number(2.5, unit: "day"))]) - try XCTAssertEqualTokensAndVals(zinc: "12%", expected: [(.num, Number(12, unit: "%"))]) - try XCTAssertEqualTokensAndVals(zinc: "987_foo", expected: [(.num, Number(987, unit: "_foo"))]) - try XCTAssertEqualTokensAndVals(zinc: "-1.2m/s", expected: [(.num, Number(-1.2, unit: "m/s"))]) - try XCTAssertEqualTokensAndVals(zinc: #"12kWh/ft\u00B2"#, expected: [(.num, Number(12, unit: "kWh/ft\u{00B2}"))]) - try XCTAssertEqualTokensAndVals(zinc: "3_000.5J/kg_dry", expected: [(.num, Number(3000.5, unit: "J/kg_dry"))]) + @Test func numberWithUnits() throws { + try expectEqualTokensAndVals(zinc: "-40ms", expected: [(.num, Number(-40, unit: "ms"))]) + try expectEqualTokensAndVals(zinc: "1sec", expected: [(.num, Number(1, unit: "sec"))]) + try expectEqualTokensAndVals(zinc: "5hr", expected: [(.num, Number(5, unit: "hr"))]) + try expectEqualTokensAndVals(zinc: "2.5day", expected: [(.num, Number(2.5, unit: "day"))]) + try expectEqualTokensAndVals(zinc: "12%", expected: [(.num, Number(12, unit: "%"))]) + try expectEqualTokensAndVals(zinc: "987_foo", expected: [(.num, Number(987, unit: "_foo"))]) + try expectEqualTokensAndVals(zinc: "-1.2m/s", expected: [(.num, Number(-1.2, unit: "m/s"))]) + try expectEqualTokensAndVals(zinc: #"12kWh/ft\u00B2"#, expected: [(.num, Number(12, unit: "kWh/ft\u{00B2}"))]) + try expectEqualTokensAndVals(zinc: "3_000.5J/kg_dry", expected: [(.num, Number(3000.5, unit: "J/kg_dry"))]) } - func testStrings() throws { - try XCTAssertEqualTokensAndVals(zinc: #""""#, expected: [(.str, "")]) - try XCTAssertEqualTokensAndVals(zinc: #""x y""#, expected: [(.str, "x y")]) - try XCTAssertEqualTokensAndVals(zinc: #""x\"y""#, expected: [(.str, #"x"y"#)]) - try XCTAssertEqualTokensAndVals(zinc: #""_\u012f \n \t \\_""#, expected: [(.str, "_\u{012f} \n \t \\_")]) + @Test func strings() throws { + try expectEqualTokensAndVals(zinc: #""""#, expected: [(.str, "")]) + try expectEqualTokensAndVals(zinc: #""x y""#, expected: [(.str, "x y")]) + try expectEqualTokensAndVals(zinc: #""x\"y""#, expected: [(.str, #"x"y"#)]) + try expectEqualTokensAndVals(zinc: #""_\u012f \n \t \\_""#, expected: [(.str, "_\u{012f} \n \t \\_")]) } - func testDate() throws { - try XCTAssertEqualTokensAndVals(zinc: "2016-06-06", expected: [(.date, Date(year: 2016, month: 06, day: 06))]) + @Test func date() throws { + try expectEqualTokensAndVals(zinc: "2016-06-06", expected: [(.date, Date(year: 2016, month: 06, day: 06))]) } - func testTime() throws { - try XCTAssertEqualTokensAndVals(zinc: "8:30", expected: [(.time, Time(hour: 8, minute: 30, second: 0))]) - try XCTAssertEqualTokensAndVals(zinc: "20:15", expected: [(.time, Time(hour: 20, minute: 15, second: 0))]) - try XCTAssertEqualTokensAndVals(zinc: "00:00", expected: [(.time, Time(hour: 0, minute: 0, second: 0))]) - try XCTAssertEqualTokensAndVals(zinc: "00:00:00", expected: [(.time, Time(hour: 0, minute: 0, second: 0))]) - try XCTAssertEqualTokensAndVals(zinc: "01:02:03", expected: [(.time, Time(hour: 1, minute: 2, second: 3))]) - try XCTAssertEqualTokensAndVals(zinc: "23:59:59", expected: [(.time, Time(hour: 23, minute: 59, second: 59))]) - try XCTAssertEqualTokensAndVals(zinc: "12:00:12.9", expected: [(.time, Time(hour: 12, minute: 0, second: 12, millisecond: 900))]) - try XCTAssertEqualTokensAndVals(zinc: "12:00:12.99", expected: [(.time, Time(hour: 12, minute: 0, second: 12, millisecond: 990))]) - try XCTAssertEqualTokensAndVals(zinc: "12:00:12.999", expected: [(.time, Time(hour: 12, minute: 0, second: 12, millisecond: 999))]) - try XCTAssertEqualTokensAndVals(zinc: "12:00:12.000", expected: [(.time, Time(hour: 12, minute: 0, second: 12))]) - try XCTAssertEqualTokensAndVals(zinc: "12:00:12.001", expected: [(.time, Time(hour: 12, minute: 0, second: 12, millisecond: 1))]) + @Test func time() throws { + try expectEqualTokensAndVals(zinc: "8:30", expected: [(.time, Time(hour: 8, minute: 30, second: 0))]) + try expectEqualTokensAndVals(zinc: "20:15", expected: [(.time, Time(hour: 20, minute: 15, second: 0))]) + try expectEqualTokensAndVals(zinc: "00:00", expected: [(.time, Time(hour: 0, minute: 0, second: 0))]) + try expectEqualTokensAndVals(zinc: "00:00:00", expected: [(.time, Time(hour: 0, minute: 0, second: 0))]) + try expectEqualTokensAndVals(zinc: "01:02:03", expected: [(.time, Time(hour: 1, minute: 2, second: 3))]) + try expectEqualTokensAndVals(zinc: "23:59:59", expected: [(.time, Time(hour: 23, minute: 59, second: 59))]) + try expectEqualTokensAndVals(zinc: "12:00:12.9", expected: [(.time, Time(hour: 12, minute: 0, second: 12, millisecond: 900))]) + try expectEqualTokensAndVals(zinc: "12:00:12.99", expected: [(.time, Time(hour: 12, minute: 0, second: 12, millisecond: 990))]) + try expectEqualTokensAndVals(zinc: "12:00:12.999", expected: [(.time, Time(hour: 12, minute: 0, second: 12, millisecond: 999))]) + try expectEqualTokensAndVals(zinc: "12:00:12.000", expected: [(.time, Time(hour: 12, minute: 0, second: 12))]) + try expectEqualTokensAndVals(zinc: "12:00:12.001", expected: [(.time, Time(hour: 12, minute: 0, second: 12, millisecond: 1))]) } - func testDateTime() throws { - try XCTAssertEqualTokensAndVals( + @Test func dateTime() throws { + try expectEqualTokensAndVals( zinc: "2016-01-13T09:51:33-05:00 New_York", - expected: try [(.datetime, DateTime(year: 2016, month: 1, day: 13, hour: 9, minute: 51, second: 33, gmtOffset: -5 * 60 * 60, timezone: "New_York"))] + expected: [(.datetime, DateTime(year: 2016, month: 1, day: 13, hour: 9, minute: 51, second: 33, gmtOffset: -5 * 60 * 60, timezone: "New_York"))] ) - try XCTAssertEqualTokensAndVals( + try expectEqualTokensAndVals( zinc: "2016-01-13T09:51:33.352-05:00 New_York", - expected: try [(.datetime, DateTime(year: 2016, month: 1, day: 13, hour: 9, minute: 51, second: 33, millisecond: 352, gmtOffset: -5 * 60 * 60, timezone: "New_York"))] + expected: [(.datetime, DateTime(year: 2016, month: 1, day: 13, hour: 9, minute: 51, second: 33, millisecond: 352, gmtOffset: -5 * 60 * 60, timezone: "New_York"))] ) - try XCTAssertEqualTokensAndVals( + try expectEqualTokensAndVals( zinc: "2010-12-18T14:11:30.924Z", - expected: try [(.datetime, DateTime(year: 2010, month: 12, day: 18, hour: 14, minute: 11, second: 30, millisecond: 924, timezone: DateTime.utcName))] + expected: [(.datetime, DateTime(year: 2010, month: 12, day: 18, hour: 14, minute: 11, second: 30, millisecond: 924, timezone: DateTime.utcName))] ) - try XCTAssertEqualTokensAndVals( + try expectEqualTokensAndVals( zinc: "2010-12-18T14:11:30.924Z UTC", - expected: try [(.datetime, DateTime(year: 2010, month: 12, day: 18, hour: 14, minute: 11, second: 30, millisecond: 924, timezone: DateTime.utcName))] + expected: [(.datetime, DateTime(year: 2010, month: 12, day: 18, hour: 14, minute: 11, second: 30, millisecond: 924, timezone: DateTime.utcName))] ) - try XCTAssertEqualTokensAndVals( + try expectEqualTokensAndVals( zinc: "2010-12-18T14:11:30.924Z London", - expected: try [(.datetime, DateTime(year: 2010, month: 12, day: 18, hour: 14, minute: 11, second: 30, millisecond: 924, timezone: "London"))] + expected: [(.datetime, DateTime(year: 2010, month: 12, day: 18, hour: 14, minute: 11, second: 30, millisecond: 924, timezone: "London"))] ) - try XCTAssertEqualTokensAndVals( + try expectEqualTokensAndVals( zinc: "2010-03-01T23:55:00.013-05:00 GMT+5", - expected: try [(.datetime, DateTime(year: 2010, month: 3, day: 1, hour: 23, minute: 55, second: 0, millisecond: 13, gmtOffset: -5 * 60 * 60, timezone: "GMT+5"))] + expected: [(.datetime, DateTime(year: 2010, month: 3, day: 1, hour: 23, minute: 55, second: 0, millisecond: 13, gmtOffset: -5 * 60 * 60, timezone: "GMT+5"))] ) - try XCTAssertEqualTokensAndVals( + try expectEqualTokensAndVals( zinc: "2010-03-01T23:55:00.013+10:00 GMT-10", - expected: try [(.datetime, DateTime(year: 2010, month: 3, day: 1, hour: 23, minute: 55, second: 0, millisecond: 13, gmtOffset: 10 * 60 * 60, timezone: "GMT-10"))] + expected: [(.datetime, DateTime(year: 2010, month: 3, day: 1, hour: 23, minute: 55, second: 0, millisecond: 13, gmtOffset: 10 * 60 * 60, timezone: "GMT-10"))] ) } - func testRef() throws { - try XCTAssertEqualTokensAndVals(zinc: "@125b780e-0684e169", expected: [(.ref, Ref("125b780e-0684e169"))]) - try XCTAssertEqualTokensAndVals(zinc: "@demo:_:-.~", expected: [(.ref, Ref("demo:_:-.~"))]) + @Test func ref() throws { + try expectEqualTokensAndVals(zinc: "@125b780e-0684e169", expected: [(.ref, Ref("125b780e-0684e169"))]) + try expectEqualTokensAndVals(zinc: "@demo:_:-.~", expected: [(.ref, Ref("demo:_:-.~"))]) } - func testUri() throws { - try XCTAssertEqualTokensAndVals(zinc: "`http://foo/`", expected: [(.uri, Uri("http://foo/"))]) - try XCTAssertEqualTokensAndVals(zinc: "`_ \\n \\\\ \\`_`", expected: [(.uri, Uri("_ \n \\\\ `_"))]) + @Test func uri() throws { + try expectEqualTokensAndVals(zinc: "`http://foo/`", expected: [(.uri, Uri("http://foo/"))]) + try expectEqualTokensAndVals(zinc: "`_ \\n \\\\ \\`_`", expected: [(.uri, Uri("_ \n \\\\ `_"))]) } - func testWhitespace() throws { - try XCTAssertEqualTokensAndVals( + @Test func whitespace() throws { + try expectEqualTokensAndVals( zinc: "a\n b \rc \r\nd\n\ne", expected: [ (.id, "a"), @@ -124,7 +124,7 @@ final class ZincTokenizerTests: XCTestCase { ) } - private func XCTAssertEqualTokensAndVals( + private func expectEqualTokensAndVals( zinc: String, expected: [(ZincToken, (any Val)?)], file _: StaticString = #filePath, @@ -134,30 +134,30 @@ final class ZincTokenizerTests: XCTestCase { let tokenizer = try ZincTokenizer(zinc) while true { let token = try tokenizer.next() - XCTAssertEqual(token, tokenizer.token) + #expect(token == tokenizer.token) if token == ZincToken.eof { break } actual.append((token, tokenizer.val)) } - XCTAssertEqual(actual.count, expected.count, "\(actual) does not equal \(expected)") + #expect(actual.count == expected.count, "\(actual) does not equal \(expected)") for (actualElement, expectedElement) in zip(actual, expected) { - XCTAssertEqual(actualElement.0, expectedElement.0) + #expect(actualElement.0 == expectedElement.0) switch actualElement.1 { case .none: switch expectedElement.1 { case .none: continue case let .some(expectedVal): - XCTFail("Val nil does not equal \(expectedVal)") + Issue.record("Val nil does not equal \(expectedVal)") } case let .some(actualVal): switch expectedElement.1 { case .none: - XCTFail("Val \(actualVal) does not equal nil") + Issue.record("Val \(actualVal) does not equal nil") case let .some(expectedVal): - XCTAssertTrue( + #expect( actualVal.equals(expectedVal), "Val \(actualVal) does not equal \(expectedVal)" ) diff --git a/Tests/HaystackTests/ListTests.swift b/Tests/HaystackTests/ListTests.swift index 7827f3e..ac35dc8 100644 --- a/Tests/HaystackTests/ListTests.swift +++ b/Tests/HaystackTests/ListTests.swift @@ -1,8 +1,9 @@ +import Foundation import Haystack -import XCTest +import Testing -final class ListTests: XCTestCase { - func testJsonCoding() throws { +struct ListTests { + @Test func jsonCoding() throws { let value: List = [ true, "abc", @@ -16,20 +17,14 @@ final class ListTests: XCTestCase { // Must encode/decode b/c JSON ordering is not deterministic let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - try JSONDecoder().decode(List.self, from: encodedData), - value - ) + #expect(try JSONDecoder().decode(List.self, from: encodedData) == value) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(List.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(List.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual( + @Test func toZinc() throws { + #expect( List([ true, "abc", @@ -38,56 +33,26 @@ final class ListTests: XCTestCase { false, "xyz", ]), - ]).toZinc(), - #"[T, "abc", 42furloghs, [F, "xyz"]]"# + ]).toZinc() + == + #"[T, "abc", 42furloghs, [F, "xyz"]]"# ) } - func testEquatable() { + @Test func equatable() { // Test basic - XCTAssertEqual( - List(["a"]), - List(["a"]) - ) - XCTAssertNotEqual( - List(["a"]), - List(["b"]) - ) + #expect(List(["a"]) == List(["a"])) + #expect(List(["a"]) != List(["b"])) // Test element count matters - XCTAssertNotEqual( - List([ - "a", - "a", - ]), - List([ - "a", - ]) - ) - XCTAssertNotEqual( - List([ - "a", - ]), - List([ - "a", - "a", - ]) - ) + #expect(List(["a", "a"]) != List(["a"])) + #expect(List(["a"]) != List(["a", "a"])) // Test order matters - XCTAssertNotEqual( - List([ - "a", - "b", - ]), - List([ - "b", - "a", - ]) - ) + #expect(List(["a", "b"]) != List(["b", "a"])) // Test nested - XCTAssertEqual( + #expect( List([ true, "abc", @@ -96,18 +61,18 @@ final class ListTests: XCTestCase { false, "xyz", ]), - ]), - List([ - true, - "abc", - Number(42, unit: "furloghs"), + ]) == List([ - false, - "xyz", - ]), - ]) + true, + "abc", + Number(42, unit: "furloghs"), + List([ + false, + "xyz", + ]), + ]) ) - XCTAssertNotEqual( + #expect( List([ true, "abc", @@ -116,20 +81,20 @@ final class ListTests: XCTestCase { false, "xyz", ]), - ]), - List([ - true, - "abc", - Number(42, unit: "furloghs"), + ]) != List([ true, - "xyz", - ]), - ]) + "abc", + Number(42, unit: "furloghs"), + List([ + true, + "xyz", + ]), + ]) ) } - func testCollection() { + @Test func collection() { let list: List = [ true, "abc", @@ -138,18 +103,18 @@ final class ListTests: XCTestCase { ] // Test index access - XCTAssertEqual(list[0] as? Bool, true) - XCTAssertEqual(list[1] as? String, "abc") - XCTAssertEqual((list[2] as? Number), Number(42, unit: "furloghs")) - XCTAssertEqual((list[3] as? List), [true, "xyz"]) + #expect(list[0] as? Bool == true) + #expect(list[1] as? String == "abc") + #expect((list[2] as? Number) == Number(42, unit: "furloghs")) + #expect((list[3] as? List) == [true, "xyz"]) // Test loop for (i, element) in list.enumerated() { switch i { - case 0: XCTAssertEqual(element as? Bool, true) - case 1: XCTAssertEqual(element as? String, "abc") - case 2: XCTAssertEqual((element as? Number), Number(42, unit: "furloghs")) - case 3: XCTAssertEqual((element as? List), [true, "xyz"]) + case 0: #expect(element as? Bool == true) + case 1: #expect(element as? String == "abc") + case 2: #expect((element as? Number) == Number(42, unit: "furloghs")) + case 3: #expect((element as? List) == [true, "xyz"]) default: break } } diff --git a/Tests/HaystackTests/MarkerTests.swift b/Tests/HaystackTests/MarkerTests.swift index 2291a16..eca2e71 100644 --- a/Tests/HaystackTests/MarkerTests.swift +++ b/Tests/HaystackTests/MarkerTests.swift @@ -1,28 +1,20 @@ +import Foundation import Haystack -import XCTest +import Testing -final class MarkerTests: XCTestCase { - func testJsonCoding() throws { +struct MarkerTests { + @Test func jsonCoding() throws { let value = marker let jsonString = #"{"_kind":"marker"}"# let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - String(data: encodedData, encoding: .utf8), - jsonString - ) + #expect(String(data: encodedData, encoding: .utf8) == jsonString) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Marker.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Marker.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual( - marker.toZinc(), - "M" - ) + @Test func toZinc() throws { + #expect(marker.toZinc() == "M") } } diff --git a/Tests/HaystackTests/NATests.swift b/Tests/HaystackTests/NATests.swift index 434ec55..4d1d8c1 100644 --- a/Tests/HaystackTests/NATests.swift +++ b/Tests/HaystackTests/NATests.swift @@ -1,28 +1,20 @@ +import Foundation import Haystack -import XCTest +import Testing -final class NATests: XCTestCase { - func testJsonCoding() throws { +struct NATests { + @Test func jsonCoding() throws { let value = na let jsonString = #"{"_kind":"na"}"# let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - String(data: encodedData, encoding: .utf8), - jsonString - ) + #expect(String(data: encodedData, encoding: .utf8) == jsonString) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(NA.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(NA.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual( - na.toZinc(), - "NA" - ) + @Test func toZinc() throws { + #expect(na.toZinc() == "NA") } } diff --git a/Tests/HaystackTests/NullTests.swift b/Tests/HaystackTests/NullTests.swift index 6de8af8..9981daf 100644 --- a/Tests/HaystackTests/NullTests.swift +++ b/Tests/HaystackTests/NullTests.swift @@ -1,28 +1,20 @@ +import Foundation import Haystack -import XCTest +import Testing -final class NullTests: XCTestCase { - func testJsonCoding() throws { +struct NullTests { + @Test func jsonCoding() throws { let value = null let jsonString = #"null"# let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - String(data: encodedData, encoding: .utf8), - jsonString - ) + #expect(String(data: encodedData, encoding: .utf8) == jsonString) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Null.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Null.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual( - null.toZinc(), - "N" - ) + @Test func toZinc() throws { + #expect(null.toZinc() == "N") } } diff --git a/Tests/HaystackTests/NumberTests.swift b/Tests/HaystackTests/NumberTests.swift index a8bb549..4f15d49 100644 --- a/Tests/HaystackTests/NumberTests.swift +++ b/Tests/HaystackTests/NumberTests.swift @@ -1,95 +1,57 @@ +import Foundation import Haystack -import XCTest - -final class NumberTests: XCTestCase { - func testIsInt() throws { - XCTAssertTrue(Number(5).isInt) - XCTAssertFalse(Number(5.5).isInt) - XCTAssertTrue(Number(-1).isInt) - XCTAssertFalse(Number(-1.99999).isInt) +import Testing + +struct NumberTests { + @Test func isInt() throws { + #expect(Number(5).isInt) + #expect(!Number(5.5).isInt) + #expect(Number(-1).isInt) + #expect(!Number(-1.99999).isInt) } - func testJsonCoding() throws { + @Test func jsonCoding() throws { let value = Number(12.199, unit: "kWh") let jsonString = #"{"_kind":"number","val":12.199,"unit":"kWh"}"# // Must encode/decode b/c JSON ordering is not deterministic let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - try JSONDecoder().decode(Number.self, from: encodedData), - value - ) + #expect(try JSONDecoder().decode(Number.self, from: encodedData) == value) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Number.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Number.self, from: decodedData) == value) } - func testJsonCoding_noUnit() throws { + @Test func jsonCoding_noUnit() throws { let value = Number(3.899) let jsonString = #"3.899"# let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - String(data: encodedData, encoding: .utf8), - jsonString - ) + #expect(String(data: encodedData, encoding: .utf8) == jsonString) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Number.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Number.self, from: decodedData) == value) } - func testJsonCoding_infinity() throws { + @Test func jsonCoding_infinity() throws { let value = Number(.infinity) let jsonString = #"{"_kind":"number","val":"INF"}"# // Must encode/decode b/c JSON ordering is not deterministic let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - try JSONDecoder().decode(Number.self, from: encodedData), - value - ) + #expect(try JSONDecoder().decode(Number.self, from: encodedData) == value) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Number.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Number.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual( - Number(12.199, unit: "kWh").toZinc(), - "12.199kWh" - ) - XCTAssertEqual( - Number(1, unit: "kWh/ft\u{00b2}").toZinc(), - #"1kWh/ft\u00b2"# - ) - XCTAssertEqual( - Number(3.899).toZinc(), - "3.899" - ) - XCTAssertEqual( - Number(4).toZinc(), - "4" - ) - XCTAssertEqual( - Number.infinity.toZinc(), - "INF" - ) - XCTAssertEqual( - Number.negativeInfinity.toZinc(), - "-INF" - ) - XCTAssertEqual( - Number.nan.toZinc(), - "NaN" - ) + @Test func toZinc() throws { + #expect(Number(12.199, unit: "kWh").toZinc() == "12.199kWh") + #expect(Number(1, unit: "kWh/ft\u{00b2}").toZinc() == #"1kWh/ft\u00b2"#) + #expect(Number(3.899).toZinc() == "3.899") + #expect(Number(4).toZinc() == "4") + #expect(Number.infinity.toZinc() == "INF") + #expect(Number.negativeInfinity.toZinc() == "-INF") + #expect(Number.nan.toZinc() == "NaN") } } diff --git a/Tests/HaystackTests/RefTests.swift b/Tests/HaystackTests/RefTests.swift index 2f76336..7ae4e28 100644 --- a/Tests/HaystackTests/RefTests.swift +++ b/Tests/HaystackTests/RefTests.swift @@ -1,39 +1,28 @@ +import Foundation import Haystack -import XCTest +import Testing -final class RefTests: XCTestCase { - func testInit() throws { - try XCTAssertThrowsError(Ref("123 abc")) - try XCTAssertThrowsError(Ref("123$abc")) - try XCTAssertThrowsError(Ref("123%abc")) +struct RefTests { + @Test func testInit() throws { + #expect(throws: RefError.self) { try Ref("123 abc") } + #expect(throws: RefError.self) { try Ref("123$abc") } + #expect(throws: RefError.self) { try Ref("123%abc") } } - func testJsonCoding() throws { + @Test func jsonCoding() throws { let value = try Ref("123-abc", dis: "Name") let jsonString = #"{"_kind":"ref","val":"123-abc","dis":"Name"}"# // Must encode/decode b/c JSON ordering is not deterministic let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - try JSONDecoder().decode(Ref.self, from: encodedData), - value - ) + #expect(try JSONDecoder().decode(Ref.self, from: encodedData) == value) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Ref.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Ref.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual( - try Ref("123-abc", dis: "Name").toZinc(), - "@123-abc Name" - ) - XCTAssertEqual( - try Ref("123-abc").toZinc(), - "@123-abc" - ) + @Test func toZinc() throws { + #expect(try Ref("123-abc", dis: "Name").toZinc() == "@123-abc Name") + #expect(try Ref("123-abc").toZinc() == "@123-abc") } } diff --git a/Tests/HaystackTests/RemoveTests.swift b/Tests/HaystackTests/RemoveTests.swift index 0592310..564bd81 100644 --- a/Tests/HaystackTests/RemoveTests.swift +++ b/Tests/HaystackTests/RemoveTests.swift @@ -1,28 +1,20 @@ +import Foundation import Haystack -import XCTest +import Testing -final class RemoveTests: XCTestCase { - func testJsonCoding() throws { +struct RemoveTests { + @Test func jsonCoding() throws { let value = remove let jsonString = #"{"_kind":"remove"}"# let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - String(data: encodedData, encoding: .utf8), - jsonString - ) + #expect(String(data: encodedData, encoding: .utf8) == jsonString) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Remove.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Remove.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual( - remove.toZinc(), - "R" - ) + @Test func toZinc() throws { + #expect(remove.toZinc() == "R") } } diff --git a/Tests/HaystackTests/StringTests.swift b/Tests/HaystackTests/StringTests.swift index c0b1760..5c9dfb8 100644 --- a/Tests/HaystackTests/StringTests.swift +++ b/Tests/HaystackTests/StringTests.swift @@ -1,27 +1,22 @@ +import Foundation import Haystack -import XCTest +import Testing -final class StringTests: XCTestCase { - func testJsonCoding() throws { +struct StringTests { + @Test func jsonCoding() throws { let value = "hello" let jsonString = #""hello""# let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - String(data: encodedData, encoding: .utf8), - jsonString - ) + #expect(String(data: encodedData, encoding: .utf8) == jsonString) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(String.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(String.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual("hello".toZinc(), #""hello""#) - XCTAssertEqual("_ \\ \" \n \r \t \u{0011} _".toZinc(), #""_ \\ \" \n \r \t \u0011 _""#) - XCTAssertEqual("\u{0abc}".toZinc(), #""\u0abc""#) + @Test func toZinc() throws { + #expect("hello".toZinc() == #""hello""#) + #expect("_ \\ \" \n \r \t \u{0011} _".toZinc() == #""_ \\ \" \n \r \t \u0011 _""#) + #expect("\u{0abc}".toZinc() == #""\u0abc""#) } } diff --git a/Tests/HaystackTests/SymbolTests.swift b/Tests/HaystackTests/SymbolTests.swift index b2973fe..595c45f 100644 --- a/Tests/HaystackTests/SymbolTests.swift +++ b/Tests/HaystackTests/SymbolTests.swift @@ -1,35 +1,27 @@ +import Foundation import Haystack -import XCTest +import Testing -final class SymbolTests: XCTestCase { - func testInit() throws { - try XCTAssertThrowsError(Symbol("tag name")) - try XCTAssertThrowsError(Symbol("tag name")) - try XCTAssertThrowsError(Symbol("tag name")) +struct SymbolTests { + @Test func testInit() throws { + #expect(throws: SymbolError.self) { try Symbol("tag name") } + #expect(throws: SymbolError.self) { try Symbol("tag name") } + #expect(throws: SymbolError.self) { try Symbol("tag name") } } - func testJsonCoding() throws { + @Test func jsonCoding() throws { let value = try Symbol("tagName") let jsonString = #"{"_kind":"symbol","val":"tagName"}"# // Must encode/decode b/c JSON ordering is not deterministic let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - try JSONDecoder().decode(Symbol.self, from: encodedData), - value - ) + #expect(try JSONDecoder().decode(Symbol.self, from: encodedData) == value) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Symbol.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Symbol.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual( - try Symbol("tagName").toZinc(), - "^tagName" - ) + @Test func toZinc() throws { + #expect(try Symbol("tagName").toZinc() == "^tagName") } } diff --git a/Tests/HaystackTests/TimeTests.swift b/Tests/HaystackTests/TimeTests.swift index b5d9a0f..c96039b 100644 --- a/Tests/HaystackTests/TimeTests.swift +++ b/Tests/HaystackTests/TimeTests.swift @@ -1,51 +1,34 @@ +import Foundation import Haystack -import XCTest +import Testing -final class TimeTests: XCTestCase { - func testJsonCoding() throws { +struct TimeTests { + @Test func jsonCoding() throws { let value = try Time(hour: 7, minute: 7, second: 7, millisecond: 7) let jsonString = #"{"_kind":"time","val":"07:07:07.007"}"# // Must encode/decode b/c JSON ordering is not deterministic let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - try JSONDecoder().decode(Haystack.Time.self, from: encodedData), - value - ) + #expect(try JSONDecoder().decode(Haystack.Time.self, from: encodedData) == value) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Haystack.Time.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Haystack.Time.self, from: decodedData) == value) } - func testJsonCoding_zeroMillis() throws { + @Test func jsonCoding_zeroMillis() throws { let value = try Time(hour: 7, minute: 7, second: 7, millisecond: 0) let jsonString = #"{"_kind":"time","val":"07:07:07"}"# // Must encode/decode b/c JSON ordering is not deterministic let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - try JSONDecoder().decode(Haystack.Time.self, from: encodedData), - value - ) + #expect(try JSONDecoder().decode(Haystack.Time.self, from: encodedData) == value) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Haystack.Time.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Haystack.Time.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual( - try Time(hour: 7, minute: 7, second: 7, millisecond: 0).toZinc(), - "07:07:07" - ) - XCTAssertEqual( - try Time(hour: 7, minute: 7, second: 7, millisecond: 7).toZinc(), - "07:07:07.007" - ) + @Test func toZinc() throws { + #expect(try Time(hour: 7, minute: 7, second: 7, millisecond: 0).toZinc() == "07:07:07") + #expect(try Time(hour: 7, minute: 7, second: 7, millisecond: 7).toZinc() == "07:07:07.007") } } diff --git a/Tests/HaystackTests/UriTests.swift b/Tests/HaystackTests/UriTests.swift index 2d761b4..b23040a 100644 --- a/Tests/HaystackTests/UriTests.swift +++ b/Tests/HaystackTests/UriTests.swift @@ -1,29 +1,21 @@ +import Foundation import Haystack -import XCTest +import Testing -final class UriTests: XCTestCase { - func testJsonCoding() throws { +struct UriTests { + @Test func jsonCoding() throws { let value = Uri("http://en.wikipedia.org/") let jsonString = #"{"_kind":"uri","val":"http:\/\/en.wikipedia.org\/"}"# // Must encode/decode b/c JSON ordering is not deterministic let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - try JSONDecoder().decode(Uri.self, from: encodedData), - value - ) + #expect(try JSONDecoder().decode(Uri.self, from: encodedData) == value) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(Uri.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(Uri.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual( - Uri("http://en.wikipedia.org/").toZinc(), - "`http://en.wikipedia.org/`" - ) + @Test func toZinc() throws { + #expect(Uri("http://en.wikipedia.org/").toZinc() == "`http://en.wikipedia.org/`") } } diff --git a/Tests/HaystackTests/XStrTests.swift b/Tests/HaystackTests/XStrTests.swift index c1b1f1e..359ac03 100644 --- a/Tests/HaystackTests/XStrTests.swift +++ b/Tests/HaystackTests/XStrTests.swift @@ -1,35 +1,27 @@ +import Foundation import Haystack -import XCTest +import Testing -final class XStrTests: XCTestCase { - func testInit() throws { - try XCTAssertThrowsError(XStr(type: "span", val: "today")) - try XCTAssertThrowsError(XStr(type: "Span range", val: "today")) - try XCTAssertThrowsError(XStr(type: "Span!", val: "today")) +struct XStrTests { + @Test func testInit() throws { + #expect(throws: (any Error).self) { try XStr(type: "span", val: "today") } + #expect(throws: (any Error).self) { try XStr(type: "Span range", val: "today") } + #expect(throws: (any Error).self) { try XStr(type: "Span!", val: "today") } } - func testJsonCoding() throws { + @Test func jsonCoding() throws { let value = try XStr(type: "Span", val: "today") let jsonString = #"{"_kind":"xstr","type":"Span","val":"today"}"# // Must encode/decode b/c JSON ordering is not deterministic let encodedData = try JSONEncoder().encode(value) - XCTAssertEqual( - try JSONDecoder().decode(XStr.self, from: encodedData), - value - ) + #expect(try JSONDecoder().decode(XStr.self, from: encodedData) == value) - let decodedData = try XCTUnwrap(jsonString.data(using: .utf8)) - XCTAssertEqual( - try JSONDecoder().decode(XStr.self, from: decodedData), - value - ) + let decodedData = try #require(jsonString.data(using: .utf8)) + #expect(try JSONDecoder().decode(XStr.self, from: decodedData) == value) } - func testToZinc() throws { - XCTAssertEqual( - try XStr(type: "Span", val: "today").toZinc(), - #"Span("today")"# - ) + @Test func toZinc() throws { + #expect(try XStr(type: "Span", val: "today").toZinc() == #"Span("today")"#) } }