From 37cb86993cc9481a6541f5f1b77d181292881dd2 Mon Sep 17 00:00:00 2001 From: Pete Gautier Date: Thu, 7 Dec 2023 14:35:08 -0800 Subject: [PATCH 01/12] chore: improve pattern matching experience for response types --- Sources/Momento/CacheClient.swift | 6 +- Sources/Momento/internal/DataClient.swift | 18 ++--- .../cache/data/scalar/CacheGet.swift | 16 +++- Tests/MomentoTests/cacheTests.swift | 77 +++++++++++-------- Tests/MomentoTests/testUtils.swift | 2 +- 5 files changed, 68 insertions(+), 51 deletions(-) diff --git a/Sources/Momento/CacheClient.swift b/Sources/Momento/CacheClient.swift index 55657d5..2812306 100644 --- a/Sources/Momento/CacheClient.swift +++ b/Sources/Momento/CacheClient.swift @@ -408,11 +408,11 @@ public class CacheClient: CacheClientProtocol { try validateCacheName(cacheName: cacheName) try validateCacheKey(key: key) } catch let err as SdkError { - return CacheGetError(error: err) + return CacheGetResponse.error(CacheGetError(error: err)) } catch { - return CacheGetError(error: UnknownError( + return CacheGetResponse.error(CacheGetError(error: UnknownError( message: "unexpected error: \(error)") - ) + )) } return await self.dataClient.get(cacheName: cacheName, key: key) } diff --git a/Sources/Momento/internal/DataClient.swift b/Sources/Momento/internal/DataClient.swift index f2d58ac..ca122bf 100644 --- a/Sources/Momento/internal/DataClient.swift +++ b/Sources/Momento/internal/DataClient.swift @@ -171,24 +171,24 @@ class DataClient: DataClientProtocol { do { let result = try await call.response.get() if result.result == .hit { - return CacheGetHit(value: result.cacheBody) + return CacheGetResponse.hit(CacheGetHit(value: result.cacheBody)) } else if result.result == .miss { - return CacheGetMiss() + return CacheGetResponse.miss(CacheGetMiss()) } else { - return CacheGetError( + return CacheGetResponse.error(CacheGetError( error: UnknownError(message: "unknown cache get error \(result)") - ) + )) } } catch let err as GRPCStatus { - return CacheGetError(error: grpcStatusToSdkError(grpcStatus: err)) + return CacheGetResponse.error(CacheGetError(error: grpcStatusToSdkError(grpcStatus: err))) } catch let err as GRPCConnectionPoolError { - return CacheGetError( + return CacheGetResponse.error(CacheGetError( error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus()) - ) + )) } catch { - return CacheGetError( + return CacheGetResponse.error(CacheGetError( error: UnknownError(message: "unknown cache get error \(error)") - ) + )) } } diff --git a/Sources/Momento/messages/responses/cache/data/scalar/CacheGet.swift b/Sources/Momento/messages/responses/cache/data/scalar/CacheGet.swift index 756d9c7..186c68c 100644 --- a/Sources/Momento/messages/responses/cache/data/scalar/CacheGet.swift +++ b/Sources/Momento/messages/responses/cache/data/scalar/CacheGet.swift @@ -1,8 +1,12 @@ import Foundation -public protocol CacheGetResponse {} +public enum CacheGetResponse { + case hit(CacheGetHit) + case miss(CacheGetMiss) + case error(CacheGetError) +} -public class CacheGetHit: CacheGetResponse { +public class CacheGetHit: Equatable { public let valueString: String public let valueData: Data @@ -10,8 +14,12 @@ public class CacheGetHit: CacheGetResponse { self.valueData = value self.valueString = String(decoding: value, as: UTF8.self) } + + public static func == (lhs: CacheGetHit, rhs: CacheGetHit) -> Bool { + return lhs.valueData == rhs.valueData + } } -public class CacheGetMiss: CacheGetResponse {} +public class CacheGetMiss {} -public class CacheGetError: ErrorResponseBase, CacheGetResponse {} +public class CacheGetError: ErrorResponseBase {} diff --git a/Tests/MomentoTests/cacheTests.swift b/Tests/MomentoTests/cacheTests.swift index 9ebdfc7..328b1d6 100644 --- a/Tests/MomentoTests/cacheTests.swift +++ b/Tests/MomentoTests/cacheTests.swift @@ -118,47 +118,56 @@ final class cacheTests: XCTestCase { } func testScalarGet() async throws { - let invalidCacheName = await self.cacheClient.get( - cacheName: " ", - key: generateStringWithUuid(prefix: "hello") - ) - XCTAssertTrue( - invalidCacheName is CacheGetError, - "Unexpected response: \(invalidCacheName)" - ) - let invalidCacheNameErrorCode = (invalidCacheName as! CacheGetError).errorCode - XCTAssertEqual( - invalidCacheNameErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidCacheNameErrorCode)" - ) - - let invalidKey = await self.cacheClient.get( - cacheName: self.integrationTestCacheName, - key: " " - ) - XCTAssertTrue( - invalidKey is CacheGetError, - "Unexpected response: \(invalidKey)" - ) - let invalidKeyErrorCode = (invalidKey as! CacheGetError).errorCode - XCTAssertEqual( - invalidKeyErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidKeyErrorCode)" - ) - +// let invalidCacheName = await self.cacheClient.get( +// cacheName: " ", +// key: ScalarType.string(generateStringWithUuid(prefix: "hello")) +// ) +// XCTAssertTrue( +// invalidCacheName is CacheGetError, +// "Unexpected response: \(invalidCacheName)" +// ) +// let invalidCacheNameErrorCode = (invalidCacheName as! CacheGetError).errorCode +// XCTAssertEqual( +// invalidCacheNameErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, +// "Unexpected error code: \(invalidCacheNameErrorCode)" +// ) +// let invalidKey = await self.cacheClient.get( +// cacheName: self.integrationTestCacheName, +// key: ScalarType.string(" ") +// ) +// XCTAssertTrue( +// invalidKey is CacheGetError, +// "Unexpected response: \(invalidKey)" +// ) +// let invalidKeyErrorCode = (invalidKey as! CacheGetError).errorCode +// XCTAssertEqual( +// invalidKeyErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, +// "Unexpected error code: \(invalidKeyErrorCode)" +// ) +// let testKey = generateStringWithUuid(prefix: "hello") let stringKey = await self.cacheClient.get( cacheName: self.integrationTestCacheName, key: testKey ) - XCTAssertTrue(stringKey is CacheGetMiss, "Unexpected response: \(stringKey)") + + switch stringKey { + case .hit(let hit): + XCTFail("expected a miss but got \(hit)") + case .miss: + XCTAssertTrue(true) + case .error(let err): + XCTFail("expected a miss but got \(err)") + } - let bytesKey = await self.cacheClient.get( - cacheName: self.integrationTestCacheName, - key: Data(testKey.utf8) - ) - XCTAssertTrue(bytesKey is CacheGetMiss, "Unexpected response: \(bytesKey)") + XCTAssertTrue(stringKey is CacheGetResponse, "Unexpected response: \(stringKey)") + +// let bytesKey = await self.cacheClient.get( +// cacheName: self.integrationTestCacheName, +// key: ScalarType.data(Data(testKey.utf8)) +// ) +// XCTAssertTrue(bytesKey is CacheGetMiss, "Unexpected response: \(bytesKey)") } func testScalarSet() async throws { diff --git a/Tests/MomentoTests/testUtils.swift b/Tests/MomentoTests/testUtils.swift index 62697d4..7f64709 100644 --- a/Tests/MomentoTests/testUtils.swift +++ b/Tests/MomentoTests/testUtils.swift @@ -17,7 +17,7 @@ func setUpIntegrationTests() async -> TestSetup { configuration: TopicConfigurations.Default.latest(), credentialProvider: creds ) - + let cacheClient = CacheClient( configuration: CacheConfigurations.Default.latest().withClientTimeout(timeout: 30), credentialProvider: creds, From 207889b7f00900ecdcce171e3afb09d28a6dac7b Mon Sep 17 00:00:00 2001 From: Pete Gautier Date: Thu, 7 Dec 2023 17:08:28 -0800 Subject: [PATCH 02/12] chore: continue enum-based responses Also adds scalar delete operation and renames control plane response classes to avoid conflicts with data plan response names. --- Sources/Momento/CacheClient.swift | 37 +- Sources/Momento/internal/ControlClient.swift | 30 +- Sources/Momento/internal/DataClient.swift | 60 ++- .../responses/cache/control/CacheCreate.swift | 7 - .../responses/cache/control/CacheDelete.swift | 5 - .../responses/cache/control/CreateCache.swift | 7 + .../responses/cache/control/DeleteCache.swift | 5 + .../{CacheList.swift => ListCaches.swift} | 6 +- .../cache/data/scalar/CacheSet.swift | 9 +- .../responses/cache/data/scalar/Delete.swift | 8 + Tests/MomentoTests/cacheTests.swift | 359 +++++++++++------- Tests/MomentoTests/testUtils.swift | 2 +- 12 files changed, 343 insertions(+), 192 deletions(-) delete mode 100644 Sources/Momento/messages/responses/cache/control/CacheCreate.swift delete mode 100644 Sources/Momento/messages/responses/cache/control/CacheDelete.swift create mode 100644 Sources/Momento/messages/responses/cache/control/CreateCache.swift create mode 100644 Sources/Momento/messages/responses/cache/control/DeleteCache.swift rename Sources/Momento/messages/responses/cache/control/{CacheList.swift => ListCaches.swift} (66%) create mode 100644 Sources/Momento/messages/responses/cache/data/scalar/Delete.swift diff --git a/Sources/Momento/CacheClient.swift b/Sources/Momento/CacheClient.swift index 2812306..49e3996 100644 --- a/Sources/Momento/CacheClient.swift +++ b/Sources/Momento/CacheClient.swift @@ -301,13 +301,13 @@ public class CacheClient: CacheClientProtocol { } ``` */ - public func createCache(cacheName: String) async -> CacheCreateResponse { + public func createCache(cacheName: String) async -> CreateCacheResponse { do { try validateCacheName(cacheName: cacheName) } catch let err as SdkError { - return CacheCreateError(error: err) + return CreateCacheError(error: err) } catch { - return CacheCreateError(error: UnknownError( + return CreateCacheError(error: UnknownError( message: "unexpected error: \(error)") ) } @@ -317,7 +317,7 @@ public class CacheClient: CacheClientProtocol { /** Deletes a cache and all items in it. - Parameter cacheName: name of the cache to be deleted - - Returns: CacheDeleteResponse representing the result of the delete cache operation. + - Returns: DeleteCacheResponse representing the result of the delete cache operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { @@ -328,7 +328,7 @@ public class CacheClient: CacheClientProtocol { } ``` */ - public func deleteCache(cacheName: String) async -> CacheDeleteResponse { + public func deleteCache(cacheName: String) async -> DeleteCacheResponse { do { try validateCacheName(cacheName: cacheName) } catch let err as SdkError { @@ -343,19 +343,19 @@ public class CacheClient: CacheClientProtocol { /** Lists all caches. - - Returns: CacheListResponse representing the result of the list caches operation. + - Returns: ListCachesResponse representing the result of the list caches operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheListError: + case let responseError as ListCachesError: // handle error - case let responseSuccess as CacheListSuccess: + case let responseSuccess as ListCachesSuccess: // handle success print(responseSuccess.caches) } ``` */ - public func listCaches() async -> CacheListResponse { + public func listCaches() async -> ListCachesResponse { return await self.controlClient.listCaches() } @@ -556,11 +556,11 @@ public class CacheClient: CacheClientProtocol { try validateCacheKey(key: key) try validateTtl(ttl: ttl) } catch let err as SdkError { - return CacheSetError(error: err) + return CacheSetResponse.error(CacheSetError(error: err)) } catch { - return CacheSetError(error: UnknownError( + return CacheSetResponse.error(CacheSetError(error: UnknownError( message: "unexpected error: \(error)") - ) + )) } return await self.dataClient.set( cacheName: cacheName, @@ -570,6 +570,19 @@ public class CacheClient: CacheClientProtocol { ) } + public func delete(cacheName: String, key: ScalarType) async -> DeleteResponse { + do { + try validateCacheName(cacheName: cacheName) + try validateCacheKey(key: key) + } catch let err as SdkError { + return DeleteResponse.error(DeleteError(error: err)) + } catch { + return DeleteResponse.error(DeleteError(error: UnknownError( + message: "unexpected error: \(error)") + )) + } + return await self.dataClient.delete(cacheName: cacheName, key: key) + } /** Adds multiple elements to the back of the given list. Creates the list if it does not already exist. - Parameters: diff --git a/Sources/Momento/internal/ControlClient.swift b/Sources/Momento/internal/ControlClient.swift index 8fe4ce8..5a155cf 100644 --- a/Sources/Momento/internal/ControlClient.swift +++ b/Sources/Momento/internal/ControlClient.swift @@ -4,11 +4,11 @@ import NIOHPACK import Logging protocol ControlClientProtocol { - func createCache(cacheName: String) async -> CacheCreateResponse + func createCache(cacheName: String) async -> CreateCacheResponse - func deleteCache(cacheName: String) async -> CacheDeleteResponse + func deleteCache(cacheName: String) async -> DeleteCacheResponse - func listCaches() async -> CacheListResponse + func listCaches() async -> ListCachesResponse } @available(macOS 10.15, iOS 13, *) @@ -59,27 +59,27 @@ class ControlClient: ControlClientProtocol { ) } - func createCache(cacheName: String) async -> CacheCreateResponse { + func createCache(cacheName: String) async -> CreateCacheResponse { var request = ControlClient__CreateCacheRequest() request.cacheName = cacheName let call = self.client.createCache(request) do { _ = try await call.response.get() // Successful creation returns ControlClient__CreateCacheResponse - return CacheCreateSuccess() + return CreateCacheSuccess() } catch let err as GRPCStatus { if err.code == GRPCStatus.Code.alreadyExists { - return CacheCreateCacheAlreadyExists() + return CreateCacheAlreadyExists() } - return CacheCreateError(error: grpcStatusToSdkError(grpcStatus: err)) + return CreateCacheError(error: grpcStatusToSdkError(grpcStatus: err)) } catch let err as GRPCConnectionPoolError { - return CacheCreateError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) + return CreateCacheError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) } catch { - return CacheCreateError(error: UnknownError(message: "unknown cache create error \(error)")) + return CreateCacheError(error: UnknownError(message: "unknown cache create error \(error)")) } } - func deleteCache(cacheName: String) async -> CacheDeleteResponse { + func deleteCache(cacheName: String) async -> DeleteCacheResponse { var request = ControlClient__DeleteCacheRequest() request.cacheName = cacheName let call = self.client.deleteCache(request) @@ -96,19 +96,19 @@ class ControlClient: ControlClientProtocol { } } - func listCaches() async -> CacheListResponse { + func listCaches() async -> ListCachesResponse { let call = self.client.listCaches(ControlClient__ListCachesRequest()) do { let result = try await call.response.get() // Successful creation returns ControlClient__ListCachesResponse self.logger.debug("list caches received: \(result.cache)") - return CacheListSuccess(caches: result.cache) + return ListCachesSuccess(caches: result.cache) } catch let err as GRPCStatus { - return CacheListError(error: grpcStatusToSdkError(grpcStatus: err)) + return ListCachesError(error: grpcStatusToSdkError(grpcStatus: err)) } catch let err as GRPCConnectionPoolError { - return CacheListError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) + return ListCachesError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) } catch { - return CacheListError(error: UnknownError(message: "unknown cache create error \(error)")) + return ListCachesError(error: UnknownError(message: "unknown cache create error \(error)")) } } } diff --git a/Sources/Momento/internal/DataClient.swift b/Sources/Momento/internal/DataClient.swift index ca122bf..2299c26 100644 --- a/Sources/Momento/internal/DataClient.swift +++ b/Sources/Momento/internal/DataClient.swift @@ -13,7 +13,9 @@ protocol DataClientProtocol { value: ScalarType, ttl: TimeInterval? ) async -> CacheSetResponse - + + func delete(cacheName: String, key: ScalarType) async -> DeleteResponse + func listConcatenateBack( cacheName: String, listName: String, @@ -21,7 +23,7 @@ protocol DataClientProtocol { truncateFrontToSize: Int?, ttl: CollectionTtl? ) async -> CacheListConcatenateBackResponse - + func listConcatenateFront( cacheName: String, listName: String, @@ -29,14 +31,14 @@ protocol DataClientProtocol { truncateBackToSize: Int?, ttl: CollectionTtl? ) async -> CacheListConcatenateFrontResponse - + func listFetch( cacheName: String, listName: String, startIndex: Int?, endIndex: Int? ) async -> CacheListFetchResponse - + func listLength( cacheName: String, listName: String @@ -214,7 +216,7 @@ class DataClient: DataClientProtocol { case .data(let d): request.cacheBody = d } - + let headers = self.makeHeaders(cacheName: cacheName) let call = self.client.set( request, @@ -224,23 +226,57 @@ class DataClient: DataClientProtocol { ) ) ) - + do { _ = try await call.response.get() - return CacheSetSuccess() + return CacheSetResponse.success(CacheSetSuccess()) } catch let err as GRPCStatus { - return CacheSetError(error: grpcStatusToSdkError(grpcStatus: err)) + return CacheSetResponse.error(CacheSetError(error: grpcStatusToSdkError(grpcStatus: err))) } catch let err as GRPCConnectionPoolError { - return CacheSetError( + return CacheSetResponse.error(CacheSetError( error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus()) - ) + )) } catch { - return CacheSetError( + return CacheSetResponse.error(CacheSetError( error: UnknownError(message: "unknown cache set error \(error)") - ) + )) } } + func delete(cacheName: String, key: ScalarType) async -> DeleteResponse { + var request = CacheClient__DeleteRequest() + switch key { + case .data(let b): + request.cacheKey = b + case .string(let s): + request.cacheKey = Data(s.utf8) + } + let headers = self.makeHeaders(cacheName: cacheName) + let call = self.client.delete( + request, + callOptions: CallOptions( + customMetadata: .init( + headers.map { ($0, $1) } + ) + ) + ) + + do { + _ = try await call.response.get() + return DeleteResponse.success(DeleteSuccess()) + } catch let err as GRPCStatus { + return DeleteResponse.error(DeleteError(error: grpcStatusToSdkError(grpcStatus: err))) + } catch let err as GRPCConnectionPoolError { + return DeleteResponse.error(DeleteError( + error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus()) + )) + } catch { + return DeleteResponse.error(DeleteError( + error: UnknownError(message: "unknown cache set error \(error)") + )) + } + } + func listConcatenateBack( cacheName: String, listName: String, diff --git a/Sources/Momento/messages/responses/cache/control/CacheCreate.swift b/Sources/Momento/messages/responses/cache/control/CacheCreate.swift deleted file mode 100644 index b8c9672..0000000 --- a/Sources/Momento/messages/responses/cache/control/CacheCreate.swift +++ /dev/null @@ -1,7 +0,0 @@ -public protocol CacheCreateResponse {} - -public class CacheCreateSuccess: CacheCreateResponse {} - -public class CacheCreateCacheAlreadyExists: CacheCreateResponse {} - -public class CacheCreateError: ErrorResponseBase, CacheCreateResponse {} diff --git a/Sources/Momento/messages/responses/cache/control/CacheDelete.swift b/Sources/Momento/messages/responses/cache/control/CacheDelete.swift deleted file mode 100644 index 48f13b7..0000000 --- a/Sources/Momento/messages/responses/cache/control/CacheDelete.swift +++ /dev/null @@ -1,5 +0,0 @@ -public protocol CacheDeleteResponse {} - -public class CacheDeleteSuccess: CacheDeleteResponse {} - -public class CacheDeleteError: ErrorResponseBase, CacheDeleteResponse {} diff --git a/Sources/Momento/messages/responses/cache/control/CreateCache.swift b/Sources/Momento/messages/responses/cache/control/CreateCache.swift new file mode 100644 index 0000000..7bd01c8 --- /dev/null +++ b/Sources/Momento/messages/responses/cache/control/CreateCache.swift @@ -0,0 +1,7 @@ +public protocol CreateCacheResponse {} + +public class CreateCacheSuccess: CreateCacheResponse {} + +public class CreateCacheAlreadyExists: CreateCacheResponse {} + +public class CreateCacheError: ErrorResponseBase, CreateCacheResponse {} diff --git a/Sources/Momento/messages/responses/cache/control/DeleteCache.swift b/Sources/Momento/messages/responses/cache/control/DeleteCache.swift new file mode 100644 index 0000000..ac73a98 --- /dev/null +++ b/Sources/Momento/messages/responses/cache/control/DeleteCache.swift @@ -0,0 +1,5 @@ +public protocol DeleteCacheResponse {} + +public class CacheDeleteSuccess: DeleteCacheResponse {} + +public class CacheDeleteError: ErrorResponseBase, DeleteCacheResponse {} diff --git a/Sources/Momento/messages/responses/cache/control/CacheList.swift b/Sources/Momento/messages/responses/cache/control/ListCaches.swift similarity index 66% rename from Sources/Momento/messages/responses/cache/control/CacheList.swift rename to Sources/Momento/messages/responses/cache/control/ListCaches.swift index 64c4890..92ed2d6 100644 --- a/Sources/Momento/messages/responses/cache/control/CacheList.swift +++ b/Sources/Momento/messages/responses/cache/control/ListCaches.swift @@ -6,9 +6,9 @@ public class CacheInfo { } } -public protocol CacheListResponse {} +public protocol ListCachesResponse {} -public class CacheListSuccess: CacheListResponse { +public class ListCachesSuccess: ListCachesResponse { public let caches: [CacheInfo] init(caches: [ControlClient__Cache]) { @@ -18,4 +18,4 @@ public class CacheListSuccess: CacheListResponse { } } -public class CacheListError: ErrorResponseBase, CacheListResponse {} +public class ListCachesError: ErrorResponseBase, ListCachesResponse {} diff --git a/Sources/Momento/messages/responses/cache/data/scalar/CacheSet.swift b/Sources/Momento/messages/responses/cache/data/scalar/CacheSet.swift index b8ad74f..08bffd0 100644 --- a/Sources/Momento/messages/responses/cache/data/scalar/CacheSet.swift +++ b/Sources/Momento/messages/responses/cache/data/scalar/CacheSet.swift @@ -1,5 +1,8 @@ -public protocol CacheSetResponse {} +public enum CacheSetResponse { + case success(CacheSetSuccess) + case error(CacheSetError) +} -public class CacheSetSuccess: CacheSetResponse {} +public class CacheSetSuccess {} -public class CacheSetError: ErrorResponseBase, CacheSetResponse {} +public class CacheSetError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/cache/data/scalar/Delete.swift b/Sources/Momento/messages/responses/cache/data/scalar/Delete.swift new file mode 100644 index 0000000..dd2ec1d --- /dev/null +++ b/Sources/Momento/messages/responses/cache/data/scalar/Delete.swift @@ -0,0 +1,8 @@ +public enum DeleteResponse { + case success(DeleteSuccess) + case error(DeleteError) +} + +public class DeleteSuccess {} + +public class DeleteError: ErrorResponseBase {} diff --git a/Tests/MomentoTests/cacheTests.swift b/Tests/MomentoTests/cacheTests.swift index 328b1d6..a3853dc 100644 --- a/Tests/MomentoTests/cacheTests.swift +++ b/Tests/MomentoTests/cacheTests.swift @@ -21,10 +21,10 @@ final class cacheTests: XCTestCase { func testCacheClientValidatesCacheName() async throws { let createInvalidName = await self.cacheClient.createCache(cacheName: " ") XCTAssertTrue( - createInvalidName is CacheCreateError, + createInvalidName is CreateCacheError, "Unexpected response: \(createInvalidName)" ) - let createErrorCode = (createInvalidName as! CacheCreateError).errorCode + let createErrorCode = (createInvalidName as! CreateCacheError).errorCode XCTAssertEqual( createErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, "Unexpected error code: \(createErrorCode)" @@ -46,7 +46,7 @@ final class cacheTests: XCTestCase { let cacheName = generateStringWithUuid(prefix: "a-totally-new-cache") let createResult = await self.cacheClient.createCache(cacheName: cacheName) XCTAssertTrue( - createResult is CacheCreateSuccess, + createResult is CreateCacheSuccess, "Unexpected response: \(createResult)" ) @@ -62,7 +62,7 @@ final class cacheTests: XCTestCase { // Expect list to include integration test cache switch listResult { - case let listResult as CacheListSuccess: + case let listResult as ListCachesSuccess: let caches = listResult.caches XCTAssertTrue( caches.contains(where: {item in @@ -72,7 +72,7 @@ final class cacheTests: XCTestCase { ) default: XCTAssertTrue( - listResult is CacheListSuccess, + listResult is ListCachesSuccess, "Unexpected response: \(listResult)" ) } @@ -81,14 +81,14 @@ final class cacheTests: XCTestCase { let newCacheName = generateStringWithUuid(prefix: "a-totally-different-cache") let createResult = await self.cacheClient.createCache(cacheName: newCacheName) XCTAssertTrue( - createResult is CacheCreateSuccess, + createResult is CreateCacheSuccess, "Unexpected response: \(createResult)" ) // Expect list to include both new cache and integration test cache let listResult2 = await self.cacheClient.listCaches() switch listResult2 { - case let listResult2 as CacheListSuccess: + case let listResult2 as ListCachesSuccess: let caches = listResult2.caches XCTAssertTrue( caches.contains(where: {item in @@ -104,7 +104,7 @@ final class cacheTests: XCTestCase { ) default: XCTAssertTrue( - listResult is CacheListSuccess, + listResult is ListCachesSuccess, "Unexpected response: \(listResult)" ) } @@ -118,35 +118,41 @@ final class cacheTests: XCTestCase { } func testScalarGet() async throws { -// let invalidCacheName = await self.cacheClient.get( -// cacheName: " ", -// key: ScalarType.string(generateStringWithUuid(prefix: "hello")) -// ) -// XCTAssertTrue( -// invalidCacheName is CacheGetError, -// "Unexpected response: \(invalidCacheName)" -// ) -// let invalidCacheNameErrorCode = (invalidCacheName as! CacheGetError).errorCode -// XCTAssertEqual( -// invalidCacheNameErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, -// "Unexpected error code: \(invalidCacheNameErrorCode)" -// ) -// let invalidKey = await self.cacheClient.get( -// cacheName: self.integrationTestCacheName, -// key: ScalarType.string(" ") -// ) -// XCTAssertTrue( -// invalidKey is CacheGetError, -// "Unexpected response: \(invalidKey)" -// ) -// let invalidKeyErrorCode = (invalidKey as! CacheGetError).errorCode -// XCTAssertEqual( -// invalidKeyErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, -// "Unexpected error code: \(invalidKeyErrorCode)" -// ) -// + let invalidCacheName = await self.cacheClient.get( + cacheName: " ", + key: ScalarType.string(generateStringWithUuid(prefix: "hello")) + ) + switch invalidCacheName { + case .hit(let hit): + XCTFail("expected error but got \(hit)") + case .miss(let miss): + XCTFail("expected error but got \(miss)") + case .error(let err): + XCTAssertEqual( + err.errorCode, + MomentoErrorCode.INVALID_ARGUMENT_ERROR, + "Unexpected error code: \(err.errorCode)" + ) + } + + let invalidKey = await self.cacheClient.get( + cacheName: self.integrationTestCacheName, + key: ScalarType.string(" ") + ) + switch invalidKey { + case .hit(let hit): + XCTFail("expected error but got \(hit)") + case .miss(let miss): + XCTFail("expected error but got \(miss)") + case .error(let err): + XCTAssertEqual( + err.errorCode, + MomentoErrorCode.INVALID_ARGUMENT_ERROR, + "Unexpected error code: \(err.errorCode)" + ) + } + let testKey = generateStringWithUuid(prefix: "hello") - let stringKey = await self.cacheClient.get( cacheName: self.integrationTestCacheName, key: testKey @@ -160,16 +166,72 @@ final class cacheTests: XCTestCase { case .error(let err): XCTFail("expected a miss but got \(err)") } - - XCTAssertTrue(stringKey is CacheGetResponse, "Unexpected response: \(stringKey)") -// let bytesKey = await self.cacheClient.get( -// cacheName: self.integrationTestCacheName, -// key: ScalarType.data(Data(testKey.utf8)) -// ) -// XCTAssertTrue(bytesKey is CacheGetMiss, "Unexpected response: \(bytesKey)") + let bytesKey = await self.cacheClient.get( + cacheName: self.integrationTestCacheName, + key: ScalarType.data(Data(testKey.utf8)) + ) + switch bytesKey { + case .hit(let hit): + XCTFail("expected a miss but got \(hit)") + case .miss: + XCTAssertTrue(true) + case .error(let err): + XCTFail("expected a miss but got \(err)") + } } + func testScalarDelete() async throws { + let key = "foo" + let value = "fooaswell" + let setResponse = await self.cacheClient.set( + cacheName: self.integrationTestCacheName, + key: ScalarType.string(key), + value: ScalarType.string(value), + ttl: TimeInterval(30) + ) + switch setResponse { + case .error(let err): + XCTFail("expected success but got \(err))") + case .success(_): + XCTAssertTrue(true) + } + + var getResponse = await self.cacheClient.get( + cacheName: self.integrationTestCacheName, key: ScalarType.string(key) + ) + switch getResponse { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(value, hit.valueString) + } + + let deleteResponse = await self.cacheClient.delete( + cacheName: self.integrationTestCacheName, key: ScalarType.string(key) + ) + switch deleteResponse { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(_): + XCTAssertTrue(true) + } + + getResponse = await self.cacheClient.get( + cacheName: self.integrationTestCacheName, key: ScalarType.string(key) + ) + switch getResponse { + case .error(let err): + XCTFail("expected miss but got \(err)") + case .miss(_): + XCTAssertTrue(true) + case .hit(let hit): + XCTFail("expected miss but got \(hit)") + } + } + func testScalarSet() async throws { let invalidCacheName = await self.cacheClient.set( cacheName: " ", @@ -177,48 +239,51 @@ final class cacheTests: XCTestCase { value: "world", ttl: nil ) - XCTAssertTrue( - invalidCacheName is CacheSetError, - "Unexpected response: \(invalidCacheName)" - ) - let invalidCacheNameErrorCode = (invalidCacheName as! CacheSetError).errorCode - XCTAssertEqual( - invalidCacheNameErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidCacheNameErrorCode)" - ) - + switch invalidCacheName { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual( + err.errorCode, + MomentoErrorCode.INVALID_ARGUMENT_ERROR, + "Unexpected error code: \(err.errorCode)" + ) + } + let invalidKey = await self.cacheClient.set( cacheName: self.integrationTestCacheName, key: " ", value: "world", ttl: nil ) - XCTAssertTrue( - invalidKey is CacheSetError, - "Unexpected response: \(invalidKey)" - ) - let invalidKeyErrorCode = (invalidKey as! CacheSetError).errorCode - XCTAssertEqual( - invalidKeyErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidKeyErrorCode)" - ) - + switch invalidKey { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual( + err.errorCode, + MomentoErrorCode.INVALID_ARGUMENT_ERROR, + "Unexpected error code: \(err.errorCode)" + ) + } + let invalidTtl = await self.cacheClient.set( cacheName: self.integrationTestCacheName, key: "hello", value: "world", ttl: -5 ) - XCTAssertTrue( - invalidTtl is CacheSetError, - "Unexpected response: \(invalidTtl)" - ) - let invalidTtlErrorCode = (invalidTtl as! CacheSetError).errorCode - XCTAssertEqual( - invalidTtlErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidTtlErrorCode)" - ) - + switch invalidTtl { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual( + err.errorCode, + MomentoErrorCode.INVALID_ARGUMENT_ERROR, + "Unexpected error code: \(err.errorCode)" + ) + } + let testKey1 = generateStringWithUuid(prefix: "hello") let testValue1 = "world" let stringKeyStringValue = await self.cacheClient.set( @@ -227,19 +292,23 @@ final class cacheTests: XCTestCase { value: testValue1, ttl: nil ) - XCTAssertTrue( - stringKeyStringValue is CacheSetSuccess, - "Unexpected response: \(stringKeyStringValue)" - ) + switch stringKeyStringValue { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(_): + XCTAssertTrue(true) + } let getStringKeyStringValue = await self.cacheClient.get( cacheName: self.integrationTestCacheName, key: testKey1 ) - XCTAssertTrue( - getStringKeyStringValue is CacheGetHit, - "Unexpected response: \(getStringKeyStringValue)" - ) - let value1 = (getStringKeyStringValue as! CacheGetHit).valueString - XCTAssertTrue(value1 == testValue1) + switch getStringKeyStringValue { + case .hit(let hit): + XCTAssertEqual(hit.valueString, testValue1) + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .error(let err): + XCTFail("expected hit but got \(err)") + } let testKey2 = generateStringWithUuid(prefix: "foo") let testValue2 = Data("bar".utf8) @@ -249,20 +318,24 @@ final class cacheTests: XCTestCase { value: testValue2, ttl: nil ) - XCTAssertTrue( - stringKeyBytesValue is CacheSetSuccess, - "Unexpected response: \(stringKeyBytesValue)" - ) + switch stringKeyBytesValue { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(_): + XCTAssertTrue(true) + } let getStringKeyBytesValue = await self.cacheClient.get( cacheName: self.integrationTestCacheName, key: testKey2 ) - XCTAssertTrue( - getStringKeyBytesValue is CacheGetHit, - "Unexpected response: \(getStringKeyBytesValue)" - ) - let value2 = (getStringKeyBytesValue as! CacheGetHit).valueData - XCTAssertTrue(value2 == testValue2) - + switch getStringKeyBytesValue { + case .hit(let hit): + XCTAssertEqual(hit.valueData, testValue2) + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .error(let err): + XCTFail("expected hit but got \(err)") + } + let testKey3 = Data(generateStringWithUuid(prefix: "abc").utf8) let testValue3 = "123" let bytesKeyStringValue = await self.cacheClient.set( @@ -271,20 +344,24 @@ final class cacheTests: XCTestCase { value: testValue3, ttl: nil ) - XCTAssertTrue( - bytesKeyStringValue is CacheSetSuccess, - "Unexpected response: \(bytesKeyStringValue)" - ) + switch bytesKeyStringValue { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(_): + XCTAssertTrue(true) + } let getBytesKeyStringValue = await self.cacheClient.get( cacheName: self.integrationTestCacheName, key: testKey3 ) - XCTAssertTrue( - getBytesKeyStringValue is CacheGetHit, - "Unexpected response: \(getBytesKeyStringValue)" - ) - let value3 = (getBytesKeyStringValue as! CacheGetHit).valueString - XCTAssertTrue(value3 == testValue3) - + switch getBytesKeyStringValue { + case .hit(let hit): + XCTAssertEqual(hit.valueString, testValue3) + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .error(let err): + XCTFail("expected hit but got \(err)") + } + let testKey4 = Data(generateStringWithUuid(prefix: "321").utf8) let testValue4 = Data("xyz".utf8) let bytesKeyBytesValue = await self.cacheClient.set( @@ -293,20 +370,24 @@ final class cacheTests: XCTestCase { value: testValue4, ttl: nil ) - XCTAssertTrue( - bytesKeyBytesValue is CacheSetSuccess, - "Unexpected response: \(bytesKeyBytesValue)" - ) + switch bytesKeyBytesValue { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(_): + XCTAssertTrue(true) + } let getBytesKeyBytesValue = await self.cacheClient.get( cacheName: self.integrationTestCacheName, key: testKey4 ) - XCTAssertTrue( - getBytesKeyBytesValue is CacheGetHit, - "Unexpected response: \(getBytesKeyBytesValue)" - ) - let value4 = (getBytesKeyBytesValue as! CacheGetHit).valueData - XCTAssertTrue(value4 == testValue4) - + switch getBytesKeyBytesValue { + case .hit(let hit): + XCTAssertEqual(hit.valueData, testValue4) + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .error(let err): + XCTFail("expected hit but got \(err)") + } + let testKey5 = generateStringWithUuid(prefix: "apple") let testValue5 = "pie" let shortTtl = await self.cacheClient.set( @@ -315,10 +396,12 @@ final class cacheTests: XCTestCase { value: testValue5, ttl: 1 // ttl = 1 second ) - XCTAssertTrue( - shortTtl is CacheSetSuccess, - "Unexpected response: \(shortTtl)" - ) + switch shortTtl { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(_): + XCTAssertTrue(true) + } // sleep for 5 seconds try await Task.sleep(nanoseconds: 5_000_000_000) @@ -326,10 +409,14 @@ final class cacheTests: XCTestCase { let getShortTtl = await self.cacheClient.get( cacheName: self.integrationTestCacheName, key: testKey5 ) - XCTAssertTrue( - getShortTtl is CacheGetMiss, - "Unexpected response: \(getShortTtl)" - ) + switch getShortTtl { + case .error(let err): + XCTFail("expected miss but got \(err)") + case .hit(let hit): + XCTFail("expected miss but got \(hit)") + case .miss: + XCTAssertTrue(true) + } let testKey6 = generateStringWithUuid(prefix: "hello") let testValue6 = "world" @@ -338,18 +425,22 @@ final class cacheTests: XCTestCase { key: testKey6, value: testValue6 ) - XCTAssertTrue( - noTtlSetValue is CacheSetSuccess, - "Unexpected response: \(stringKeyStringValue)" - ) + switch noTtlSetValue { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(_): + XCTAssertTrue(true) + } let getNoTtlValue = await self.cacheClient.get( cacheName: self.integrationTestCacheName, key: testKey6 ) - XCTAssertTrue( - getNoTtlValue is CacheGetHit, - "Unexpected response: \(getNoTtlValue)" - ) - let value6 = (getNoTtlValue as! CacheGetHit).valueString - XCTAssertTrue(value6 == testValue6) + switch getNoTtlValue { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(hit.valueString, testValue6) + } } } diff --git a/Tests/MomentoTests/testUtils.swift b/Tests/MomentoTests/testUtils.swift index 7f64709..d685a83 100644 --- a/Tests/MomentoTests/testUtils.swift +++ b/Tests/MomentoTests/testUtils.swift @@ -27,7 +27,7 @@ func setUpIntegrationTests() async -> TestSetup { let cacheName = generateStringWithUuid(prefix: "swift-test") let result = await cacheClient.createCache(cacheName: cacheName) switch result { - case let error as CacheCreateError: + case let error as CreateCacheError: fatalError("Unable to create integration test cache: \(error.description)") default: break From 696a6b7e32cd1945c5f52baf0b1dc8ab0de648bc Mon Sep 17 00:00:00 2001 From: Pete Gautier Date: Thu, 7 Dec 2023 17:17:30 -0800 Subject: [PATCH 03/12] fix: remove some redundant switch statements --- Sources/Momento/internal/DataClient.swift | 33 ++++------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/Sources/Momento/internal/DataClient.swift b/Sources/Momento/internal/DataClient.swift index 2299c26..4a679c4 100644 --- a/Sources/Momento/internal/DataClient.swift +++ b/Sources/Momento/internal/DataClient.swift @@ -152,14 +152,8 @@ class DataClient: DataClientProtocol { func get(cacheName: String, key: ScalarType) async -> CacheGetResponse { var request = CacheClient__GetRequest() - - switch key { - case .string(let s): - request.cacheKey = Data(s.utf8) - case .data(let d): - request.cacheKey = d - } - + request.cacheKey = self.convertScalarTypeToData(element: key) + let headers = self.makeHeaders(cacheName: cacheName) let call = self.client.get( request, @@ -202,20 +196,8 @@ class DataClient: DataClientProtocol { ) async -> CacheSetResponse { var request = CacheClient__SetRequest() request.ttlMilliseconds = UInt64(ttl ?? self.defaultTtlSeconds*1000) - - switch key { - case .string(let s): - request.cacheKey = Data(s.utf8) - case .data(let b): - request.cacheKey = b - } - - switch value { - case .string(let s): - request.cacheBody = Data(s.utf8) - case .data(let d): - request.cacheBody = d - } + request.cacheKey = self.convertScalarTypeToData(element: key) + request.cacheBody = self.convertScalarTypeToData(element: value) let headers = self.makeHeaders(cacheName: cacheName) let call = self.client.set( @@ -245,12 +227,7 @@ class DataClient: DataClientProtocol { func delete(cacheName: String, key: ScalarType) async -> DeleteResponse { var request = CacheClient__DeleteRequest() - switch key { - case .data(let b): - request.cacheKey = b - case .string(let s): - request.cacheKey = Data(s.utf8) - } + request.cacheKey = self.convertScalarTypeToData(element: key) let headers = self.makeHeaders(cacheName: cacheName) let call = self.client.delete( request, From bd4e56cee7d8aaa5d290e3f0214f79577910d9e8 Mon Sep 17 00:00:00 2001 From: Pete Gautier Date: Fri, 8 Dec 2023 09:48:47 -0800 Subject: [PATCH 04/12] chore: remove response class name prefix --- Sources/Momento/CacheClient.swift | 24 ++++++++-------- Sources/Momento/internal/DataClient.swift | 28 +++++++++---------- .../cache/data/scalar/CacheGet.swift | 25 ----------------- .../cache/data/scalar/CacheSet.swift | 8 ------ .../responses/cache/data/scalar/Get.swift | 25 +++++++++++++++++ .../responses/cache/data/scalar/Set.swift | 8 ++++++ 6 files changed, 59 insertions(+), 59 deletions(-) delete mode 100644 Sources/Momento/messages/responses/cache/data/scalar/CacheGet.swift delete mode 100644 Sources/Momento/messages/responses/cache/data/scalar/CacheSet.swift create mode 100644 Sources/Momento/messages/responses/cache/data/scalar/Get.swift create mode 100644 Sources/Momento/messages/responses/cache/data/scalar/Set.swift diff --git a/Sources/Momento/CacheClient.swift b/Sources/Momento/CacheClient.swift index 49e3996..6c272a0 100644 --- a/Sources/Momento/CacheClient.swift +++ b/Sources/Momento/CacheClient.swift @@ -364,15 +364,15 @@ public class CacheClient: CacheClientProtocol { - Parameters: - cacheName: the name of the cache to perform the lookup in - key: the key to look up as type String - - Returns: CacheGetResponse representing the result of the get operation. + - Returns: GetResponse representing the result of the get operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheGetError: + case let responseError as GetError: // handle error - case let responseMiss as CacheGetMiss: + case let responseMiss as GetMiss: // handle miss - case let responseHit as CacheGetHit: + case let responseHit as GetHit: // handle hit } ``` @@ -408,9 +408,9 @@ public class CacheClient: CacheClientProtocol { try validateCacheName(cacheName: cacheName) try validateCacheKey(key: key) } catch let err as SdkError { - return CacheGetResponse.error(CacheGetError(error: err)) + return GetResponse.error(GetError(error: err)) } catch { - return CacheGetResponse.error(CacheGetError(error: UnknownError( + return GetResponse.error(GetError(error: UnknownError( message: "unexpected error: \(error)") )) } @@ -424,13 +424,13 @@ public class CacheClient: CacheClientProtocol { - key: the key to set the value for - value: the value to associate with the key - ttl: the time to live for the item in the cache. Uses the client's default TTL if this is not supplied. - - Returns: CacheSetResponse representing the result of the set operation. + - Returns: SetResponse representing the result of the set operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheSetError: + case let responseError as SetError: // handle error - case let responseSuccess as CacheSetSuccess: + case let responseSuccess as SetSuccess: // handle success } ``` @@ -550,15 +550,15 @@ public class CacheClient: CacheClientProtocol { key: ScalarType, value: ScalarType, ttl: TimeInterval? = nil - ) async -> CacheSetResponse { + ) async -> SetResponse { do { try validateCacheName(cacheName: cacheName) try validateCacheKey(key: key) try validateTtl(ttl: ttl) } catch let err as SdkError { - return CacheSetResponse.error(CacheSetError(error: err)) + return SetResponse.error(SetError(error: err)) } catch { - return CacheSetResponse.error(CacheSetError(error: UnknownError( + return SetResponse.error(SetError(error: UnknownError( message: "unexpected error: \(error)") )) } diff --git a/Sources/Momento/internal/DataClient.swift b/Sources/Momento/internal/DataClient.swift index 4a679c4..24bb1e8 100644 --- a/Sources/Momento/internal/DataClient.swift +++ b/Sources/Momento/internal/DataClient.swift @@ -5,14 +5,14 @@ import NIOHPACK import Logging protocol DataClientProtocol { - func get(cacheName: String, key: ScalarType) async -> CacheGetResponse + func get(cacheName: String, key: ScalarType) async -> GetResponse func set( cacheName: String, key: ScalarType, value: ScalarType, ttl: TimeInterval? - ) async -> CacheSetResponse + ) async -> SetResponse func delete(cacheName: String, key: ScalarType) async -> DeleteResponse @@ -150,7 +150,7 @@ class DataClient: DataClientProtocol { } } - func get(cacheName: String, key: ScalarType) async -> CacheGetResponse { + func get(cacheName: String, key: ScalarType) async -> GetResponse { var request = CacheClient__GetRequest() request.cacheKey = self.convertScalarTypeToData(element: key) @@ -167,22 +167,22 @@ class DataClient: DataClientProtocol { do { let result = try await call.response.get() if result.result == .hit { - return CacheGetResponse.hit(CacheGetHit(value: result.cacheBody)) + return GetResponse.hit(GetHit(value: result.cacheBody)) } else if result.result == .miss { - return CacheGetResponse.miss(CacheGetMiss()) + return GetResponse.miss(GetMiss()) } else { - return CacheGetResponse.error(CacheGetError( + return GetResponse.error(GetError( error: UnknownError(message: "unknown cache get error \(result)") )) } } catch let err as GRPCStatus { - return CacheGetResponse.error(CacheGetError(error: grpcStatusToSdkError(grpcStatus: err))) + return GetResponse.error(GetError(error: grpcStatusToSdkError(grpcStatus: err))) } catch let err as GRPCConnectionPoolError { - return CacheGetResponse.error(CacheGetError( + return GetResponse.error(GetError( error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus()) )) } catch { - return CacheGetResponse.error(CacheGetError( + return GetResponse.error(GetError( error: UnknownError(message: "unknown cache get error \(error)") )) } @@ -193,7 +193,7 @@ class DataClient: DataClientProtocol { key: ScalarType, value: ScalarType, ttl: TimeInterval? = nil - ) async -> CacheSetResponse { + ) async -> SetResponse { var request = CacheClient__SetRequest() request.ttlMilliseconds = UInt64(ttl ?? self.defaultTtlSeconds*1000) request.cacheKey = self.convertScalarTypeToData(element: key) @@ -211,15 +211,15 @@ class DataClient: DataClientProtocol { do { _ = try await call.response.get() - return CacheSetResponse.success(CacheSetSuccess()) + return SetResponse.success(SetSuccess()) } catch let err as GRPCStatus { - return CacheSetResponse.error(CacheSetError(error: grpcStatusToSdkError(grpcStatus: err))) + return SetResponse.error(SetError(error: grpcStatusToSdkError(grpcStatus: err))) } catch let err as GRPCConnectionPoolError { - return CacheSetResponse.error(CacheSetError( + return SetResponse.error(SetError( error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus()) )) } catch { - return CacheSetResponse.error(CacheSetError( + return SetResponse.error(SetError( error: UnknownError(message: "unknown cache set error \(error)") )) } diff --git a/Sources/Momento/messages/responses/cache/data/scalar/CacheGet.swift b/Sources/Momento/messages/responses/cache/data/scalar/CacheGet.swift deleted file mode 100644 index 186c68c..0000000 --- a/Sources/Momento/messages/responses/cache/data/scalar/CacheGet.swift +++ /dev/null @@ -1,25 +0,0 @@ -import Foundation - -public enum CacheGetResponse { - case hit(CacheGetHit) - case miss(CacheGetMiss) - case error(CacheGetError) -} - -public class CacheGetHit: Equatable { - public let valueString: String - public let valueData: Data - - init(value: Data) { - self.valueData = value - self.valueString = String(decoding: value, as: UTF8.self) - } - - public static func == (lhs: CacheGetHit, rhs: CacheGetHit) -> Bool { - return lhs.valueData == rhs.valueData - } -} - -public class CacheGetMiss {} - -public class CacheGetError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/cache/data/scalar/CacheSet.swift b/Sources/Momento/messages/responses/cache/data/scalar/CacheSet.swift deleted file mode 100644 index 08bffd0..0000000 --- a/Sources/Momento/messages/responses/cache/data/scalar/CacheSet.swift +++ /dev/null @@ -1,8 +0,0 @@ -public enum CacheSetResponse { - case success(CacheSetSuccess) - case error(CacheSetError) -} - -public class CacheSetSuccess {} - -public class CacheSetError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/cache/data/scalar/Get.swift b/Sources/Momento/messages/responses/cache/data/scalar/Get.swift new file mode 100644 index 0000000..6e05f41 --- /dev/null +++ b/Sources/Momento/messages/responses/cache/data/scalar/Get.swift @@ -0,0 +1,25 @@ +import Foundation + +public enum GetResponse { + case hit(GetHit) + case miss(GetMiss) + case error(GetError) +} + +public class GetHit: Equatable { + public let valueString: String + public let valueData: Data + + init(value: Data) { + self.valueData = value + self.valueString = String(decoding: value, as: UTF8.self) + } + + public static func == (lhs: GetHit, rhs: GetHit) -> Bool { + return lhs.valueData == rhs.valueData + } +} + +public class GetMiss {} + +public class GetError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/cache/data/scalar/Set.swift b/Sources/Momento/messages/responses/cache/data/scalar/Set.swift new file mode 100644 index 0000000..7446c93 --- /dev/null +++ b/Sources/Momento/messages/responses/cache/data/scalar/Set.swift @@ -0,0 +1,8 @@ +public enum SetResponse { + case success(SetSuccess) + case error(SetError) +} + +public class SetSuccess {} + +public class SetError: ErrorResponseBase {} From eb7a4c7acebc81568b014f35c89c73cf6f15a020 Mon Sep 17 00:00:00 2001 From: Pete Gautier Date: Fri, 8 Dec 2023 10:08:33 -0800 Subject: [PATCH 05/12] fix: fix a couple class names --- Sources/Momento/CacheClient.swift | 8 ++++---- Sources/Momento/internal/ControlClient.swift | 8 ++++---- .../messages/responses/cache/control/DeleteCache.swift | 4 ++-- Tests/MomentoTests/cacheTests.swift | 8 ++++---- Tests/MomentoTests/testUtils.swift | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Sources/Momento/CacheClient.swift b/Sources/Momento/CacheClient.swift index 6c272a0..f691770 100644 --- a/Sources/Momento/CacheClient.swift +++ b/Sources/Momento/CacheClient.swift @@ -321,9 +321,9 @@ public class CacheClient: CacheClientProtocol { Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheDeleteError: + case let responseError as DeleteCacheError: // handle error - case let responseSuccess as CacheDeleteSuccess: + case let responseSuccess as DeleteCacheSuccess: // handle success } ``` @@ -332,9 +332,9 @@ public class CacheClient: CacheClientProtocol { do { try validateCacheName(cacheName: cacheName) } catch let err as SdkError { - return CacheDeleteError(error: err) + return DeleteCacheError(error: err) } catch { - return CacheDeleteError(error: UnknownError( + return DeleteCacheError(error: UnknownError( message: "unexpected error: \(error)") ) } diff --git a/Sources/Momento/internal/ControlClient.swift b/Sources/Momento/internal/ControlClient.swift index 5a155cf..6a3525c 100644 --- a/Sources/Momento/internal/ControlClient.swift +++ b/Sources/Momento/internal/ControlClient.swift @@ -86,13 +86,13 @@ class ControlClient: ControlClientProtocol { do { _ = try await call.response.get() // Successful creation returns ControlClient__DeleteCacheResponse - return CacheDeleteSuccess() + return DeleteCacheSuccess() } catch let err as GRPCStatus { - return CacheDeleteError(error: grpcStatusToSdkError(grpcStatus: err)) + return DeleteCacheError(error: grpcStatusToSdkError(grpcStatus: err)) } catch let err as GRPCConnectionPoolError { - return CacheDeleteError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) + return DeleteCacheError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) } catch { - return CacheDeleteError(error: UnknownError(message: "unknown cache create error \(error)")) + return DeleteCacheError(error: UnknownError(message: "unknown cache create error \(error)")) } } diff --git a/Sources/Momento/messages/responses/cache/control/DeleteCache.swift b/Sources/Momento/messages/responses/cache/control/DeleteCache.swift index ac73a98..4af0155 100644 --- a/Sources/Momento/messages/responses/cache/control/DeleteCache.swift +++ b/Sources/Momento/messages/responses/cache/control/DeleteCache.swift @@ -1,5 +1,5 @@ public protocol DeleteCacheResponse {} -public class CacheDeleteSuccess: DeleteCacheResponse {} +public class DeleteCacheSuccess: DeleteCacheResponse {} -public class CacheDeleteError: ErrorResponseBase, DeleteCacheResponse {} +public class DeleteCacheError: ErrorResponseBase, DeleteCacheResponse {} diff --git a/Tests/MomentoTests/cacheTests.swift b/Tests/MomentoTests/cacheTests.swift index a3853dc..487d7b2 100644 --- a/Tests/MomentoTests/cacheTests.swift +++ b/Tests/MomentoTests/cacheTests.swift @@ -32,10 +32,10 @@ final class cacheTests: XCTestCase { let deleteInvalidName = await self.cacheClient.deleteCache(cacheName: " ") XCTAssertTrue( - deleteInvalidName is CacheDeleteError, + deleteInvalidName is DeleteCacheError, "Unexpected response: \(deleteInvalidName)" ) - let deleteErrorCode = (deleteInvalidName as! CacheDeleteError).errorCode + let deleteErrorCode = (deleteInvalidName as! DeleteCacheError).errorCode XCTAssertEqual( deleteErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, "Unexpected error code: \(deleteErrorCode)" @@ -52,7 +52,7 @@ final class cacheTests: XCTestCase { let deleteResult = await self.cacheClient.deleteCache(cacheName: cacheName) XCTAssertTrue( - deleteResult is CacheDeleteSuccess, + deleteResult is DeleteCacheSuccess, "Unexpected response: \(deleteResult)" ) } @@ -112,7 +112,7 @@ final class cacheTests: XCTestCase { // Clean up additional created cache let deleteResult = await self.cacheClient.deleteCache(cacheName: newCacheName) XCTAssertTrue( - deleteResult is CacheDeleteSuccess, + deleteResult is DeleteCacheSuccess, "Unexpected response: \(deleteResult)" ) } diff --git a/Tests/MomentoTests/testUtils.swift b/Tests/MomentoTests/testUtils.swift index d685a83..5b11f6f 100644 --- a/Tests/MomentoTests/testUtils.swift +++ b/Tests/MomentoTests/testUtils.swift @@ -45,7 +45,7 @@ func setUpIntegrationTests() async -> TestSetup { func cleanUpIntegrationTests(cacheName: String, cacheClient: CacheClientProtocol) async { let result = await cacheClient.deleteCache(cacheName: cacheName) - if result is CacheDeleteError { + if result is DeleteCacheError { fatalError("Unable to tear down integration test setup: \(result)") } } From 3f381de8ae2fe84eaeb595c65ff11ddd7096c202 Mon Sep 17 00:00:00 2001 From: Pete Gautier Date: Fri, 8 Dec 2023 15:48:03 -0800 Subject: [PATCH 06/12] fix: fix error in calculating user-provided ttl --- Sources/Momento/internal/DataClient.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/Momento/internal/DataClient.swift b/Sources/Momento/internal/DataClient.swift index 24bb1e8..2659227 100644 --- a/Sources/Momento/internal/DataClient.swift +++ b/Sources/Momento/internal/DataClient.swift @@ -195,7 +195,8 @@ class DataClient: DataClientProtocol { ttl: TimeInterval? = nil ) async -> SetResponse { var request = CacheClient__SetRequest() - request.ttlMilliseconds = UInt64(ttl ?? self.defaultTtlSeconds*1000) + let ttlSeconds = ttl ?? self.defaultTtlSeconds + request.ttlMilliseconds = UInt64(ttlSeconds*1000) request.cacheKey = self.convertScalarTypeToData(element: key) request.cacheBody = self.convertScalarTypeToData(element: value) From 76d66fcd0db6232c5f2e5a3ff73fae6fa0526ebc Mon Sep 17 00:00:00 2001 From: Pete Gautier Date: Fri, 8 Dec 2023 16:57:41 -0800 Subject: [PATCH 07/12] fix: cleanup after fixing conflicts --- Sources/Momento/CacheClient.swift | 44 ++++++++++++++++++------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/Sources/Momento/CacheClient.swift b/Sources/Momento/CacheClient.swift index f691770..e3269f4 100644 --- a/Sources/Momento/CacheClient.swift +++ b/Sources/Momento/CacheClient.swift @@ -12,11 +12,11 @@ enum ScalarType { protocol CacheClientProtocol: ControlClientProtocol & DataClientProtocol {} extension CacheClientProtocol { - public func get(cacheName: String, key: String) async -> CacheGetResponse { + public func get(cacheName: String, key: String) async -> GetResponse { return await self.get(cacheName: cacheName, key: ScalarType.string(key)) } - public func get(cacheName: String, key: Data) async -> CacheGetResponse { + public func get(cacheName: String, key: Data) async -> GetResponse { return await self.get(cacheName: cacheName, key: ScalarType.data(key)) } @@ -25,7 +25,7 @@ extension CacheClientProtocol { key: String, value: String, ttl: TimeInterval? = nil - ) async -> CacheSetResponse { + ) async -> SetResponse { return await set( cacheName: cacheName, key: ScalarType.string(key), @@ -39,7 +39,7 @@ extension CacheClientProtocol { key: String, value: Data, ttl: TimeInterval? = nil - ) async -> CacheSetResponse { + ) async -> SetResponse { return await set( cacheName: cacheName, key: ScalarType.string(key), @@ -53,7 +53,7 @@ extension CacheClientProtocol { key: Data, value: String, ttl: TimeInterval? = nil - ) async -> CacheSetResponse { + ) async -> SetResponse { return await set( cacheName: cacheName, key: ScalarType.data(key), @@ -67,7 +67,7 @@ extension CacheClientProtocol { key: Data, value: Data, ttl: TimeInterval? = nil - ) async -> CacheSetResponse { + ) async -> SetResponse { return await set( cacheName: cacheName, key: ScalarType.data(key), @@ -76,6 +76,14 @@ extension CacheClientProtocol { ) } + public func delete(cacheName: String, key: String) async -> DeleteResponse { + return await delete(cacheName: cacheName, key: ScalarType.string(key)) + } + + public func delete(cacheName: String, key: Data) async -> DeleteResponse { + return await delete(cacheName: cacheName, key: ScalarType.data(key)) + } + public func listConcatenateBack( cacheName: String, listName: String, @@ -377,7 +385,7 @@ public class CacheClient: CacheClientProtocol { } ``` */ - public func get(cacheName: String, key: String) async -> CacheGetResponse { + public func get(cacheName: String, key: String) async -> GetResponse { return await self.get(cacheName: cacheName, key: ScalarType.string(key)) } @@ -386,7 +394,7 @@ public class CacheClient: CacheClientProtocol { - Parameters: - cacheName: the name of the cache to perform the lookup in - key: the key to look up as type Data - - Returns: CacheGetResponse representing the result of the get operation. + - Returns: GetResponse representing the result of the get operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { @@ -399,11 +407,11 @@ public class CacheClient: CacheClientProtocol { } ``` */ - public func get(cacheName: String, key: Data) async -> CacheGetResponse { + public func get(cacheName: String, key: Data) async -> GetResponse { return await self.get(cacheName: cacheName, key: ScalarType.data(key)) } - internal func get(cacheName: String, key: ScalarType) async -> CacheGetResponse { + internal func get(cacheName: String, key: ScalarType) async -> GetResponse { do { try validateCacheName(cacheName: cacheName) try validateCacheKey(key: key) @@ -440,7 +448,7 @@ public class CacheClient: CacheClientProtocol { key: String, value: String, ttl: TimeInterval? = nil - ) async -> CacheSetResponse { + ) async -> SetResponse { return await set( cacheName: cacheName, key: ScalarType.string(key), @@ -456,7 +464,7 @@ public class CacheClient: CacheClientProtocol { - key: the key to set the value for - value: the value to associate with the key - ttl: the time to live for the item in the cache. Uses the client's default TTL if this is not supplied. - - Returns: CacheSetResponse representing the result of the set operation. + - Returns: SetResponse representing the result of the set operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { @@ -472,7 +480,7 @@ public class CacheClient: CacheClientProtocol { key: String, value: Data, ttl: TimeInterval? = nil - ) async -> CacheSetResponse { + ) async -> SetResponse { return await set( cacheName: cacheName, key: ScalarType.string(key), @@ -488,7 +496,7 @@ public class CacheClient: CacheClientProtocol { - key: the key to set the value for - value: the value to associate with the key - ttl: the time to live for the item in the cache. Uses the client's default TTL if this is not supplied. - - Returns: CacheSetResponse representing the result of the set operation. + - Returns: SetResponse representing the result of the set operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { @@ -504,7 +512,7 @@ public class CacheClient: CacheClientProtocol { key: Data, value: String, ttl: TimeInterval? = nil - ) async -> CacheSetResponse { + ) async -> SetResponse { return await set( cacheName: cacheName, key: ScalarType.data(key), @@ -520,7 +528,7 @@ public class CacheClient: CacheClientProtocol { - key: the key to set the value for - value: the value to associate with the key - ttl: the time to live for the item in the cache. Uses the client's default TTL if this is not supplied. - - Returns: CacheSetResponse representing the result of the set operation. + - Returns: SetResponse representing the result of the set operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { @@ -536,7 +544,7 @@ public class CacheClient: CacheClientProtocol { key: Data, value: Data, ttl: TimeInterval? = nil - ) async -> CacheSetResponse { + ) async -> SetResponse { return await set( cacheName: cacheName, key: ScalarType.data(key), @@ -570,7 +578,7 @@ public class CacheClient: CacheClientProtocol { ) } - public func delete(cacheName: String, key: ScalarType) async -> DeleteResponse { + internal func delete(cacheName: String, key: ScalarType) async -> DeleteResponse { do { try validateCacheName(cacheName: cacheName) try validateCacheKey(key: key) From e06c88ffb6b9607a123f544c366a8b0dde5420da Mon Sep 17 00:00:00 2001 From: Pete Gautier Date: Mon, 11 Dec 2023 10:38:13 -0800 Subject: [PATCH 08/12] chore: convert control plane responses to enum-based --- Sources/Momento/CacheClient.swift | 12 +- Sources/Momento/internal/ControlClient.swift | 44 ++++-- .../responses/cache/control/CreateCache.swift | 12 +- .../responses/cache/control/DeleteCache.swift | 9 +- .../responses/cache/control/ListCaches.swift | 9 +- Tests/MomentoTests/cacheTests.swift | 126 ++++++++---------- Tests/MomentoTests/testUtils.swift | 16 ++- 7 files changed, 125 insertions(+), 103 deletions(-) diff --git a/Sources/Momento/CacheClient.swift b/Sources/Momento/CacheClient.swift index e3269f4..d1c7bcd 100644 --- a/Sources/Momento/CacheClient.swift +++ b/Sources/Momento/CacheClient.swift @@ -313,10 +313,10 @@ public class CacheClient: CacheClientProtocol { do { try validateCacheName(cacheName: cacheName) } catch let err as SdkError { - return CreateCacheError(error: err) + return CreateCacheResponse.error(CreateCacheError(error: err)) } catch { - return CreateCacheError(error: UnknownError( - message: "unexpected error: \(error)") + return CreateCacheResponse.error( + CreateCacheError(error: UnknownError(message: "unexpected error: \(error)")) ) } return await self.controlClient.createCache(cacheName: cacheName) @@ -340,10 +340,10 @@ public class CacheClient: CacheClientProtocol { do { try validateCacheName(cacheName: cacheName) } catch let err as SdkError { - return DeleteCacheError(error: err) + return DeleteCacheResponse.error(DeleteCacheError(error: err)) } catch { - return DeleteCacheError(error: UnknownError( - message: "unexpected error: \(error)") + return DeleteCacheResponse.error( + DeleteCacheError(error: UnknownError(message: "unexpected error: \(error)")) ) } return await self.controlClient.deleteCache(cacheName: cacheName) diff --git a/Sources/Momento/internal/ControlClient.swift b/Sources/Momento/internal/ControlClient.swift index 6a3525c..039c976 100644 --- a/Sources/Momento/internal/ControlClient.swift +++ b/Sources/Momento/internal/ControlClient.swift @@ -66,16 +66,22 @@ class ControlClient: ControlClientProtocol { do { _ = try await call.response.get() // Successful creation returns ControlClient__CreateCacheResponse - return CreateCacheSuccess() + return CreateCacheResponse.success(CreateCacheSuccess()) } catch let err as GRPCStatus { if err.code == GRPCStatus.Code.alreadyExists { - return CreateCacheAlreadyExists() + return CreateCacheResponse.alreadyExists(CreateCacheAlreadyExists()) } - return CreateCacheError(error: grpcStatusToSdkError(grpcStatus: err)) + return CreateCacheResponse.error( + CreateCacheError(error: grpcStatusToSdkError(grpcStatus: err)) + ) } catch let err as GRPCConnectionPoolError { - return CreateCacheError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) + return CreateCacheResponse.error( + CreateCacheError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) + ) } catch { - return CreateCacheError(error: UnknownError(message: "unknown cache create error \(error)")) + return CreateCacheResponse.error( + CreateCacheError(error: UnknownError(message: "unknown cache create error \(error)")) + ) } } @@ -86,13 +92,19 @@ class ControlClient: ControlClientProtocol { do { _ = try await call.response.get() // Successful creation returns ControlClient__DeleteCacheResponse - return DeleteCacheSuccess() + return DeleteCacheResponse.success(DeleteCacheSuccess()) } catch let err as GRPCStatus { - return DeleteCacheError(error: grpcStatusToSdkError(grpcStatus: err)) + return DeleteCacheResponse.error( + DeleteCacheError(error: grpcStatusToSdkError(grpcStatus: err)) + ) } catch let err as GRPCConnectionPoolError { - return DeleteCacheError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) + return DeleteCacheResponse.error( + DeleteCacheError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) + ) } catch { - return DeleteCacheError(error: UnknownError(message: "unknown cache create error \(error)")) + return DeleteCacheResponse.error( + DeleteCacheError(error: UnknownError(message: "unknown cache create error \(error)")) + ) } } @@ -102,13 +114,19 @@ class ControlClient: ControlClientProtocol { let result = try await call.response.get() // Successful creation returns ControlClient__ListCachesResponse self.logger.debug("list caches received: \(result.cache)") - return ListCachesSuccess(caches: result.cache) + return ListCachesResponse.success(ListCachesSuccess(caches: result.cache)) } catch let err as GRPCStatus { - return ListCachesError(error: grpcStatusToSdkError(grpcStatus: err)) + return ListCachesResponse.error( + ListCachesError(error: grpcStatusToSdkError(grpcStatus: err)) + ) } catch let err as GRPCConnectionPoolError { - return ListCachesError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) + return ListCachesResponse.error( + ListCachesError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) + ) } catch { - return ListCachesError(error: UnknownError(message: "unknown cache create error \(error)")) + return ListCachesResponse.error( + ListCachesError(error: UnknownError(message: "unknown cache create error \(error)")) + ) } } } diff --git a/Sources/Momento/messages/responses/cache/control/CreateCache.swift b/Sources/Momento/messages/responses/cache/control/CreateCache.swift index 7bd01c8..2411ac5 100644 --- a/Sources/Momento/messages/responses/cache/control/CreateCache.swift +++ b/Sources/Momento/messages/responses/cache/control/CreateCache.swift @@ -1,7 +1,11 @@ -public protocol CreateCacheResponse {} +public enum CreateCacheResponse { + case success(CreateCacheSuccess) + case alreadyExists(CreateCacheAlreadyExists) + case error(CreateCacheError) +} -public class CreateCacheSuccess: CreateCacheResponse {} +public class CreateCacheSuccess {} -public class CreateCacheAlreadyExists: CreateCacheResponse {} +public class CreateCacheAlreadyExists {} -public class CreateCacheError: ErrorResponseBase, CreateCacheResponse {} +public class CreateCacheError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/cache/control/DeleteCache.swift b/Sources/Momento/messages/responses/cache/control/DeleteCache.swift index 4af0155..c9697c9 100644 --- a/Sources/Momento/messages/responses/cache/control/DeleteCache.swift +++ b/Sources/Momento/messages/responses/cache/control/DeleteCache.swift @@ -1,5 +1,8 @@ -public protocol DeleteCacheResponse {} +public enum DeleteCacheResponse { + case success(DeleteCacheSuccess) + case error(DeleteCacheError) +} -public class DeleteCacheSuccess: DeleteCacheResponse {} +public class DeleteCacheSuccess {} -public class DeleteCacheError: ErrorResponseBase, DeleteCacheResponse {} +public class DeleteCacheError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/cache/control/ListCaches.swift b/Sources/Momento/messages/responses/cache/control/ListCaches.swift index 92ed2d6..278f872 100644 --- a/Sources/Momento/messages/responses/cache/control/ListCaches.swift +++ b/Sources/Momento/messages/responses/cache/control/ListCaches.swift @@ -6,9 +6,12 @@ public class CacheInfo { } } -public protocol ListCachesResponse {} +public enum ListCachesResponse { + case success(ListCachesSuccess) + case error(ListCachesError) +} -public class ListCachesSuccess: ListCachesResponse { +public class ListCachesSuccess { public let caches: [CacheInfo] init(caches: [ControlClient__Cache]) { @@ -18,4 +21,4 @@ public class ListCachesSuccess: ListCachesResponse { } } -public class ListCachesError: ErrorResponseBase, ListCachesResponse {} +public class ListCachesError: ErrorResponseBase {} diff --git a/Tests/MomentoTests/cacheTests.swift b/Tests/MomentoTests/cacheTests.swift index 487d7b2..f76d61d 100644 --- a/Tests/MomentoTests/cacheTests.swift +++ b/Tests/MomentoTests/cacheTests.swift @@ -20,101 +20,93 @@ final class cacheTests: XCTestCase { func testCacheClientValidatesCacheName() async throws { let createInvalidName = await self.cacheClient.createCache(cacheName: " ") - XCTAssertTrue( - createInvalidName is CreateCacheError, - "Unexpected response: \(createInvalidName)" - ) - let createErrorCode = (createInvalidName as! CreateCacheError).errorCode - XCTAssertEqual( - createErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(createErrorCode)" - ) - + switch createInvalidName { + case .alreadyExists(let exists): + XCTFail("expected error but got \(exists)") + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + let deleteInvalidName = await self.cacheClient.deleteCache(cacheName: " ") - XCTAssertTrue( - deleteInvalidName is DeleteCacheError, - "Unexpected response: \(deleteInvalidName)" - ) - let deleteErrorCode = (deleteInvalidName as! DeleteCacheError).errorCode - XCTAssertEqual( - deleteErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(deleteErrorCode)" - ) + switch deleteInvalidName { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } } func testCacheClientCreatesAndDeletesCache() async throws { let cacheName = generateStringWithUuid(prefix: "a-totally-new-cache") let createResult = await self.cacheClient.createCache(cacheName: cacheName) - XCTAssertTrue( - createResult is CreateCacheSuccess, - "Unexpected response: \(createResult)" - ) - + switch createResult { + case .alreadyExists(let exists): + XCTFail("expected success but got \(exists)") + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(_): + XCTAssertTrue(true) + } + let deleteResult = await self.cacheClient.deleteCache(cacheName: cacheName) - XCTAssertTrue( - deleteResult is DeleteCacheSuccess, - "Unexpected response: \(deleteResult)" - ) + switch deleteResult { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(_): + XCTAssertTrue(true) + } } func testListCaches() async throws { let listResult = await self.cacheClient.listCaches() - - // Expect list to include integration test cache + switch listResult { - case let listResult as ListCachesSuccess: - let caches = listResult.caches + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(let cacheList): XCTAssertTrue( - caches.contains(where: {item in + cacheList.caches.contains(where: {item in item.name == self.integrationTestCacheName }), - "Integration test cache not found in list caches result: \(caches)" - ) - default: - XCTAssertTrue( - listResult is ListCachesSuccess, - "Unexpected response: \(listResult)" + "Integration test cache not found in list caches result: \(cacheList)" ) } - + // Create new cache let newCacheName = generateStringWithUuid(prefix: "a-totally-different-cache") let createResult = await self.cacheClient.createCache(cacheName: newCacheName) - XCTAssertTrue( - createResult is CreateCacheSuccess, - "Unexpected response: \(createResult)" - ) - - // Expect list to include both new cache and integration test cache + switch createResult { + case .alreadyExists(let exists): + XCTFail("expected success but got \(exists)") + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(_): + XCTAssertTrue(true) + } + + // Expect list to include newly created cache let listResult2 = await self.cacheClient.listCaches() switch listResult2 { - case let listResult2 as ListCachesSuccess: - let caches = listResult2.caches - XCTAssertTrue( - caches.contains(where: {item in - item.name == self.integrationTestCacheName - }), - "Integration test cache not found in list caches result: \(caches)" - ) + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(let cacheList): XCTAssertTrue( - caches.contains(where: {item in + cacheList.caches.contains(where: {item in item.name == newCacheName - }), - "Test cache not found in list caches result: \(caches)" - ) - default: - XCTAssertTrue( - listResult is ListCachesSuccess, - "Unexpected response: \(listResult)" + }) ) } - + // Clean up additional created cache let deleteResult = await self.cacheClient.deleteCache(cacheName: newCacheName) - XCTAssertTrue( - deleteResult is DeleteCacheSuccess, - "Unexpected response: \(deleteResult)" - ) + switch deleteResult { + case .error(let err): + XCTFail("error deleting test cache: \(err)") + default: + XCTAssertTrue(true) + } } func testScalarGet() async throws { diff --git a/Tests/MomentoTests/testUtils.swift b/Tests/MomentoTests/testUtils.swift index 5b11f6f..fccbed7 100644 --- a/Tests/MomentoTests/testUtils.swift +++ b/Tests/MomentoTests/testUtils.swift @@ -27,12 +27,12 @@ func setUpIntegrationTests() async -> TestSetup { let cacheName = generateStringWithUuid(prefix: "swift-test") let result = await cacheClient.createCache(cacheName: cacheName) switch result { - case let error as CreateCacheError: - fatalError("Unable to create integration test cache: \(error.description)") - default: + case .error(let err): + fatalError("Unable to create integration test cache: \(err)") + default: break } - + return TestSetup( cacheName: cacheName, cacheClient: cacheClient, @@ -45,8 +45,11 @@ func setUpIntegrationTests() async -> TestSetup { func cleanUpIntegrationTests(cacheName: String, cacheClient: CacheClientProtocol) async { let result = await cacheClient.deleteCache(cacheName: cacheName) - if result is DeleteCacheError { - fatalError("Unable to tear down integration test setup: \(result)") + switch result { + case DeleteCacheResponse.error(let err): + fatalError("Unable to tear delete integration test cache \(cacheName): \(err)") + default: + break } } @@ -55,4 +58,3 @@ func cleanUpIntegrationTests(cacheName: String, cacheClient: CacheClientProtocol func generateStringWithUuid(prefix: String?) -> String { return "\(prefix ?? "")-\(UUID().uuidString)" } - From 7778a94bcd6a402b0b089f41def2459f1abbcfbf Mon Sep 17 00:00:00 2001 From: Pete Gautier Date: Mon, 11 Dec 2023 14:34:33 -0800 Subject: [PATCH 09/12] feat: converting list responses to enum --- Sources/Momento/CacheClient.swift | 224 +-- Sources/Momento/internal/DataClient.swift | 186 +-- .../data/list/CacheListConcatenateBack.swift | 11 - .../data/list/CacheListConcatenateFront.swift | 11 - .../cache/data/list/CacheListLength.swift | 16 - .../cache/data/list/CacheListPopBack.swift | 18 - .../cache/data/list/CacheListPopFront.swift | 19 - .../cache/data/list/CacheListPushBack.swift | 11 - .../cache/data/list/CacheListPushFront.swift | 12 - .../data/list/CacheListRemoveValue.swift | 7 - .../cache/data/list/CacheListRetain.swift | 7 - .../cache/data/list/ListConcatenateBack.swift | 14 + .../data/list/ListConcatenateFront.swift | 14 + .../{CacheListFetch.swift => ListFetch.swift} | 12 +- .../cache/data/list/ListLength.swift | 19 + .../cache/data/list/ListPopBack.swift | 21 + .../cache/data/list/ListPopFront.swift | 21 + .../cache/data/list/ListPushBack.swift | 14 + .../cache/data/list/ListPushFront.swift | 14 + .../cache/data/list/ListRemoveValue.swift | 8 + .../cache/data/list/ListRetain.swift | 8 + Tests/MomentoTests/listTests.swift | 1350 +++++++++-------- 22 files changed, 1045 insertions(+), 972 deletions(-) delete mode 100644 Sources/Momento/messages/responses/cache/data/list/CacheListConcatenateBack.swift delete mode 100644 Sources/Momento/messages/responses/cache/data/list/CacheListConcatenateFront.swift delete mode 100644 Sources/Momento/messages/responses/cache/data/list/CacheListLength.swift delete mode 100644 Sources/Momento/messages/responses/cache/data/list/CacheListPopBack.swift delete mode 100644 Sources/Momento/messages/responses/cache/data/list/CacheListPopFront.swift delete mode 100644 Sources/Momento/messages/responses/cache/data/list/CacheListPushBack.swift delete mode 100644 Sources/Momento/messages/responses/cache/data/list/CacheListPushFront.swift delete mode 100644 Sources/Momento/messages/responses/cache/data/list/CacheListRemoveValue.swift delete mode 100644 Sources/Momento/messages/responses/cache/data/list/CacheListRetain.swift create mode 100644 Sources/Momento/messages/responses/cache/data/list/ListConcatenateBack.swift create mode 100644 Sources/Momento/messages/responses/cache/data/list/ListConcatenateFront.swift rename Sources/Momento/messages/responses/cache/data/list/{CacheListFetch.swift => ListFetch.swift} (52%) create mode 100644 Sources/Momento/messages/responses/cache/data/list/ListLength.swift create mode 100644 Sources/Momento/messages/responses/cache/data/list/ListPopBack.swift create mode 100644 Sources/Momento/messages/responses/cache/data/list/ListPopFront.swift create mode 100644 Sources/Momento/messages/responses/cache/data/list/ListPushBack.swift create mode 100644 Sources/Momento/messages/responses/cache/data/list/ListPushFront.swift create mode 100644 Sources/Momento/messages/responses/cache/data/list/ListRemoveValue.swift create mode 100644 Sources/Momento/messages/responses/cache/data/list/ListRetain.swift diff --git a/Sources/Momento/CacheClient.swift b/Sources/Momento/CacheClient.swift index d1c7bcd..1344717 100644 --- a/Sources/Momento/CacheClient.swift +++ b/Sources/Momento/CacheClient.swift @@ -90,7 +90,7 @@ extension CacheClientProtocol { values: [String], truncateFrontToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListConcatenateBackResponse { + ) async -> ListConcatenateBackResponse { return await listConcatenateBack( cacheName: cacheName, listName: listName, @@ -106,7 +106,7 @@ extension CacheClientProtocol { values: [Data], truncateFrontToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListConcatenateBackResponse { + ) async -> ListConcatenateBackResponse { return await listConcatenateBack( cacheName: cacheName, listName: listName, @@ -122,7 +122,7 @@ extension CacheClientProtocol { values: [String], truncateBackToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListConcatenateFrontResponse { + ) async -> ListConcatenateFrontResponse { return await listConcatenateFront( cacheName: cacheName, listName: listName, @@ -138,7 +138,7 @@ extension CacheClientProtocol { values: [Data], truncateBackToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListConcatenateFrontResponse { + ) async -> ListConcatenateFrontResponse { return await listConcatenateFront( cacheName: cacheName, listName: listName, @@ -153,7 +153,7 @@ extension CacheClientProtocol { listName: String, startIndex: Int? = nil, endIndex: Int? = nil - ) async -> CacheListFetchResponse { + ) async -> ListFetchResponse { return await listFetch( cacheName: cacheName, listName: listName, @@ -168,7 +168,7 @@ extension CacheClientProtocol { value: String, truncateFrontToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListPushBackResponse { + ) async -> ListPushBackResponse { return await listPushBack( cacheName: cacheName, listName: listName, @@ -184,7 +184,7 @@ extension CacheClientProtocol { value: Data, truncateFrontToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListPushBackResponse { + ) async -> ListPushBackResponse { return await listPushBack( cacheName: cacheName, listName: listName, @@ -200,7 +200,7 @@ extension CacheClientProtocol { value: String, truncateBackToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListPushFrontResponse { + ) async -> ListPushFrontResponse { return await listPushFront( cacheName: cacheName, listName: listName, @@ -216,7 +216,7 @@ extension CacheClientProtocol { value: Data, truncateBackToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListPushFrontResponse { + ) async -> ListPushFrontResponse { return await listPushFront( cacheName: cacheName, listName: listName, @@ -230,7 +230,7 @@ extension CacheClientProtocol { cacheName: String, listName: String, value: String - ) async -> CacheListRemoveValueResponse { + ) async -> ListRemoveValueResponse { return await listRemoveValue(cacheName: cacheName, listName: listName, value: ScalarType.string(value)) } @@ -238,7 +238,7 @@ extension CacheClientProtocol { cacheName: String, listName: String, value: Data - ) async -> CacheListRemoveValueResponse { + ) async -> ListRemoveValueResponse { return await listRemoveValue(cacheName: cacheName, listName: listName, value: ScalarType.data(value)) } @@ -248,7 +248,7 @@ extension CacheClientProtocol { startIndex: Int? = nil, endIndex: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListRetainResponse { + ) async -> ListRetainResponse { return await listRetain( cacheName: cacheName, listName: listName, @@ -599,13 +599,13 @@ public class CacheClient: CacheClientProtocol { - values: the elements to add to the list - truncateFrontToSize: If the list exceeds this length, remove excess from the front of the list. Must be positive. - ttl: refreshes the list's TTL using the client's default if this is not supplied. - - Returns: CacheListConcatenateBackResponse representing the result of the operation. + - Returns: ListConcatenateBackResponse representing the result of the operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheListConcatenateBackError: + case let responseError as ListConcatenateBackError: // handle error - case let responseSuccess as CacheListConcatenateBackSuccess: + case let responseSuccess as ListConcatenateBackSuccess: // handle success } ``` @@ -616,7 +616,7 @@ public class CacheClient: CacheClientProtocol { values: [String], truncateFrontToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListConcatenateBackResponse { + ) async -> ListConcatenateBackResponse { return await listConcatenateBack( cacheName: cacheName, listName: listName, @@ -634,13 +634,13 @@ public class CacheClient: CacheClientProtocol { - values: the elements to add to the list - truncateFrontToSize: If the list exceeds this length, remove excess from the front of the list. Must be positive. - ttl: refreshes the list's TTL using the client's default if this is not supplied. - - Returns: CacheListConcatenateBackResponse representing the result of the operation. + - Returns: ListConcatenateBackResponse representing the result of the operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheListConcatenateBackError: + case let responseError as ListConcatenateBackError: // handle error - case let responseSuccess as CacheListConcatenateBackSuccess: + case let responseSuccess as ListConcatenateBackSuccess: // handle success } ``` @@ -651,7 +651,7 @@ public class CacheClient: CacheClientProtocol { values: [Data], truncateFrontToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListConcatenateBackResponse { + ) async -> ListConcatenateBackResponse { return await listConcatenateBack( cacheName: cacheName, listName: listName, @@ -667,7 +667,7 @@ public class CacheClient: CacheClientProtocol { values: [ScalarType], truncateFrontToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListConcatenateBackResponse { + ) async -> ListConcatenateBackResponse { do { try validateCacheName(cacheName: cacheName) try validateListName(listName: listName) @@ -675,10 +675,12 @@ public class CacheClient: CacheClientProtocol { try validateTtl(ttl: ttl?.ttlSeconds()) try validateListSize(list: values) } catch let err as SdkError { - return CacheListConcatenateBackError(error: err) + return ListConcatenateBackResponse.error(ListConcatenateBackError(error: err)) } catch { - return CacheListConcatenateBackError(error: UnknownError( - message: "unexpected error: \(error)") + return ListConcatenateBackResponse.error( + ListConcatenateBackError(error: UnknownError( + message: "unexpected error: \(error)") + ) ) } return await self.dataClient.listConcatenateBack( @@ -698,13 +700,13 @@ public class CacheClient: CacheClientProtocol { - values: the elements to add to the list - truncateBackToSize: If the list exceeds this length, remove excess from the back of the list. Must be positive. - ttl: refreshes the list's TTL using the client's default if this is not supplied. - - Returns: CacheListConcatenateFrontResponse representing the result of the operation. + - Returns: ListConcatenateFrontResponse representing the result of the operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheListConcatenateFrontError: + case let responseError as ListConcatenateFrontError: // handle error - case let responseSuccess as CacheListConcatenateFrontSuccess: + case let responseSuccess as ListConcatenateFrontSuccess: // handle success } ``` @@ -715,7 +717,7 @@ public class CacheClient: CacheClientProtocol { values: [String], truncateBackToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListConcatenateFrontResponse { + ) async -> ListConcatenateFrontResponse { return await listConcatenateFront( cacheName: cacheName, listName: listName, @@ -733,13 +735,13 @@ public class CacheClient: CacheClientProtocol { - values: the elements to add to the list - truncateBackToSize: If the list exceeds this length, remove excess from the back of the list. Must be positive. - ttl: refreshes the list's TTL using the client's default if this is not supplied. - - Returns: CacheListConcatenateFrontResponse representing the result of the operation. + - Returns: ListConcatenateFrontResponse representing the result of the operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheListConcatenateFrontError: + case let responseError as ListConcatenateFrontError: // handle error - case let responseSuccess as CacheListConcatenateFrontSuccess: + case let responseSuccess as ListConcatenateFrontSuccess: // handle success } ``` @@ -750,7 +752,7 @@ public class CacheClient: CacheClientProtocol { values: [Data], truncateBackToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListConcatenateFrontResponse { + ) async -> ListConcatenateFrontResponse { return await listConcatenateFront( cacheName: cacheName, listName: listName, @@ -766,7 +768,7 @@ public class CacheClient: CacheClientProtocol { values: [ScalarType], truncateBackToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListConcatenateFrontResponse { + ) async -> ListConcatenateFrontResponse { do { try validateCacheName(cacheName: cacheName) try validateListName(listName: listName) @@ -774,10 +776,10 @@ public class CacheClient: CacheClientProtocol { try validateTtl(ttl: ttl?.ttlSeconds()) try validateListSize(list: values) } catch let err as SdkError { - return CacheListConcatenateFrontError(error: err) + return ListConcatenateFrontResponse.error(ListConcatenateFrontError(error: err)) } catch { - return CacheListConcatenateFrontError(error: UnknownError( - message: "unexpected error: \(error)") + return ListConcatenateFrontResponse.error( + ListConcatenateFrontError(error: UnknownError(message: "unexpected error: \(error)")) ) } return await self.dataClient.listConcatenateFront( @@ -796,15 +798,15 @@ public class CacheClient: CacheClientProtocol { - listName: the list to fetch - startIndex: start index (inclusive) to begin fetching - endIndex: end index (exclusive) to stop fetching - - Returns: CacheListFetchResponse representing the result of the operation. + - Returns: ListFetchResponse representing the result of the operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheListFetchError: + case let responseError as ListFetchError: // handle error - case let responseMiss as CacheListFetchMiss: + case let responseMiss as ListFetchMiss: // list does not exist - case let responseHit as CacheListFetchHit: + case let responseHit as ListFetchHit: // list exists, handle values } ``` @@ -814,16 +816,16 @@ public class CacheClient: CacheClientProtocol { listName: String, startIndex: Int? = nil, endIndex: Int? = nil - ) async -> CacheListFetchResponse { + ) async -> ListFetchResponse { do { try validateCacheName(cacheName: cacheName) try validateListName(listName: listName) try validateListSliceStartEnd(startIndex: startIndex, endIndex: endIndex) } catch let err as SdkError { - return CacheListFetchError(error: err) + return ListFetchResponse.error(ListFetchError(error: err)) } catch { - return CacheListFetchError(error: UnknownError( - message: "unexpected error: \(error)") + return ListFetchResponse.error( + ListFetchError(error: UnknownError(message: "unexpected error: \(error)")) ) } return await self.dataClient.listFetch( @@ -839,15 +841,15 @@ public class CacheClient: CacheClientProtocol { - Parameters: - cacheName: the name of the cache containing the list - listName: the list to get the length of - - Returns: CacheListLengthResponse representing the result of the operation. + - Returns: ListLengthResponse representing the result of the operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheListLengthError: + case let responseError as ListLengthError: // handle error - case let responseMiss as CacheListLengthMiss: + case let responseMiss as ListLengthMiss: // list does not exist - case let responseHit as CacheListLengthHit: + case let responseHit as ListLengthHit: // list exists, handle length } ``` @@ -855,15 +857,15 @@ public class CacheClient: CacheClientProtocol { public func listLength( cacheName: String, listName: String - ) async -> CacheListLengthResponse { + ) async -> ListLengthResponse { do { try validateCacheName(cacheName: cacheName) try validateListName(listName: listName) } catch let err as SdkError { - return CacheListLengthError(error: err) + return ListLengthResponse.error(ListLengthError(error: err)) } catch { - return CacheListLengthError(error: UnknownError( - message: "unexpected error: \(error)") + return ListLengthResponse.error( + ListLengthError(error: UnknownError(message: "unexpected error: \(error)")) ) } return await self.dataClient.listLength(cacheName: cacheName, listName: listName) @@ -874,15 +876,15 @@ public class CacheClient: CacheClientProtocol { - Parameters: - cacheName: the name of the cache containing the list - listName: the list to get the last element from - - Returns: CacheListPopBackResponse representing the result of the operation. + - Returns: ListPopBackResponse representing the result of the operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheListPopBackError: + case let responseError as ListPopBackError: // handle error - case let responseMiss as CacheListPopBackMiss: + case let responseMiss as ListPopBackMiss: // list does not exist - case let responseHit as CacheListPopBackHit: + case let responseHit as ListPopBackHit: // list exists, handle value } ``` @@ -890,15 +892,15 @@ public class CacheClient: CacheClientProtocol { public func listPopBack( cacheName: String, listName: String - ) async -> CacheListPopBackResponse { + ) async -> ListPopBackResponse { do { try validateCacheName(cacheName: cacheName) try validateListName(listName: listName) } catch let err as SdkError { - return CacheListPopBackError(error: err) + return ListPopBackResponse.error(ListPopBackError(error: err)) } catch { - return CacheListPopBackError(error: UnknownError( - message: "unexpected error: \(error)") + return ListPopBackResponse.error( + ListPopBackError(error: UnknownError(message: "unexpected error: \(error)")) ) } return await self.dataClient.listPopBack(cacheName: cacheName, listName: listName) @@ -909,15 +911,15 @@ public class CacheClient: CacheClientProtocol { - Parameters: - cacheName: the name of the cache containing the list - listName: the list to get the first element from - - Returns: CacheListPopFrontResponse representing the result of the operation. + - Returns: ListPopFrontResponse representing the result of the operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheListPopFrontError: + case let responseError as ListPopFrontError: // handle error - case let responseMiss as CacheListPopFrontMiss: + case let responseMiss as ListPopFrontMiss: // list does not exist - case let responseHit as CacheListPopFrontHit: + case let responseHit as ListPopFrontHit: // list exists, handle value } ``` @@ -925,15 +927,15 @@ public class CacheClient: CacheClientProtocol { public func listPopFront( cacheName: String, listName: String - ) async -> CacheListPopFrontResponse { + ) async -> ListPopFrontResponse { do { try validateCacheName(cacheName: cacheName) try validateListName(listName: listName) } catch let err as SdkError { - return CacheListPopFrontError(error: err) + return ListPopFrontResponse.error(ListPopFrontError(error: err)) } catch { - return CacheListPopFrontError(error: UnknownError( - message: "unexpected error: \(error)") + return ListPopFrontResponse.error( + ListPopFrontError(error: UnknownError(message: "unexpected error: \(error)")) ) } return await self.dataClient.listPopFront(cacheName: cacheName, listName: listName) @@ -947,13 +949,13 @@ public class CacheClient: CacheClientProtocol { - value: the element to add to the list - truncateFrontToSize: If the list exceeds this length, remove excess from the front of the list. Must be positive. - ttl: refreshes the list's TTL using the client's default if this is not supplied. - - Returns: CacheListPushBackResponse representing the result of the operation. + - Returns: ListPushBackResponse representing the result of the operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheListPushBackError: + case let responseError as ListPushBackError: // handle error - case let responseSuccess as CacheListPushBackSuccess: + case let responseSuccess as ListPushBackSuccess: // handle success } ``` @@ -964,7 +966,7 @@ public class CacheClient: CacheClientProtocol { value: String, truncateFrontToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListPushBackResponse { + ) async -> ListPushBackResponse { return await listPushBack( cacheName: cacheName, listName: listName, @@ -982,13 +984,13 @@ public class CacheClient: CacheClientProtocol { - value: the element to add to the list - truncateFrontToSize: If the list exceeds this length, remove excess from the front of the list. Must be positive. - ttl: refreshes the list's TTL using the client's default if this is not supplied. - - Returns: CacheListPushBackResponse representing the result of the operation. + - Returns: ListPushBackResponse representing the result of the operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheListPushBackError: + case let responseError as ListPushBackError: // handle error - case let responseSuccess as CacheListPushBackSuccess: + case let responseSuccess as ListPushBackSuccess: // handle success } ``` @@ -999,7 +1001,7 @@ public class CacheClient: CacheClientProtocol { value: Data, truncateFrontToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListPushBackResponse { + ) async -> ListPushBackResponse { return await listPushBack( cacheName: cacheName, listName: listName, @@ -1015,17 +1017,17 @@ public class CacheClient: CacheClientProtocol { value: ScalarType, truncateFrontToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListPushBackResponse { + ) async -> ListPushBackResponse { do { try validateCacheName(cacheName: cacheName) try validateListName(listName: listName) try validateTruncateSize(size: truncateFrontToSize) try validateTtl(ttl: ttl?.ttlSeconds()) } catch let err as SdkError { - return CacheListPushBackError(error: err) + return ListPushBackResponse.error(ListPushBackError(error: err)) } catch { - return CacheListPushBackError(error: UnknownError( - message: "unexpected error: \(error)") + return ListPushBackResponse.error( + ListPushBackError(error: UnknownError(message: "unexpected error: \(error)")) ) } return await self.dataClient.listPushBack( @@ -1045,13 +1047,13 @@ public class CacheClient: CacheClientProtocol { - value: the element to add to the list - truncateBackToSize: If the list exceeds this length, remove excess from the back of the list. Must be positive. - ttl: refreshes the list's TTL using the client's default if this is not supplied. - - Returns: CacheListPushFrontResponse representing the result of the operation. + - Returns: ListPushFrontResponse representing the result of the operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheListPushFrontError: + case let responseError as ListPushFrontError: // handle error - case let responseSuccess as CacheListPushFrontSuccess: + case let responseSuccess as ListPushFrontSuccess: // handle success } ``` @@ -1062,7 +1064,7 @@ public class CacheClient: CacheClientProtocol { value: String, truncateBackToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListPushFrontResponse { + ) async -> ListPushFrontResponse { return await listPushFront( cacheName: cacheName, listName: listName, @@ -1080,13 +1082,13 @@ public class CacheClient: CacheClientProtocol { - value: the element to add to the list - truncateBackToSize: If the list exceeds this length, remove excess from the back of the list. Must be positive. - ttl: refreshes the list's TTL using the client's default if this is not supplied. - - Returns: CacheListPushFrontResponse representing the result of the operation. + - Returns: ListPushFrontResponse representing the result of the operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheListPushFrontError: + case let responseError as ListPushFrontError: // handle error - case let responseSuccess as CacheListPushFrontSuccess: + case let responseSuccess as ListPushFrontSuccess: // handle success } ``` @@ -1097,7 +1099,7 @@ public class CacheClient: CacheClientProtocol { value: Data, truncateBackToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListPushFrontResponse { + ) async -> ListPushFrontResponse { return await listPushFront( cacheName: cacheName, listName: listName, @@ -1113,17 +1115,17 @@ public class CacheClient: CacheClientProtocol { value: ScalarType, truncateBackToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListPushFrontResponse { + ) async -> ListPushFrontResponse { do { try validateCacheName(cacheName: cacheName) try validateListName(listName: listName) try validateTruncateSize(size: truncateBackToSize) try validateTtl(ttl: ttl?.ttlSeconds()) } catch let err as SdkError { - return CacheListPushFrontError(error: err) + return ListPushFrontResponse.error(ListPushFrontError(error: err)) } catch { - return CacheListPushFrontError(error: UnknownError( - message: "unexpected error: \(error)") + return ListPushFrontResponse.error( + ListPushFrontError(error: UnknownError(message: "unexpected error: \(error)")) ) } return await self.dataClient.listPushFront( @@ -1141,13 +1143,13 @@ public class CacheClient: CacheClientProtocol { - cacheName: the name of the cache containing the list - listName: the list to remove values from - value: the value to remove - - Returns: CacheListRemoveValueResponse representing the result of the operation. + - Returns: ListRemoveValueResponse representing the result of the operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheListRemoveValueError: + case let responseError as ListRemoveValueError: // handle error - case let responseSuccess as CacheListRemoveValueSuccess: + case let responseSuccess as ListRemoveValueSuccess: // handle success } ``` @@ -1156,7 +1158,7 @@ public class CacheClient: CacheClientProtocol { cacheName: String, listName: String, value: String - ) async -> CacheListRemoveValueResponse { + ) async -> ListRemoveValueResponse { return await listRemoveValue(cacheName: cacheName, listName: listName, value: ScalarType.string(value)) } @@ -1166,13 +1168,13 @@ public class CacheClient: CacheClientProtocol { - cacheName: the name of the cache containing the list - listName: the list to remove values from - value: the value to remove - - Returns: CacheListRemoveValueResponse representing the result of the operation. + - Returns: ListRemoveValueResponse representing the result of the operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheListRemoveValueError: + case let responseError as ListRemoveValueError: // handle error - case let responseSuccess as CacheListRemoveValueSuccess: + case let responseSuccess as ListRemoveValueSuccess: // handle success } ``` @@ -1181,7 +1183,7 @@ public class CacheClient: CacheClientProtocol { cacheName: String, listName: String, value: Data - ) async -> CacheListRemoveValueResponse { + ) async -> ListRemoveValueResponse { return await listRemoveValue(cacheName: cacheName, listName: listName, value: ScalarType.data(value)) } @@ -1189,15 +1191,15 @@ public class CacheClient: CacheClientProtocol { cacheName: String, listName: String, value: ScalarType - ) async -> CacheListRemoveValueResponse { + ) async -> ListRemoveValueResponse { do { try validateCacheName(cacheName: cacheName) try validateListName(listName: listName) } catch let err as SdkError { - return CacheListRemoveValueError(error: err) + return ListRemoveValueResponse.error(ListRemoveValueError(error: err)) } catch { - return CacheListRemoveValueError(error: UnknownError( - message: "unexpected error: \(error)") + return ListRemoveValueResponse.error( + ListRemoveValueError(error: UnknownError(message: "unexpected error: \(error)")) ) } return await self.dataClient.listRemoveValue( @@ -1215,13 +1217,13 @@ public class CacheClient: CacheClientProtocol { - startIndex: start index (inclusive) of the slice to retain. Defaults to the start of the list. - endIndex: end index (exclusive) of the slice to retain. Defaults to the end of the list. - ttl: refreshes the list's TTL using the client's default if this is not supplied. - - Returns: CacheListRetainResponse representing the result of the operation. + - Returns: ListRetainResponse representing the result of the operation. Pattern matching can be used to operate on the appropriate subtype. ``` switch response { - case let responseError as CacheListRetainError: + case let responseError as ListRetainError: // handle error - case let responseSuccess as CacheListRetainSuccess: + case let responseSuccess as ListRetainSuccess: // handle success } ``` @@ -1232,17 +1234,17 @@ public class CacheClient: CacheClientProtocol { startIndex: Int? = nil, endIndex: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListRetainResponse { + ) async -> ListRetainResponse { do { try validateCacheName(cacheName: cacheName) try validateListName(listName: listName) try validateListSliceStartEnd(startIndex: startIndex, endIndex: endIndex) try validateTtl(ttl: ttl?.ttlSeconds()) } catch let err as SdkError { - return CacheListRetainError(error: err) + return ListRetainResponse.error(ListRetainError(error: err)) } catch { - return CacheListRetainError(error: UnknownError( - message: "unexpected error: \(error)") + return ListRetainResponse.error( + ListRetainError(error: UnknownError(message: "unexpected error: \(error)")) ) } return await self.dataClient.listRetain( diff --git a/Sources/Momento/internal/DataClient.swift b/Sources/Momento/internal/DataClient.swift index 2659227..c7bce5f 100644 --- a/Sources/Momento/internal/DataClient.swift +++ b/Sources/Momento/internal/DataClient.swift @@ -22,7 +22,7 @@ protocol DataClientProtocol { values: [ScalarType], truncateFrontToSize: Int?, ttl: CollectionTtl? - ) async -> CacheListConcatenateBackResponse + ) async -> ListConcatenateBackResponse func listConcatenateFront( cacheName: String, @@ -30,29 +30,29 @@ protocol DataClientProtocol { values: [ScalarType], truncateBackToSize: Int?, ttl: CollectionTtl? - ) async -> CacheListConcatenateFrontResponse + ) async -> ListConcatenateFrontResponse func listFetch( cacheName: String, listName: String, startIndex: Int?, endIndex: Int? - ) async -> CacheListFetchResponse + ) async -> ListFetchResponse func listLength( cacheName: String, listName: String - ) async -> CacheListLengthResponse + ) async -> ListLengthResponse func listPopBack( cacheName: String, listName: String - ) async -> CacheListPopBackResponse + ) async -> ListPopBackResponse func listPopFront( cacheName: String, listName: String - ) async -> CacheListPopFrontResponse + ) async -> ListPopFrontResponse func listPushBack( cacheName: String, @@ -60,7 +60,7 @@ protocol DataClientProtocol { value: ScalarType, truncateFrontToSize: Int?, ttl: CollectionTtl? - ) async -> CacheListPushBackResponse + ) async -> ListPushBackResponse func listPushFront( cacheName: String, @@ -68,13 +68,13 @@ protocol DataClientProtocol { value: ScalarType, truncateBackToSize: Int?, ttl: CollectionTtl? - ) async -> CacheListPushFrontResponse + ) async -> ListPushFrontResponse func listRemoveValue( cacheName: String, listName: String, value: ScalarType - ) async -> CacheListRemoveValueResponse + ) async -> ListRemoveValueResponse func listRetain( cacheName: String, @@ -82,7 +82,7 @@ protocol DataClientProtocol { startIndex: Int?, endIndex: Int?, ttl: CollectionTtl? - ) async -> CacheListRetainResponse + ) async -> ListRetainResponse } @available(macOS 10.15, iOS 13, *) @@ -261,7 +261,7 @@ class DataClient: DataClientProtocol { values: [ScalarType], truncateFrontToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListConcatenateBackResponse { + ) async -> ListConcatenateBackResponse { var request = CacheClient__ListConcatenateBackRequest() request.listName = Data(listName.utf8) request.values = values.map(self.convertScalarTypeToData) @@ -283,16 +283,18 @@ class DataClient: DataClientProtocol { do { let result = try await call.response.get() - return CacheListConcatenateBackSuccess(length: result.listLength) + return ListConcatenateBackResponse.success(ListConcatenateBackSuccess(length: result.listLength)) } catch let err as GRPCStatus { - return CacheListConcatenateBackError(error: grpcStatusToSdkError(grpcStatus: err)) + return ListConcatenateBackResponse.error( + ListConcatenateBackError(error: grpcStatusToSdkError(grpcStatus: err)) + ) } catch let err as GRPCConnectionPoolError { - return CacheListConcatenateBackError( - error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus()) + return ListConcatenateBackResponse.error( + ListConcatenateBackError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) ) } catch { - return CacheListConcatenateBackError( - error: UnknownError(message: "unknown list concatenate back error \(error)") + return ListConcatenateBackResponse.error(ListConcatenateBackError( + error: UnknownError(message: "unknown list concatenate back error \(error)")) ) } } @@ -303,7 +305,7 @@ class DataClient: DataClientProtocol { values: [ScalarType], truncateBackToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListConcatenateFrontResponse { + ) async -> ListConcatenateFrontResponse { var request = CacheClient__ListConcatenateFrontRequest() request.listName = Data(listName.utf8) request.values = values.map(self.convertScalarTypeToData) @@ -325,16 +327,16 @@ class DataClient: DataClientProtocol { do { let result = try await call.response.get() - return CacheListConcatenateFrontSuccess(length: result.listLength) + return ListConcatenateFrontResponse.success(ListConcatenateFrontSuccess(length: result.listLength)) } catch let err as GRPCStatus { - return CacheListConcatenateFrontError(error: grpcStatusToSdkError(grpcStatus: err)) + return ListConcatenateFrontResponse.error(ListConcatenateFrontError(error: grpcStatusToSdkError(grpcStatus: err))) } catch let err as GRPCConnectionPoolError { - return CacheListConcatenateFrontError( - error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus()) + return ListConcatenateFrontResponse.error( + ListConcatenateFrontError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) ) } catch { - return CacheListConcatenateFrontError( - error: UnknownError(message: "unknown list concatenate front error \(error)") + return ListConcatenateFrontResponse.error( + ListConcatenateFrontError(error: UnknownError(message: "unknown list concatenate front error \(error)")) ) } } @@ -344,7 +346,7 @@ class DataClient: DataClientProtocol { listName: String, startIndex: Int? = nil, endIndex: Int? = nil - ) async -> CacheListFetchResponse { + ) async -> ListFetchResponse { var request = CacheClient__ListFetchRequest() request.listName = Data(listName.utf8) @@ -374,23 +376,23 @@ class DataClient: DataClientProtocol { let result = try await call.response.get() switch result.list { case .found(let foundList): - return CacheListFetchHit(values: foundList.values) + return ListFetchResponse.hit(ListFetchHit(values: foundList.values)) case .missing: - return CacheListFetchMiss() + return ListFetchResponse.miss(ListFetchMiss()) default: - return CacheListFetchError( - error: UnknownError(message: "unknown list fetch error \(result)") + return ListFetchResponse.error( + ListFetchError(error: UnknownError(message: "unknown list fetch error \(result)")) ) } } catch let err as GRPCStatus { - return CacheListFetchError(error: grpcStatusToSdkError(grpcStatus: err)) + return ListFetchResponse.error(ListFetchError(error: grpcStatusToSdkError(grpcStatus: err))) } catch let err as GRPCConnectionPoolError { - return CacheListFetchError( - error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus()) + return ListFetchResponse.error( + ListFetchError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) ) } catch { - return CacheListFetchError( - error: UnknownError(message: "unknown list fetch error \(error)") + return ListFetchResponse.error( + ListFetchError(error: UnknownError(message: "unknown list fetch error \(error)")) ) } } @@ -398,7 +400,7 @@ class DataClient: DataClientProtocol { func listLength( cacheName: String, listName: String - ) async -> CacheListLengthResponse { + ) async -> ListLengthResponse { var request = CacheClient__ListLengthRequest() request.listName = Data(listName.utf8) @@ -416,23 +418,23 @@ class DataClient: DataClientProtocol { let result = try await call.response.get() switch result.list { case .found(let foundList): - return CacheListLengthHit(length: foundList.length) + return ListLengthResponse.hit(ListLengthHit(length: foundList.length)) case .missing: - return CacheListLengthMiss() + return ListLengthResponse.miss(ListLengthMiss()) default: - return CacheListLengthError( - error: UnknownError(message: "unknown list length error \(result)") + return ListLengthResponse.error( + ListLengthError(error: UnknownError(message: "unknown list length error \(result)")) ) } } catch let err as GRPCStatus { - return CacheListLengthError(error: grpcStatusToSdkError(grpcStatus: err)) + return ListLengthResponse.error(ListLengthError(error: grpcStatusToSdkError(grpcStatus: err))) } catch let err as GRPCConnectionPoolError { - return CacheListLengthError( - error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus()) + return ListLengthResponse.error( + ListLengthError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) ) } catch { - return CacheListLengthError( - error: UnknownError(message: "unknown list length error \(error)") + return ListLengthResponse.error( + ListLengthError(error: UnknownError(message: "unknown list length error \(error)")) ) } } @@ -440,7 +442,7 @@ class DataClient: DataClientProtocol { func listPopBack( cacheName: String, listName: String - ) async -> CacheListPopBackResponse { + ) async -> ListPopBackResponse { var request = CacheClient__ListPopBackRequest() request.listName = Data(listName.utf8) @@ -458,23 +460,23 @@ class DataClient: DataClientProtocol { let result = try await call.response.get() switch result.list { case .found(let foundList): - return CacheListPopBackHit(value: foundList.back) + return ListPopBackResponse.hit(ListPopBackHit(value: foundList.back)) case .missing: - return CacheListPopBackMiss() + return ListPopBackResponse.miss(ListPopBackMiss()) default: - return CacheListPopBackError( - error: UnknownError(message: "unknown list pop back error \(result)") + return ListPopBackResponse.error( + ListPopBackError(error: UnknownError(message: "unknown list pop back error \(result)")) ) } } catch let err as GRPCStatus { - return CacheListPopBackError(error: grpcStatusToSdkError(grpcStatus: err)) + return ListPopBackResponse.error(ListPopBackError(error: grpcStatusToSdkError(grpcStatus: err))) } catch let err as GRPCConnectionPoolError { - return CacheListPopBackError( - error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus()) + return ListPopBackResponse.error( + ListPopBackError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) ) } catch { - return CacheListPopBackError( - error: UnknownError(message: "unknown list pop back error \(error)") + return ListPopBackResponse.error( + ListPopBackError(error: UnknownError(message: "unknown list pop back error \(error)")) ) } } @@ -482,7 +484,7 @@ class DataClient: DataClientProtocol { func listPopFront( cacheName: String, listName: String - ) async -> CacheListPopFrontResponse { + ) async -> ListPopFrontResponse { var request = CacheClient__ListPopFrontRequest() request.listName = Data(listName.utf8) @@ -500,23 +502,23 @@ class DataClient: DataClientProtocol { let result = try await call.response.get() switch result.list { case .found(let foundList): - return CacheListPopFrontHit(value: foundList.front) + return ListPopFrontResponse.hit(ListPopFrontHit(value: foundList.front)) case .missing: - return CacheListPopFrontMiss() + return ListPopFrontResponse.miss(ListPopFrontMiss()) default: - return CacheListPopFrontError( - error: UnknownError(message: "unknown list pop front error \(result)") + return ListPopFrontResponse.error( + ListPopFrontError(error: UnknownError(message: "unknown list pop front error \(result)")) ) } } catch let err as GRPCStatus { - return CacheListPopFrontError(error: grpcStatusToSdkError(grpcStatus: err)) + return ListPopFrontResponse.error(ListPopFrontError(error: grpcStatusToSdkError(grpcStatus: err))) } catch let err as GRPCConnectionPoolError { - return CacheListPopFrontError( - error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus()) + return ListPopFrontResponse.error( + ListPopFrontError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) ) } catch { - return CacheListPopFrontError( - error: UnknownError(message: "unknown list pop front error \(error)") + return ListPopFrontResponse.error( + ListPopFrontError(error: UnknownError(message: "unknown list pop front error \(error)")) ) } } @@ -527,7 +529,7 @@ class DataClient: DataClientProtocol { value: ScalarType, truncateFrontToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListPushBackResponse { + ) async -> ListPushBackResponse { var request = CacheClient__ListPushBackRequest() request.listName = Data(listName.utf8) request.value = self.convertScalarTypeToData(element: value) @@ -549,16 +551,16 @@ class DataClient: DataClientProtocol { do { let result = try await call.response.get() - return CacheListPushBackSuccess(length: result.listLength) + return ListPushBackResponse.success(ListPushBackSuccess(length: result.listLength)) } catch let err as GRPCStatus { - return CacheListPushBackError(error: grpcStatusToSdkError(grpcStatus: err)) + return ListPushBackResponse.error(ListPushBackError(error: grpcStatusToSdkError(grpcStatus: err))) } catch let err as GRPCConnectionPoolError { - return CacheListPushBackError( - error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus()) + return ListPushBackResponse.error( + ListPushBackError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) ) } catch { - return CacheListPushBackError( - error: UnknownError(message: "unknown list push back error \(error)") + return ListPushBackResponse.error( + ListPushBackError(error: UnknownError(message: "unknown list push back error \(error)")) ) } } @@ -569,7 +571,7 @@ class DataClient: DataClientProtocol { value: ScalarType, truncateBackToSize: Int? = nil, ttl: CollectionTtl? = nil - ) async -> CacheListPushFrontResponse { + ) async -> ListPushFrontResponse { var request = CacheClient__ListPushFrontRequest() request.listName = Data(listName.utf8) request.value = self.convertScalarTypeToData(element: value) @@ -591,16 +593,16 @@ class DataClient: DataClientProtocol { do { let result = try await call.response.get() - return CacheListPushFrontSuccess(length: result.listLength) + return ListPushFrontResponse.success(ListPushFrontSuccess(length: result.listLength)) } catch let err as GRPCStatus { - return CacheListPushFrontError(error: grpcStatusToSdkError(grpcStatus: err)) + return ListPushFrontResponse.error(ListPushFrontError(error: grpcStatusToSdkError(grpcStatus: err))) } catch let err as GRPCConnectionPoolError { - return CacheListPushFrontError( - error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus()) + return ListPushFrontResponse.error( + ListPushFrontError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) ) } catch { - return CacheListPushFrontError( - error: UnknownError(message: "unknown list push front error \(error)") + return ListPushFrontResponse.error( + ListPushFrontError(error: UnknownError(message: "unknown list push front error \(error)")) ) } } @@ -609,7 +611,7 @@ class DataClient: DataClientProtocol { cacheName: String, listName: String, value: ScalarType - ) async -> CacheListRemoveValueResponse { + ) async -> ListRemoveValueResponse { var request = CacheClient__ListRemoveRequest() request.listName = Data(listName.utf8) request.allElementsWithValue = self.convertScalarTypeToData(element: value) @@ -626,16 +628,16 @@ class DataClient: DataClientProtocol { do { _ = try await call.response.get() - return CacheListRemoveValueSuccess() + return ListRemoveValueResponse.success(ListRemoveValueSuccess()) } catch let err as GRPCStatus { - return CacheListRemoveValueError(error: grpcStatusToSdkError(grpcStatus: err)) + return ListRemoveValueResponse.error(ListRemoveValueError(error: grpcStatusToSdkError(grpcStatus: err))) } catch let err as GRPCConnectionPoolError { - return CacheListRemoveValueError( - error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus()) + return ListRemoveValueResponse.error( + ListRemoveValueError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) ) } catch { - return CacheListRemoveValueError( - error: UnknownError(message: "unknown list remove value error \(error)") + return ListRemoveValueResponse.error( + ListRemoveValueError(error: UnknownError(message: "unknown list remove value error \(error)")) ) } } @@ -646,7 +648,7 @@ class DataClient: DataClientProtocol { startIndex: Int? = nil, endIndex: Int? = nil, ttl: CollectionTtl? - ) async -> CacheListRetainResponse { + ) async -> ListRetainResponse { var request = CacheClient__ListRetainRequest() request.listName = Data(listName.utf8) @@ -678,16 +680,16 @@ class DataClient: DataClientProtocol { do { _ = try await call.response.get() - return CacheListRetainSuccess() + return ListRetainResponse.success(ListRetainSuccess()) } catch let err as GRPCStatus { - return CacheListRetainError(error: grpcStatusToSdkError(grpcStatus: err)) + return ListRetainResponse.error(ListRetainError(error: grpcStatusToSdkError(grpcStatus: err))) } catch let err as GRPCConnectionPoolError { - return CacheListRetainError( - error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus()) + return ListRetainResponse.error( + ListRetainError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) ) } catch { - return CacheListRetainError( - error: UnknownError(message: "unknown list retain error \(error)") + return ListRetainResponse.error( + ListRetainError(error: UnknownError(message: "unknown list retain error \(error)")) ) } } diff --git a/Sources/Momento/messages/responses/cache/data/list/CacheListConcatenateBack.swift b/Sources/Momento/messages/responses/cache/data/list/CacheListConcatenateBack.swift deleted file mode 100644 index 2df2121..0000000 --- a/Sources/Momento/messages/responses/cache/data/list/CacheListConcatenateBack.swift +++ /dev/null @@ -1,11 +0,0 @@ -public protocol CacheListConcatenateBackResponse {} - -public class CacheListConcatenateBackSuccess: CacheListConcatenateBackResponse { - public let listLength: UInt32 - - init(length: UInt32) { - self.listLength = length - } -} - -public class CacheListConcatenateBackError: ErrorResponseBase, CacheListConcatenateBackResponse {} diff --git a/Sources/Momento/messages/responses/cache/data/list/CacheListConcatenateFront.swift b/Sources/Momento/messages/responses/cache/data/list/CacheListConcatenateFront.swift deleted file mode 100644 index b164e52..0000000 --- a/Sources/Momento/messages/responses/cache/data/list/CacheListConcatenateFront.swift +++ /dev/null @@ -1,11 +0,0 @@ -public protocol CacheListConcatenateFrontResponse {} - -public class CacheListConcatenateFrontSuccess: CacheListConcatenateFrontResponse { - public let listLength: UInt32 - - init(length: UInt32) { - self.listLength = length - } -} - -public class CacheListConcatenateFrontError: ErrorResponseBase, CacheListConcatenateFrontResponse {} diff --git a/Sources/Momento/messages/responses/cache/data/list/CacheListLength.swift b/Sources/Momento/messages/responses/cache/data/list/CacheListLength.swift deleted file mode 100644 index 6c7c98f..0000000 --- a/Sources/Momento/messages/responses/cache/data/list/CacheListLength.swift +++ /dev/null @@ -1,16 +0,0 @@ -import Foundation - -public protocol CacheListLengthResponse {} - -public class CacheListLengthHit: CacheListLengthResponse { - public let length: UInt32 - - init(length: UInt32) { - self.length = length - } -} - -public class CacheListLengthMiss: CacheListLengthResponse {} - -public class CacheListLengthError: ErrorResponseBase, CacheListLengthResponse {} - diff --git a/Sources/Momento/messages/responses/cache/data/list/CacheListPopBack.swift b/Sources/Momento/messages/responses/cache/data/list/CacheListPopBack.swift deleted file mode 100644 index 1fc62d5..0000000 --- a/Sources/Momento/messages/responses/cache/data/list/CacheListPopBack.swift +++ /dev/null @@ -1,18 +0,0 @@ -import Foundation - -public protocol CacheListPopBackResponse {} - -public class CacheListPopBackHit: CacheListPopBackResponse { - public let valueString: String - public let valueData: Data - - init(value: Data) { - self.valueData = value - self.valueString = String(decoding: value, as: UTF8.self) - } -} - -public class CacheListPopBackMiss: CacheListPopBackResponse {} - -public class CacheListPopBackError: ErrorResponseBase, CacheListPopBackResponse {} - diff --git a/Sources/Momento/messages/responses/cache/data/list/CacheListPopFront.swift b/Sources/Momento/messages/responses/cache/data/list/CacheListPopFront.swift deleted file mode 100644 index 42736f9..0000000 --- a/Sources/Momento/messages/responses/cache/data/list/CacheListPopFront.swift +++ /dev/null @@ -1,19 +0,0 @@ -import Foundation - -public protocol CacheListPopFrontResponse {} - -public class CacheListPopFrontHit: CacheListPopFrontResponse { - public let valueString: String - public let valueData: Data - - init(value: Data) { - self.valueData = value - self.valueString = String(decoding: value, as: UTF8.self) - } -} - -public class CacheListPopFrontMiss: CacheListPopFrontResponse {} - -public class CacheListPopFrontError: ErrorResponseBase, CacheListPopFrontResponse {} - - diff --git a/Sources/Momento/messages/responses/cache/data/list/CacheListPushBack.swift b/Sources/Momento/messages/responses/cache/data/list/CacheListPushBack.swift deleted file mode 100644 index 52ee6f1..0000000 --- a/Sources/Momento/messages/responses/cache/data/list/CacheListPushBack.swift +++ /dev/null @@ -1,11 +0,0 @@ -public protocol CacheListPushBackResponse {} - -public class CacheListPushBackSuccess: CacheListPushBackResponse { - public let listLength: UInt32 - - init(length: UInt32) { - self.listLength = length - } -} - -public class CacheListPushBackError: ErrorResponseBase, CacheListPushBackResponse {} diff --git a/Sources/Momento/messages/responses/cache/data/list/CacheListPushFront.swift b/Sources/Momento/messages/responses/cache/data/list/CacheListPushFront.swift deleted file mode 100644 index 44a7c75..0000000 --- a/Sources/Momento/messages/responses/cache/data/list/CacheListPushFront.swift +++ /dev/null @@ -1,12 +0,0 @@ -public protocol CacheListPushFrontResponse {} - -public class CacheListPushFrontSuccess: CacheListPushFrontResponse { - public let listLength: UInt32 - - init(length: UInt32) { - self.listLength = length - } -} - -public class CacheListPushFrontError: ErrorResponseBase, CacheListPushFrontResponse {} - diff --git a/Sources/Momento/messages/responses/cache/data/list/CacheListRemoveValue.swift b/Sources/Momento/messages/responses/cache/data/list/CacheListRemoveValue.swift deleted file mode 100644 index 26662d7..0000000 --- a/Sources/Momento/messages/responses/cache/data/list/CacheListRemoveValue.swift +++ /dev/null @@ -1,7 +0,0 @@ -public protocol CacheListRemoveValueResponse {} - -public class CacheListRemoveValueSuccess: CacheListRemoveValueResponse {} - -public class CacheListRemoveValueError: ErrorResponseBase, CacheListRemoveValueResponse {} - - diff --git a/Sources/Momento/messages/responses/cache/data/list/CacheListRetain.swift b/Sources/Momento/messages/responses/cache/data/list/CacheListRetain.swift deleted file mode 100644 index 22c80a5..0000000 --- a/Sources/Momento/messages/responses/cache/data/list/CacheListRetain.swift +++ /dev/null @@ -1,7 +0,0 @@ -public protocol CacheListRetainResponse {} - -public class CacheListRetainSuccess: CacheListRetainResponse {} - -public class CacheListRetainError: ErrorResponseBase, CacheListRetainResponse {} - - diff --git a/Sources/Momento/messages/responses/cache/data/list/ListConcatenateBack.swift b/Sources/Momento/messages/responses/cache/data/list/ListConcatenateBack.swift new file mode 100644 index 0000000..54edc7d --- /dev/null +++ b/Sources/Momento/messages/responses/cache/data/list/ListConcatenateBack.swift @@ -0,0 +1,14 @@ +public enum ListConcatenateBackResponse { + case success(ListConcatenateBackSuccess) + case error(ListConcatenateBackError) +} + +public class ListConcatenateBackSuccess { + public let listLength: UInt32 + + init(length: UInt32) { + self.listLength = length + } +} + +public class ListConcatenateBackError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/cache/data/list/ListConcatenateFront.swift b/Sources/Momento/messages/responses/cache/data/list/ListConcatenateFront.swift new file mode 100644 index 0000000..0dda4f9 --- /dev/null +++ b/Sources/Momento/messages/responses/cache/data/list/ListConcatenateFront.swift @@ -0,0 +1,14 @@ +public enum ListConcatenateFrontResponse { + case success(ListConcatenateFrontSuccess) + case error(ListConcatenateFrontError) +} + +public class ListConcatenateFrontSuccess { + public let listLength: UInt32 + + init(length: UInt32) { + self.listLength = length + } +} + +public class ListConcatenateFrontError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/cache/data/list/CacheListFetch.swift b/Sources/Momento/messages/responses/cache/data/list/ListFetch.swift similarity index 52% rename from Sources/Momento/messages/responses/cache/data/list/CacheListFetch.swift rename to Sources/Momento/messages/responses/cache/data/list/ListFetch.swift index 9a6e888..374db1f 100644 --- a/Sources/Momento/messages/responses/cache/data/list/CacheListFetch.swift +++ b/Sources/Momento/messages/responses/cache/data/list/ListFetch.swift @@ -1,8 +1,12 @@ import Foundation -public protocol CacheListFetchResponse {} +public enum ListFetchResponse { + case hit(ListFetchHit) + case miss(ListFetchMiss) + case error(ListFetchError) +} -public class CacheListFetchHit: CacheListFetchResponse { +public class ListFetchHit { public let valueListString: [String] public let valueListData: [Data] @@ -12,6 +16,6 @@ public class CacheListFetchHit: CacheListFetchResponse { } } -public class CacheListFetchMiss: CacheListFetchResponse {} +public class ListFetchMiss {} -public class CacheListFetchError: ErrorResponseBase, CacheListFetchResponse {} +public class ListFetchError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/cache/data/list/ListLength.swift b/Sources/Momento/messages/responses/cache/data/list/ListLength.swift new file mode 100644 index 0000000..4686645 --- /dev/null +++ b/Sources/Momento/messages/responses/cache/data/list/ListLength.swift @@ -0,0 +1,19 @@ +import Foundation + +public enum ListLengthResponse { + case hit(ListLengthHit) + case miss(ListLengthMiss) + case error(ListLengthError) +} + +public class ListLengthHit { + public let length: UInt32 + + init(length: UInt32) { + self.length = length + } +} + +public class ListLengthMiss {} + +public class ListLengthError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/cache/data/list/ListPopBack.swift b/Sources/Momento/messages/responses/cache/data/list/ListPopBack.swift new file mode 100644 index 0000000..06f9f50 --- /dev/null +++ b/Sources/Momento/messages/responses/cache/data/list/ListPopBack.swift @@ -0,0 +1,21 @@ +import Foundation + +public enum ListPopBackResponse { + case hit(ListPopBackHit) + case miss(ListPopBackMiss) + case error(ListPopBackError) +} + +public class ListPopBackHit { + public let valueString: String + public let valueData: Data + + init(value: Data) { + self.valueData = value + self.valueString = String(decoding: value, as: UTF8.self) + } +} + +public class ListPopBackMiss {} + +public class ListPopBackError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/cache/data/list/ListPopFront.swift b/Sources/Momento/messages/responses/cache/data/list/ListPopFront.swift new file mode 100644 index 0000000..dfa1d7a --- /dev/null +++ b/Sources/Momento/messages/responses/cache/data/list/ListPopFront.swift @@ -0,0 +1,21 @@ +import Foundation + +public enum ListPopFrontResponse { + case hit(ListPopFrontHit) + case miss(ListPopFrontMiss) + case error(ListPopFrontError) +} + +public class ListPopFrontHit { + public let valueString: String + public let valueData: Data + + init(value: Data) { + self.valueData = value + self.valueString = String(decoding: value, as: UTF8.self) + } +} + +public class ListPopFrontMiss {} + +public class ListPopFrontError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/cache/data/list/ListPushBack.swift b/Sources/Momento/messages/responses/cache/data/list/ListPushBack.swift new file mode 100644 index 0000000..09e3604 --- /dev/null +++ b/Sources/Momento/messages/responses/cache/data/list/ListPushBack.swift @@ -0,0 +1,14 @@ +public enum ListPushBackResponse { + case success(ListPushBackSuccess) + case error(ListPushBackError) +} + +public class ListPushBackSuccess { + public let listLength: UInt32 + + init(length: UInt32) { + self.listLength = length + } +} + +public class ListPushBackError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/cache/data/list/ListPushFront.swift b/Sources/Momento/messages/responses/cache/data/list/ListPushFront.swift new file mode 100644 index 0000000..4dfae38 --- /dev/null +++ b/Sources/Momento/messages/responses/cache/data/list/ListPushFront.swift @@ -0,0 +1,14 @@ +public enum ListPushFrontResponse { + case success(ListPushFrontSuccess) + case error(ListPushFrontError) +} + +public class ListPushFrontSuccess { + public let listLength: UInt32 + + init(length: UInt32) { + self.listLength = length + } +} + +public class ListPushFrontError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/cache/data/list/ListRemoveValue.swift b/Sources/Momento/messages/responses/cache/data/list/ListRemoveValue.swift new file mode 100644 index 0000000..c8f6d79 --- /dev/null +++ b/Sources/Momento/messages/responses/cache/data/list/ListRemoveValue.swift @@ -0,0 +1,8 @@ +public enum ListRemoveValueResponse { + case success(ListRemoveValueSuccess) + case error(ListRemoveValueError) +} + +public class ListRemoveValueSuccess {} + +public class ListRemoveValueError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/cache/data/list/ListRetain.swift b/Sources/Momento/messages/responses/cache/data/list/ListRetain.swift new file mode 100644 index 0000000..c623d68 --- /dev/null +++ b/Sources/Momento/messages/responses/cache/data/list/ListRetain.swift @@ -0,0 +1,8 @@ +public enum ListRetainResponse { + case success(ListRetainSuccess) + case error(ListRetainError) +} + +public class ListRetainSuccess {} + +public class ListRetainError: ErrorResponseBase {} diff --git a/Tests/MomentoTests/listTests.swift b/Tests/MomentoTests/listTests.swift index fdb49aa..6cf8dfc 100644 --- a/Tests/MomentoTests/listTests.swift +++ b/Tests/MomentoTests/listTests.swift @@ -27,32 +27,26 @@ final class listTests: XCTestCase { listName: listName, values: ["abc", "xyz"] ) - XCTAssertTrue( - invalidCacheName is CacheListConcatenateBackError, - "Unexpected response: \(invalidCacheName)" - ) - let invalidCacheNameCode = (invalidCacheName as! CacheListConcatenateBackError).errorCode - XCTAssertEqual( - invalidCacheNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidCacheNameCode)" - ) - + switch invalidCacheName { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks list name let invalidListName = await self.cacheClient.listConcatenateBack( cacheName: self.integrationTestCacheName, listName: " ", values: ["abc", "xyz"] ) - XCTAssertTrue( - invalidListName is CacheListConcatenateBackError, - "Unexpected response: \(invalidListName)" - ) - let invalidListNameCode = (invalidListName as! CacheListConcatenateBackError).errorCode - XCTAssertEqual( - invalidListNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidListNameCode)" - ) - + switch invalidListName { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks truncateFrontToSize let invalidTruncateSize = await self.cacheClient.listConcatenateBack( cacheName: self.integrationTestCacheName, @@ -60,16 +54,13 @@ final class listTests: XCTestCase { values: ["abc", "xyz"], truncateFrontToSize: -5 ) - XCTAssertTrue( - invalidTruncateSize is CacheListConcatenateBackError, - "Unexpected response: \(invalidTruncateSize)" - ) - let invalidTruncateSizeCode = (invalidTruncateSize as! CacheListConcatenateBackError).errorCode - XCTAssertEqual( - invalidTruncateSizeCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidTruncateSizeCode)" - ) - + switch invalidTruncateSize { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks ttl let invalidTtl = await self.cacheClient.listConcatenateBack( cacheName: self.integrationTestCacheName, @@ -77,15 +68,12 @@ final class listTests: XCTestCase { values: ["abc", "xyz"], ttl: CollectionTtl(ttlSeconds: -5) ) - XCTAssertTrue( - invalidTtl is CacheListConcatenateBackError, - "Unexpected response: \(invalidTtl)" - ) - let invalidTtlCode = (invalidTtl as! CacheListConcatenateBackError).errorCode - XCTAssertEqual( - invalidTtlCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidTtlCode)" - ) + switch invalidTtl { + case .success(let success): + XCTFail("expected error but gor \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } } func testConcatBack() async throws { @@ -97,22 +85,26 @@ final class listTests: XCTestCase { listName: stringListName, values: stringValues ) - XCTAssertTrue( - concatStrings is CacheListConcatenateBackSuccess, - "Unexpected response: \(concatStrings)" - ) - XCTAssertEqual((concatStrings as! CacheListConcatenateBackSuccess).listLength, 3) + switch concatStrings { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(let success): + XCTAssertEqual(Int(stringValues.count), Int(success.listLength)) + } + let fetchStringList = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: stringListName ) - XCTAssertTrue( - fetchStringList is CacheListFetchHit, - "Unexpected response: \(fetchStringList)" - ) - let fetchedStringList = (fetchStringList as! CacheListFetchHit).valueListString - XCTAssertEqual(fetchedStringList, stringValues) - + switch fetchStringList { + case .error(let err): + XCTFail("expected success but got \(err)") + case .miss(let miss): + XCTFail("expected success but got \(miss)") + case .hit(let hit): + XCTAssertEqual(stringValues, hit.valueListString) + } + // Successfully concatenates data values to the back let dataListName = generateStringWithUuid(prefix: "swift-list-concat-back-data") let dataValues = [Data("abc".utf8), Data("lmn".utf8), Data("xyz".utf8)] @@ -121,22 +113,26 @@ final class listTests: XCTestCase { listName: dataListName, values: dataValues ) - XCTAssertTrue( - concatData is CacheListConcatenateBackSuccess, - "Unexpected response: \(concatData)" - ) - XCTAssertEqual((concatData as! CacheListConcatenateBackSuccess).listLength, 3) + switch concatData { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(let success): + XCTAssertEqual(Int(stringValues.count), Int(success.listLength)) + } + let fetchDataList = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: dataListName ) - XCTAssertTrue( - fetchDataList is CacheListFetchHit, - "Unexpected response: \(fetchDataList)" - ) - let fetchedDataList = (fetchDataList as! CacheListFetchHit).valueListData - XCTAssertEqual(fetchedDataList, dataValues) - + switch fetchDataList { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(dataValues, hit.valueListData) + } + // Does not concatenate empty list to the back let emptyStringList: [String] = [] let emptyList = await self.cacheClient.listConcatenateBack( @@ -144,15 +140,12 @@ final class listTests: XCTestCase { listName: stringListName, values: emptyStringList ) - XCTAssertTrue( - emptyList is CacheListConcatenateBackError, - "Unexpected response: \(emptyList)" - ) - let emptyListCode = (emptyList as! CacheListConcatenateBackError).errorCode - XCTAssertEqual( - emptyListCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(emptyListCode)" - ) + switch emptyList { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } } func testConcatFrontValidatesParameters() async throws { @@ -164,32 +157,26 @@ final class listTests: XCTestCase { listName: listName, values: ["abc", "xyz"] ) - XCTAssertTrue( - invalidCacheName is CacheListConcatenateFrontError, - "Unexpected response: \(invalidCacheName)" - ) - let invalidCacheNameCode = (invalidCacheName as! CacheListConcatenateFrontError).errorCode - XCTAssertEqual( - invalidCacheNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidCacheNameCode)" - ) - + switch invalidCacheName { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks list name let invalidListName = await self.cacheClient.listConcatenateFront( cacheName: self.integrationTestCacheName, listName: " ", values: ["abc", "xyz"] ) - XCTAssertTrue( - invalidListName is CacheListConcatenateFrontError, - "Unexpected response: \(invalidListName)" - ) - let invalidListNameCode = (invalidListName as! CacheListConcatenateFrontError).errorCode - XCTAssertEqual( - invalidListNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidListNameCode)" - ) - + switch invalidListName { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks truncateFrontToSize let invalidTruncateSize = await self.cacheClient.listConcatenateFront( cacheName: self.integrationTestCacheName, @@ -197,16 +184,13 @@ final class listTests: XCTestCase { values: ["abc", "xyz"], truncateBackToSize: -5 ) - XCTAssertTrue( - invalidTruncateSize is CacheListConcatenateFrontError, - "Unexpected response: \(invalidTruncateSize)" - ) - let invalidTruncateSizeCode = (invalidTruncateSize as! CacheListConcatenateFrontError).errorCode - XCTAssertEqual( - invalidTruncateSizeCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidTruncateSizeCode)" - ) - + switch invalidTruncateSize { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks ttl let invalidTtl = await self.cacheClient.listConcatenateFront( cacheName: self.integrationTestCacheName, @@ -214,19 +198,16 @@ final class listTests: XCTestCase { values: ["abc", "xyz"], ttl: CollectionTtl(ttlSeconds: -5) ) - XCTAssertTrue( - invalidTtl is CacheListConcatenateFrontError, - "Unexpected response: \(invalidTtl)" - ) - let invalidTtlCode = (invalidTtl as! CacheListConcatenateFrontError).errorCode - XCTAssertEqual( - invalidTtlCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidTtlCode)" - ) + switch invalidTtl { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } } func testConcatFront() async throws { - // Successfully concatenates string values to the back + // Successfully concatenates string values to the front let stringListName = generateStringWithUuid(prefix: "swift-list-concat-front-string") let stringValues = ["abc", "lmn", "xyz"] let concatStrings = await self.cacheClient.listConcatenateFront( @@ -234,22 +215,26 @@ final class listTests: XCTestCase { listName: stringListName, values: stringValues ) - XCTAssertTrue( - concatStrings is CacheListConcatenateFrontSuccess, - "Unexpected response: \(concatStrings)" - ) - XCTAssertEqual((concatStrings as! CacheListConcatenateFrontSuccess).listLength, 3) + switch concatStrings { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(let success): + XCTAssertEqual(Int(stringValues.count), Int(success.listLength)) + } + let fetchStringList = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: stringListName ) - XCTAssertTrue( - fetchStringList is CacheListFetchHit, - "Unexpected response: \(fetchStringList)" - ) - let fetchedStringList = (fetchStringList as! CacheListFetchHit).valueListString - XCTAssertEqual(fetchedStringList, stringValues) - + switch fetchStringList { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(stringValues, hit.valueListString) + } + // Successfully concatenates data values to the back let dataListName = generateStringWithUuid(prefix: "swift-list-concat-back-data") let dataValues = [Data("abc".utf8), Data("lmn".utf8), Data("xyz".utf8)] @@ -258,22 +243,26 @@ final class listTests: XCTestCase { listName: dataListName, values: dataValues ) - XCTAssertTrue( - concatData is CacheListConcatenateFrontSuccess, - "Unexpected response: \(concatData)" - ) - XCTAssertEqual((concatData as! CacheListConcatenateFrontSuccess).listLength, 3) + switch concatData { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(let success): + XCTAssertEqual(Int(dataValues.count), Int(success.listLength)) + } + let fetchDataList = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: dataListName ) - XCTAssertTrue( - fetchDataList is CacheListFetchHit, - "Unexpected response: \(fetchDataList)" - ) - let fetchedDataList = (fetchDataList as! CacheListFetchHit).valueListData - XCTAssertEqual(fetchedDataList, dataValues) - + switch fetchDataList { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(dataValues, hit.valueListData) + } + // Does not concatenate empty list to the back let emptyStringList: [String] = [] let emptyList = await self.cacheClient.listConcatenateFront( @@ -281,15 +270,12 @@ final class listTests: XCTestCase { listName: stringListName, values: emptyStringList ) - XCTAssertTrue( - emptyList is CacheListConcatenateFrontError, - "Unexpected response: \(emptyList)" - ) - let emptyListCode = (emptyList as! CacheListConcatenateFrontError).errorCode - XCTAssertEqual( - emptyListCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(emptyListCode)" - ) + switch emptyList { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } } func testFetchValidatesParameters() async throws { @@ -300,31 +286,29 @@ final class listTests: XCTestCase { cacheName: " ", listName: listName ) - XCTAssertTrue( - invalidCacheName is CacheListFetchError, - "Unexpected response: \(invalidCacheName)" - ) - let invalidCacheNameCode = (invalidCacheName as! CacheListFetchError).errorCode - XCTAssertEqual( - invalidCacheNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidCacheNameCode)" - ) - + switch invalidCacheName { + case .hit(let hit): + XCTFail("expected error but got \(hit)") + case .miss(let miss): + XCTFail("expected error but got \(miss)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks list name let invalidListName = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: " " ) - XCTAssertTrue( - invalidListName is CacheListFetchError, - "Unexpected response: \(invalidListName)" - ) - let invalidListNameCode = (invalidListName as! CacheListFetchError).errorCode - XCTAssertEqual( - invalidListNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidListNameCode)" - ) - + switch invalidListName { + case .hit(let hit): + XCTFail("expected error but got \(hit)") + case .miss(let miss): + XCTFail("expected error but got \(miss)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks start and end index range let invalidSlice = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, @@ -332,15 +316,14 @@ final class listTests: XCTestCase { startIndex: 2, endIndex: 1 ) - XCTAssertTrue( - invalidSlice is CacheListFetchError, - "Unexpected response: \(invalidSlice)" - ) - let invalidSliceCode = (invalidSlice as! CacheListFetchError).errorCode - XCTAssertEqual( - invalidSliceCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidSliceCode)" - ) + switch invalidSlice { + case .hit(let hit): + XCTFail("expected error but got \(hit)") + case .miss(let miss): + XCTFail("expected error but got \(miss)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } } func testListFetch() async throws { @@ -352,23 +335,27 @@ final class listTests: XCTestCase { listName: listName, values: stringValues ) - XCTAssertTrue( - concatStrings is CacheListConcatenateBackSuccess, - "Unexpected response: \(concatStrings)" - ) - + switch concatStrings { + case .error(let err): + XCTFail("expected success but got \(err)") + default: + break + } + // Fetches full list when no slice specified let fullList = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: listName ) - XCTAssertTrue( - fullList is CacheListFetchHit, - "Unexpected response: \(fullList)" - ) - let fetchedFullList = (fullList as! CacheListFetchHit).valueListString - XCTAssertEqual(fetchedFullList, stringValues) - + switch fullList { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(stringValues, hit.valueListString) + } + // Fetches positive slice range let positiveSliceList = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, @@ -376,13 +363,15 @@ final class listTests: XCTestCase { startIndex: 2, endIndex: 5 ) - XCTAssertTrue( - positiveSliceList is CacheListFetchHit, - "Unexpected response: \(positiveSliceList)" - ) - let fetchedPositiveSliceList = (positiveSliceList as! CacheListFetchHit).valueListString - XCTAssertEqual(fetchedPositiveSliceList, Array(stringValues[2...4])) - + switch positiveSliceList { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(Array(stringValues[2...4]), hit.valueListString) + } + // Fetches negative slice range let negativeSliceList = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, @@ -390,13 +379,15 @@ final class listTests: XCTestCase { startIndex: 2, endIndex: -2 ) - XCTAssertTrue( - negativeSliceList is CacheListFetchHit, - "Unexpected response: \(negativeSliceList)" - ) - let fetchedNegativeSliceList = (negativeSliceList as! CacheListFetchHit).valueListString - XCTAssertEqual(fetchedNegativeSliceList, Array(stringValues[2...4])) - + switch negativeSliceList { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(Array(stringValues[2...4]), hit.valueListString) + } + // Fetches slice with nil start index let nilStart = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, @@ -404,13 +395,15 @@ final class listTests: XCTestCase { startIndex: nil, endIndex: 4 ) - XCTAssertTrue( - nilStart is CacheListFetchHit, - "Unexpected response: \(nilStart)" - ) - let fetchedNilStart = (nilStart as! CacheListFetchHit).valueListString - XCTAssertEqual(fetchedNilStart, Array(stringValues[0...3])) - + switch nilStart { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(Array(stringValues[0...3]), hit.valueListString) + } + // Fetches slice with nil end index let nilEnd = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, @@ -418,12 +411,14 @@ final class listTests: XCTestCase { startIndex: 3, endIndex: nil ) - XCTAssertTrue( - nilEnd is CacheListFetchHit, - "Unexpected response: \(nilEnd)" - ) - let fetchedNilEnd = (nilEnd as! CacheListFetchHit).valueListString - XCTAssertEqual(fetchedNilEnd, Array(stringValues[3...])) + switch nilEnd { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(Array(stringValues[3...]), hit.valueListString) + } } func testLengthValidatesParameters() async throws { @@ -434,78 +429,85 @@ final class listTests: XCTestCase { cacheName: " ", listName: listName ) - XCTAssertTrue( - invalidCacheName is CacheListLengthError, - "Unexpected response: \(invalidCacheName)" - ) - let invalidCacheNameCode = (invalidCacheName as! CacheListLengthError).errorCode - XCTAssertEqual( - invalidCacheNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidCacheNameCode)" - ) - + switch invalidCacheName { + case .hit(let hit): + XCTFail("expected error but got \(hit)") + case .miss(let miss): + XCTFail("expected error but got \(miss)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks list name let invalidListName = await self.cacheClient.listLength( cacheName: self.integrationTestCacheName, listName: " " ) - XCTAssertTrue( - invalidListName is CacheListLengthError, - "Unexpected response: \(invalidListName)" - ) - let invalidListNameCode = (invalidListName as! CacheListLengthError).errorCode - XCTAssertEqual( - invalidListNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidListNameCode)" - ) + switch invalidListName { + case .hit(let hit): + XCTFail("expected error but got \(hit)") + case .miss(let miss): + XCTFail("expected error but got \(miss)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } } func testListLength() async throws { let listName = generateStringWithUuid(prefix: "swift-list-length") let stringValues = ["apple", "banana", "carrot", "durian", "eggplant", "fig", "guava"] - + let frontSlice = Array(stringValues[0...3]) + let backSlice = Array(stringValues[4...]) + let insert1 = await self.cacheClient.listConcatenateBack( cacheName: self.integrationTestCacheName, listName: listName, - values: Array(stringValues[0...3]) + values: frontSlice ) - XCTAssertTrue( - insert1 is CacheListConcatenateBackSuccess, - "Unexpected response: \(insert1)" - ) - + switch insert1 { + case .error(let err): + XCTFail("expected succes but got \(err)") + default: + break + } + let fetchLength1 = await self.cacheClient.listLength( cacheName: self.integrationTestCacheName, listName: listName ) - XCTAssertTrue( - fetchLength1 is CacheListLengthHit, - "Unexpected response: \(fetchLength1)" - ) - let length1 = (fetchLength1 as! CacheListLengthHit).length - XCTAssertEqual(length1, 4) - + switch fetchLength1 { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(Int(frontSlice.count), Int(hit.length)) + } let insert2 = await self.cacheClient.listConcatenateBack( cacheName: self.integrationTestCacheName, listName: listName, - values: Array(stringValues[4...]) - ) - XCTAssertTrue( - insert2 is CacheListConcatenateBackSuccess, - "Unexpected response: \(insert2)" + values: backSlice ) - + switch insert2 { + case .error(let err): + XCTFail("expected succes but got \(err)") + default: + break + } + let fetchLength2 = await self.cacheClient.listLength( cacheName: self.integrationTestCacheName, listName: listName ) - XCTAssertTrue( - fetchLength2 is CacheListLengthHit, - "Unexpected response: \(fetchLength2)" - ) - let length2 = (fetchLength2 as! CacheListLengthHit).length - XCTAssertEqual(length2, 7) + switch fetchLength2 { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(Int(stringValues.count), Int(hit.length)) + } } func testPopBackValidatesParameters() async throws { @@ -516,30 +518,28 @@ final class listTests: XCTestCase { cacheName: " ", listName: listName ) - XCTAssertTrue( - invalidCacheName is CacheListPopBackError, - "Unexpected response: \(invalidCacheName)" - ) - let invalidCacheNameCode = (invalidCacheName as! CacheListPopBackError).errorCode - XCTAssertEqual( - invalidCacheNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidCacheNameCode)" - ) - + switch invalidCacheName { + case .hit(let hit): + XCTFail("expected error but got \(hit)") + case .miss(let miss): + XCTFail("expected error but got \(miss)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks list name let invalidListName = await self.cacheClient.listPopBack( cacheName: self.integrationTestCacheName, listName: " " ) - XCTAssertTrue( - invalidListName is CacheListPopBackError, - "Unexpected response: \(invalidListName)" - ) - let invalidListNameCode = (invalidListName as! CacheListPopBackError).errorCode - XCTAssertEqual( - invalidListNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidListNameCode)" - ) + switch invalidListName { + case .hit(let hit): + XCTFail("expected error but got \(hit)") + case .miss(let miss): + XCTFail("expected error but got \(miss)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } } func testPopBack() async throws { @@ -551,43 +551,53 @@ final class listTests: XCTestCase { listName: listName, values: stringValues ) - XCTAssertTrue( - concatStrings is CacheListConcatenateBackSuccess, - "Unexpected response: \(concatStrings)" - ) - + switch concatStrings { + case .error(let err): + XCTFail("expected succes but got \(err)") + default: + break + } + // Expecting to receive values in back to front order let pop1 = await self.cacheClient.listPopBack( cacheName: self.integrationTestCacheName, listName: listName ) - XCTAssertTrue( - pop1 is CacheListPopBackHit, - "Unexpected response: \(pop1)" - ) - let popValue1 = (pop1 as! CacheListPopBackHit).valueString - XCTAssertEqual(popValue1, "banana") - + switch pop1 { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(stringValues[1], hit.valueString) + } + let pop2 = await self.cacheClient.listPopBack( cacheName: self.integrationTestCacheName, listName: listName ) - XCTAssertTrue( - pop2 is CacheListPopBackHit, - "Unexpected response: \(pop2)" - ) - let popValue2 = (pop2 as! CacheListPopBackHit).valueString - XCTAssertEqual(popValue2, "apple") - + switch pop2 { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(stringValues[0], hit.valueString) + } + // Miss when popping from empty list let pop3 = await self.cacheClient.listPopBack( cacheName: self.integrationTestCacheName, listName: listName ) - XCTAssertTrue( - pop3 is CacheListPopBackMiss, - "Unexpected response: \(pop3)" - ) + switch pop3 { + case .error(let err): + XCTFail("expected miss but got \(err)") + case .hit(let hit): + XCTFail("expected miss but got \(hit)") + case .miss(_): + XCTAssertTrue(true) + } } func testPopFrontValidatesParameters() async throws { @@ -598,30 +608,28 @@ final class listTests: XCTestCase { cacheName: " ", listName: listName ) - XCTAssertTrue( - invalidCacheName is CacheListPopFrontError, - "Unexpected response: \(invalidCacheName)" - ) - let invalidCacheNameCode = (invalidCacheName as! CacheListPopFrontError).errorCode - XCTAssertEqual( - invalidCacheNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidCacheNameCode)" - ) - + switch invalidCacheName { + case .hit(let hit): + XCTFail("expected error but got \(hit)") + case .miss(let miss): + XCTFail("expected error but got \(miss)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks list name let invalidListName = await self.cacheClient.listPopFront( cacheName: self.integrationTestCacheName, listName: " " ) - XCTAssertTrue( - invalidListName is CacheListPopFrontError, - "Unexpected response: \(invalidListName)" - ) - let invalidListNameCode = (invalidListName as! CacheListPopFrontError).errorCode - XCTAssertEqual( - invalidListNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidListNameCode)" - ) + switch invalidListName { + case .hit(let hit): + XCTFail("expected error but got \(hit)") + case .miss(let miss): + XCTFail("expected error but got \(miss)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } } func testPopFront() async throws { @@ -633,43 +641,53 @@ final class listTests: XCTestCase { listName: listName, values: stringValues ) - XCTAssertTrue( - concatStrings is CacheListConcatenateBackSuccess, - "Unexpected response: \(concatStrings)" - ) - + switch concatStrings { + case .error(let err): + XCTFail("expected succes but got \(err)") + default: + break + } + // Expecting to receive values in front to back order let pop1 = await self.cacheClient.listPopFront( cacheName: self.integrationTestCacheName, listName: listName ) - XCTAssertTrue( - pop1 is CacheListPopFrontHit, - "Unexpected response: \(pop1)" - ) - let popValue1 = (pop1 as! CacheListPopFrontHit).valueString - XCTAssertEqual(popValue1, "apple") - + switch pop1 { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(stringValues[0], hit.valueString) + } + let pop2 = await self.cacheClient.listPopFront( cacheName: self.integrationTestCacheName, listName: listName ) - XCTAssertTrue( - pop2 is CacheListPopFrontHit, - "Unexpected response: \(pop2)" - ) - let popValue2 = (pop2 as! CacheListPopFrontHit).valueString - XCTAssertEqual(popValue2, "banana") - + switch pop2 { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(stringValues[1], hit.valueString) + } + // Miss when popping from empty list let pop3 = await self.cacheClient.listPopFront( cacheName: self.integrationTestCacheName, listName: listName ) - XCTAssertTrue( - pop3 is CacheListPopFrontMiss, - "Unexpected response: \(pop3)" - ) + switch pop3 { + case .error(let err): + XCTFail("expected miss but got \(err)") + case .miss(_): + XCTAssertTrue(true) + case .hit(let hit): + XCTFail("expected miss but got \(hit)") + } } func testPushBackValidatesParameters() async throws { @@ -681,32 +699,26 @@ final class listTests: XCTestCase { listName: listName, value: "abc" ) - XCTAssertTrue( - invalidCacheName is CacheListPushBackError, - "Unexpected response: \(invalidCacheName)" - ) - let invalidCacheNameCode = (invalidCacheName as! CacheListPushBackError).errorCode - XCTAssertEqual( - invalidCacheNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidCacheNameCode)" - ) - + switch invalidCacheName { + case .success(let success): + XCTFail("expecgted error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks list name let invalidListName = await self.cacheClient.listPushBack( cacheName: self.integrationTestCacheName, listName: " ", value: "abc" ) - XCTAssertTrue( - invalidListName is CacheListPushBackError, - "Unexpected response: \(invalidListName)" - ) - let invalidListNameCode = (invalidListName as! CacheListPushBackError).errorCode - XCTAssertEqual( - invalidListNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidListNameCode)" - ) - + switch invalidListName { + case .success(let success): + XCTFail("expecgted error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks truncateFrontToSize let invalidTruncateSize = await self.cacheClient.listPushBack( cacheName: self.integrationTestCacheName, @@ -714,16 +726,13 @@ final class listTests: XCTestCase { value: "abc", truncateFrontToSize: -5 ) - XCTAssertTrue( - invalidTruncateSize is CacheListPushBackError, - "Unexpected response: \(invalidTruncateSize)" - ) - let invalidTruncateSizeCode = (invalidTruncateSize as! CacheListPushBackError).errorCode - XCTAssertEqual( - invalidTruncateSizeCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidTruncateSizeCode)" - ) - + switch invalidTruncateSize { + case .success(let success): + XCTFail("expecgted error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks ttl let invalidTtl = await self.cacheClient.listPushBack( cacheName: self.integrationTestCacheName, @@ -731,15 +740,12 @@ final class listTests: XCTestCase { value: "abc", ttl: CollectionTtl(ttlSeconds: -5) ) - XCTAssertTrue( - invalidTtl is CacheListPushBackError, - "Unexpected response: \(invalidTtl)" - ) - let invalidTtlCode = (invalidTtl as! CacheListPushBackError).errorCode - XCTAssertEqual( - invalidTtlCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidTtlCode)" - ) + switch invalidTtl { + case .success(let success): + XCTFail("expecgted error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } } func testPushBack() async throws { @@ -753,22 +759,27 @@ final class listTests: XCTestCase { value: value, truncateFrontToSize: 2 ) - XCTAssertTrue( - pushBack is CacheListPushBackSuccess, - "Unexpected response: \(pushBack)" - ) + switch pushBack { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(_): + XCTAssertTrue(true) + } } + let fetchStringList = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: stringListName ) - XCTAssertTrue( - fetchStringList is CacheListFetchHit, - "Unexpected response: \(fetchStringList)" - ) - let fetchedStringList = (fetchStringList as! CacheListFetchHit).valueListString - XCTAssertEqual(fetchedStringList, Array(stringValues[1...2])) - + switch fetchStringList { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(Array(stringValues[1...2]), hit.valueListString) + } + // Pushes data values let dataListName = generateStringWithUuid(prefix: "swift-list-push-back-data") let dataValues = [Data("abc".utf8), Data("lmn".utf8), Data("xyz".utf8)] @@ -779,21 +790,25 @@ final class listTests: XCTestCase { value: value, truncateFrontToSize: 2 ) - XCTAssertTrue( - pushBack is CacheListPushBackSuccess, - "Unexpected response: \(pushBack)" - ) + switch pushBack { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(_): + XCTAssertTrue(true) + } } let fetchDataList = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: dataListName ) - XCTAssertTrue( - fetchDataList is CacheListFetchHit, - "Unexpected response: \(fetchStringList)" - ) - let fetchedDataList = (fetchDataList as! CacheListFetchHit).valueListData - XCTAssertEqual(fetchedDataList, Array(dataValues[1...2])) + switch fetchDataList { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(Array(dataValues[1...2]), hit.valueListData) + } } func testPushFrontValidatesParameters() async throws { @@ -805,32 +820,26 @@ final class listTests: XCTestCase { listName: listName, value: "abc" ) - XCTAssertTrue( - invalidCacheName is CacheListPushFrontError, - "Unexpected response: \(invalidCacheName)" - ) - let invalidCacheNameCode = (invalidCacheName as! CacheListPushFrontError).errorCode - XCTAssertEqual( - invalidCacheNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidCacheNameCode)" - ) - + switch invalidCacheName { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks list name let invalidListName = await self.cacheClient.listPushFront( cacheName: self.integrationTestCacheName, listName: " ", value: "abc" ) - XCTAssertTrue( - invalidListName is CacheListPushFrontError, - "Unexpected response: \(invalidListName)" - ) - let invalidListNameCode = (invalidListName as! CacheListPushFrontError).errorCode - XCTAssertEqual( - invalidListNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidListNameCode)" - ) - + switch invalidListName { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks truncateFrontToSize let invalidTruncateSize = await self.cacheClient.listPushFront( cacheName: self.integrationTestCacheName, @@ -838,16 +847,13 @@ final class listTests: XCTestCase { value: "abc", truncateBackToSize: -5 ) - XCTAssertTrue( - invalidTruncateSize is CacheListPushFrontError, - "Unexpected response: \(invalidTruncateSize)" - ) - let invalidTruncateSizeCode = (invalidTruncateSize as! CacheListPushFrontError).errorCode - XCTAssertEqual( - invalidTruncateSizeCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidTruncateSizeCode)" - ) - + switch invalidTruncateSize { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks ttl let invalidTtl = await self.cacheClient.listPushFront( cacheName: self.integrationTestCacheName, @@ -855,15 +861,12 @@ final class listTests: XCTestCase { value: "abc", ttl: CollectionTtl(ttlSeconds: -5) ) - XCTAssertTrue( - invalidTtl is CacheListPushFrontError, - "Unexpected response: \(invalidTtl)" - ) - let invalidTtlCode = (invalidTtl as! CacheListPushFrontError).errorCode - XCTAssertEqual( - invalidTtlCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidTtlCode)" - ) + switch invalidTtl { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } } func testPushFront() async throws { @@ -877,22 +880,26 @@ final class listTests: XCTestCase { value: value, truncateBackToSize: 2 ) - XCTAssertTrue( - pushFront is CacheListPushFrontSuccess, - "Unexpected response: \(pushFront)" - ) + switch pushFront { + case .success(_): + break + case .error(let err): + XCTFail("expected success but got \(err)") + } } let fetchStringList = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: stringListName ) - XCTAssertTrue( - fetchStringList is CacheListFetchHit, - "Unexpected response: \(fetchStringList)" - ) - let fetchedStringList = (fetchStringList as! CacheListFetchHit).valueListString - XCTAssertEqual(fetchedStringList, Array(stringValues[1...2]).reversed()) - + switch fetchStringList { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(Array(stringValues[1...2]).reversed(), hit.valueListString) + } + // Pushes data values let dataListName = generateStringWithUuid(prefix: "swift-list-push-front-data") let dataValues = [Data("abc".utf8), Data("lmn".utf8), Data("xyz".utf8)] @@ -903,21 +910,25 @@ final class listTests: XCTestCase { value: value, truncateBackToSize: 2 ) - XCTAssertTrue( - pushFront is CacheListPushFrontSuccess, - "Unexpected response: \(pushFront)" - ) + switch pushFront { + case .success(_): + break + case .error(let err): + XCTFail("expected success but got \(err)") + } } let fetchDataList = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: dataListName ) - XCTAssertTrue( - fetchDataList is CacheListFetchHit, - "Unexpected response: \(fetchStringList)" - ) - let fetchedDataList = (fetchDataList as! CacheListFetchHit).valueListData - XCTAssertEqual(fetchedDataList, Array(dataValues[1...2]).reversed()) + switch fetchDataList { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(Array(dataValues[1...2]).reversed(), hit.valueListData) + } } func testRemoveValueValidatesParameters() async throws { @@ -929,149 +940,163 @@ final class listTests: XCTestCase { listName: listName, value: "abc" ) - XCTAssertTrue( - invalidCacheName is CacheListRemoveValueError, - "Unexpected response: \(invalidCacheName)" - ) - let invalidCacheNameCode = (invalidCacheName as! CacheListRemoveValueError).errorCode - XCTAssertEqual( - invalidCacheNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidCacheNameCode)" - ) - + switch invalidCacheName { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks list name let invalidListName = await self.cacheClient.listRemoveValue( cacheName: self.integrationTestCacheName, listName: " ", value: "abc" ) - XCTAssertTrue( - invalidListName is CacheListRemoveValueError, - "Unexpected response: \(invalidListName)" - ) - let invalidListNameCode = (invalidListName as! CacheListRemoveValueError).errorCode - XCTAssertEqual( - invalidListNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidListNameCode)" - ) + switch invalidListName { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } } func testRemoveValue() async throws { // Insert some string values let stringListName = generateStringWithUuid(prefix: "swift-list-remove-value-string") let stringValues = ["apple", "banana", "apple", "apple", "carrot"] + let noAppleStrings = stringValues.filter { $0 != "apple"} let concatStrings = await self.cacheClient.listConcatenateBack( cacheName: self.integrationTestCacheName, listName: stringListName, values: stringValues ) - XCTAssertTrue( - concatStrings is CacheListConcatenateBackSuccess, - "Unexpected response: \(concatStrings)" - ) - + switch concatStrings { + case .error(let err): + XCTFail("expected succes but got \(err)") + default: + break + } + // Removes all instances of given string let remove1 = await self.cacheClient.listRemoveValue( cacheName: self.integrationTestCacheName, listName: stringListName, value: "apple" ) - XCTAssertTrue( - remove1 is CacheListRemoveValueSuccess, - "Unexpected response: \(remove1)" - ) - + switch remove1 { + case .error(let err): + XCTFail("expected success but got \(err)") + default: + break + } + let fetchStringList = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: stringListName ) - XCTAssertTrue( - fetchStringList is CacheListFetchHit, - "Unexpected response: \(fetchStringList)" - ) - let fetchedStringList = (fetchStringList as! CacheListFetchHit).valueListString - let noAppleStrings = stringValues.filter { $0 != "apple"} - XCTAssertEqual(fetchedStringList, noAppleStrings) - + switch fetchStringList { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(noAppleStrings, hit.valueListString) + } + // Removes no elements if given string not found let remove2 = await self.cacheClient.listRemoveValue( cacheName: self.integrationTestCacheName, listName: stringListName, value: "apple" ) - XCTAssertTrue( - remove2 is CacheListRemoveValueSuccess, - "Unexpected response: \(remove2)" - ) - + switch remove2 { + case .error(let err): + XCTFail("expected success but got \(err)") + default: + break + } + let fetchStringList2 = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: stringListName ) - XCTAssertTrue( - fetchStringList2 is CacheListFetchHit, - "Unexpected response: \(fetchStringList2)" - ) - let fetchedStringList2 = (fetchStringList2 as! CacheListFetchHit).valueListString - XCTAssertEqual(fetchedStringList2, noAppleStrings) - + switch fetchStringList2 { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(noAppleStrings, hit.valueListString) + } + // Insert some data values let dataListName = generateStringWithUuid(prefix: "swift-list-remove-value-data") let dataValues = [Data("abc".utf8), Data("lmn".utf8), Data("xyz".utf8), Data("abc".utf8), Data("abc".utf8)] + let noAbcData = dataValues.filter { $0 != Data("abc".utf8)} let concatData = await self.cacheClient.listConcatenateBack( cacheName: self.integrationTestCacheName, listName: dataListName, values: dataValues ) - XCTAssertTrue( - concatData is CacheListConcatenateBackSuccess, - "Unexpected response: \(concatData)" - ) - + switch concatData { + case .error(let err): + XCTFail("expected succes but got \(err)") + default: + break + } + // Removes all instances of given data let removeData1 = await self.cacheClient.listRemoveValue( cacheName: self.integrationTestCacheName, listName: dataListName, value: Data("abc".utf8) ) - XCTAssertTrue( - removeData1 is CacheListRemoveValueSuccess, - "Unexpected response: \(removeData1)" - ) - + switch removeData1 { + case .error(let err): + XCTFail("expected success but got \(err)") + default: + break + } + let fetchDataList = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: dataListName ) - XCTAssertTrue( - fetchDataList is CacheListFetchHit, - "Unexpected response: \(fetchDataList)" - ) - let fetchedDataList = (fetchDataList as! CacheListFetchHit).valueListData - let noAbcData = dataValues.filter { $0 != Data("abc".utf8)} - XCTAssertEqual(fetchedDataList, noAbcData) - + switch fetchDataList { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(noAbcData, hit.valueListData) + } + // Removes no elements if given string not found let removeData2 = await self.cacheClient.listRemoveValue( cacheName: self.integrationTestCacheName, listName: dataListName, value: Data("abc".utf8) ) - XCTAssertTrue( - removeData2 is CacheListRemoveValueSuccess, - "Unexpected response: \(removeData2)" - ) - + switch removeData2 { + case .error(let err): + XCTFail("expected success but got \(err)") + default: + break + } + let fetchDataList2 = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: dataListName ) - XCTAssertTrue( - fetchDataList2 is CacheListFetchHit, - "Unexpected response: \(fetchDataList2)" - ) - let fetchedDataList2 = (fetchDataList2 as! CacheListFetchHit).valueListData - XCTAssertEqual(fetchedDataList2, noAbcData) + switch fetchDataList2 { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but goit \(miss)") + case .hit(let hit): + XCTAssertEqual(noAbcData, hit.valueListData) + } } func testRetainValidatesParameters() async throws { @@ -1082,31 +1107,25 @@ final class listTests: XCTestCase { cacheName: " ", listName: listName ) - XCTAssertTrue( - invalidCacheName is CacheListRetainError, - "Unexpected response: \(invalidCacheName)" - ) - let invalidCacheNameCode = (invalidCacheName as! CacheListRetainError).errorCode - XCTAssertEqual( - invalidCacheNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidCacheNameCode)" - ) - + switch invalidCacheName { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks list name let invalidListName = await self.cacheClient.listRetain( cacheName: self.integrationTestCacheName, listName: " " ) - XCTAssertTrue( - invalidListName is CacheListRetainError, - "Unexpected response: \(invalidListName)" - ) - let invalidListNameCode = (invalidListName as! CacheListRetainError).errorCode - XCTAssertEqual( - invalidListNameCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidListNameCode)" - ) - + switch invalidListName { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks start and end index range let invalidSlice = await self.cacheClient.listRetain( cacheName: self.integrationTestCacheName, @@ -1114,31 +1133,25 @@ final class listTests: XCTestCase { startIndex: 2, endIndex: 1 ) - XCTAssertTrue( - invalidSlice is CacheListRetainError, - "Unexpected response: \(invalidSlice)" - ) - let invalidSliceCode = (invalidSlice as! CacheListRetainError).errorCode - XCTAssertEqual( - invalidSliceCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidSliceCode)" - ) - + switch invalidSlice { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + // Checks ttl let invalidTtl = await self.cacheClient.listRetain( cacheName: self.integrationTestCacheName, listName: listName, ttl: CollectionTtl(ttlSeconds: -5) ) - XCTAssertTrue( - invalidTtl is CacheListRetainError, - "Unexpected response: \(invalidTtl)" - ) - let invalidTtlCode = (invalidTtl as! CacheListRetainError).errorCode - XCTAssertEqual( - invalidTtlCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidTtlCode)" - ) + switch invalidTtl { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } } func testRetainFullList() async throws { @@ -1150,30 +1163,36 @@ final class listTests: XCTestCase { listName: listName, values: stringValues ) - XCTAssertTrue( - concatStrings is CacheListConcatenateBackSuccess, - "Unexpected response: \(concatStrings)" - ) - + switch concatStrings { + case .error(let err): + XCTFail("expected succes but got \(err)") + default: + break + } + // Retains full list when no slice specified let retainFullList = await self.cacheClient.listRetain( cacheName: self.integrationTestCacheName, listName: listName ) - XCTAssertTrue( - retainFullList is CacheListRetainSuccess, - "Unexpected response: \(retainFullList)" - ) + switch retainFullList { + case .error(let err): + XCTFail("expected success but got \(err)") + default: + break + } let fetch = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: listName ) - XCTAssertTrue( - fetch is CacheListFetchHit, - "Unexpected response: \(fetch)" - ) - let fetchedList = (fetch as! CacheListFetchHit).valueListString - XCTAssertEqual(fetchedList, stringValues) + switch fetch { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(stringValues, hit.valueListString) + } } func testRetainPositiveSlice() async throws { @@ -1185,11 +1204,13 @@ final class listTests: XCTestCase { listName: listName, values: stringValues ) - XCTAssertTrue( - concatStrings is CacheListConcatenateBackSuccess, - "Unexpected response: \(concatStrings)" - ) - + switch concatStrings { + case .error(let err): + XCTFail("expected succes but got \(err)") + default: + break + } + // Retains positive slice range let retainPositiveSlice = await self.cacheClient.listRetain( cacheName: self.integrationTestCacheName, @@ -1197,20 +1218,24 @@ final class listTests: XCTestCase { startIndex: 2, endIndex: 5 ) - XCTAssertTrue( - retainPositiveSlice is CacheListRetainSuccess, - "Unexpected response: \(retainPositiveSlice)" - ) + switch retainPositiveSlice { + case .error(let err): + XCTFail("expected success but got \(err)") + default: + break + } let fetch = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: listName ) - XCTAssertTrue( - fetch is CacheListFetchHit, - "Unexpected response: \(fetch)" - ) - let fetchedList = (fetch as! CacheListFetchHit).valueListString - XCTAssertEqual(fetchedList, Array(stringValues[2...4])) + switch fetch { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(Array(stringValues[2...4]), hit.valueListString) + } } func testRetainNegativeSlice() async throws { @@ -1222,11 +1247,13 @@ final class listTests: XCTestCase { listName: listName, values: stringValues ) - XCTAssertTrue( - concatStrings is CacheListConcatenateBackSuccess, - "Unexpected response: \(concatStrings)" - ) - + switch concatStrings { + case .error(let err): + XCTFail("expected succes but got \(err)") + default: + break + } + // Retains negative slice range let retainsNegativeSlice = await self.cacheClient.listRetain( cacheName: self.integrationTestCacheName, @@ -1234,20 +1261,24 @@ final class listTests: XCTestCase { startIndex: 2, endIndex: -2 ) - XCTAssertTrue( - retainsNegativeSlice is CacheListRetainSuccess, - "Unexpected response: \(retainsNegativeSlice)" - ) + switch retainsNegativeSlice { + case .error(let err): + XCTFail("expected success but got \(err)") + default: + break + } let fetch = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: listName ) - XCTAssertTrue( - fetch is CacheListFetchHit, - "Unexpected response: \(fetch)" - ) - let fetchedList = (fetch as! CacheListFetchHit).valueListString - XCTAssertEqual(fetchedList, Array(stringValues[2...4])) + switch fetch { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(Array(stringValues[2...4]), hit.valueListString) + } } func testRetainSliceWithNilStart() async throws { @@ -1259,11 +1290,13 @@ final class listTests: XCTestCase { listName: listName, values: stringValues ) - XCTAssertTrue( - concatStrings is CacheListConcatenateBackSuccess, - "Unexpected response: \(concatStrings)" - ) - + switch concatStrings { + case .error(let err): + XCTFail("expected succes but got \(err)") + default: + break + } + // Retains slice with nil start index let retainsNilStart = await self.cacheClient.listRetain( cacheName: self.integrationTestCacheName, @@ -1271,20 +1304,24 @@ final class listTests: XCTestCase { startIndex: nil, endIndex: 4 ) - XCTAssertTrue( - retainsNilStart is CacheListRetainSuccess, - "Unexpected response: \(retainsNilStart)" - ) + switch retainsNilStart { + case .error(let err): + XCTFail("expected success but got \(err)") + default: + break + } let fetch = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: listName ) - XCTAssertTrue( - fetch is CacheListFetchHit, - "Unexpected response: \(fetch)" - ) - let fetchedList = (fetch as! CacheListFetchHit).valueListString - XCTAssertEqual(fetchedList, Array(stringValues[0...3])) + switch fetch { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(Array(stringValues[0...3]), hit.valueListString) + } } func testRetainSliceWithNilEnd() async throws { @@ -1296,10 +1333,13 @@ final class listTests: XCTestCase { listName: listName, values: stringValues ) - XCTAssertTrue( - concatStrings is CacheListConcatenateBackSuccess, - "Unexpected response: \(concatStrings)" - ) + switch concatStrings { + case .error(let err): + XCTFail("expected succes but got \(err)") + default: + break + } + // Retains slice with nil end index let retainsNilEnd = await self.cacheClient.listRetain( cacheName: self.integrationTestCacheName, @@ -1307,19 +1347,23 @@ final class listTests: XCTestCase { startIndex: 3, endIndex: nil ) - XCTAssertTrue( - retainsNilEnd is CacheListRetainSuccess, - "Unexpected response: \(retainsNilEnd)" - ) + switch retainsNilEnd { + case .error(let err): + XCTFail("expected success but got \(err)") + default: + break + } let fetch = await self.cacheClient.listFetch( cacheName: self.integrationTestCacheName, listName: listName ) - XCTAssertTrue( - fetch is CacheListFetchHit, - "Unexpected response: \(fetch)" - ) - let fetchedList = (fetch as! CacheListFetchHit).valueListString - XCTAssertEqual(fetchedList, Array(stringValues[3...])) + switch fetch { + case .error(let err): + XCTFail("expected hit but got \(err)") + case .miss(let miss): + XCTFail("expected hit but got \(miss)") + case .hit(let hit): + XCTAssertEqual(Array(stringValues[3...]), hit.valueListString) + } } } From 677e9e05b2b49dcae5765a59084ff5efb910edaa Mon Sep 17 00:00:00 2001 From: Pete Gautier Date: Mon, 11 Dec 2023 16:39:16 -0800 Subject: [PATCH 10/12] feat: converting topics responses to enum --- Sources/Momento/TopicClient.swift | 27 +-- Sources/Momento/internal/PubsubClient.swift | 13 +- .../responses/topics/TopicPublish.swift | 9 +- .../responses/topics/TopicSubscribe.swift | 10 +- .../topics/TopicSubscriptionItem.swift | 20 +- Tests/MomentoTests/configTests.swift | 8 +- Tests/MomentoTests/topicsTests.swift | 183 +++++++++--------- 7 files changed, 145 insertions(+), 125 deletions(-) diff --git a/Sources/Momento/TopicClient.swift b/Sources/Momento/TopicClient.swift index cbefb41..2b80ec7 100644 --- a/Sources/Momento/TopicClient.swift +++ b/Sources/Momento/TopicClient.swift @@ -1,5 +1,6 @@ import Foundation +@available(macOS 10.15, iOS 13, *) public protocol TopicClientProtocol { func publish( cacheName: String, @@ -107,10 +108,10 @@ public class TopicClient: TopicClientProtocol { try validateCacheName(cacheName: cacheName) try validateTopicName(topicName: topicName) } catch let err as SdkError { - return TopicPublishError(error: err) + return TopicPublishResponse.error(TopicPublishError(error: err)) } catch { - return TopicPublishError(error: UnknownError( - message: "unexpected error: \(error)") + return TopicPublishResponse.error( + TopicPublishError(error: UnknownError(message: "unexpected error: \(error)")) ) } @@ -122,10 +123,12 @@ public class TopicClient: TopicClientProtocol { ) return result } catch { - return TopicPublishError( - error: UnknownError( - message: "Unknown error from publish", - innerException: error + return TopicPublishResponse.error( + TopicPublishError( + error: UnknownError( + message: "Unknown error from publish", + innerException: error + ) ) ) } @@ -153,10 +156,10 @@ public class TopicClient: TopicClientProtocol { try validateCacheName(cacheName: cacheName) try validateTopicName(topicName: topicName) } catch let err as SdkError { - return TopicSubscribeError(error: err) + return TopicSubscribeResponse.error(TopicSubscribeError(error: err)) } catch { - return TopicSubscribeError(error: UnknownError( - message: "unexpected error: \(error)") + return TopicSubscribeResponse.error( + TopicSubscribeError(error: UnknownError(message: "unexpected error: \(error)")) ) } @@ -167,12 +170,12 @@ public class TopicClient: TopicClientProtocol { ) return result } catch { - return TopicSubscribeError( + return TopicSubscribeResponse.error(TopicSubscribeError( error: UnknownError( message: "Unknown error from subscribe", innerException: error ) - ) + )) } } diff --git a/Sources/Momento/internal/PubsubClient.swift b/Sources/Momento/internal/PubsubClient.swift index 21589f6..bd25864 100644 --- a/Sources/Momento/internal/PubsubClient.swift +++ b/Sources/Momento/internal/PubsubClient.swift @@ -3,6 +3,7 @@ import NIO import NIOHPACK import Logging +@available(macOS 10.15, iOS 13, *) protocol PubsubClientProtocol { var configuration: TopicClientConfigurationProtocol { get } @@ -93,13 +94,15 @@ class PubsubClient: PubsubClientProtocol { // TODO: I'm just resetting customMetadata after it's sent once to prevent the agent // header from being sent more than once. Need to repeat this in subscribe(). self.client.defaultCallOptions.customMetadata = HPACKHeaders() - return TopicPublishSuccess() + return TopicPublishResponse.success(TopicPublishSuccess()) } catch let err as GRPCStatus { - return TopicPublishError(error: grpcStatusToSdkError(grpcStatus: err)) + return TopicPublishResponse.error(TopicPublishError(error: grpcStatusToSdkError(grpcStatus: err))) } catch let err as GRPCConnectionPoolError { - return TopicPublishError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus())) + return TopicPublishResponse.error(TopicPublishError(error: grpcStatusToSdkError(grpcStatus: err.makeGRPCStatus()))) } catch { - return TopicPublishError(error: UnknownError(message: "unknown publish error \(error)")) + return TopicPublishResponse.error( + TopicPublishError(error: UnknownError(message: "unknown publish error \(error)")) + ) } } @@ -109,7 +112,7 @@ class PubsubClient: PubsubClientProtocol { request.topic = topicName let result = self.client.subscribe(request) - return TopicSubscription(subscription: result) + return TopicSubscribeResponse.subscription(TopicSubscription(subscription: result)) } func close() { diff --git a/Sources/Momento/messages/responses/topics/TopicPublish.swift b/Sources/Momento/messages/responses/topics/TopicPublish.swift index 6d8be6a..7258e15 100644 --- a/Sources/Momento/messages/responses/topics/TopicPublish.swift +++ b/Sources/Momento/messages/responses/topics/TopicPublish.swift @@ -1,5 +1,8 @@ -public protocol TopicPublishResponse {} +public enum TopicPublishResponse { + case success(TopicPublishSuccess) + case error(TopicPublishError) +} -public class TopicPublishSuccess: TopicPublishResponse {} +public class TopicPublishSuccess {} -public class TopicPublishError: ErrorResponseBase, TopicPublishResponse {} +public class TopicPublishError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/topics/TopicSubscribe.swift b/Sources/Momento/messages/responses/topics/TopicSubscribe.swift index cecb994..5958a4e 100644 --- a/Sources/Momento/messages/responses/topics/TopicSubscribe.swift +++ b/Sources/Momento/messages/responses/topics/TopicSubscribe.swift @@ -1,10 +1,14 @@ import GRPC import Logging -public protocol TopicSubscribeResponse {} +@available(macOS 10.15, iOS 13, *) +public enum TopicSubscribeResponse { + case subscription(TopicSubscription) + case error(TopicSubscribeError) +} @available(macOS 10.15, iOS 13, *) -public class TopicSubscription: TopicSubscribeResponse { +public class TopicSubscription { public typealias SubscriptionItemsMap = AsyncCompactMapSequence, TopicSubscriptionItemResponse> public let stream: SubscriptionItemsMap @@ -30,4 +34,4 @@ internal func processResult(item: CacheClient_Pubsub__SubscriptionItem) -> Topic return nil } -public class TopicSubscribeError: ErrorResponseBase, TopicSubscribeResponse {} +public class TopicSubscribeError: ErrorResponseBase {} diff --git a/Sources/Momento/messages/responses/topics/TopicSubscriptionItem.swift b/Sources/Momento/messages/responses/topics/TopicSubscriptionItem.swift index fe73c24..3384960 100644 --- a/Sources/Momento/messages/responses/topics/TopicSubscriptionItem.swift +++ b/Sources/Momento/messages/responses/topics/TopicSubscriptionItem.swift @@ -1,8 +1,12 @@ import Foundation -public protocol TopicSubscriptionItemResponse {} +public enum TopicSubscriptionItemResponse { + case itemText(TopicSubscriptionItemText) + case itemBinary(TopicSubscriptionItemBinary) + case error(TopicSubscriptionItemError) +} -public class TopicSubscriptionItemText: TopicSubscriptionItemResponse { +public class TopicSubscriptionItemText { public let value: String init(value: String) { @@ -10,7 +14,7 @@ public class TopicSubscriptionItemText: TopicSubscriptionItemResponse { } } -public class TopicSubscriptionItemBinary: TopicSubscriptionItemResponse { +public class TopicSubscriptionItemBinary { public let value: Data init(value: Data) { @@ -18,15 +22,17 @@ public class TopicSubscriptionItemBinary: TopicSubscriptionItemResponse { } } -public class TopicSubscriptionItemError: ErrorResponseBase, TopicSubscriptionItemResponse {} +public class TopicSubscriptionItemError: ErrorResponseBase {} internal func createTopicItemResponse(item: CacheClient_Pubsub__TopicItem) -> TopicSubscriptionItemResponse { switch item.value.kind { case .text: - return TopicSubscriptionItemText(value: item.value.text) + return TopicSubscriptionItemResponse.itemText(TopicSubscriptionItemText(value: item.value.text)) case .binary: - return TopicSubscriptionItemBinary(value: item.value.binary) + return TopicSubscriptionItemResponse.itemBinary(TopicSubscriptionItemBinary(value: item.value.binary)) default: - return TopicSubscriptionItemError(error: UnknownError(message: "unknown TopicItemResponse value: \(item.value)")) + return TopicSubscriptionItemResponse.error( + TopicSubscriptionItemError(error: UnknownError(message: "unknown TopicItemResponse value: \(item.value)")) + ) } } diff --git a/Tests/MomentoTests/configTests.swift b/Tests/MomentoTests/configTests.swift index 1b88391..8c76d4e 100644 --- a/Tests/MomentoTests/configTests.swift +++ b/Tests/MomentoTests/configTests.swift @@ -52,7 +52,11 @@ final class configTests: XCTestCase { topicName: generateStringWithUuid(prefix: "test-topic"), value: "test-message" ) - XCTAssertTrue(pubResp is TopicPublishError) - XCTAssertEqual(MomentoErrorCode.TIMEOUT_ERROR, (pubResp as! TopicPublishError).errorCode) + switch pubResp { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.TIMEOUT_ERROR, err.errorCode) + } } } diff --git a/Tests/MomentoTests/topicsTests.swift b/Tests/MomentoTests/topicsTests.swift index ec12e04..0ee3c4d 100644 --- a/Tests/MomentoTests/topicsTests.swift +++ b/Tests/MomentoTests/topicsTests.swift @@ -28,41 +28,37 @@ final class topicsTests: XCTestCase { topicName: topicName, value: "test-message" ) - XCTAssertTrue( - invalidCacheNameResp is TopicPublishError, - "Unexpected response: \(invalidCacheNameResp)" - ) - let invalidCacheNameErrorCode = (invalidCacheNameResp as! TopicPublishError).errorCode - XCTAssertEqual( - invalidCacheNameErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidCacheNameErrorCode)" - ) - + switch invalidCacheNameResp { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + let invalidTopicNameResp = await self.topicClient.publish( cacheName: self.integrationTestCacheName, topicName: "", value: "test-message" ) - XCTAssertTrue( - invalidTopicNameResp is TopicPublishError, - "Unexpected response: \(invalidTopicNameResp)" - ) - let invalidTopicNameErrorCode = (invalidTopicNameResp as! TopicPublishError).errorCode - XCTAssertEqual( - invalidTopicNameErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidTopicNameErrorCode)" - ) - + switch invalidTopicNameResp { + case .success(let success): + XCTFail("expected error but got \(success)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + let pubResp = await self.topicClient.publish( cacheName: self.integrationTestCacheName, topicName: topicName, value: "test-message" ) - XCTAssertTrue( - pubResp is TopicPublishSuccess, - "Unexpected response: \((pubResp as! TopicPublishError).description)" - ) - } + switch pubResp { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(_): + XCTAssertTrue(true) + } + } func testTopicClientSubscribes() async throws { let topicName = generateStringWithUuid(prefix: "test-topic") @@ -71,73 +67,74 @@ final class topicsTests: XCTestCase { cacheName: "", topicName: topicName ) - XCTAssertTrue( - invalidCacheNameResp is TopicSubscribeError, - "Unexpected response: \(invalidCacheNameResp)" - ) - let invalidCacheNameErrorCode = (invalidCacheNameResp as! TopicSubscribeError).errorCode - XCTAssertEqual( - invalidCacheNameErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidCacheNameErrorCode)" - ) - + switch invalidCacheNameResp { + case .subscription(let sub): + XCTFail("expected error but got \(sub)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + let invalidTopicNameResp = await self.topicClient.subscribe( cacheName: self.integrationTestCacheName, topicName: "" ) - XCTAssertTrue( - invalidTopicNameResp is TopicSubscribeError, - "Unexpected response: \(invalidTopicNameResp)" - ) - let invalidTopicNameErrorCode = (invalidTopicNameResp as! TopicSubscribeError).errorCode - XCTAssertEqual( - invalidTopicNameErrorCode, MomentoErrorCode.INVALID_ARGUMENT_ERROR, - "Unexpected error code: \(invalidTopicNameErrorCode)" - ) - + switch invalidTopicNameResp { + case .subscription(let sub): + XCTFail("expected error but got \(sub)") + case .error(let err): + XCTAssertEqual(MomentoErrorCode.INVALID_ARGUMENT_ERROR, err.errorCode) + } + let subResp = await self.topicClient.subscribe( cacheName: self.integrationTestCacheName, topicName: topicName ) - XCTAssertTrue( - subResp is TopicSubscription, - "Unexpected response: \((subResp as! TopicSubscribeError).description)" - ) + switch subResp { + case .error(let err): + XCTFail("expected subscription but got \(err)") + case .subscription(let sub): + print("got subscription: \(sub)") + XCTAssertTrue(true) + } } func testTopicClientPublishesAndSubscribes() async throws { let topicName = generateStringWithUuid(prefix: "test-topic") - + let topicValue = "publishing and subscribing!" let subResp = await self.topicClient.subscribe( cacheName: self.integrationTestCacheName, topicName: topicName ) - XCTAssertTrue( - subResp is TopicSubscription, - "Unexpected response: \((subResp as! TopicSubscribeError).description)" - ) - + var subscription: TopicSubscription? = nil + switch subResp { + case .error(let err): + XCTFail("expected subscription but got \(err)") + case .subscription(let sub): + subscription = sub + } + try await Task.sleep(nanoseconds: 1_000_000_000) let pubResp = await self.topicClient.publish( cacheName: self.integrationTestCacheName, topicName: topicName, - value: "publishing and subscribing!" + value: topicValue ) - XCTAssertTrue( - pubResp is TopicPublishSuccess, - "Unexpected response: \((pubResp as! TopicPublishError).description)" - ) - - let subscription = (subResp as! TopicSubscription).stream - for try await item in subscription { - XCTAssertTrue( - item is TopicSubscriptionItemText, - "received subscription item that was not text: \(String(describing: item))" - ) - - let value = (item as! TopicSubscriptionItemText).value - XCTAssertEqual(value, "publishing and subscribing!", "unexpected topic subscription item value: \(value)") - break + switch pubResp { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(_): + XCTAssertTrue(true) + } + + for try await item in subscription!.stream { + switch item { + case .error(let err): + XCTFail("expected itemText but got \(err)") + case .itemBinary(let bin): + XCTFail("expected itemText but got \(bin)") + case .itemText(let itemText): + XCTAssertEqual(itemText.value, topicValue) + } } } @@ -148,10 +145,13 @@ final class topicsTests: XCTestCase { cacheName: self.integrationTestCacheName, topicName: topicName ) - XCTAssertTrue( - subResp is TopicSubscription, - "Unexpected response: \((subResp as! TopicSubscribeError).description)" - ) + var subscription: TopicSubscription? = nil + switch subResp { + case .error(let err): + XCTFail("expected subscription but got \(err)") + case .subscription(let sub): + subscription = sub + } try await Task.sleep(nanoseconds: 1_000_000_000) let binaryValue = "publishing and subscribing!".data(using: .utf8)! @@ -160,25 +160,22 @@ final class topicsTests: XCTestCase { topicName: topicName, value: binaryValue ) - XCTAssertTrue( - pubResp is TopicPublishSuccess, - "Unexpected response: \((pubResp as! TopicPublishError).description)" - ) - - let subscription = (subResp as! TopicSubscription).stream - for try await item in subscription { - XCTAssertTrue( - item is TopicSubscriptionItemBinary, - "received subscription item that was not binary: \(String(describing: item))" - ) + switch pubResp { + case .error(let err): + XCTFail("expected success but got \(err)") + case .success(_): + XCTAssertTrue(true) + } - let value = (item as! TopicSubscriptionItemBinary).value - XCTAssertEqual( - value, - binaryValue, - "unexpected topic subscription item value: \(value)" - ) - break + for try await item in subscription!.stream { + switch item { + case .error(let err): + XCTFail("expected itemBinary but got \(err)") + case .itemText(let text): + XCTFail("expected itemBinary but got \(text)") + case .itemBinary(let itemBinary): + XCTAssertEqual(binaryValue, itemBinary.value) + } } } } From e387518bbf522b7ba267f21f9c07e8335ea2a6f2 Mon Sep 17 00:00:00 2001 From: Pete Gautier Date: Mon, 11 Dec 2023 17:22:11 -0800 Subject: [PATCH 11/12] chore: skip hanging tests --- Tests/MomentoTests/topicsTests.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tests/MomentoTests/topicsTests.swift b/Tests/MomentoTests/topicsTests.swift index 0ee3c4d..77d7642 100644 --- a/Tests/MomentoTests/topicsTests.swift +++ b/Tests/MomentoTests/topicsTests.swift @@ -99,6 +99,7 @@ final class topicsTests: XCTestCase { } func testTopicClientPublishesAndSubscribes() async throws { + throw XCTSkip("skipping-- need to rework") let topicName = generateStringWithUuid(prefix: "test-topic") let topicValue = "publishing and subscribing!" let subResp = await self.topicClient.subscribe( @@ -139,6 +140,7 @@ final class topicsTests: XCTestCase { } func testTopicClientPublishesAndSubscribesBinary() async throws { + throw XCTSkip("skipping-- need to rework") let topicName = generateStringWithUuid(prefix: "test-topic") let subResp = await self.topicClient.subscribe( From 05d667b2d1483241e9d65b0b9047c233e9f674a2 Mon Sep 17 00:00:00 2001 From: Pete Gautier Date: Tue, 12 Dec 2023 09:40:40 -0800 Subject: [PATCH 12/12] fix: break after first subscription item in tests --- Tests/MomentoTests/topicsTests.swift | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Tests/MomentoTests/topicsTests.swift b/Tests/MomentoTests/topicsTests.swift index 77d7642..9aade2e 100644 --- a/Tests/MomentoTests/topicsTests.swift +++ b/Tests/MomentoTests/topicsTests.swift @@ -99,14 +99,13 @@ final class topicsTests: XCTestCase { } func testTopicClientPublishesAndSubscribes() async throws { - throw XCTSkip("skipping-- need to rework") let topicName = generateStringWithUuid(prefix: "test-topic") let topicValue = "publishing and subscribing!" let subResp = await self.topicClient.subscribe( cacheName: self.integrationTestCacheName, topicName: topicName ) - var subscription: TopicSubscription? = nil + var subscription: TopicSubscription! = nil switch subResp { case .error(let err): XCTFail("expected subscription but got \(err)") @@ -127,7 +126,7 @@ final class topicsTests: XCTestCase { XCTAssertTrue(true) } - for try await item in subscription!.stream { + for try await item in subscription.stream { switch item { case .error(let err): XCTFail("expected itemText but got \(err)") @@ -136,18 +135,17 @@ final class topicsTests: XCTestCase { case .itemText(let itemText): XCTAssertEqual(itemText.value, topicValue) } + break } } func testTopicClientPublishesAndSubscribesBinary() async throws { - throw XCTSkip("skipping-- need to rework") let topicName = generateStringWithUuid(prefix: "test-topic") - let subResp = await self.topicClient.subscribe( cacheName: self.integrationTestCacheName, topicName: topicName ) - var subscription: TopicSubscription? = nil + var subscription: TopicSubscription! = nil switch subResp { case .error(let err): XCTFail("expected subscription but got \(err)") @@ -169,7 +167,7 @@ final class topicsTests: XCTestCase { XCTAssertTrue(true) } - for try await item in subscription!.stream { + for try await item in subscription.stream { switch item { case .error(let err): XCTFail("expected itemBinary but got \(err)") @@ -178,6 +176,7 @@ final class topicsTests: XCTestCase { case .itemBinary(let itemBinary): XCTAssertEqual(binaryValue, itemBinary.value) } + break } } }