diff --git a/Sources/ZcashLightClientKit/Modules/Service/LightWalletService.swift b/Sources/ZcashLightClientKit/Modules/Service/LightWalletService.swift index 3d7e8263..6eed7374 100644 --- a/Sources/ZcashLightClientKit/Modules/Service/LightWalletService.swift +++ b/Sources/ZcashLightClientKit/Modules/Service/LightWalletService.swift @@ -180,6 +180,7 @@ protocol LightWalletService: AnyObject { func fetchTransaction(txId: Data) async throws -> ZcashTransaction.Fetched /// - Throws: `serviceFetchUTXOsFailed` when GRPC call fails. + // sourcery: mockedName="fetchUTXOsSingle" func fetchUTXOs(for tAddress: String, height: BlockHeight) -> AsyncThrowingStream /// - Throws: `serviceFetchUTXOsFailed` when GRPC call fails. diff --git a/Tests/OfflineTests/BlockBatchValidationTests.swift b/Tests/OfflineTests/BlockBatchValidationTests.swift index 4baf9680..904cb399 100644 --- a/Tests/OfflineTests/BlockBatchValidationTests.swift +++ b/Tests/OfflineTests/BlockBatchValidationTests.swift @@ -45,564 +45,560 @@ class BlockBatchValidationTests: ZcashTestCase { testTempDirectory = nil } - func testBranchIdFailure() async throws { - let network = ZcashNetworkBuilder.network(for: .mainnet) - let service = MockLightWalletService( - latestBlockHeight: 1210000, - service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default).make() - ) - mockContainer.mock(type: LightWalletService.self, isSingleton: true) { _ in service } - - let storage = FSCompactBlockRepository( - fsBlockDbRoot: testTempDirectory, - metadataStore: FSMetadataStore.live( - fsBlockDbRoot: testTempDirectory, - rustBackend: rustBackend, - logger: logger - ), - blockDescriptor: .live, - contentProvider: DirectoryListingProviders.defaultSorted, - logger: logger - ) - mockContainer.mock(type: CompactBlockRepository.self, isSingleton: true) { _ in storage } - - try await storage.create() - - mockContainer.mock(type: BlockDownloaderService.self, isSingleton: true) { _ in - let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) - return BlockDownloaderServiceImpl(service: service, storage: repository) - } - - let config = CompactBlockProcessor.Configuration( - alias: .default, - fsBlockCacheRoot: testTempDirectory, - dataDb: try! __dataDbURL(), - spendParamsURL: try! __spendParamsURL(), - outputParamsURL: try! __outputParamsURL(), - saplingParamsSourceURL: SaplingParamsSourceURL.tests, - downloadBatchSize: 100, - retries: 5, - maxBackoffInterval: 10, - rewindDistance: 100, - walletBirthdayProvider: { 1210000 }, - saplingActivation: network.constants.saplingActivationHeight, - network: network - ) - - var info = LightdInfo() - info.blockHeight = 130000 - info.branch = "d34db33f" - info.chainName = "main" - info.buildUser = "test user" - info.consensusBranchID = "d34db33f" - info.saplingActivationHeight = UInt64(network.constants.saplingActivationHeight) - service.mockLightDInfo = info - - let mockBackend = await RustBackendMockHelper(rustBackend: rustBackend, consensusBranchID: Int32(0xd34d)) - mockContainer.mock(type: ZcashRustBackendWelding.self, isSingleton: true) { _ in mockBackend.rustBackendMock } - - let compactBlockProcessor = CompactBlockProcessor( - container: mockContainer, - config: config - ) - - do { - try await compactBlockProcessor.figureNextBatch(downloaderService: mockContainer.resolve(BlockDownloaderService.self)) - XCTAssertFalse(Task.isCancelled) - } catch { - switch error { - case ZcashError.compactBlockProcessorWrongConsensusBranchId: - break - default: - XCTFail("Expected ZcashError.compactBlockProcessorWrongConsensusBranchId but found \(error)") - } - } - } - - func testBranchNetworkMismatchFailure() async throws { - let network = ZcashNetworkBuilder.network(for: .mainnet) - let service = MockLightWalletService( - latestBlockHeight: 1210000, - service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default).make() - ) - mockContainer.mock(type: LightWalletService.self, isSingleton: true) { _ in service } - - let storage = FSCompactBlockRepository( - fsBlockDbRoot: testTempDirectory, - metadataStore: FSMetadataStore.live( - fsBlockDbRoot: testTempDirectory, - rustBackend: rustBackend, - logger: logger - ), - blockDescriptor: .live, - contentProvider: DirectoryListingProviders.defaultSorted, - logger: logger - ) - mockContainer.mock(type: CompactBlockRepository.self, isSingleton: true) { _ in storage } - - try await storage.create() - - mockContainer.mock(type: BlockDownloaderService.self, isSingleton: true) { _ in - let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) - return BlockDownloaderServiceImpl(service: service, storage: repository) - } - - let config = CompactBlockProcessor.Configuration( - alias: .default, - fsBlockCacheRoot: testTempDirectory, - dataDb: try! __dataDbURL(), - spendParamsURL: try! __spendParamsURL(), - outputParamsURL: try! __outputParamsURL(), - saplingParamsSourceURL: SaplingParamsSourceURL.tests, - downloadBatchSize: 100, - retries: 5, - maxBackoffInterval: 10, - rewindDistance: 100, - walletBirthdayProvider: { 1210000 }, - saplingActivation: network.constants.saplingActivationHeight, - network: network - ) - var info = LightdInfo() - info.blockHeight = 130000 - info.branch = "d34db33f" - info.chainName = "test" - info.buildUser = "test user" - info.consensusBranchID = "d34db4d" - info.saplingActivationHeight = UInt64(network.constants.saplingActivationHeight) - - service.mockLightDInfo = info - - let mockBackend = await RustBackendMockHelper(rustBackend: rustBackend, consensusBranchID: 0xd34db4d) - mockContainer.mock(type: ZcashRustBackendWelding.self, isSingleton: true) { _ in mockBackend.rustBackendMock } - - let compactBlockProcessor = CompactBlockProcessor( - container: mockContainer, - config: config - ) - - do { - try await compactBlockProcessor.figureNextBatch(downloaderService: mockContainer.resolve(BlockDownloaderService.self)) - XCTAssertFalse(Task.isCancelled) - } catch { - switch error { - case ZcashError.compactBlockProcessorNetworkMismatch(.mainnet, .testnet): - break - default: - XCTFail("Expected ZcashError.compactBlockProcessorNetworkMismatch but found \(error)") - } - } - } - - func testBranchNetworkTypeWrongFailure() async throws { - let network = ZcashNetworkBuilder.network(for: .testnet) - let service = MockLightWalletService( - latestBlockHeight: 1210000, - service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default).make() - ) - mockContainer.mock(type: LightWalletService.self, isSingleton: true) { _ in service } - - let storage = FSCompactBlockRepository( - fsBlockDbRoot: testTempDirectory, - metadataStore: FSMetadataStore.live( - fsBlockDbRoot: testTempDirectory, - rustBackend: rustBackend, - logger: logger - ), - blockDescriptor: .live, - contentProvider: DirectoryListingProviders.defaultSorted, - logger: logger - ) - mockContainer.mock(type: CompactBlockRepository.self, isSingleton: true) { _ in storage } - - try await storage.create() - - mockContainer.mock(type: BlockDownloaderService.self, isSingleton: true) { _ in - let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) - return BlockDownloaderServiceImpl(service: service, storage: repository) - } - - let config = CompactBlockProcessor.Configuration( - alias: .default, - fsBlockCacheRoot: testTempDirectory, - dataDb: try! __dataDbURL(), - spendParamsURL: try! __spendParamsURL(), - outputParamsURL: try! __outputParamsURL(), - saplingParamsSourceURL: SaplingParamsSourceURL.tests, - downloadBatchSize: 100, - retries: 5, - maxBackoffInterval: 10, - rewindDistance: 100, - walletBirthdayProvider: { 1210000 }, - saplingActivation: network.constants.saplingActivationHeight, - network: network - ) - var info = LightdInfo() - info.blockHeight = 130000 - info.branch = "d34db33f" - info.chainName = "another" - info.buildUser = "test user" - info.consensusBranchID = "d34db4d" - info.saplingActivationHeight = UInt64(network.constants.saplingActivationHeight) - - service.mockLightDInfo = info - - let mockBackend = await RustBackendMockHelper(rustBackend: rustBackend, consensusBranchID: 0xd34db4d) - mockContainer.mock(type: ZcashRustBackendWelding.self, isSingleton: true) { _ in mockBackend.rustBackendMock } - - let compactBlockProcessor = CompactBlockProcessor( - container: mockContainer, - config: config - ) - - do { - try await compactBlockProcessor.figureNextBatch(downloaderService: mockContainer.resolve(BlockDownloaderService.self)) - XCTAssertFalse(Task.isCancelled) - } catch { - switch error { - case ZcashError.compactBlockProcessorChainName: - break - default: - XCTFail("Expected ZcashError.compactBlockProcessorChainName but found \(error)") - } - } - } - - func testSaplingActivationHeightMismatch() async throws { - let network = ZcashNetworkBuilder.network(for: .mainnet) - let service = MockLightWalletService( - latestBlockHeight: 1210000, - service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default).make() - ) - mockContainer.mock(type: LightWalletService.self, isSingleton: true) { _ in service } - - let storage = FSCompactBlockRepository( - fsBlockDbRoot: testTempDirectory, - metadataStore: FSMetadataStore.live( - fsBlockDbRoot: testTempDirectory, - rustBackend: rustBackend, - logger: logger - ), - blockDescriptor: .live, - contentProvider: DirectoryListingProviders.defaultSorted, - logger: logger - ) - mockContainer.mock(type: CompactBlockRepository.self, isSingleton: true) { _ in storage } - - try await storage.create() - - mockContainer.mock(type: BlockDownloaderService.self, isSingleton: true) { _ in - let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) - return BlockDownloaderServiceImpl(service: service, storage: repository) - } - - let config = CompactBlockProcessor.Configuration( - alias: .default, - fsBlockCacheRoot: testTempDirectory, - dataDb: try! __dataDbURL(), - spendParamsURL: try! __spendParamsURL(), - outputParamsURL: try! __outputParamsURL(), - saplingParamsSourceURL: SaplingParamsSourceURL.tests, - downloadBatchSize: 100, - retries: 5, - maxBackoffInterval: 10, - rewindDistance: 100, - walletBirthdayProvider: { 1210000 }, - saplingActivation: network.constants.saplingActivationHeight, - network: network - ) - - var info = LightdInfo() - info.blockHeight = 130000 - info.branch = "d34db33f" - info.chainName = "main" - info.buildUser = "test user" - info.consensusBranchID = "d34db4d" - info.saplingActivationHeight = UInt64(3434343) - - service.mockLightDInfo = info - - let mockBackend = await RustBackendMockHelper(rustBackend: rustBackend, consensusBranchID: 0xd34db4d) - mockContainer.mock(type: ZcashRustBackendWelding.self, isSingleton: true) { _ in mockBackend.rustBackendMock } - - let compactBlockProcessor = CompactBlockProcessor( - container: mockContainer, - config: config - ) - - do { - try await compactBlockProcessor.figureNextBatch(downloaderService: mockContainer.resolve(BlockDownloaderService.self)) - XCTAssertFalse(Task.isCancelled) - } catch { - switch error { - case ZcashError.compactBlockProcessorSaplingActivationMismatch( - network.constants.saplingActivationHeight, - BlockHeight(info.saplingActivationHeight) - ): - break - default: - XCTFail("Expected ZcashError.compactBlockProcessorSaplingActivationMismatch but found \(error)") - } - } - } - - func testResultIsWait() async throws { - let network = ZcashNetworkBuilder.network(for: .mainnet) - - let expectedLatestHeight = BlockHeight(1210000) - let service = MockLightWalletService( - latestBlockHeight: expectedLatestHeight, - service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default).make() - ) - let expectedStoredLatestHeight = BlockHeight(1220000) - let expectedResult = CompactBlockProcessor.NextState.wait( - latestHeight: expectedLatestHeight, - latestDownloadHeight: expectedStoredLatestHeight - ) - - let repository = ZcashConsoleFakeStorage(latestBlockHeight: expectedStoredLatestHeight) - let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository) - - let config = CompactBlockProcessor.Configuration( - alias: .default, - fsBlockCacheRoot: testTempDirectory, - dataDb: try! __dataDbURL(), - spendParamsURL: try! __spendParamsURL(), - outputParamsURL: try! __outputParamsURL(), - saplingParamsSourceURL: SaplingParamsSourceURL.tests, - downloadBatchSize: 100, - retries: 5, - maxBackoffInterval: 10, - rewindDistance: 100, - walletBirthdayProvider: { 1210000 }, - saplingActivation: network.constants.saplingActivationHeight, - network: network - ) - - var info = LightdInfo() - info.blockHeight = UInt64(expectedLatestHeight) - info.branch = "d34db33f" - info.chainName = "main" - info.buildUser = "test user" - info.consensusBranchID = "d34db4d" - info.saplingActivationHeight = UInt64(network.constants.saplingActivationHeight) - - service.mockLightDInfo = info - - let mockBackend = await RustBackendMockHelper(rustBackend: rustBackend, consensusBranchID: 0xd34db4d) - - var nextBatch: CompactBlockProcessor.NextState? - do { - nextBatch = try await CompactBlockProcessor.NextStateHelper.nextState( - service: service, - downloaderService: downloaderService, - latestBlocksDataProvider: LatestBlocksDataProviderMock( - latestScannedHeight: expectedStoredLatestHeight, - latestBlockHeight: expectedLatestHeight - ), - config: config, - rustBackend: mockBackend.rustBackendMock, - internalSyncProgress: InternalSyncProgress( - alias: .default, - storage: InternalSyncProgressMemoryStorage(), - logger: logger - ) - ) - XCTAssertFalse(Task.isCancelled) - } catch { - XCTFail("this shouldn't happen: \(error)") - } - - guard nextBatch != nil else { - XCTFail("result should not be nil") - return - } - - XCTAssertTrue( - { - switch (nextBatch, expectedResult) { - case let (.wait(latestHeight, latestDownloadHeight), .wait(expectedLatestHeight, exectedLatestDownloadHeight)): - return latestHeight == expectedLatestHeight && latestDownloadHeight == exectedLatestDownloadHeight - default: - return false - } - }(), - "Expected \(expectedResult) got: \(String(describing: nextBatch))" - ) - } - - func testResultProcessNew() async throws { - let network = ZcashNetworkBuilder.network(for: .mainnet) - let expectedLatestHeight = BlockHeight(1230000) - let service = MockLightWalletService( - latestBlockHeight: expectedLatestHeight, - service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default).make() - ) - let expectedStoredLatestHeight = BlockHeight(1220000) - let walletBirthday = BlockHeight(1210000) - - let ranges = SyncRanges( - latestBlockHeight: expectedLatestHeight, - downloadedButUnscannedRange: nil, - downloadAndScanRange: expectedStoredLatestHeight + 1...expectedLatestHeight, - enhanceRange: walletBirthday...expectedLatestHeight, - fetchUTXORange: walletBirthday...expectedLatestHeight, - latestScannedHeight: expectedStoredLatestHeight, - latestDownloadedBlockHeight: expectedStoredLatestHeight - ) - let expectedResult = CompactBlockProcessor.NextState.processNewBlocks(ranges: ranges) - - let repository = ZcashConsoleFakeStorage(latestBlockHeight: expectedStoredLatestHeight) - let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository) - let config = CompactBlockProcessor.Configuration( - alias: .default, - fsBlockCacheRoot: testTempDirectory, - dataDb: try! __dataDbURL(), - spendParamsURL: try! __spendParamsURL(), - outputParamsURL: try! __outputParamsURL(), - saplingParamsSourceURL: SaplingParamsSourceURL.tests, - downloadBatchSize: 100, - retries: 5, - maxBackoffInterval: 10, - rewindDistance: 100, - walletBirthdayProvider: { walletBirthday }, - saplingActivation: network.constants.saplingActivationHeight, - network: network - ) - - var info = LightdInfo() - info.blockHeight = UInt64(expectedLatestHeight) - info.branch = "d34db33f" - info.chainName = "main" - info.buildUser = "test user" - info.consensusBranchID = "d34db4d" - info.saplingActivationHeight = UInt64(network.constants.saplingActivationHeight) - - service.mockLightDInfo = info - - let mockBackend = await RustBackendMockHelper(rustBackend: rustBackend, consensusBranchID: 0xd34db4d) - - var nextBatch: CompactBlockProcessor.NextState? - do { - nextBatch = try await CompactBlockProcessor.NextStateHelper.nextState( - service: service, - downloaderService: downloaderService, - latestBlocksDataProvider: LatestBlocksDataProviderMock( - latestScannedHeight: expectedStoredLatestHeight, - latestBlockHeight: expectedLatestHeight - ), - config: config, - rustBackend: mockBackend.rustBackendMock, - internalSyncProgress: InternalSyncProgress( - alias: .default, - storage: InternalSyncProgressMemoryStorage(), - logger: logger - ) - ) - XCTAssertFalse(Task.isCancelled) - } catch { - XCTFail("this shouldn't happen: \(error)") - } - - guard nextBatch != nil else { - XCTFail("result should not be nil") - return - } - - XCTAssertTrue( - { - switch (nextBatch, expectedResult) { - case let (.processNewBlocks(ranges), .processNewBlocks(expectedRanges)): - return ranges == expectedRanges - default: - return false - } - }(), - "Expected \(expectedResult) got: \(String(describing: nextBatch))" - ) - } - - func testResultProcessorFinished() async throws { - let network = ZcashNetworkBuilder.network(for: .mainnet) - let expectedLatestHeight = BlockHeight(1230000) - let service = MockLightWalletService( - latestBlockHeight: expectedLatestHeight, - service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default).make() - ) - let expectedStoredLatestHeight = BlockHeight(1230000) - let walletBirthday = BlockHeight(1210000) - let expectedResult = CompactBlockProcessor.NextState.finishProcessing(height: expectedStoredLatestHeight) - let repository = ZcashConsoleFakeStorage(latestBlockHeight: expectedStoredLatestHeight) - let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository) - let config = CompactBlockProcessor.Configuration( - alias: .default, - fsBlockCacheRoot: testTempDirectory, - dataDb: try! __dataDbURL(), - spendParamsURL: try! __spendParamsURL(), - outputParamsURL: try! __outputParamsURL(), - saplingParamsSourceURL: SaplingParamsSourceURL.tests, - downloadBatchSize: 100, - retries: 5, - maxBackoffInterval: 10, - rewindDistance: 100, - walletBirthdayProvider: { walletBirthday }, - saplingActivation: network.constants.saplingActivationHeight, - network: network - ) - - let internalSyncProgress = InternalSyncProgress( - alias: .default, - storage: InternalSyncProgressMemoryStorage(), - logger: logger - ) - await internalSyncProgress.set(expectedStoredLatestHeight, .latestEnhancedHeight) - await internalSyncProgress.set(expectedStoredLatestHeight, .latestUTXOFetchedHeight) - - var info = LightdInfo() - info.blockHeight = UInt64(expectedLatestHeight) - info.branch = "d34db33f" - info.chainName = "main" - info.buildUser = "test user" - info.consensusBranchID = "d34db4d" - info.saplingActivationHeight = UInt64(network.constants.saplingActivationHeight) - - service.mockLightDInfo = info - - let mockBackend = await RustBackendMockHelper(rustBackend: rustBackend, consensusBranchID: 0xd34db4d) - - var nextBatch: CompactBlockProcessor.NextState? - do { - nextBatch = try await CompactBlockProcessor.NextStateHelper.nextState( - service: service, - downloaderService: downloaderService, - latestBlocksDataProvider: LatestBlocksDataProviderMock( - latestScannedHeight: expectedStoredLatestHeight, - latestBlockHeight: expectedLatestHeight - ), - config: config, - rustBackend: mockBackend.rustBackendMock, - internalSyncProgress: internalSyncProgress - ) - - XCTAssertFalse(Task.isCancelled) - } catch { - XCTFail("this shouldn't happen: \(error)") - } - - guard nextBatch != nil else { - XCTFail("result should not be nil") - return - } - - XCTAssertTrue( - { - switch (nextBatch, expectedResult) { - case let (.finishProcessing(height), .finishProcessing(expectedHeight)): - return height == expectedHeight - default: - return false - } - }(), - "Expected \(expectedResult) got: \(String(describing: nextBatch))" - ) - } + // TODO: [1094] review the tests and potentially fix it https://github.com/zcash/ZcashLightClientKit/issues/1094 +// func testBranchIdFailure() async throws { +// let network = ZcashNetworkBuilder.network(for: .mainnet) +// let service = MockLightWalletService( +// latestBlockHeight: 1210000, +// service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default).make() +// ) +// mockContainer.mock(type: LightWalletService.self, isSingleton: true) { _ in service } +// +// let storage = FSCompactBlockRepository( +// fsBlockDbRoot: testTempDirectory, +// metadataStore: FSMetadataStore.live( +// fsBlockDbRoot: testTempDirectory, +// rustBackend: rustBackend, +// logger: logger +// ), +// blockDescriptor: .live, +// contentProvider: DirectoryListingProviders.defaultSorted, +// logger: logger +// ) +// mockContainer.mock(type: CompactBlockRepository.self, isSingleton: true) { _ in storage } +// +// try await storage.create() +// +// mockContainer.mock(type: BlockDownloaderService.self, isSingleton: true) { _ in +// let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) +// return BlockDownloaderServiceImpl(service: service, storage: repository) +// } +// +// let config = CompactBlockProcessor.Configuration( +// alias: .default, +// fsBlockCacheRoot: testTempDirectory, +// dataDb: try! __dataDbURL(), +// spendParamsURL: try! __spendParamsURL(), +// outputParamsURL: try! __outputParamsURL(), +// saplingParamsSourceURL: SaplingParamsSourceURL.tests, +// retries: 5, +// maxBackoffInterval: 10, +// rewindDistance: 100, +// walletBirthdayProvider: { 1210000 }, +// saplingActivation: network.constants.saplingActivationHeight, +// network: network +// ) +// +// var info = LightdInfo() +// info.blockHeight = 130000 +// info.branch = "d34db33f" +// info.chainName = "main" +// info.buildUser = "test user" +// info.consensusBranchID = "d34db33f" +// info.saplingActivationHeight = UInt64(network.constants.saplingActivationHeight) +// service.mockLightDInfo = info +// +// let mockBackend = await RustBackendMockHelper(rustBackend: rustBackend, consensusBranchID: Int32(0xd34d)) +// mockContainer.mock(type: ZcashRustBackendWelding.self, isSingleton: true) { _ in mockBackend.rustBackendMock } +// +// let compactBlockProcessor = CompactBlockProcessor( +// container: mockContainer, +// config: config +// ) +// +// do { +// try await compactBlockProcessor.figureNextBatch(downloaderService: mockContainer.resolve(BlockDownloaderService.self)) +// XCTAssertFalse(Task.isCancelled) +// } catch { +// switch error { +// case ZcashError.compactBlockProcessorWrongConsensusBranchId: +// break +// default: +// XCTFail("Expected ZcashError.compactBlockProcessorWrongConsensusBranchId but found \(error)") +// } +// } +// } +// +// func testBranchNetworkMismatchFailure() async throws { +// let network = ZcashNetworkBuilder.network(for: .mainnet) +// let service = MockLightWalletService( +// latestBlockHeight: 1210000, +// service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default).make() +// ) +// mockContainer.mock(type: LightWalletService.self, isSingleton: true) { _ in service } +// +// let storage = FSCompactBlockRepository( +// fsBlockDbRoot: testTempDirectory, +// metadataStore: FSMetadataStore.live( +// fsBlockDbRoot: testTempDirectory, +// rustBackend: rustBackend, +// logger: logger +// ), +// blockDescriptor: .live, +// contentProvider: DirectoryListingProviders.defaultSorted, +// logger: logger +// ) +// mockContainer.mock(type: CompactBlockRepository.self, isSingleton: true) { _ in storage } +// +// try await storage.create() +// +// mockContainer.mock(type: BlockDownloaderService.self, isSingleton: true) { _ in +// let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) +// return BlockDownloaderServiceImpl(service: service, storage: repository) +// } +// +// let config = CompactBlockProcessor.Configuration( +// alias: .default, +// fsBlockCacheRoot: testTempDirectory, +// dataDb: try! __dataDbURL(), +// spendParamsURL: try! __spendParamsURL(), +// outputParamsURL: try! __outputParamsURL(), +// saplingParamsSourceURL: SaplingParamsSourceURL.tests, +// retries: 5, +// maxBackoffInterval: 10, +// rewindDistance: 100, +// walletBirthdayProvider: { 1210000 }, +// saplingActivation: network.constants.saplingActivationHeight, +// network: network +// ) +// var info = LightdInfo() +// info.blockHeight = 130000 +// info.branch = "d34db33f" +// info.chainName = "test" +// info.buildUser = "test user" +// info.consensusBranchID = "d34db4d" +// info.saplingActivationHeight = UInt64(network.constants.saplingActivationHeight) +// +// service.mockLightDInfo = info +// +// let mockBackend = await RustBackendMockHelper(rustBackend: rustBackend, consensusBranchID: 0xd34db4d) +// mockContainer.mock(type: ZcashRustBackendWelding.self, isSingleton: true) { _ in mockBackend.rustBackendMock } +// +// let compactBlockProcessor = CompactBlockProcessor( +// container: mockContainer, +// config: config +// ) +// +// do { +// try await compactBlockProcessor.figureNextBatch(downloaderService: mockContainer.resolve(BlockDownloaderService.self)) +// XCTAssertFalse(Task.isCancelled) +// } catch { +// switch error { +// case ZcashError.compactBlockProcessorNetworkMismatch(.mainnet, .testnet): +// break +// default: +// XCTFail("Expected ZcashError.compactBlockProcessorNetworkMismatch but found \(error)") +// } +// } +// } +// +// func testBranchNetworkTypeWrongFailure() async throws { +// let network = ZcashNetworkBuilder.network(for: .testnet) +// let service = MockLightWalletService( +// latestBlockHeight: 1210000, +// service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default).make() +// ) +// mockContainer.mock(type: LightWalletService.self, isSingleton: true) { _ in service } +// +// let storage = FSCompactBlockRepository( +// fsBlockDbRoot: testTempDirectory, +// metadataStore: FSMetadataStore.live( +// fsBlockDbRoot: testTempDirectory, +// rustBackend: rustBackend, +// logger: logger +// ), +// blockDescriptor: .live, +// contentProvider: DirectoryListingProviders.defaultSorted, +// logger: logger +// ) +// mockContainer.mock(type: CompactBlockRepository.self, isSingleton: true) { _ in storage } +// +// try await storage.create() +// +// mockContainer.mock(type: BlockDownloaderService.self, isSingleton: true) { _ in +// let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) +// return BlockDownloaderServiceImpl(service: service, storage: repository) +// } +// +// let config = CompactBlockProcessor.Configuration( +// alias: .default, +// fsBlockCacheRoot: testTempDirectory, +// dataDb: try! __dataDbURL(), +// spendParamsURL: try! __spendParamsURL(), +// outputParamsURL: try! __outputParamsURL(), +// saplingParamsSourceURL: SaplingParamsSourceURL.tests, +// retries: 5, +// maxBackoffInterval: 10, +// rewindDistance: 100, +// walletBirthdayProvider: { 1210000 }, +// saplingActivation: network.constants.saplingActivationHeight, +// network: network +// ) +// var info = LightdInfo() +// info.blockHeight = 130000 +// info.branch = "d34db33f" +// info.chainName = "another" +// info.buildUser = "test user" +// info.consensusBranchID = "d34db4d" +// info.saplingActivationHeight = UInt64(network.constants.saplingActivationHeight) +// +// service.mockLightDInfo = info +// +// let mockBackend = await RustBackendMockHelper(rustBackend: rustBackend, consensusBranchID: 0xd34db4d) +// mockContainer.mock(type: ZcashRustBackendWelding.self, isSingleton: true) { _ in mockBackend.rustBackendMock } +// +// let compactBlockProcessor = CompactBlockProcessor( +// container: mockContainer, +// config: config +// ) +// +// do { +// try await compactBlockProcessor.figureNextBatch(downloaderService: mockContainer.resolve(BlockDownloaderService.self)) +// XCTAssertFalse(Task.isCancelled) +// } catch { +// switch error { +// case ZcashError.compactBlockProcessorChainName: +// break +// default: +// XCTFail("Expected ZcashError.compactBlockProcessorChainName but found \(error)") +// } +// } +// } +// +// func testSaplingActivationHeightMismatch() async throws { +// let network = ZcashNetworkBuilder.network(for: .mainnet) +// let service = MockLightWalletService( +// latestBlockHeight: 1210000, +// service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default).make() +// ) +// mockContainer.mock(type: LightWalletService.self, isSingleton: true) { _ in service } +// +// let storage = FSCompactBlockRepository( +// fsBlockDbRoot: testTempDirectory, +// metadataStore: FSMetadataStore.live( +// fsBlockDbRoot: testTempDirectory, +// rustBackend: rustBackend, +// logger: logger +// ), +// blockDescriptor: .live, +// contentProvider: DirectoryListingProviders.defaultSorted, +// logger: logger +// ) +// mockContainer.mock(type: CompactBlockRepository.self, isSingleton: true) { _ in storage } +// +// try await storage.create() +// +// mockContainer.mock(type: BlockDownloaderService.self, isSingleton: true) { _ in +// let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000) +// return BlockDownloaderServiceImpl(service: service, storage: repository) +// } +// +// let config = CompactBlockProcessor.Configuration( +// alias: .default, +// fsBlockCacheRoot: testTempDirectory, +// dataDb: try! __dataDbURL(), +// spendParamsURL: try! __spendParamsURL(), +// outputParamsURL: try! __outputParamsURL(), +// saplingParamsSourceURL: SaplingParamsSourceURL.tests, +// retries: 5, +// maxBackoffInterval: 10, +// rewindDistance: 100, +// walletBirthdayProvider: { 1210000 }, +// saplingActivation: network.constants.saplingActivationHeight, +// network: network +// ) +// +// var info = LightdInfo() +// info.blockHeight = 130000 +// info.branch = "d34db33f" +// info.chainName = "main" +// info.buildUser = "test user" +// info.consensusBranchID = "d34db4d" +// info.saplingActivationHeight = UInt64(3434343) +// +// service.mockLightDInfo = info +// +// let mockBackend = await RustBackendMockHelper(rustBackend: rustBackend, consensusBranchID: 0xd34db4d) +// mockContainer.mock(type: ZcashRustBackendWelding.self, isSingleton: true) { _ in mockBackend.rustBackendMock } +// +// let compactBlockProcessor = CompactBlockProcessor( +// container: mockContainer, +// config: config +// ) +// +// do { +// try await compactBlockProcessor.figureNextBatch(downloaderService: mockContainer.resolve(BlockDownloaderService.self)) +// XCTAssertFalse(Task.isCancelled) +// } catch { +// switch error { +// case ZcashError.compactBlockProcessorSaplingActivationMismatch( +// network.constants.saplingActivationHeight, +// BlockHeight(info.saplingActivationHeight) +// ): +// break +// default: +// XCTFail("Expected ZcashError.compactBlockProcessorSaplingActivationMismatch but found \(error)") +// } +// } +// } +// +// func testResultIsWait() async throws { +// let network = ZcashNetworkBuilder.network(for: .mainnet) +// +// let expectedLatestHeight = BlockHeight(1210000) +// let service = MockLightWalletService( +// latestBlockHeight: expectedLatestHeight, +// service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default).make() +// ) +// let expectedStoredLatestHeight = BlockHeight(1220000) +// let expectedResult = CompactBlockProcessor.NextState.wait( +// latestHeight: expectedLatestHeight, +// latestDownloadHeight: expectedStoredLatestHeight +// ) +// +// let repository = ZcashConsoleFakeStorage(latestBlockHeight: expectedStoredLatestHeight) +// let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository) +// +// let config = CompactBlockProcessor.Configuration( +// alias: .default, +// fsBlockCacheRoot: testTempDirectory, +// dataDb: try! __dataDbURL(), +// spendParamsURL: try! __spendParamsURL(), +// outputParamsURL: try! __outputParamsURL(), +// saplingParamsSourceURL: SaplingParamsSourceURL.tests, +// retries: 5, +// maxBackoffInterval: 10, +// rewindDistance: 100, +// walletBirthdayProvider: { 1210000 }, +// saplingActivation: network.constants.saplingActivationHeight, +// network: network +// ) +// +// var info = LightdInfo() +// info.blockHeight = UInt64(expectedLatestHeight) +// info.branch = "d34db33f" +// info.chainName = "main" +// info.buildUser = "test user" +// info.consensusBranchID = "d34db4d" +// info.saplingActivationHeight = UInt64(network.constants.saplingActivationHeight) +// +// service.mockLightDInfo = info +// +// let mockBackend = await RustBackendMockHelper(rustBackend: rustBackend, consensusBranchID: 0xd34db4d) +// +// var nextBatch: CompactBlockProcessor.NextState? +// do { +// nextBatch = try await CompactBlockProcessor.NextStateHelper.nextState( +// service: service, +// downloaderService: downloaderService, +// latestBlocksDataProvider: LatestBlocksDataProviderMock( +// latestScannedHeight: expectedStoredLatestHeight, +// latestBlockHeight: expectedLatestHeight +// ), +// config: config, +// rustBackend: mockBackend.rustBackendMock, +// internalSyncProgress: InternalSyncProgress( +// alias: .default, +// storage: InternalSyncProgressMemoryStorage(), +// logger: logger +// ) +// ) +// XCTAssertFalse(Task.isCancelled) +// } catch { +// XCTFail("this shouldn't happen: \(error)") +// } +// +// guard nextBatch != nil else { +// XCTFail("result should not be nil") +// return +// } +// +// XCTAssertTrue( +// { +// switch (nextBatch, expectedResult) { +// case let (.wait(latestHeight, latestDownloadHeight), .wait(expectedLatestHeight, exectedLatestDownloadHeight)): +// return latestHeight == expectedLatestHeight && latestDownloadHeight == exectedLatestDownloadHeight +// default: +// return false +// } +// }(), +// "Expected \(expectedResult) got: \(String(describing: nextBatch))" +// ) +// } +// +// func testResultProcessNew() async throws { +// let network = ZcashNetworkBuilder.network(for: .mainnet) +// let expectedLatestHeight = BlockHeight(1230000) +// let service = MockLightWalletService( +// latestBlockHeight: expectedLatestHeight, +// service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default).make() +// ) +// let expectedStoredLatestHeight = BlockHeight(1220000) +// let walletBirthday = BlockHeight(1210000) +// +// let ranges = SyncRanges( +// latestBlockHeight: expectedLatestHeight, +// downloadedButUnscannedRange: nil, +// downloadAndScanRange: expectedStoredLatestHeight + 1...expectedLatestHeight, +// enhanceRange: walletBirthday...expectedLatestHeight, +// fetchUTXORange: walletBirthday...expectedLatestHeight, +// latestScannedHeight: expectedStoredLatestHeight, +// latestDownloadedBlockHeight: expectedStoredLatestHeight +// ) +// let expectedResult = CompactBlockProcessor.NextState.processNewBlocks(ranges: ranges) +// +// let repository = ZcashConsoleFakeStorage(latestBlockHeight: expectedStoredLatestHeight) +// let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository) +// let config = CompactBlockProcessor.Configuration( +// alias: .default, +// fsBlockCacheRoot: testTempDirectory, +// dataDb: try! __dataDbURL(), +// spendParamsURL: try! __spendParamsURL(), +// outputParamsURL: try! __outputParamsURL(), +// saplingParamsSourceURL: SaplingParamsSourceURL.tests, +// downloadBatchSize: 100, +// retries: 5, +// maxBackoffInterval: 10, +// rewindDistance: 100, +// walletBirthdayProvider: { walletBirthday }, +// saplingActivation: network.constants.saplingActivationHeight, +// network: network +// ) +// +// var info = LightdInfo() +// info.blockHeight = UInt64(expectedLatestHeight) +// info.branch = "d34db33f" +// info.chainName = "main" +// info.buildUser = "test user" +// info.consensusBranchID = "d34db4d" +// info.saplingActivationHeight = UInt64(network.constants.saplingActivationHeight) +// +// service.mockLightDInfo = info +// +// let mockBackend = await RustBackendMockHelper(rustBackend: rustBackend, consensusBranchID: 0xd34db4d) +// +// var nextBatch: CompactBlockProcessor.NextState? +// do { +// nextBatch = try await CompactBlockProcessor.NextStateHelper.nextState( +// service: service, +// downloaderService: downloaderService, +// latestBlocksDataProvider: LatestBlocksDataProviderMock( +// latestScannedHeight: expectedStoredLatestHeight, +// latestBlockHeight: expectedLatestHeight +// ), +// config: config, +// rustBackend: mockBackend.rustBackendMock, +// internalSyncProgress: InternalSyncProgress( +// alias: .default, +// storage: InternalSyncProgressMemoryStorage(), +// logger: logger +// ) +// ) +// XCTAssertFalse(Task.isCancelled) +// } catch { +// XCTFail("this shouldn't happen: \(error)") +// } +// +// guard nextBatch != nil else { +// XCTFail("result should not be nil") +// return +// } +// +// XCTAssertTrue( +// { +// switch (nextBatch, expectedResult) { +// case let (.processNewBlocks(ranges), .processNewBlocks(expectedRanges)): +// return ranges == expectedRanges +// default: +// return false +// } +// }(), +// "Expected \(expectedResult) got: \(String(describing: nextBatch))" +// ) +// } +// +// func testResultProcessorFinished() async throws { +// let network = ZcashNetworkBuilder.network(for: .mainnet) +// let expectedLatestHeight = BlockHeight(1230000) +// let service = MockLightWalletService( +// latestBlockHeight: expectedLatestHeight, +// service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default).make() +// ) +// let expectedStoredLatestHeight = BlockHeight(1230000) +// let walletBirthday = BlockHeight(1210000) +// let expectedResult = CompactBlockProcessor.NextState.finishProcessing(height: expectedStoredLatestHeight) +// let repository = ZcashConsoleFakeStorage(latestBlockHeight: expectedStoredLatestHeight) +// let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository) +// let config = CompactBlockProcessor.Configuration( +// alias: .default, +// fsBlockCacheRoot: testTempDirectory, +// dataDb: try! __dataDbURL(), +// spendParamsURL: try! __spendParamsURL(), +// outputParamsURL: try! __outputParamsURL(), +// saplingParamsSourceURL: SaplingParamsSourceURL.tests, +// downloadBatchSize: 100, +// retries: 5, +// maxBackoffInterval: 10, +// rewindDistance: 100, +// walletBirthdayProvider: { walletBirthday }, +// saplingActivation: network.constants.saplingActivationHeight, +// network: network +// ) +// +// let internalSyncProgress = InternalSyncProgress( +// alias: .default, +// storage: InternalSyncProgressMemoryStorage(), +// logger: logger +// ) +// await internalSyncProgress.set(expectedStoredLatestHeight, .latestEnhancedHeight) +// await internalSyncProgress.set(expectedStoredLatestHeight, .latestUTXOFetchedHeight) +// +// var info = LightdInfo() +// info.blockHeight = UInt64(expectedLatestHeight) +// info.branch = "d34db33f" +// info.chainName = "main" +// info.buildUser = "test user" +// info.consensusBranchID = "d34db4d" +// info.saplingActivationHeight = UInt64(network.constants.saplingActivationHeight) +// +// service.mockLightDInfo = info +// +// let mockBackend = await RustBackendMockHelper(rustBackend: rustBackend, consensusBranchID: 0xd34db4d) +// +// var nextBatch: CompactBlockProcessor.NextState? +// do { +// nextBatch = try await CompactBlockProcessor.NextStateHelper.nextState( +// service: service, +// downloaderService: downloaderService, +// latestBlocksDataProvider: LatestBlocksDataProviderMock( +// latestScannedHeight: expectedStoredLatestHeight, +// latestBlockHeight: expectedLatestHeight +// ), +// config: config, +// rustBackend: mockBackend.rustBackendMock, +// internalSyncProgress: internalSyncProgress +// ) +// +// XCTAssertFalse(Task.isCancelled) +// } catch { +// XCTFail("this shouldn't happen: \(error)") +// } +// +// guard nextBatch != nil else { +// XCTFail("result should not be nil") +// return +// } +// +// XCTAssertTrue( +// { +// switch (nextBatch, expectedResult) { +// case let (.finishProcessing(height), .finishProcessing(expectedHeight)): +// return height == expectedHeight +// default: +// return false +// } +// }(), +// "Expected \(expectedResult) got: \(String(describing: nextBatch))" +// ) +// } } diff --git a/Tests/OfflineTests/CompactBlockProcessorActions/ValidateServerActionTests.swift b/Tests/OfflineTests/CompactBlockProcessorActions/ValidateServerActionTests.swift new file mode 100644 index 00000000..40c6e753 --- /dev/null +++ b/Tests/OfflineTests/CompactBlockProcessorActions/ValidateServerActionTests.swift @@ -0,0 +1,148 @@ +// +// ValidateServerActionTests.swift +// +// +// Created by Lukáš Korba on 16.05.2023. +// + +import XCTest +@testable import TestUtils +@testable import ZcashLightClientKit + +final class ValidateServerActionTests: ZcashTestCase { + var underlyingChainName = "" + var underlyingNetworkType = NetworkType.testnet + var underlyingSaplingActivationHeight: BlockHeight? + var underlyingConsensusBranchID = "" + + override func setUp() { + super.setUp() + + underlyingChainName = "test" + underlyingNetworkType = .testnet + underlyingSaplingActivationHeight = nil + underlyingConsensusBranchID = "c2d6d0b4" + } + + func testValidateServerAction_NextAction() async throws { + let validateAction = setupAction() + + do { + let nextContext = try await validateAction.run(with: .init(state: .validateServer)) { _ in } + let nextState = await nextContext.state + XCTAssertTrue( + nextState == .computeSyncRanges, + "nextContext after .validateServer is expected to be .computeSyncRanges but received \(nextState)" + ) + } catch { + XCTFail("testValidateServerActionNextAction is not expected to fail. \(error)") + } + } + + func testValidateServerAction_ChainNameError() async throws { + underlyingChainName = "invalid" + + let validateAction = setupAction() + + do { + _ = try await validateAction.run(with: .init(state: .validateServer)) { _ in } + XCTFail("testValidateServerAction_ChainNameError is expected to fail.") + } catch ZcashError.compactBlockProcessorChainName(let chainName) { + XCTAssertEqual(chainName, "invalid") + } catch { + XCTFail("testValidateServerActionNextAction is expected to fail but error \(error) doesn't match ZcashError.compactBlockProcessorChainName") + } + } + + func testValidateServerAction_NetworkMatchError() async throws { + underlyingNetworkType = .mainnet + + let validateAction = setupAction() + + do { + _ = try await validateAction.run(with: .init(state: .validateServer)) { _ in } + XCTFail("testValidateServerAction_NetworkMatchError is expected to fail.") + } catch let ZcashError.compactBlockProcessorNetworkMismatch(expected, found) { + XCTAssertEqual(expected, .mainnet) + XCTAssertEqual(found, .testnet) + } catch { + XCTFail("testValidateServerAction_NetworkMatchError is expected to fail but error \(error) doesn't match ZcashError.compactBlockProcessorNetworkMismatch") + } + } + + func testValidateServerAction_SaplingActivationError() async throws { + underlyingSaplingActivationHeight = 1 + + let validateAction = setupAction() + + do { + _ = try await validateAction.run(with: .init(state: .validateServer)) { _ in } + XCTFail("testValidateServerAction_SaplingActivationError is expected to fail.") + } catch let ZcashError.compactBlockProcessorSaplingActivationMismatch(expected, found) { + XCTAssertEqual(expected, 280_000) + XCTAssertEqual(found, 1) + } catch { + XCTFail("testValidateServerAction_SaplingActivationError is expected to fail but error \(error) doesn't match ZcashError.compactBlockProcessorSaplingActivationMismatch") + } + } + + func testValidateServerAction_ConsensusBranchIDError_InvalidRemoteBranch() async throws { + underlyingConsensusBranchID = "1 1" + + let validateAction = setupAction() + + do { + _ = try await validateAction.run(with: .init(state: .validateServer)) { _ in } + XCTFail("testValidateServerAction_ConsensusBranchIDError_InvalidRemoteBranch is expected to fail.") + } catch ZcashError.compactBlockProcessorConsensusBranchID { + } catch { + XCTFail("testValidateServerAction_ConsensusBranchIDError_InvalidRemoteBranch is expected to fail but error \(error) doesn't match ZcashError.compactBlockProcessorConsensusBranchID") + } + } + + func testValidateServerAction_ConsensusBranchIDError_ValidRemoteBranch() async throws { + underlyingConsensusBranchID = "1" + + let validateAction = setupAction() + + do { + _ = try await validateAction.run(with: .init(state: .validateServer)) { _ in } + XCTFail("testValidateServerAction_ConsensusBranchIDError_ValidRemoteBranch is expected to fail.") + } catch let ZcashError.compactBlockProcessorWrongConsensusBranchId(expected, found) { + XCTAssertEqual(expected, -1026109260) + XCTAssertEqual(found, 1) + } catch { + XCTFail("testValidateServerAction_ConsensusBranchIDError_ValidRemoteBranch is expected to fail but error \(error) doesn't match ZcashError.compactBlockProcessorWrongConsensusBranchId") + } + } + + func setupAction() -> ValidateServerAction { + let config: CompactBlockProcessor.Configuration = .standard( + for: ZcashNetworkBuilder.network(for: underlyingNetworkType), walletBirthday: 0 + ) + + let rustBackendMock = ZcashRustBackendWeldingMock( + consensusBranchIdForHeightClosure: { height in + XCTAssertEqual(height, 2, "") + return -1026109260 + } + ) + + let lightWalletdInfoMock = LightWalletdInfoMock() + lightWalletdInfoMock.underlyingConsensusBranchID = underlyingConsensusBranchID + lightWalletdInfoMock.underlyingSaplingActivationHeight = UInt64(underlyingSaplingActivationHeight ?? config.saplingActivation) + lightWalletdInfoMock.underlyingBlockHeight = 2 + lightWalletdInfoMock.underlyingChainName = underlyingChainName + + let serviceMock = LightWalletServiceMock() + serviceMock.getInfoReturnValue = lightWalletdInfoMock + + mockContainer.mock(type: ZcashRustBackendWelding.self, isSingleton: true) { _ in rustBackendMock } + mockContainer.mock(type: LightWalletService.self, isSingleton: true) { _ in serviceMock } + + return ValidateServerAction( + container: mockContainer, + config: config + ) + } +} diff --git a/Tests/OfflineTests/CompactBlockProcessorOfflineTests.swift b/Tests/OfflineTests/CompactBlockProcessorOfflineTests.swift index 1e3b9211..fe775ffa 100644 --- a/Tests/OfflineTests/CompactBlockProcessorOfflineTests.swift +++ b/Tests/OfflineTests/CompactBlockProcessorOfflineTests.swift @@ -39,49 +39,50 @@ class CompactBlockProcessorOfflineTests: ZcashTestCase { try FileManager.default.removeItem(at: testTempDirectory) } - func testComputeProcessingRangeForSingleLoop() async throws { - let network = ZcashNetworkBuilder.network(for: .testnet) - let rustBackend = ZcashRustBackend.makeForTests(fsBlockDbRoot: testTempDirectory, networkType: .testnet) - - let processorConfig = CompactBlockProcessor.Configuration.standard( - for: network, - walletBirthday: ZcashNetworkBuilder.network(for: .testnet).constants.saplingActivationHeight - ) - - let service = MockLightWalletService( - latestBlockHeight: 690000, - service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.eccTestnet).make() - ) - mockContainer.mock(type: LightWalletService.self, isSingleton: true) { _ in service } - - let storage = FSCompactBlockRepository( - fsBlockDbRoot: testTempDirectory, - metadataStore: FSMetadataStore.live( - fsBlockDbRoot: testTempDirectory, - rustBackend: rustBackend, - logger: logger - ), - blockDescriptor: .live, - contentProvider: DirectoryListingProviders.defaultSorted, - logger: logger - ) - mockContainer.mock(type: CompactBlockRepository.self, isSingleton: true) { _ in storage } - mockContainer.mock(type: LatestBlocksDataProvider.self, isSingleton: true) { _ in LatestBlocksDataProviderMock() } - - let processor = CompactBlockProcessor( - container: mockContainer, - config: processorConfig - ) - - let fullRange = 0...1000 - - var range = await processor.computeSingleLoopDownloadRange(fullRange: fullRange, loopCounter: 0, batchSize: 100) - XCTAssertEqual(range, 0...99) - - range = await processor.computeSingleLoopDownloadRange(fullRange: fullRange, loopCounter: 5, batchSize: 100) - XCTAssertEqual(range, 500...599) - - range = await processor.computeSingleLoopDownloadRange(fullRange: fullRange, loopCounter: 10, batchSize: 100) - XCTAssertEqual(range, 1000...1000) - } + // TODO: [1095] review this test https://github.com/zcash/ZcashLightClientKit/issues/1095 +// func testComputeProcessingRangeForSingleLoop() async throws { +// let network = ZcashNetworkBuilder.network(for: .testnet) +// let rustBackend = ZcashRustBackend.makeForTests(fsBlockDbRoot: testTempDirectory, networkType: .testnet) +// +// let processorConfig = CompactBlockProcessor.Configuration.standard( +// for: network, +// walletBirthday: ZcashNetworkBuilder.network(for: .testnet).constants.saplingActivationHeight +// ) +// +// let service = MockLightWalletService( +// latestBlockHeight: 690000, +// service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.eccTestnet).make() +// ) +// mockContainer.mock(type: LightWalletService.self, isSingleton: true) { _ in service } +// +// let storage = FSCompactBlockRepository( +// fsBlockDbRoot: testTempDirectory, +// metadataStore: FSMetadataStore.live( +// fsBlockDbRoot: testTempDirectory, +// rustBackend: rustBackend, +// logger: logger +// ), +// blockDescriptor: .live, +// contentProvider: DirectoryListingProviders.defaultSorted, +// logger: logger +// ) +// mockContainer.mock(type: CompactBlockRepository.self, isSingleton: true) { _ in storage } +// mockContainer.mock(type: LatestBlocksDataProvider.self, isSingleton: true) { _ in LatestBlocksDataProviderMock() } +// +// let processor = CompactBlockProcessor( +// container: mockContainer, +// config: processorConfig +// ) +// +// let fullRange = 0...1000 +// +// var range = await processor.computeSingleLoopDownloadRange(fullRange: fullRange, loopCounter: 0, batchSize: 100) +// XCTAssertEqual(range, 0...99) +// +// range = await processor.computeSingleLoopDownloadRange(fullRange: fullRange, loopCounter: 5, batchSize: 100) +// XCTAssertEqual(range, 500...599) +// +// range = await processor.computeSingleLoopDownloadRange(fullRange: fullRange, loopCounter: 10, batchSize: 100) +// XCTAssertEqual(range, 1000...1000) +// } } diff --git a/Tests/TestUtils/Sourcery/AutoMockable.stencil b/Tests/TestUtils/Sourcery/AutoMockable.stencil index f14be10b..388bbf54 100644 --- a/Tests/TestUtils/Sourcery/AutoMockable.stencil +++ b/Tests/TestUtils/Sourcery/AutoMockable.stencil @@ -1,5 +1,6 @@ import Combine @testable import ZcashLightClientKit +import Foundation {% macro methodName method%}{%if method|annotated:"mockedName" %}{{ method.annotations.mockedName }}{% else %}{% call swiftifyMethodName method.selectorName %}{% endif %}{% endmacro %} {% macro swiftifyMethodName name %}{{ name | replace:"(","_" | replace:")","" | replace:":","_" | replace:"`","" | snakeToCamelCase | lowerFirstWord }}{% endmacro %} diff --git a/Tests/TestUtils/Sourcery/AutoMockable.swift b/Tests/TestUtils/Sourcery/AutoMockable.swift index c1b6e08d..18d42d6f 100644 --- a/Tests/TestUtils/Sourcery/AutoMockable.swift +++ b/Tests/TestUtils/Sourcery/AutoMockable.swift @@ -14,5 +14,7 @@ extension ZcashRustBackendWelding { } extension Synchronizer { } +extension LightWalletService { } +extension LightWalletdInfo { } // sourcery:end: diff --git a/Tests/TestUtils/Sourcery/GeneratedMocks/AutoMockable.generated.swift b/Tests/TestUtils/Sourcery/GeneratedMocks/AutoMockable.generated.swift index a400794e..c5325771 100644 --- a/Tests/TestUtils/Sourcery/GeneratedMocks/AutoMockable.generated.swift +++ b/Tests/TestUtils/Sourcery/GeneratedMocks/AutoMockable.generated.swift @@ -2,10 +2,291 @@ // DO NOT EDIT import Combine @testable import ZcashLightClientKit +import Foundation // MARK: - AutoMockable protocols +class LightWalletServiceMock: LightWalletService { + + + init( + ) { + } + var connectionStateChange: ((_ from: ConnectionState, _ to: ConnectionState) -> Void)? + + // MARK: - getInfo + + var getInfoThrowableError: Error? + var getInfoCallsCount = 0 + var getInfoCalled: Bool { + return getInfoCallsCount > 0 + } + var getInfoReturnValue: LightWalletdInfo! + var getInfoClosure: (() async throws -> LightWalletdInfo)? + + func getInfo() async throws -> LightWalletdInfo { + if let error = getInfoThrowableError { + throw error + } + getInfoCallsCount += 1 + if let closure = getInfoClosure { + return try await closure() + } else { + return getInfoReturnValue + } + } + + // MARK: - latestBlock + + var latestBlockThrowableError: Error? + var latestBlockCallsCount = 0 + var latestBlockCalled: Bool { + return latestBlockCallsCount > 0 + } + var latestBlockReturnValue: BlockID! + var latestBlockClosure: (() async throws -> BlockID)? + + func latestBlock() async throws -> BlockID { + if let error = latestBlockThrowableError { + throw error + } + latestBlockCallsCount += 1 + if let closure = latestBlockClosure { + return try await closure() + } else { + return latestBlockReturnValue + } + } + + // MARK: - latestBlockHeight + + var latestBlockHeightThrowableError: Error? + var latestBlockHeightCallsCount = 0 + var latestBlockHeightCalled: Bool { + return latestBlockHeightCallsCount > 0 + } + var latestBlockHeightReturnValue: BlockHeight! + var latestBlockHeightClosure: (() async throws -> BlockHeight)? + + func latestBlockHeight() async throws -> BlockHeight { + if let error = latestBlockHeightThrowableError { + throw error + } + latestBlockHeightCallsCount += 1 + if let closure = latestBlockHeightClosure { + return try await closure() + } else { + return latestBlockHeightReturnValue + } + } + + // MARK: - blockRange + + var blockRangeCallsCount = 0 + var blockRangeCalled: Bool { + return blockRangeCallsCount > 0 + } + var blockRangeReceivedRange: CompactBlockRange? + var blockRangeReturnValue: AsyncThrowingStream! + var blockRangeClosure: ((CompactBlockRange) -> AsyncThrowingStream)? + + func blockRange(_ range: CompactBlockRange) -> AsyncThrowingStream { + blockRangeCallsCount += 1 + blockRangeReceivedRange = range + if let closure = blockRangeClosure { + return closure(range) + } else { + return blockRangeReturnValue + } + } + + // MARK: - submit + + var submitSpendTransactionThrowableError: Error? + var submitSpendTransactionCallsCount = 0 + var submitSpendTransactionCalled: Bool { + return submitSpendTransactionCallsCount > 0 + } + var submitSpendTransactionReceivedSpendTransaction: Data? + var submitSpendTransactionReturnValue: LightWalletServiceResponse! + var submitSpendTransactionClosure: ((Data) async throws -> LightWalletServiceResponse)? + + func submit(spendTransaction: Data) async throws -> LightWalletServiceResponse { + if let error = submitSpendTransactionThrowableError { + throw error + } + submitSpendTransactionCallsCount += 1 + submitSpendTransactionReceivedSpendTransaction = spendTransaction + if let closure = submitSpendTransactionClosure { + return try await closure(spendTransaction) + } else { + return submitSpendTransactionReturnValue + } + } + + // MARK: - fetchTransaction + + var fetchTransactionTxIdThrowableError: Error? + var fetchTransactionTxIdCallsCount = 0 + var fetchTransactionTxIdCalled: Bool { + return fetchTransactionTxIdCallsCount > 0 + } + var fetchTransactionTxIdReceivedTxId: Data? + var fetchTransactionTxIdReturnValue: ZcashTransaction.Fetched! + var fetchTransactionTxIdClosure: ((Data) async throws -> ZcashTransaction.Fetched)? + + func fetchTransaction(txId: Data) async throws -> ZcashTransaction.Fetched { + if let error = fetchTransactionTxIdThrowableError { + throw error + } + fetchTransactionTxIdCallsCount += 1 + fetchTransactionTxIdReceivedTxId = txId + if let closure = fetchTransactionTxIdClosure { + return try await closure(txId) + } else { + return fetchTransactionTxIdReturnValue + } + } + + // MARK: - fetchUTXOs + + var fetchUTXOsSingleCallsCount = 0 + var fetchUTXOsSingleCalled: Bool { + return fetchUTXOsSingleCallsCount > 0 + } + var fetchUTXOsSingleReceivedArguments: (tAddress: String, height: BlockHeight)? + var fetchUTXOsSingleReturnValue: AsyncThrowingStream! + var fetchUTXOsSingleClosure: ((String, BlockHeight) -> AsyncThrowingStream)? + + func fetchUTXOs(for tAddress: String, height: BlockHeight) -> AsyncThrowingStream { + fetchUTXOsSingleCallsCount += 1 + fetchUTXOsSingleReceivedArguments = (tAddress: tAddress, height: height) + if let closure = fetchUTXOsSingleClosure { + return closure(tAddress, height) + } else { + return fetchUTXOsSingleReturnValue + } + } + + // MARK: - fetchUTXOs + + var fetchUTXOsForHeightCallsCount = 0 + var fetchUTXOsForHeightCalled: Bool { + return fetchUTXOsForHeightCallsCount > 0 + } + var fetchUTXOsForHeightReceivedArguments: (tAddresses: [String], height: BlockHeight)? + var fetchUTXOsForHeightReturnValue: AsyncThrowingStream! + var fetchUTXOsForHeightClosure: (([String], BlockHeight) -> AsyncThrowingStream)? + + func fetchUTXOs(for tAddresses: [String], height: BlockHeight) -> AsyncThrowingStream { + fetchUTXOsForHeightCallsCount += 1 + fetchUTXOsForHeightReceivedArguments = (tAddresses: tAddresses, height: height) + if let closure = fetchUTXOsForHeightClosure { + return closure(tAddresses, height) + } else { + return fetchUTXOsForHeightReturnValue + } + } + + // MARK: - blockStream + + var blockStreamStartHeightEndHeightCallsCount = 0 + var blockStreamStartHeightEndHeightCalled: Bool { + return blockStreamStartHeightEndHeightCallsCount > 0 + } + var blockStreamStartHeightEndHeightReceivedArguments: (startHeight: BlockHeight, endHeight: BlockHeight)? + var blockStreamStartHeightEndHeightReturnValue: AsyncThrowingStream! + var blockStreamStartHeightEndHeightClosure: ((BlockHeight, BlockHeight) -> AsyncThrowingStream)? + + func blockStream(startHeight: BlockHeight, endHeight: BlockHeight) -> AsyncThrowingStream { + blockStreamStartHeightEndHeightCallsCount += 1 + blockStreamStartHeightEndHeightReceivedArguments = (startHeight: startHeight, endHeight: endHeight) + if let closure = blockStreamStartHeightEndHeightClosure { + return closure(startHeight, endHeight) + } else { + return blockStreamStartHeightEndHeightReturnValue + } + } + + // MARK: - closeConnection + + var closeConnectionCallsCount = 0 + var closeConnectionCalled: Bool { + return closeConnectionCallsCount > 0 + } + var closeConnectionClosure: (() -> Void)? + + func closeConnection() { + closeConnectionCallsCount += 1 + closeConnectionClosure?() + } + +} +class LightWalletdInfoMock: LightWalletdInfo { + + + init( + ) { + } + var version: String { + get { return underlyingVersion } + } + var underlyingVersion: String! + var vendor: String { + get { return underlyingVendor } + } + var underlyingVendor: String! + var taddrSupport: Bool { + get { return underlyingTaddrSupport } + } + var underlyingTaddrSupport: Bool! + var chainName: String { + get { return underlyingChainName } + } + var underlyingChainName: String! + var saplingActivationHeight: UInt64 { + get { return underlyingSaplingActivationHeight } + } + var underlyingSaplingActivationHeight: UInt64! + var consensusBranchID: String { + get { return underlyingConsensusBranchID } + } + var underlyingConsensusBranchID: String! + var blockHeight: UInt64 { + get { return underlyingBlockHeight } + } + var underlyingBlockHeight: UInt64! + var gitCommit: String { + get { return underlyingGitCommit } + } + var underlyingGitCommit: String! + var branch: String { + get { return underlyingBranch } + } + var underlyingBranch: String! + var buildDate: String { + get { return underlyingBuildDate } + } + var underlyingBuildDate: String! + var buildUser: String { + get { return underlyingBuildUser } + } + var underlyingBuildUser: String! + var estimatedHeight: UInt64 { + get { return underlyingEstimatedHeight } + } + var underlyingEstimatedHeight: UInt64! + var zcashdBuild: String { + get { return underlyingZcashdBuild } + } + var underlyingZcashdBuild: String! + var zcashdSubversion: String { + get { return underlyingZcashdSubversion } + } + var underlyingZcashdSubversion: String! + +} class SynchronizerMock: Synchronizer { diff --git a/Tests/TestUtils/TestCoordinator.swift b/Tests/TestUtils/TestCoordinator.swift index c93ffd14..5e474754 100644 --- a/Tests/TestUtils/TestCoordinator.swift +++ b/Tests/TestUtils/TestCoordinator.swift @@ -221,7 +221,6 @@ extension TestCoordinator { spendParamsURL: config.spendParamsURL, outputParamsURL: config.outputParamsURL, saplingParamsSourceURL: config.saplingParamsSourceURL, - downloadBatchSize: config.downloadBatchSize, retries: config.retries, maxBackoffInterval: config.maxBackoffInterval, rewindDistance: config.rewindDistance, @@ -230,7 +229,7 @@ extension TestCoordinator { network: config.network ) - await self.synchronizer.blockProcessor.update(config: newConfig) +// await self.synchronizer.blockProcessor.update(config: newConfig) } try service.reset(saplingActivation: saplingActivation, branchID: branchID, chainName: chainName)