[#1042] Implement ComputeSyncRangesAction
- draft [#1042] Implement ComputeSyncRangesAction - ComputeSyncRangesAction tests - fixed all tests after merge of latest SDK changes related InternalSyncProgress - all actions marked as final class [#1042] Implement ComputeSyncRangesAction (#1120) - Custom LatestBlocksDataProviderMock removed from the project
This commit is contained in:
parent
b4d8aedaa1
commit
78d72d32ab
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class ChecksBeforeSyncAction {
|
||||
final class ChecksBeforeSyncAction {
|
||||
let internalSyncProgress: InternalSyncProgress
|
||||
let storage: CompactBlockRepository
|
||||
init(container: DIContainer) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class ClearAlreadyScannedBlocksAction {
|
||||
final class ClearAlreadyScannedBlocksAction {
|
||||
let storage: CompactBlockRepository
|
||||
let transactionRepository: TransactionRepository
|
||||
init(container: DIContainer) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class ClearCacheAction {
|
||||
final class ClearCacheAction {
|
||||
let storage: CompactBlockRepository
|
||||
init(container: DIContainer) {
|
||||
storage = container.resolve(CompactBlockRepository.self)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class ComputeSyncRangesAction {
|
||||
final class ComputeSyncRangesAction {
|
||||
let config: CompactBlockProcessor.Configuration
|
||||
let downloaderService: BlockDownloaderService
|
||||
let internalSyncProgress: InternalSyncProgress
|
||||
|
@ -24,7 +24,7 @@ class ComputeSyncRangesAction {
|
|||
|
||||
/// It may happen that sync process start with syncing blocks that were downloaded but not synced in previous run of the sync process. This
|
||||
/// methods analyses what must be done and computes range that should be used to compute reported progress.
|
||||
private func computeTotalProgressRange(from syncRanges: SyncRanges) -> CompactBlockRange {
|
||||
func computeTotalProgressRange(from syncRanges: SyncRanges) -> CompactBlockRange {
|
||||
guard syncRanges.downloadRange != nil || syncRanges.scanRange != nil else {
|
||||
// In this case we are sure that no downloading or scanning happens so this returned range won't be even used. And it's easier to return
|
||||
// this "fake" range than to handle nil.
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class DownloadAction {
|
||||
final class DownloadAction {
|
||||
let config: CompactBlockProcessor.Configuration
|
||||
let downloader: BlockDownloader
|
||||
let transactionRepository: TransactionRepository
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class EnhanceAction {
|
||||
final class EnhanceAction {
|
||||
let blockEnhancer: BlockEnhancer
|
||||
let config: CompactBlockProcessor.Configuration
|
||||
let internalSyncProgress: InternalSyncProgress
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class FetchUTXOsAction {
|
||||
final class FetchUTXOsAction {
|
||||
let utxoFetcher: UTXOFetcher
|
||||
let logger: Logger
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class MigrateLegacyCacheDBAction {
|
||||
final class MigrateLegacyCacheDBAction {
|
||||
private let config: CompactBlockProcessor.Configuration
|
||||
private let internalSyncProgress: InternalSyncProgress
|
||||
private let storage: CompactBlockRepository
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class SaplingParamsAction {
|
||||
final class SaplingParamsAction {
|
||||
let saplingParametersHandler: SaplingParametersHandler
|
||||
let logger: Logger
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class ScanAction {
|
||||
final class ScanAction {
|
||||
let config: CompactBlockProcessor.Configuration
|
||||
let blockScanner: BlockScanner
|
||||
let logger: Logger
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class ValidateAction {
|
||||
final class ValidateAction {
|
||||
let validator: BlockValidator
|
||||
|
||||
init(container: DIContainer) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class ValidateServerAction {
|
||||
final class ValidateServerAction {
|
||||
let config: CompactBlockProcessor.Configuration
|
||||
let rustBackend: ZcashRustBackendWelding
|
||||
let service: LightWalletService
|
||||
|
|
|
@ -10,19 +10,21 @@ import XCTest
|
|||
@testable import ZcashLightClientKit
|
||||
|
||||
final class ChecksBeforeSyncActionTests: ZcashTestCase {
|
||||
var underlyingDownloadedButUnscannedRange: CompactBlockRange?
|
||||
var underlyingDownloadRange: CompactBlockRange?
|
||||
var underlyingScanRange: CompactBlockRange?
|
||||
var underlyingLatestScannedHeight: BlockHeight?
|
||||
var underlyingLatestDownloadedBlockHeight: BlockHeight?
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
|
||||
underlyingDownloadedButUnscannedRange = nil
|
||||
underlyingDownloadRange = nil
|
||||
underlyingScanRange = nil
|
||||
underlyingLatestScannedHeight = nil
|
||||
underlyingLatestDownloadedBlockHeight = nil
|
||||
}
|
||||
|
||||
func testChecksBeforeSyncAction_shouldClearBlockCacheAndUpdateInternalState_noDownloadedButUnscannedRange() async throws {
|
||||
func testChecksBeforeSyncAction_shouldClearBlockCacheAndUpdateInternalState_noDownloadNoScanRange() async throws {
|
||||
let checksBeforeSyncAction = setupAction()
|
||||
|
||||
let syncRanges = setupSyncRanges()
|
||||
|
@ -34,7 +36,8 @@ final class ChecksBeforeSyncActionTests: ZcashTestCase {
|
|||
func testChecksBeforeSyncAction_shouldClearBlockCacheAndUpdateInternalState_nothingToClear() async throws {
|
||||
let checksBeforeSyncAction = setupAction()
|
||||
|
||||
underlyingDownloadedButUnscannedRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
underlyingDownloadRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
underlyingScanRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
underlyingLatestScannedHeight = BlockHeight(2000)
|
||||
underlyingLatestDownloadedBlockHeight = BlockHeight(2000)
|
||||
|
||||
|
@ -47,7 +50,8 @@ final class ChecksBeforeSyncActionTests: ZcashTestCase {
|
|||
func testChecksBeforeSyncAction_shouldClearBlockCacheAndUpdateInternalState_somethingToClear() async throws {
|
||||
let checksBeforeSyncAction = setupAction()
|
||||
|
||||
underlyingDownloadedButUnscannedRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
underlyingDownloadRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
underlyingScanRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
underlyingLatestScannedHeight = BlockHeight(2000)
|
||||
underlyingLatestDownloadedBlockHeight = BlockHeight(1000)
|
||||
|
||||
|
@ -70,7 +74,8 @@ final class ChecksBeforeSyncActionTests: ZcashTestCase {
|
|||
internalSyncProgressStorageMock
|
||||
)
|
||||
|
||||
underlyingDownloadedButUnscannedRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
underlyingDownloadRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
underlyingScanRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
underlyingLatestScannedHeight = BlockHeight(2000)
|
||||
underlyingLatestDownloadedBlockHeight = BlockHeight(1000)
|
||||
|
||||
|
@ -133,8 +138,8 @@ final class ChecksBeforeSyncActionTests: ZcashTestCase {
|
|||
private func setupSyncRanges() -> SyncRanges {
|
||||
SyncRanges(
|
||||
latestBlockHeight: 0,
|
||||
downloadedButUnscannedRange: underlyingDownloadedButUnscannedRange,
|
||||
downloadAndScanRange: nil,
|
||||
downloadRange: underlyingDownloadRange,
|
||||
scanRange: underlyingScanRange,
|
||||
enhanceRange: nil,
|
||||
fetchUTXORange: nil,
|
||||
latestScannedHeight: underlyingLatestScannedHeight,
|
||||
|
|
|
@ -0,0 +1,225 @@
|
|||
//
|
||||
// ComputeSyncRangesActionTests.swift
|
||||
//
|
||||
//
|
||||
// Created by Lukáš Korba on 22.05.2023.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import TestUtils
|
||||
@testable import ZcashLightClientKit
|
||||
|
||||
final class ComputeSyncRangesActionTests: ZcashTestCase {
|
||||
var underlyingDownloadRange: CompactBlockRange?
|
||||
var underlyingScanRange: CompactBlockRange?
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
|
||||
underlyingDownloadRange = nil
|
||||
underlyingScanRange = nil
|
||||
}
|
||||
|
||||
func testComputeSyncRangesActionTests_computeTotalProgressRange_noDownloadNoScanRange() async throws {
|
||||
let computeSyncRangesAction = setupAction()
|
||||
|
||||
let syncRanges = setupSyncRanges()
|
||||
|
||||
let totalProgressRange = computeSyncRangesAction.computeTotalProgressRange(from: syncRanges)
|
||||
|
||||
XCTAssertTrue(
|
||||
totalProgressRange == 0...0,
|
||||
"testComputeSyncRangesActionTests_computeTotalProgressRange_A is expected to be 0...0 but received \(totalProgressRange)"
|
||||
)
|
||||
}
|
||||
|
||||
func testComputeSyncRangesActionTests_computeTotalProgressRange_ValidRange() async throws {
|
||||
let computeSyncRangesAction = setupAction()
|
||||
|
||||
underlyingDownloadRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
underlyingScanRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
|
||||
let syncRanges = setupSyncRanges()
|
||||
let totalProgressRange = computeSyncRangesAction.computeTotalProgressRange(from: syncRanges)
|
||||
let expectedRange = 1000...2000
|
||||
|
||||
XCTAssertTrue(
|
||||
totalProgressRange == expectedRange,
|
||||
"testComputeSyncRangesActionTests_computeTotalProgressRange_ValidRange is expected to be \(expectedRange) but received \(totalProgressRange)"
|
||||
)
|
||||
}
|
||||
|
||||
func testComputeSyncRangesActionTests_finishProcessingCase() async throws {
|
||||
let blockDownloaderServiceMock = BlockDownloaderServiceMock()
|
||||
let latestBlocksDataProviderMock = LatestBlocksDataProviderMock()
|
||||
let internalSyncProgressStorageMock = InternalSyncProgressStorageMock()
|
||||
let loggerMock = LoggerMock()
|
||||
|
||||
let computeSyncRangesAction = setupDefaultMocksAndReturnAction(
|
||||
blockDownloaderServiceMock,
|
||||
latestBlocksDataProviderMock,
|
||||
internalSyncProgressStorageMock,
|
||||
loggerMock
|
||||
)
|
||||
|
||||
let syncContext = await setupActionContext()
|
||||
|
||||
do {
|
||||
let nextContext = try await computeSyncRangesAction.run(with: syncContext) { _ in }
|
||||
|
||||
XCTAssertTrue(blockDownloaderServiceMock.lastDownloadedBlockHeightCalled, "downloaderService.lastDownloadedBlockHeight() is expected to be called.")
|
||||
XCTAssertTrue(latestBlocksDataProviderMock.updateScannedDataCalled, "latestBlocksDataProvider.updateScannedData() is expected to be called.")
|
||||
XCTAssertTrue(latestBlocksDataProviderMock.updateBlockDataCalled, "latestBlocksDataProvider.updateBlockData() is expected to be called.")
|
||||
XCTAssertFalse(loggerMock.infoFileFunctionLineCalled, "logger.info() is not expected to be called.")
|
||||
|
||||
let nextState = await nextContext.state
|
||||
XCTAssertTrue(
|
||||
nextState == .finished,
|
||||
"nextContext after .computeSyncRanges is expected to be .finished but received \(nextState)"
|
||||
)
|
||||
} catch {
|
||||
XCTFail("testComputeSyncRangesActionTests_FinishProcessing is not expected to fail. \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func testComputeSyncRangesActionTests_checksBeforeSyncCase() async throws {
|
||||
let blockDownloaderServiceMock = BlockDownloaderServiceMock()
|
||||
let latestBlocksDataProviderMock = LatestBlocksDataProviderMock()
|
||||
let internalSyncProgressStorageMock = InternalSyncProgressStorageMock()
|
||||
let loggerMock = LoggerMock()
|
||||
|
||||
let computeSyncRangesAction = setupDefaultMocksAndReturnAction(
|
||||
blockDownloaderServiceMock,
|
||||
latestBlocksDataProviderMock,
|
||||
internalSyncProgressStorageMock,
|
||||
loggerMock
|
||||
)
|
||||
latestBlocksDataProviderMock.underlyingLatestBlockHeight = 10
|
||||
|
||||
let syncContext = await setupActionContext()
|
||||
|
||||
do {
|
||||
let nextContext = try await computeSyncRangesAction.run(with: syncContext) { _ in }
|
||||
|
||||
XCTAssertTrue(blockDownloaderServiceMock.lastDownloadedBlockHeightCalled, "downloaderService.lastDownloadedBlockHeight() is expected to be called.")
|
||||
XCTAssertTrue(latestBlocksDataProviderMock.updateScannedDataCalled, "latestBlocksDataProvider.updateScannedData() is expected to be called.")
|
||||
XCTAssertTrue(latestBlocksDataProviderMock.updateBlockDataCalled, "latestBlocksDataProvider.updateBlockData() is expected to be called.")
|
||||
XCTAssertFalse(loggerMock.infoFileFunctionLineCalled, "logger.info() is not expected to be called.")
|
||||
|
||||
let nextState = await nextContext.state
|
||||
XCTAssertTrue(
|
||||
nextState == .checksBeforeSync,
|
||||
"nextContext after .computeSyncRanges is expected to be .checksBeforeSync but received \(nextState)"
|
||||
)
|
||||
} catch {
|
||||
XCTFail("testComputeSyncRangesActionTests_checksBeforeSyncCase is not expected to fail. \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func testComputeSyncRangesActionTests_waitCase() async throws {
|
||||
let blockDownloaderServiceMock = BlockDownloaderServiceMock()
|
||||
let latestBlocksDataProviderMock = LatestBlocksDataProviderMock()
|
||||
let internalSyncProgressStorageMock = InternalSyncProgressStorageMock()
|
||||
let loggerMock = LoggerMock()
|
||||
|
||||
let computeSyncRangesAction = setupDefaultMocksAndReturnAction(
|
||||
blockDownloaderServiceMock,
|
||||
latestBlocksDataProviderMock,
|
||||
internalSyncProgressStorageMock,
|
||||
loggerMock
|
||||
)
|
||||
blockDownloaderServiceMock.lastDownloadedBlockHeightReturnValue = 10
|
||||
latestBlocksDataProviderMock.underlyingLatestScannedHeight = 10
|
||||
internalSyncProgressStorageMock.integerForKeyReturnValue = 10
|
||||
loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in }
|
||||
|
||||
let syncContext = await setupActionContext()
|
||||
|
||||
do {
|
||||
let nextContext = try await computeSyncRangesAction.run(with: syncContext) { _ in }
|
||||
|
||||
XCTAssertTrue(blockDownloaderServiceMock.lastDownloadedBlockHeightCalled, "downloaderService.lastDownloadedBlockHeight() is expected to be called.")
|
||||
XCTAssertTrue(latestBlocksDataProviderMock.updateScannedDataCalled, "latestBlocksDataProvider.updateScannedData() is expected to be called.")
|
||||
XCTAssertTrue(latestBlocksDataProviderMock.updateBlockDataCalled, "latestBlocksDataProvider.updateBlockData() is expected to be called.")
|
||||
XCTAssertTrue(loggerMock.infoFileFunctionLineCalled, "logger.info() is expected to be called.")
|
||||
|
||||
let nextState = await nextContext.state
|
||||
XCTAssertTrue(
|
||||
nextState == .finished,
|
||||
"nextContext after .computeSyncRanges is expected to be .finished but received \(nextState)"
|
||||
)
|
||||
} catch {
|
||||
XCTFail("testComputeSyncRangesActionTests_waitCase is not expected to fail. \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
private func setupSyncRanges() -> SyncRanges {
|
||||
SyncRanges(
|
||||
latestBlockHeight: 0,
|
||||
downloadRange: underlyingDownloadRange,
|
||||
scanRange: underlyingScanRange,
|
||||
enhanceRange: nil,
|
||||
fetchUTXORange: nil,
|
||||
latestScannedHeight: nil,
|
||||
latestDownloadedBlockHeight: nil
|
||||
)
|
||||
}
|
||||
|
||||
private func setupActionContext() async -> ActionContext {
|
||||
let syncContext: ActionContext = .init(state: .computeSyncRanges)
|
||||
|
||||
await syncContext.update(syncRanges: setupSyncRanges())
|
||||
await syncContext.update(totalProgressRange: CompactBlockRange(uncheckedBounds: (1000, 2000)))
|
||||
|
||||
return syncContext
|
||||
}
|
||||
|
||||
private func setupAction(
|
||||
_ blockDownloaderServiceMock: BlockDownloaderServiceMock = BlockDownloaderServiceMock(),
|
||||
_ latestBlocksDataProviderMock: LatestBlocksDataProviderMock = LatestBlocksDataProviderMock(),
|
||||
_ internalSyncProgressStorageMock: InternalSyncProgressStorageMock = InternalSyncProgressStorageMock(),
|
||||
_ loggerMock: LoggerMock = LoggerMock()
|
||||
) -> ComputeSyncRangesAction {
|
||||
mockContainer.register(type: InternalSyncProgress.self, isSingleton: true) { di in
|
||||
InternalSyncProgress(alias: .default, storage: internalSyncProgressStorageMock, logger: loggerMock)
|
||||
}
|
||||
|
||||
mockContainer.mock(type: BlockDownloaderService.self, isSingleton: true) { _ in blockDownloaderServiceMock }
|
||||
mockContainer.mock(type: LatestBlocksDataProvider.self, isSingleton: true) { _ in latestBlocksDataProviderMock }
|
||||
mockContainer.mock(type: Logger.self, isSingleton: true) { _ in loggerMock }
|
||||
|
||||
let config: CompactBlockProcessor.Configuration = .standard(
|
||||
for: ZcashNetworkBuilder.network(for: .testnet), walletBirthday: 0
|
||||
)
|
||||
|
||||
return ComputeSyncRangesAction(
|
||||
container: mockContainer,
|
||||
config: config
|
||||
)
|
||||
}
|
||||
|
||||
private func setupDefaultMocksAndReturnAction(
|
||||
_ blockDownloaderServiceMock: BlockDownloaderServiceMock = BlockDownloaderServiceMock(),
|
||||
_ latestBlocksDataProviderMock: LatestBlocksDataProviderMock = LatestBlocksDataProviderMock(),
|
||||
_ internalSyncProgressStorageMock: InternalSyncProgressStorageMock = InternalSyncProgressStorageMock(),
|
||||
_ loggerMock: LoggerMock = LoggerMock()
|
||||
) -> ComputeSyncRangesAction {
|
||||
blockDownloaderServiceMock.lastDownloadedBlockHeightReturnValue = 1
|
||||
latestBlocksDataProviderMock.underlyingLatestBlockHeight = 1
|
||||
latestBlocksDataProviderMock.underlyingLatestScannedHeight = 1
|
||||
latestBlocksDataProviderMock.updateScannedDataClosure = { }
|
||||
latestBlocksDataProviderMock.updateBlockDataClosure = { }
|
||||
internalSyncProgressStorageMock.integerForKeyReturnValue = 1
|
||||
internalSyncProgressStorageMock.boolForKeyReturnValue = true
|
||||
internalSyncProgressStorageMock.setBoolClosure = { _, _ in }
|
||||
internalSyncProgressStorageMock.synchronizeClosure = { true }
|
||||
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
|
||||
|
||||
return setupAction(
|
||||
blockDownloaderServiceMock,
|
||||
latestBlocksDataProviderMock,
|
||||
internalSyncProgressStorageMock,
|
||||
loggerMock
|
||||
)
|
||||
}
|
||||
}
|
|
@ -10,8 +10,9 @@ import XCTest
|
|||
@testable import ZcashLightClientKit
|
||||
|
||||
final class DownloadActionTests: ZcashTestCase {
|
||||
var underlyingDownloadAndScanRange: CompactBlockRange?
|
||||
|
||||
var underlyingDownloadRange: CompactBlockRange?
|
||||
var underlyingScanRange: CompactBlockRange?
|
||||
|
||||
func testDownloadAction_NextAction() async throws {
|
||||
let blockDownloaderMock = BlockDownloaderMock()
|
||||
let transactionRepositoryMock = TransactionRepositoryMock()
|
||||
|
@ -27,8 +28,9 @@ final class DownloadActionTests: ZcashTestCase {
|
|||
transactionRepositoryMock
|
||||
)
|
||||
|
||||
underlyingDownloadAndScanRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
|
||||
underlyingDownloadRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
underlyingScanRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
|
||||
let syncContext = await setupActionContext()
|
||||
|
||||
do {
|
||||
|
@ -97,7 +99,8 @@ final class DownloadActionTests: ZcashTestCase {
|
|||
transactionRepositoryMock
|
||||
)
|
||||
|
||||
underlyingDownloadAndScanRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
underlyingDownloadRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
underlyingScanRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
|
||||
let syncContext = await setupActionContext()
|
||||
|
||||
|
@ -139,11 +142,11 @@ final class DownloadActionTests: ZcashTestCase {
|
|||
|
||||
private func setupActionContext() async -> ActionContext {
|
||||
let syncContext: ActionContext = .init(state: .download)
|
||||
|
||||
|
||||
let syncRanges = SyncRanges(
|
||||
latestBlockHeight: 0,
|
||||
downloadedButUnscannedRange: nil,
|
||||
downloadAndScanRange: underlyingDownloadAndScanRange,
|
||||
downloadRange: underlyingDownloadRange,
|
||||
scanRange: underlyingScanRange,
|
||||
enhanceRange: nil,
|
||||
fetchUTXORange: nil,
|
||||
latestScannedHeight: nil,
|
||||
|
|
|
@ -10,13 +10,15 @@ import XCTest
|
|||
@testable import ZcashLightClientKit
|
||||
|
||||
final class EnhanceActionTests: ZcashTestCase {
|
||||
var underlyingDownloadAndScanRange: CompactBlockRange?
|
||||
var underlyingDownloadRange: CompactBlockRange?
|
||||
var underlyingScanRange: CompactBlockRange?
|
||||
var underlyingEnhanceRange: CompactBlockRange?
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
|
||||
underlyingDownloadAndScanRange = nil
|
||||
underlyingDownloadRange = nil
|
||||
underlyingScanRange = nil
|
||||
underlyingEnhanceRange = nil
|
||||
}
|
||||
|
||||
|
@ -35,8 +37,9 @@ final class EnhanceActionTests: ZcashTestCase {
|
|||
|
||||
func testEnhanceAction_decideWhatToDoNext_NothingToDownloadAndScanLeft() async throws {
|
||||
let enhanceAction = setupAction()
|
||||
underlyingDownloadAndScanRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
|
||||
underlyingDownloadRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
underlyingScanRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
|
||||
let syncContext = await setupActionContext()
|
||||
let nextContext = await enhanceAction.decideWhatToDoNext(context: syncContext, lastScannedHeight: 2000)
|
||||
let nextState = await nextContext.state
|
||||
|
@ -49,8 +52,9 @@ final class EnhanceActionTests: ZcashTestCase {
|
|||
|
||||
func testEnhanceAction_decideWhatToDoNext_DownloadExpected() async throws {
|
||||
let enhanceAction = setupAction()
|
||||
underlyingDownloadAndScanRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
|
||||
underlyingDownloadRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
underlyingScanRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
|
||||
let syncContext = await setupActionContext()
|
||||
let nextContext = await enhanceAction.decideWhatToDoNext(context: syncContext, lastScannedHeight: 1500)
|
||||
let nextState = await nextContext.state
|
||||
|
@ -247,8 +251,8 @@ final class EnhanceActionTests: ZcashTestCase {
|
|||
|
||||
let syncRanges = SyncRanges(
|
||||
latestBlockHeight: 0,
|
||||
downloadRange: underlyingDownloadAndScanRange,
|
||||
scanRange: underlyingDownloadAndScanRange,
|
||||
downloadRange: underlyingDownloadRange,
|
||||
scanRange: underlyingScanRange,
|
||||
enhanceRange: underlyingEnhanceRange,
|
||||
fetchUTXORange: nil,
|
||||
latestScannedHeight: nil,
|
||||
|
|
|
@ -28,8 +28,8 @@ final class SaplingParamsActionTests: ZcashTestCase {
|
|||
XCTAssertTrue(saplingParametersHandlerMock.handleIfNeededCalled, "saplingParametersHandler.handleIfNeeded() is expected to be called.")
|
||||
let nextState = await nextContext.state
|
||||
XCTAssertTrue(
|
||||
nextState == .scanDownloaded,
|
||||
"nextContext after .handleSaplingParams is expected to be .scanDownloaded but received \(nextState)"
|
||||
nextState == .download,
|
||||
"nextContext after .handleSaplingParams is expected to be .download but received \(nextState)"
|
||||
)
|
||||
} catch {
|
||||
XCTFail("testSaplingParamsAction_NextAction is not expected to fail. \(error)")
|
||||
|
|
|
@ -66,8 +66,8 @@ class InternalSyncProgressTests: ZcashTestCase {
|
|||
|
||||
switch nextState {
|
||||
case let .processNewBlocks(ranges):
|
||||
XCTAssertEqual(ranges.downloadedButUnscannedRange, 620001...630000)
|
||||
XCTAssertEqual(ranges.downloadAndScanRange, 630001...640000)
|
||||
XCTAssertEqual(ranges.downloadRange, 630001...640000)
|
||||
XCTAssertEqual(ranges.scanRange, 620001...640000)
|
||||
XCTAssertEqual(ranges.enhanceRange, 630001...640000)
|
||||
XCTAssertEqual(ranges.fetchUTXORange, 630001...640000)
|
||||
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
//
|
||||
// LatestBlocksDataProviderMock.swift
|
||||
//
|
||||
//
|
||||
// Created by Lukáš Korba on 12.04.2023.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@testable import ZcashLightClientKit
|
||||
|
||||
actor LatestBlocksDataProviderMock: LatestBlocksDataProvider {
|
||||
private(set) var latestScannedHeight: BlockHeight = .zero
|
||||
private(set) var latestScannedTime: TimeInterval = 0.0
|
||||
private(set) var latestBlockHeight: BlockHeight = .zero
|
||||
private(set) var walletBirthday: BlockHeight = .zero
|
||||
|
||||
init(
|
||||
latestScannedHeight: BlockHeight = .zero,
|
||||
latestScannedTime: TimeInterval = 0,
|
||||
latestBlockHeight: BlockHeight = .zero,
|
||||
walletBirthday: BlockHeight = .zero
|
||||
) {
|
||||
self.latestScannedHeight = latestScannedHeight
|
||||
self.latestScannedTime = latestScannedTime
|
||||
self.latestBlockHeight = latestBlockHeight
|
||||
self.walletBirthday = walletBirthday
|
||||
}
|
||||
|
||||
func updateScannedData() async { }
|
||||
|
||||
func updateBlockData() async { }
|
||||
|
||||
func updateWalletBirthday(_ walletBirthday: BlockHeight) async { }
|
||||
|
||||
func updateLatestScannedHeight(_ latestScannedHeight: BlockHeight) async { }
|
||||
|
||||
func updateLatestScannedTime(_ latestScannedTime: TimeInterval) async { }
|
||||
}
|
|
@ -13,11 +13,13 @@
|
|||
@testable import ZcashLightClientKit
|
||||
|
||||
extension BlockDownloader { }
|
||||
extension BlockDownloaderService { }
|
||||
extension BlockEnhancer { }
|
||||
extension BlockScanner { }
|
||||
extension BlockValidator { }
|
||||
extension CompactBlockRepository { }
|
||||
extension InternalSyncProgressStorage { }
|
||||
extension LatestBlocksDataProvider { }
|
||||
extension LightWalletdInfo { }
|
||||
extension LightWalletService { }
|
||||
extension Logger { }
|
||||
|
|
|
@ -95,6 +95,177 @@ class BlockDownloaderMock: BlockDownloader {
|
|||
try await waitUntilRequestedBlocksAreDownloadedInClosure!(range)
|
||||
}
|
||||
|
||||
}
|
||||
class BlockDownloaderServiceMock: BlockDownloaderService {
|
||||
|
||||
|
||||
init(
|
||||
) {
|
||||
}
|
||||
var storage: CompactBlockRepository {
|
||||
get { return underlyingStorage }
|
||||
}
|
||||
var underlyingStorage: CompactBlockRepository!
|
||||
|
||||
// MARK: - downloadBlockRange
|
||||
|
||||
var downloadBlockRangeThrowableError: Error?
|
||||
var downloadBlockRangeCallsCount = 0
|
||||
var downloadBlockRangeCalled: Bool {
|
||||
return downloadBlockRangeCallsCount > 0
|
||||
}
|
||||
var downloadBlockRangeReceivedHeightRange: CompactBlockRange?
|
||||
var downloadBlockRangeClosure: ((CompactBlockRange) async throws -> Void)?
|
||||
|
||||
func downloadBlockRange(_ heightRange: CompactBlockRange) async throws {
|
||||
if let error = downloadBlockRangeThrowableError {
|
||||
throw error
|
||||
}
|
||||
downloadBlockRangeCallsCount += 1
|
||||
downloadBlockRangeReceivedHeightRange = heightRange
|
||||
try await downloadBlockRangeClosure!(heightRange)
|
||||
}
|
||||
|
||||
// MARK: - rewind
|
||||
|
||||
var rewindToThrowableError: Error?
|
||||
var rewindToCallsCount = 0
|
||||
var rewindToCalled: Bool {
|
||||
return rewindToCallsCount > 0
|
||||
}
|
||||
var rewindToReceivedHeight: BlockHeight?
|
||||
var rewindToClosure: ((BlockHeight) async throws -> Void)?
|
||||
|
||||
func rewind(to height: BlockHeight) async throws {
|
||||
if let error = rewindToThrowableError {
|
||||
throw error
|
||||
}
|
||||
rewindToCallsCount += 1
|
||||
rewindToReceivedHeight = height
|
||||
try await rewindToClosure!(height)
|
||||
}
|
||||
|
||||
// MARK: - lastDownloadedBlockHeight
|
||||
|
||||
var lastDownloadedBlockHeightThrowableError: Error?
|
||||
var lastDownloadedBlockHeightCallsCount = 0
|
||||
var lastDownloadedBlockHeightCalled: Bool {
|
||||
return lastDownloadedBlockHeightCallsCount > 0
|
||||
}
|
||||
var lastDownloadedBlockHeightReturnValue: BlockHeight!
|
||||
var lastDownloadedBlockHeightClosure: (() async throws -> BlockHeight)?
|
||||
|
||||
func lastDownloadedBlockHeight() async throws -> BlockHeight {
|
||||
if let error = lastDownloadedBlockHeightThrowableError {
|
||||
throw error
|
||||
}
|
||||
lastDownloadedBlockHeightCallsCount += 1
|
||||
if let closure = lastDownloadedBlockHeightClosure {
|
||||
return try await closure()
|
||||
} else {
|
||||
return lastDownloadedBlockHeightReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
// 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: - 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: - fetchUnspentTransactionOutputs
|
||||
|
||||
var fetchUnspentTransactionOutputsTAddressStartHeightCallsCount = 0
|
||||
var fetchUnspentTransactionOutputsTAddressStartHeightCalled: Bool {
|
||||
return fetchUnspentTransactionOutputsTAddressStartHeightCallsCount > 0
|
||||
}
|
||||
var fetchUnspentTransactionOutputsTAddressStartHeightReceivedArguments: (tAddress: String, startHeight: BlockHeight)?
|
||||
var fetchUnspentTransactionOutputsTAddressStartHeightReturnValue: AsyncThrowingStream<UnspentTransactionOutputEntity, Error>!
|
||||
var fetchUnspentTransactionOutputsTAddressStartHeightClosure: ((String, BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>)?
|
||||
|
||||
func fetchUnspentTransactionOutputs(tAddress: String, startHeight: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
|
||||
fetchUnspentTransactionOutputsTAddressStartHeightCallsCount += 1
|
||||
fetchUnspentTransactionOutputsTAddressStartHeightReceivedArguments = (tAddress: tAddress, startHeight: startHeight)
|
||||
if let closure = fetchUnspentTransactionOutputsTAddressStartHeightClosure {
|
||||
return closure(tAddress, startHeight)
|
||||
} else {
|
||||
return fetchUnspentTransactionOutputsTAddressStartHeightReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - fetchUnspentTransactionOutputs
|
||||
|
||||
var fetchUnspentTransactionOutputsTAddressesStartHeightCallsCount = 0
|
||||
var fetchUnspentTransactionOutputsTAddressesStartHeightCalled: Bool {
|
||||
return fetchUnspentTransactionOutputsTAddressesStartHeightCallsCount > 0
|
||||
}
|
||||
var fetchUnspentTransactionOutputsTAddressesStartHeightReceivedArguments: (tAddresses: [String], startHeight: BlockHeight)?
|
||||
var fetchUnspentTransactionOutputsTAddressesStartHeightReturnValue: AsyncThrowingStream<UnspentTransactionOutputEntity, Error>!
|
||||
var fetchUnspentTransactionOutputsTAddressesStartHeightClosure: (([String], BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>)?
|
||||
|
||||
func fetchUnspentTransactionOutputs(tAddresses: [String], startHeight: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
|
||||
fetchUnspentTransactionOutputsTAddressesStartHeightCallsCount += 1
|
||||
fetchUnspentTransactionOutputsTAddressesStartHeightReceivedArguments = (tAddresses: tAddresses, startHeight: startHeight)
|
||||
if let closure = fetchUnspentTransactionOutputsTAddressesStartHeightClosure {
|
||||
return closure(tAddresses, startHeight)
|
||||
} else {
|
||||
return fetchUnspentTransactionOutputsTAddressesStartHeightReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - closeConnection
|
||||
|
||||
var closeConnectionCallsCount = 0
|
||||
var closeConnectionCalled: Bool {
|
||||
return closeConnectionCallsCount > 0
|
||||
}
|
||||
var closeConnectionClosure: (() -> Void)?
|
||||
|
||||
func closeConnection() {
|
||||
closeConnectionCallsCount += 1
|
||||
closeConnectionClosure!()
|
||||
}
|
||||
|
||||
}
|
||||
class BlockEnhancerMock: BlockEnhancer {
|
||||
|
||||
|
@ -412,6 +583,101 @@ class InternalSyncProgressStorageMock: InternalSyncProgressStorage {
|
|||
try await setBoolClosure!(value, key)
|
||||
}
|
||||
|
||||
}
|
||||
class LatestBlocksDataProviderMock: LatestBlocksDataProvider {
|
||||
|
||||
|
||||
init(
|
||||
) {
|
||||
}
|
||||
var latestScannedHeight: BlockHeight {
|
||||
get { return underlyingLatestScannedHeight }
|
||||
}
|
||||
var underlyingLatestScannedHeight: BlockHeight!
|
||||
var latestScannedTime: TimeInterval {
|
||||
get { return underlyingLatestScannedTime }
|
||||
}
|
||||
var underlyingLatestScannedTime: TimeInterval!
|
||||
var latestBlockHeight: BlockHeight {
|
||||
get { return underlyingLatestBlockHeight }
|
||||
}
|
||||
var underlyingLatestBlockHeight: BlockHeight!
|
||||
var walletBirthday: BlockHeight {
|
||||
get { return underlyingWalletBirthday }
|
||||
}
|
||||
var underlyingWalletBirthday: BlockHeight!
|
||||
|
||||
// MARK: - updateScannedData
|
||||
|
||||
var updateScannedDataCallsCount = 0
|
||||
var updateScannedDataCalled: Bool {
|
||||
return updateScannedDataCallsCount > 0
|
||||
}
|
||||
var updateScannedDataClosure: (() async -> Void)?
|
||||
|
||||
func updateScannedData() async {
|
||||
updateScannedDataCallsCount += 1
|
||||
await updateScannedDataClosure!()
|
||||
}
|
||||
|
||||
// MARK: - updateBlockData
|
||||
|
||||
var updateBlockDataCallsCount = 0
|
||||
var updateBlockDataCalled: Bool {
|
||||
return updateBlockDataCallsCount > 0
|
||||
}
|
||||
var updateBlockDataClosure: (() async -> Void)?
|
||||
|
||||
func updateBlockData() async {
|
||||
updateBlockDataCallsCount += 1
|
||||
await updateBlockDataClosure!()
|
||||
}
|
||||
|
||||
// MARK: - updateWalletBirthday
|
||||
|
||||
var updateWalletBirthdayCallsCount = 0
|
||||
var updateWalletBirthdayCalled: Bool {
|
||||
return updateWalletBirthdayCallsCount > 0
|
||||
}
|
||||
var updateWalletBirthdayReceivedWalletBirthday: BlockHeight?
|
||||
var updateWalletBirthdayClosure: ((BlockHeight) async -> Void)?
|
||||
|
||||
func updateWalletBirthday(_ walletBirthday: BlockHeight) async {
|
||||
updateWalletBirthdayCallsCount += 1
|
||||
updateWalletBirthdayReceivedWalletBirthday = walletBirthday
|
||||
await updateWalletBirthdayClosure!(walletBirthday)
|
||||
}
|
||||
|
||||
// MARK: - updateLatestScannedHeight
|
||||
|
||||
var updateLatestScannedHeightCallsCount = 0
|
||||
var updateLatestScannedHeightCalled: Bool {
|
||||
return updateLatestScannedHeightCallsCount > 0
|
||||
}
|
||||
var updateLatestScannedHeightReceivedLatestScannedHeight: BlockHeight?
|
||||
var updateLatestScannedHeightClosure: ((BlockHeight) async -> Void)?
|
||||
|
||||
func updateLatestScannedHeight(_ latestScannedHeight: BlockHeight) async {
|
||||
updateLatestScannedHeightCallsCount += 1
|
||||
updateLatestScannedHeightReceivedLatestScannedHeight = latestScannedHeight
|
||||
await updateLatestScannedHeightClosure!(latestScannedHeight)
|
||||
}
|
||||
|
||||
// MARK: - updateLatestScannedTime
|
||||
|
||||
var updateLatestScannedTimeCallsCount = 0
|
||||
var updateLatestScannedTimeCalled: Bool {
|
||||
return updateLatestScannedTimeCallsCount > 0
|
||||
}
|
||||
var updateLatestScannedTimeReceivedLatestScannedTime: TimeInterval?
|
||||
var updateLatestScannedTimeClosure: ((TimeInterval) async -> Void)?
|
||||
|
||||
func updateLatestScannedTime(_ latestScannedTime: TimeInterval) async {
|
||||
updateLatestScannedTimeCallsCount += 1
|
||||
updateLatestScannedTimeReceivedLatestScannedTime = latestScannedTime
|
||||
await updateLatestScannedTimeClosure!(latestScannedTime)
|
||||
}
|
||||
|
||||
}
|
||||
class LightWalletServiceMock: LightWalletService {
|
||||
|
||||
|
|
Loading…
Reference in New Issue