[#700] Fix DarksideTests
Closes #1102 Some tests that can't be compiled are disabled for now. List is in #1126. This PR contains multiple fixes. Most of the fixes is done in the code. Not in the tests. That is good news. Fixes: - `config` inside `CompactBlockProcessor` can be updated during the tests. And it must be also updated inside the actions. So `ConfigProvider` is added and it is wrapper for config that is passed to any instance of `Action` and provides updated config. - Fixed `EnhanceAction`. Now it should update all the blocks in the enhance range even when the remaining count of blocks is lower than 1000. - Fixed `fail()` and `validationFailed()`. These two were canceling `syncTask`. But that stopped run loop in a bad way.
This commit is contained in:
parent
e267435d84
commit
213c767e3c
|
@ -8,14 +8,14 @@
|
|||
import Foundation
|
||||
|
||||
final class ComputeSyncRangesAction {
|
||||
let config: CompactBlockProcessor.Configuration
|
||||
let configProvider: CompactBlockProcessor.ConfigProvider
|
||||
let downloaderService: BlockDownloaderService
|
||||
let internalSyncProgress: InternalSyncProgress
|
||||
let latestBlocksDataProvider: LatestBlocksDataProvider
|
||||
let logger: Logger
|
||||
|
||||
init(container: DIContainer, config: CompactBlockProcessor.Configuration) {
|
||||
self.config = config
|
||||
init(container: DIContainer, configProvider: CompactBlockProcessor.ConfigProvider) {
|
||||
self.configProvider = configProvider
|
||||
downloaderService = container.resolve(BlockDownloaderService.self)
|
||||
internalSyncProgress = container.resolve(InternalSyncProgress.self)
|
||||
latestBlocksDataProvider = container.resolve(LatestBlocksDataProvider.self)
|
||||
|
@ -46,6 +46,7 @@ extension ComputeSyncRangesAction: Action {
|
|||
// call internalSyncProgress and compute sync ranges and store them in context
|
||||
// if there is nothing sync just switch to finished state
|
||||
|
||||
let config = await configProvider.config
|
||||
let latestDownloadHeight = try await downloaderService.lastDownloadedBlockHeight()
|
||||
|
||||
await internalSyncProgress.migrateIfNeeded(latestDownloadedBlockHeightFromCacheDB: latestDownloadHeight)
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
import Foundation
|
||||
|
||||
final class DownloadAction {
|
||||
let config: CompactBlockProcessor.Configuration
|
||||
let configProvider: CompactBlockProcessor.ConfigProvider
|
||||
let downloader: BlockDownloader
|
||||
let transactionRepository: TransactionRepository
|
||||
let logger: Logger
|
||||
|
||||
init(container: DIContainer, config: CompactBlockProcessor.Configuration) {
|
||||
self.config = config
|
||||
init(container: DIContainer, configProvider: CompactBlockProcessor.ConfigProvider) {
|
||||
self.configProvider = configProvider
|
||||
downloader = container.resolve(BlockDownloader.self)
|
||||
transactionRepository = container.resolve(TransactionRepository.self)
|
||||
logger = container.resolve(Logger.self)
|
||||
|
@ -34,6 +34,7 @@ extension DownloadAction: Action {
|
|||
return await update(context: context)
|
||||
}
|
||||
|
||||
let config = await configProvider.config
|
||||
let lastScannedHeight = try await transactionRepository.lastScannedHeight()
|
||||
// This action is executed for each batch (batch size is 100 blocks by default) until all the blocks in whole `downloadRange` are downloaded.
|
||||
// So the right range for this batch must be computed.
|
||||
|
|
|
@ -9,13 +9,13 @@ import Foundation
|
|||
|
||||
final class EnhanceAction {
|
||||
let blockEnhancer: BlockEnhancer
|
||||
let config: CompactBlockProcessor.Configuration
|
||||
let configProvider: CompactBlockProcessor.ConfigProvider
|
||||
let internalSyncProgress: InternalSyncProgress
|
||||
let logger: Logger
|
||||
let transactionRepository: TransactionRepository
|
||||
init(container: DIContainer, config: CompactBlockProcessor.Configuration) {
|
||||
init(container: DIContainer, configProvider: CompactBlockProcessor.ConfigProvider) {
|
||||
blockEnhancer = container.resolve(BlockEnhancer.self)
|
||||
self.config = config
|
||||
self.configProvider = configProvider
|
||||
internalSyncProgress = container.resolve(InternalSyncProgress.self)
|
||||
logger = container.resolve(Logger.self)
|
||||
transactionRepository = container.resolve(TransactionRepository.self)
|
||||
|
@ -49,6 +49,7 @@ extension EnhanceAction: Action {
|
|||
// If latestScannedHeight < context.scanRanges.downloadAndScanRange?.upperBound then set state to `download` because there are blocks to
|
||||
// download and scan.
|
||||
|
||||
let config = await configProvider.config
|
||||
let lastScannedHeight = try await transactionRepository.lastScannedHeight()
|
||||
|
||||
guard let range = await context.syncRanges.enhanceRange else {
|
||||
|
@ -59,7 +60,14 @@ extension EnhanceAction: Action {
|
|||
let enhanceRangeStart = max(range.lowerBound, lastEnhancedHeight)
|
||||
let enhanceRangeEnd = min(range.upperBound, lastScannedHeight)
|
||||
|
||||
if enhanceRangeStart <= enhanceRangeEnd && lastScannedHeight - lastEnhancedHeight >= config.enhanceBatchSize {
|
||||
// This may happen:
|
||||
// For example whole enhance range is 0...2100 Without this force enhance is done for ranges: 0...1000, 1001...2000. And that's it.
|
||||
// Last 100 blocks isn't enhanced.
|
||||
//
|
||||
// This force makes sure that all the blocks are enhanced even when last enhance happened < 1000 blocks ago.
|
||||
let forceEnhance = enhanceRangeEnd == range.upperBound && enhanceRangeEnd - enhanceRangeStart <= config.enhanceBatchSize
|
||||
|
||||
if forceEnhance || (enhanceRangeStart <= enhanceRangeEnd && lastScannedHeight - lastEnhancedHeight >= config.enhanceBatchSize) {
|
||||
let enhanceRange = enhanceRangeStart...enhanceRangeEnd
|
||||
let transactions = try await blockEnhancer.enhance(
|
||||
at: enhanceRange,
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
import Foundation
|
||||
|
||||
final class MigrateLegacyCacheDBAction {
|
||||
private let config: CompactBlockProcessor.Configuration
|
||||
private let configProvider: CompactBlockProcessor.ConfigProvider
|
||||
private let internalSyncProgress: InternalSyncProgress
|
||||
private let storage: CompactBlockRepository
|
||||
private let transactionRepository: TransactionRepository
|
||||
private let fileManager: ZcashFileManager
|
||||
|
||||
init(container: DIContainer, config: CompactBlockProcessor.Configuration) {
|
||||
self.config = config
|
||||
init(container: DIContainer, configProvider: CompactBlockProcessor.ConfigProvider) {
|
||||
self.configProvider = configProvider
|
||||
internalSyncProgress = container.resolve(InternalSyncProgress.self)
|
||||
storage = container.resolve(CompactBlockRepository.self)
|
||||
transactionRepository = container.resolve(TransactionRepository.self)
|
||||
|
@ -32,6 +32,7 @@ extension MigrateLegacyCacheDBAction: Action {
|
|||
var removeBlocksCacheWhenFailed: Bool { false }
|
||||
|
||||
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
|
||||
let config = await configProvider.config
|
||||
guard let legacyCacheDbURL = config.cacheDbURL else {
|
||||
return await updateState(context)
|
||||
}
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
import Foundation
|
||||
|
||||
final class ScanAction {
|
||||
let config: CompactBlockProcessor.Configuration
|
||||
let configProvider: CompactBlockProcessor.ConfigProvider
|
||||
let blockScanner: BlockScanner
|
||||
let logger: Logger
|
||||
let transactionRepository: TransactionRepository
|
||||
|
||||
init(container: DIContainer, config: CompactBlockProcessor.Configuration) {
|
||||
self.config = config
|
||||
init(container: DIContainer, configProvider: CompactBlockProcessor.ConfigProvider) {
|
||||
self.configProvider = configProvider
|
||||
blockScanner = container.resolve(BlockScanner.self)
|
||||
transactionRepository = container.resolve(TransactionRepository.self)
|
||||
logger = container.resolve(Logger.self)
|
||||
|
@ -33,7 +33,8 @@ extension ScanAction: Action {
|
|||
guard let scanRange = await context.syncRanges.scanRange else {
|
||||
return await update(context: context)
|
||||
}
|
||||
|
||||
|
||||
let config = await configProvider.config
|
||||
let lastScannedHeight = try await transactionRepository.lastScannedHeight()
|
||||
// This action is executed for each batch (batch size is 100 blocks by default) until all the blocks in whole `scanRange` are scanned.
|
||||
// So the right range for this batch must be computed.
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
import Foundation
|
||||
|
||||
final class ValidateServerAction {
|
||||
let config: CompactBlockProcessor.Configuration
|
||||
let configProvider: CompactBlockProcessor.ConfigProvider
|
||||
let rustBackend: ZcashRustBackendWelding
|
||||
let service: LightWalletService
|
||||
|
||||
init(container: DIContainer, config: CompactBlockProcessor.Configuration) {
|
||||
self.config = config
|
||||
init(container: DIContainer, configProvider: CompactBlockProcessor.ConfigProvider) {
|
||||
self.configProvider = configProvider
|
||||
rustBackend = container.resolve(ZcashRustBackendWelding.self)
|
||||
service = container.resolve(LightWalletService.self)
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ extension ValidateServerAction: Action {
|
|||
var removeBlocksCacheWhenFailed: Bool { false }
|
||||
|
||||
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
|
||||
let config = await configProvider.config
|
||||
let info = try await service.getInfo()
|
||||
let localNetwork = config.network
|
||||
let saplingActivation = config.saplingActivation
|
||||
|
|
|
@ -25,6 +25,7 @@ actor CompactBlockProcessor {
|
|||
private var context: ActionContext
|
||||
|
||||
private(set) var config: Configuration
|
||||
private let configProvider: ConfigProvider
|
||||
private var afterSyncHooksManager = AfterSyncHooksManager()
|
||||
|
||||
private let accountRepository: AccountRepository
|
||||
|
@ -34,7 +35,7 @@ actor CompactBlockProcessor {
|
|||
private let logger: Logger
|
||||
private let metrics: SDKMetrics
|
||||
private let rustBackend: ZcashRustBackendWelding
|
||||
private let service: LightWalletService
|
||||
let service: LightWalletService
|
||||
private let storage: CompactBlockRepository
|
||||
private let transactionRepository: TransactionRepository
|
||||
private let fileManager: ZcashFileManager
|
||||
|
@ -182,8 +183,9 @@ actor CompactBlockProcessor {
|
|||
accountRepository: accountRepository
|
||||
)
|
||||
|
||||
let configProvider = ConfigProvider(config: config)
|
||||
context = ActionContext(state: .idle)
|
||||
actions = Self.makeActions(container: container, config: config)
|
||||
actions = Self.makeActions(container: container, configProvider: configProvider)
|
||||
|
||||
self.metrics = container.resolve(SDKMetrics.self)
|
||||
self.logger = container.resolve(Logger.self)
|
||||
|
@ -197,6 +199,7 @@ actor CompactBlockProcessor {
|
|||
self.transactionRepository = container.resolve(TransactionRepository.self)
|
||||
self.accountRepository = accountRepository
|
||||
self.fileManager = container.resolve(ZcashFileManager.self)
|
||||
self.configProvider = configProvider
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
@ -205,28 +208,28 @@ actor CompactBlockProcessor {
|
|||
}
|
||||
|
||||
// swiftlint:disable:next cyclomatic_complexity
|
||||
private static func makeActions(container: DIContainer, config: Configuration) -> [CBPState: Action] {
|
||||
private static func makeActions(container: DIContainer, configProvider: ConfigProvider) -> [CBPState: Action] {
|
||||
let actionsDefinition = CBPState.allCases.compactMap { state -> (CBPState, Action)? in
|
||||
let action: Action
|
||||
switch state {
|
||||
case .migrateLegacyCacheDB:
|
||||
action = MigrateLegacyCacheDBAction(container: container, config: config)
|
||||
action = MigrateLegacyCacheDBAction(container: container, configProvider: configProvider)
|
||||
case .validateServer:
|
||||
action = ValidateServerAction(container: container, config: config)
|
||||
action = ValidateServerAction(container: container, configProvider: configProvider)
|
||||
case .computeSyncRanges:
|
||||
action = ComputeSyncRangesAction(container: container, config: config)
|
||||
action = ComputeSyncRangesAction(container: container, configProvider: configProvider)
|
||||
case .checksBeforeSync:
|
||||
action = ChecksBeforeSyncAction(container: container)
|
||||
case .download:
|
||||
action = DownloadAction(container: container, config: config)
|
||||
action = DownloadAction(container: container, configProvider: configProvider)
|
||||
case .validate:
|
||||
action = ValidateAction(container: container)
|
||||
case .scan:
|
||||
action = ScanAction(container: container, config: config)
|
||||
action = ScanAction(container: container, configProvider: configProvider)
|
||||
case .clearAlreadyScannedBlocks:
|
||||
action = ClearAlreadyScannedBlocksAction(container: container)
|
||||
case .enhance:
|
||||
action = EnhanceAction(container: container, config: config)
|
||||
action = EnhanceAction(container: container, configProvider: configProvider)
|
||||
case .fetchUTXO:
|
||||
action = FetchUTXOsAction(container: container)
|
||||
case .handleSaplingParams:
|
||||
|
@ -242,6 +245,12 @@ actor CompactBlockProcessor {
|
|||
|
||||
return Dictionary(uniqueKeysWithValues: actionsDefinition)
|
||||
}
|
||||
|
||||
// This is currently used only in tests. And it should be used only in tests.
|
||||
func update(config: Configuration) async {
|
||||
self.config = config
|
||||
await configProvider.update(config: config)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - "Public" API
|
||||
|
@ -271,7 +280,10 @@ extension CompactBlockProcessor {
|
|||
}
|
||||
|
||||
func stop() async {
|
||||
await rawStop()
|
||||
syncTask?.cancel()
|
||||
self.backoffTimer?.invalidate()
|
||||
self.backoffTimer = nil
|
||||
await stopAllActions()
|
||||
retryAttempts = 0
|
||||
}
|
||||
|
||||
|
@ -621,9 +633,6 @@ extension CompactBlockProcessor {
|
|||
}
|
||||
|
||||
private func validationFailed(at height: BlockHeight) async throws {
|
||||
// cancel all Tasks
|
||||
await rawStop()
|
||||
|
||||
// rewind
|
||||
let rewindHeight = determineLowerBound(
|
||||
errorHeight: height,
|
||||
|
@ -645,7 +654,6 @@ extension CompactBlockProcessor {
|
|||
await context.update(state: .failed)
|
||||
|
||||
logger.error("Fail with error: \(error)")
|
||||
await rawStop()
|
||||
|
||||
self.retryAttempts += 1
|
||||
await send(event: .failed(error))
|
||||
|
@ -728,13 +736,6 @@ extension CompactBlockProcessor {
|
|||
return max(errorHeight - offset, walletBirthday - ZcashSDK.maxReorgSize)
|
||||
}
|
||||
|
||||
private func rawStop() async {
|
||||
syncTask?.cancel()
|
||||
self.backoffTimer?.invalidate()
|
||||
self.backoffTimer = nil
|
||||
await stopAllActions()
|
||||
}
|
||||
|
||||
private func stopAllActions() async {
|
||||
for action in actions.values {
|
||||
await action.stop()
|
||||
|
@ -841,3 +842,18 @@ extension CompactBlockProcessor {
|
|||
return (inserted: refreshed, skipped: skipped)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Config provider
|
||||
|
||||
extension CompactBlockProcessor {
|
||||
actor ConfigProvider {
|
||||
var config: Configuration
|
||||
init(config: Configuration) {
|
||||
self.config = config
|
||||
}
|
||||
|
||||
func update(config: Configuration) async {
|
||||
self.config = config
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ class SDKSynchronizerAliasDarksideTests: ZcashTestCase {
|
|||
endpoint: endpoint
|
||||
)
|
||||
|
||||
try coordinator.reset(saplingActivation: birthday, branchID: branchID, chainName: chainName)
|
||||
try await coordinator.reset(saplingActivation: birthday, branchID: branchID, chainName: chainName)
|
||||
|
||||
coordinators.append(coordinator)
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ class AdvancedReOrgTests: ZcashTestCase {
|
|||
walletBirthday: birthday + 50,
|
||||
network: network
|
||||
)
|
||||
try coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
|
||||
try await coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
|
||||
}
|
||||
|
||||
override func tearDown() async throws {
|
||||
|
@ -453,7 +453,7 @@ class AdvancedReOrgTests: ZcashTestCase {
|
|||
await hookToReOrgNotification()
|
||||
self.expectedReorgHeight = 663196
|
||||
self.expectedRewindHeight = 663175
|
||||
try coordinator.reset(saplingActivation: birthday, branchID: "2bb40e60", chainName: "main")
|
||||
try await coordinator.reset(saplingActivation: birthday, branchID: "2bb40e60", chainName: "main")
|
||||
try coordinator.resetBlocks(dataset: .predefined(dataset: .txIndexChangeBefore))
|
||||
try coordinator.applyStaged(blockheight: 663195)
|
||||
sleep(1)
|
||||
|
@ -1031,7 +1031,7 @@ class AdvancedReOrgTests: ZcashTestCase {
|
|||
/// 8. sync to latest height
|
||||
/// 9. verify that the balance is equal to the one before the reorg
|
||||
func testReOrgChangesInboundMinedHeight() async throws {
|
||||
try coordinator.reset(saplingActivation: 663150, branchID: branchID, chainName: chainName)
|
||||
try await coordinator.reset(saplingActivation: 663150, branchID: branchID, chainName: chainName)
|
||||
sleep(2)
|
||||
try coordinator.resetBlocks(dataset: .predefined(dataset: .txHeightReOrgBefore))
|
||||
sleep(2)
|
||||
|
@ -1096,7 +1096,7 @@ class AdvancedReOrgTests: ZcashTestCase {
|
|||
// FIXME [#644]: Test works with lightwalletd v0.4.13 but is broken when using newer lightwalletd. More info is in #644.
|
||||
func testReOrgRemovesIncomingTxForever() async throws {
|
||||
await hookToReOrgNotification()
|
||||
try coordinator.reset(saplingActivation: 663150, branchID: branchID, chainName: chainName)
|
||||
try await coordinator.reset(saplingActivation: 663150, branchID: branchID, chainName: chainName)
|
||||
|
||||
try coordinator.resetBlocks(dataset: .predefined(dataset: .txReOrgRemovesInboundTxBefore))
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ class BalanceTests: ZcashTestCase {
|
|||
walletBirthday: birthday,
|
||||
network: network
|
||||
)
|
||||
try coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
|
||||
try await coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
|
||||
}
|
||||
|
||||
override func tearDown() async throws {
|
||||
|
@ -672,7 +672,7 @@ class BalanceTests: ZcashTestCase {
|
|||
return
|
||||
}
|
||||
|
||||
guard let changeOutput = outputs.first(where: { $0.isChange }) else {
|
||||
guard outputs.first(where: { $0.isChange }) != nil else {
|
||||
XCTFail("Sent transaction has no change")
|
||||
return
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ class DarksideSanityCheckTests: ZcashTestCase {
|
|||
network: network
|
||||
)
|
||||
|
||||
try self.coordinator.reset(saplingActivation: self.birthday, branchID: self.branchID, chainName: self.chainName)
|
||||
try await coordinator.reset(saplingActivation: self.birthday, branchID: self.branchID, chainName: self.chainName)
|
||||
try self.coordinator.resetBlocks(dataset: .default)
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ final class InternalStateConsistencyTests: ZcashTestCase {
|
|||
network: network
|
||||
)
|
||||
|
||||
try coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
|
||||
try await coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
|
||||
}
|
||||
|
||||
override func tearDown() async throws {
|
||||
|
@ -48,95 +48,95 @@ final class InternalStateConsistencyTests: ZcashTestCase {
|
|||
try? FileManager.default.removeItem(at: coordinator.databases.dataDB)
|
||||
}
|
||||
|
||||
func testInternalStateIsConsistentWhenMigrating() async throws {
|
||||
sdkSynchronizerInternalSyncStatusHandler.subscribe(
|
||||
to: coordinator.synchronizer.stateStream,
|
||||
expectations: [.stopped: firstSyncExpectation]
|
||||
)
|
||||
|
||||
let fullSyncLength = 10000
|
||||
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName, length: fullSyncLength)
|
||||
|
||||
sleep(1)
|
||||
|
||||
// apply the height
|
||||
try coordinator.applyStaged(blockheight: 664150)
|
||||
|
||||
sleep(1)
|
||||
|
||||
try await coordinator.sync(
|
||||
completion: { _ in
|
||||
XCTFail("shouldn't have completed")
|
||||
},
|
||||
error: handleError
|
||||
)
|
||||
|
||||
let coordinator = self.coordinator!
|
||||
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
|
||||
Task(priority: .userInitiated) {
|
||||
coordinator.synchronizer.stop()
|
||||
}
|
||||
}
|
||||
|
||||
await fulfillment(of: [firstSyncExpectation], timeout: 2)
|
||||
|
||||
let isSyncing = await coordinator.synchronizer.status.isSyncing
|
||||
let status = await coordinator.synchronizer.status
|
||||
XCTAssertFalse(isSyncing, "SDKSynchronizer shouldn't be syncing")
|
||||
XCTAssertEqual(status, .stopped)
|
||||
|
||||
let internalSyncState = InternalSyncProgress(
|
||||
alias: .default,
|
||||
storage: UserDefaults.standard,
|
||||
logger: logger
|
||||
)
|
||||
|
||||
let latestDownloadHeight = await internalSyncState.latestDownloadedBlockHeight
|
||||
let latestScanHeight = try await coordinator.synchronizer.initializer.transactionRepository.lastScannedHeight()
|
||||
let dbHandle = TestDbHandle(originalDb: TestDbBuilder.prePopulatedDarksideCacheDb()!)
|
||||
try dbHandle.setUp()
|
||||
|
||||
if latestDownloadHeight > latestScanHeight {
|
||||
try await coordinator.synchronizer.blockProcessor.migrateCacheDb(dbHandle.readWriteDb)
|
||||
|
||||
let afterMigrationDownloadedHeight = await internalSyncState.latestDownloadedBlockHeight
|
||||
|
||||
XCTAssertNotEqual(latestDownloadHeight, afterMigrationDownloadedHeight)
|
||||
XCTAssertEqual(latestScanHeight, afterMigrationDownloadedHeight)
|
||||
} else {
|
||||
try await coordinator.synchronizer.blockProcessor.migrateCacheDb(dbHandle.readWriteDb)
|
||||
|
||||
let afterMigrationDownloadedHeight = await internalSyncState.latestDownloadedBlockHeight
|
||||
|
||||
XCTAssertEqual(latestDownloadHeight, afterMigrationDownloadedHeight)
|
||||
XCTAssertEqual(latestScanHeight, afterMigrationDownloadedHeight)
|
||||
}
|
||||
|
||||
XCTAssertFalse(FileManager.default.isReadableFile(atPath: dbHandle.readWriteDb.path))
|
||||
|
||||
// clear to simulate a clean slate from the FsBlockDb
|
||||
try await coordinator.synchronizer.blockProcessor.storage.clear()
|
||||
|
||||
// Now let's resume scanning and see how it goes.
|
||||
let secondSyncAttemptExpectation = XCTestExpectation(description: "second sync attempt")
|
||||
|
||||
do {
|
||||
try await coordinator.sync(
|
||||
completion: { _ in
|
||||
XCTAssertTrue(true)
|
||||
secondSyncAttemptExpectation.fulfill()
|
||||
},
|
||||
error: { [weak self] error in
|
||||
secondSyncAttemptExpectation.fulfill()
|
||||
self?.handleError(error)
|
||||
}
|
||||
)
|
||||
} catch {
|
||||
handleError(error)
|
||||
}
|
||||
|
||||
await fulfillment(of: [secondSyncAttemptExpectation], timeout: 10)
|
||||
}
|
||||
// func testInternalStateIsConsistentWhenMigrating() async throws {
|
||||
// sdkSynchronizerInternalSyncStatusHandler.subscribe(
|
||||
// to: coordinator.synchronizer.stateStream,
|
||||
// expectations: [.stopped: firstSyncExpectation]
|
||||
// )
|
||||
//
|
||||
// let fullSyncLength = 10000
|
||||
// try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName, length: fullSyncLength)
|
||||
//
|
||||
// sleep(1)
|
||||
//
|
||||
// // apply the height
|
||||
// try coordinator.applyStaged(blockheight: 664150)
|
||||
//
|
||||
// sleep(1)
|
||||
//
|
||||
// try await coordinator.sync(
|
||||
// completion: { _ in
|
||||
// XCTFail("shouldn't have completed")
|
||||
// },
|
||||
// error: handleError
|
||||
// )
|
||||
//
|
||||
// let coordinator = self.coordinator!
|
||||
// DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
|
||||
// Task(priority: .userInitiated) {
|
||||
// coordinator.synchronizer.stop()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// await fulfillment(of: [firstSyncExpectation], timeout: 2)
|
||||
//
|
||||
// let isSyncing = await coordinator.synchronizer.status.isSyncing
|
||||
// let status = await coordinator.synchronizer.status
|
||||
// XCTAssertFalse(isSyncing, "SDKSynchronizer shouldn't be syncing")
|
||||
// XCTAssertEqual(status, .stopped)
|
||||
//
|
||||
// let internalSyncState = InternalSyncProgress(
|
||||
// alias: .default,
|
||||
// storage: UserDefaults.standard,
|
||||
// logger: logger
|
||||
// )
|
||||
//
|
||||
// let latestDownloadHeight = await internalSyncState.latestDownloadedBlockHeight
|
||||
// let latestScanHeight = try await coordinator.synchronizer.initializer.transactionRepository.lastScannedHeight()
|
||||
// let dbHandle = TestDbHandle(originalDb: TestDbBuilder.prePopulatedDarksideCacheDb()!)
|
||||
// try dbHandle.setUp()
|
||||
//
|
||||
// if latestDownloadHeight > latestScanHeight {
|
||||
// try await coordinator.synchronizer.blockProcessor.migrateCacheDb(dbHandle.readWriteDb)
|
||||
//
|
||||
// let afterMigrationDownloadedHeight = await internalSyncState.latestDownloadedBlockHeight
|
||||
//
|
||||
// XCTAssertNotEqual(latestDownloadHeight, afterMigrationDownloadedHeight)
|
||||
// XCTAssertEqual(latestScanHeight, afterMigrationDownloadedHeight)
|
||||
// } else {
|
||||
// try await coordinator.synchronizer.blockProcessor.migrateCacheDb(dbHandle.readWriteDb)
|
||||
//
|
||||
// let afterMigrationDownloadedHeight = await internalSyncState.latestDownloadedBlockHeight
|
||||
//
|
||||
// XCTAssertEqual(latestDownloadHeight, afterMigrationDownloadedHeight)
|
||||
// XCTAssertEqual(latestScanHeight, afterMigrationDownloadedHeight)
|
||||
// }
|
||||
//
|
||||
// XCTAssertFalse(FileManager.default.isReadableFile(atPath: dbHandle.readWriteDb.path))
|
||||
//
|
||||
// // clear to simulate a clean slate from the FsBlockDb
|
||||
// try await coordinator.synchronizer.blockProcessor.storage.clear()
|
||||
//
|
||||
// // Now let's resume scanning and see how it goes.
|
||||
// let secondSyncAttemptExpectation = XCTestExpectation(description: "second sync attempt")
|
||||
//
|
||||
// do {
|
||||
// try await coordinator.sync(
|
||||
// completion: { _ in
|
||||
// XCTAssertTrue(true)
|
||||
// secondSyncAttemptExpectation.fulfill()
|
||||
// },
|
||||
// error: { [weak self] error in
|
||||
// secondSyncAttemptExpectation.fulfill()
|
||||
// self?.handleError(error)
|
||||
// }
|
||||
// )
|
||||
// } catch {
|
||||
// handleError(error)
|
||||
// }
|
||||
//
|
||||
// await fulfillment(of: [secondSyncAttemptExpectation], timeout: 10)
|
||||
// }
|
||||
|
||||
func handleError(_ error: Error?) {
|
||||
guard let testError = error else {
|
||||
|
|
|
@ -30,7 +30,7 @@ class PendingTransactionUpdatesTest: ZcashTestCase {
|
|||
walletBirthday: birthday,
|
||||
network: network
|
||||
)
|
||||
try self.coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
|
||||
try await coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
|
||||
}
|
||||
|
||||
override func tearDown() async throws {
|
||||
|
|
|
@ -50,7 +50,7 @@ class ReOrgTests: ZcashTestCase {
|
|||
network: self.network
|
||||
)
|
||||
|
||||
try self.coordinator.reset(saplingActivation: self.birthday, branchID: self.branchID, chainName: self.chainName)
|
||||
try await coordinator.reset(saplingActivation: self.birthday, branchID: self.branchID, chainName: self.chainName)
|
||||
|
||||
try self.coordinator.resetBlocks(dataset: .default)
|
||||
|
||||
|
@ -128,7 +128,7 @@ class ReOrgTests: ZcashTestCase {
|
|||
targetHeight: BlockHeight
|
||||
) async throws {
|
||||
do {
|
||||
try coordinator.reset(saplingActivation: birthday, branchID: branchID, chainName: chainName)
|
||||
try await coordinator.reset(saplingActivation: birthday, branchID: branchID, chainName: chainName)
|
||||
try coordinator.resetBlocks(dataset: .predefined(dataset: .beforeReOrg))
|
||||
try coordinator.applyStaged(blockheight: firstLatestHeight)
|
||||
sleep(1)
|
||||
|
|
|
@ -35,7 +35,7 @@ class RewindRescanTests: ZcashTestCase {
|
|||
walletBirthday: birthday,
|
||||
network: network
|
||||
)
|
||||
try self.coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
|
||||
try await coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
|
||||
}
|
||||
|
||||
override func tearDown() async throws {
|
||||
|
|
|
@ -30,7 +30,7 @@ class ShieldFundsTests: ZcashTestCase {
|
|||
walletBirthday: birthday,
|
||||
network: network
|
||||
)
|
||||
try coordinator.reset(saplingActivation: birthday, branchID: self.branchID, chainName: self.chainName)
|
||||
try await coordinator.reset(saplingActivation: birthday, branchID: self.branchID, chainName: self.chainName)
|
||||
try coordinator.service.clearAddedUTXOs()
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ class SynchronizerDarksideTests: ZcashTestCase {
|
|||
network: network
|
||||
)
|
||||
|
||||
try self.coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
|
||||
try await coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
|
||||
}
|
||||
|
||||
override func tearDown() async throws {
|
||||
|
@ -195,7 +195,7 @@ class SynchronizerDarksideTests: ZcashTestCase {
|
|||
syncSessionID: uuids[0],
|
||||
shieldedBalance: .zero,
|
||||
transparentBalance: .zero,
|
||||
internalSyncStatus: .syncing(BlockProgress(startHeight: 0, targetHeight: 0, progressHeight: 0)),
|
||||
internalSyncStatus: .syncing(0),
|
||||
latestScannedHeight: 663150,
|
||||
latestBlockHeight: 0,
|
||||
latestScannedTime: 1576821833
|
||||
|
@ -204,93 +204,7 @@ class SynchronizerDarksideTests: ZcashTestCase {
|
|||
syncSessionID: uuids[0],
|
||||
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
|
||||
transparentBalance: .zero,
|
||||
internalSyncStatus: .syncing(BlockProgress(startHeight: 663150, targetHeight: 663189, progressHeight: 663189)),
|
||||
latestScannedHeight: 663189,
|
||||
latestBlockHeight: 663189,
|
||||
latestScannedTime: 1
|
||||
),
|
||||
SynchronizerState(
|
||||
syncSessionID: uuids[0],
|
||||
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
|
||||
transparentBalance: .zero,
|
||||
internalSyncStatus: .enhancing(
|
||||
EnhancementProgress(totalTransactions: 0, enhancedTransactions: 0, lastFoundTransaction: nil, range: 0...0, newlyMined: false)
|
||||
),
|
||||
latestScannedHeight: 663189,
|
||||
latestBlockHeight: 663189,
|
||||
latestScannedTime: 1
|
||||
),
|
||||
SynchronizerState(
|
||||
syncSessionID: uuids[0],
|
||||
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
|
||||
transparentBalance: .zero,
|
||||
internalSyncStatus: .enhancing(
|
||||
EnhancementProgress(
|
||||
totalTransactions: 2,
|
||||
enhancedTransactions: 1,
|
||||
lastFoundTransaction: ZcashTransaction.Overview(
|
||||
accountId: 0,
|
||||
blockTime: 1.0,
|
||||
expiryHeight: 663206,
|
||||
fee: Zatoshi(0),
|
||||
id: 2,
|
||||
index: 1,
|
||||
hasChange: false,
|
||||
memoCount: 1,
|
||||
minedHeight: 663188,
|
||||
raw: Data(),
|
||||
rawID: Data(),
|
||||
receivedNoteCount: 1,
|
||||
sentNoteCount: 0,
|
||||
value: Zatoshi(100000),
|
||||
isExpiredUmined: false
|
||||
),
|
||||
range: 663150...663189,
|
||||
newlyMined: true
|
||||
)
|
||||
),
|
||||
latestScannedHeight: 663189,
|
||||
latestBlockHeight: 663189,
|
||||
latestScannedTime: 1
|
||||
),
|
||||
SynchronizerState(
|
||||
syncSessionID: uuids[0],
|
||||
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
|
||||
transparentBalance: .zero,
|
||||
internalSyncStatus: .enhancing(
|
||||
EnhancementProgress(
|
||||
totalTransactions: 2,
|
||||
enhancedTransactions: 2,
|
||||
lastFoundTransaction: ZcashTransaction.Overview(
|
||||
accountId: 0,
|
||||
blockTime: 1.0,
|
||||
expiryHeight: 663192,
|
||||
fee: Zatoshi(0),
|
||||
id: 1,
|
||||
index: 1,
|
||||
hasChange: false,
|
||||
memoCount: 1,
|
||||
minedHeight: 663174,
|
||||
raw: Data(),
|
||||
rawID: Data(),
|
||||
receivedNoteCount: 1,
|
||||
sentNoteCount: 0,
|
||||
value: Zatoshi(100000),
|
||||
isExpiredUmined: false
|
||||
),
|
||||
range: 663150...663189,
|
||||
newlyMined: true
|
||||
)
|
||||
),
|
||||
latestScannedHeight: 663189,
|
||||
latestBlockHeight: 663189,
|
||||
latestScannedTime: 1
|
||||
),
|
||||
SynchronizerState(
|
||||
syncSessionID: uuids[0],
|
||||
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
|
||||
transparentBalance: .zero,
|
||||
internalSyncStatus: .fetching(0),
|
||||
internalSyncStatus: .syncing(0.9),
|
||||
latestScannedHeight: 663189,
|
||||
latestBlockHeight: 663189,
|
||||
latestScannedTime: 1
|
||||
|
@ -359,7 +273,7 @@ class SynchronizerDarksideTests: ZcashTestCase {
|
|||
syncSessionID: uuids[0],
|
||||
shieldedBalance: .zero,
|
||||
transparentBalance: .zero,
|
||||
internalSyncStatus: .syncing(BlockProgress(startHeight: 0, targetHeight: 0, progressHeight: 0)),
|
||||
internalSyncStatus: .syncing(0),
|
||||
latestScannedHeight: 663150,
|
||||
latestBlockHeight: 0,
|
||||
latestScannedTime: 1576821833.0
|
||||
|
@ -368,93 +282,7 @@ class SynchronizerDarksideTests: ZcashTestCase {
|
|||
syncSessionID: uuids[0],
|
||||
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
|
||||
transparentBalance: .zero,
|
||||
internalSyncStatus: .syncing(BlockProgress(startHeight: 663150, targetHeight: 663189, progressHeight: 663189)),
|
||||
latestScannedHeight: 663189,
|
||||
latestBlockHeight: 663189,
|
||||
latestScannedTime: 1
|
||||
),
|
||||
SynchronizerState(
|
||||
syncSessionID: uuids[0],
|
||||
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
|
||||
transparentBalance: WalletBalance(verified: Zatoshi(0), total: Zatoshi(0)),
|
||||
internalSyncStatus: .enhancing(
|
||||
EnhancementProgress(totalTransactions: 0, enhancedTransactions: 0, lastFoundTransaction: nil, range: 0...0, newlyMined: false)
|
||||
),
|
||||
latestScannedHeight: 663189,
|
||||
latestBlockHeight: 663189,
|
||||
latestScannedTime: 1
|
||||
),
|
||||
SynchronizerState(
|
||||
syncSessionID: uuids[0],
|
||||
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
|
||||
transparentBalance: WalletBalance(verified: Zatoshi(0), total: Zatoshi(0)),
|
||||
internalSyncStatus: .enhancing(
|
||||
EnhancementProgress(
|
||||
totalTransactions: 2,
|
||||
enhancedTransactions: 1,
|
||||
lastFoundTransaction: ZcashTransaction.Overview(
|
||||
accountId: 0,
|
||||
blockTime: 1.0,
|
||||
expiryHeight: 663206,
|
||||
fee: nil,
|
||||
id: 2,
|
||||
index: 1,
|
||||
hasChange: false,
|
||||
memoCount: 1,
|
||||
minedHeight: 663188,
|
||||
raw: Data(),
|
||||
rawID: Data(),
|
||||
receivedNoteCount: 1,
|
||||
sentNoteCount: 0,
|
||||
value: Zatoshi(100000),
|
||||
isExpiredUmined: false
|
||||
),
|
||||
range: 663150...663189,
|
||||
newlyMined: true
|
||||
)
|
||||
),
|
||||
latestScannedHeight: 663189,
|
||||
latestBlockHeight: 663189,
|
||||
latestScannedTime: 1
|
||||
),
|
||||
SynchronizerState(
|
||||
syncSessionID: uuids[0],
|
||||
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
|
||||
transparentBalance: WalletBalance(verified: Zatoshi(0), total: Zatoshi(0)),
|
||||
internalSyncStatus: .enhancing(
|
||||
EnhancementProgress(
|
||||
totalTransactions: 2,
|
||||
enhancedTransactions: 2,
|
||||
lastFoundTransaction: ZcashTransaction.Overview(
|
||||
accountId: 0,
|
||||
blockTime: 1.0,
|
||||
expiryHeight: 663192,
|
||||
fee: nil,
|
||||
id: 1,
|
||||
index: 1,
|
||||
hasChange: false,
|
||||
memoCount: 1,
|
||||
minedHeight: 663174,
|
||||
raw: Data(),
|
||||
rawID: Data(),
|
||||
receivedNoteCount: 1,
|
||||
sentNoteCount: 0,
|
||||
value: Zatoshi(100000),
|
||||
isExpiredUmined: false
|
||||
),
|
||||
range: 663150...663189,
|
||||
newlyMined: true
|
||||
)
|
||||
),
|
||||
latestScannedHeight: 663189,
|
||||
latestBlockHeight: 663189,
|
||||
latestScannedTime: 1
|
||||
),
|
||||
SynchronizerState(
|
||||
syncSessionID: uuids[0],
|
||||
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
|
||||
transparentBalance: WalletBalance(verified: Zatoshi(0), total: Zatoshi(0)),
|
||||
internalSyncStatus: .fetching(0),
|
||||
internalSyncStatus: .syncing(0.9),
|
||||
latestScannedHeight: 663189,
|
||||
latestBlockHeight: 663189,
|
||||
latestScannedTime: 1
|
||||
|
@ -499,7 +327,7 @@ class SynchronizerDarksideTests: ZcashTestCase {
|
|||
syncSessionID: uuids[1],
|
||||
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
|
||||
transparentBalance: WalletBalance(verified: Zatoshi(0), total: Zatoshi(0)),
|
||||
internalSyncStatus: .syncing(BlockProgress(startHeight: 0, targetHeight: 0, progressHeight: 0)),
|
||||
internalSyncStatus: .syncing(0),
|
||||
latestScannedHeight: 663189,
|
||||
latestBlockHeight: 663189,
|
||||
latestScannedTime: 1.0
|
||||
|
@ -508,27 +336,7 @@ class SynchronizerDarksideTests: ZcashTestCase {
|
|||
syncSessionID: uuids[1],
|
||||
shieldedBalance: WalletBalance(verified: Zatoshi(200000), total: Zatoshi(200000)),
|
||||
transparentBalance: WalletBalance(verified: Zatoshi(0), total: Zatoshi(0)),
|
||||
internalSyncStatus: .syncing(BlockProgress(startHeight: 663190, targetHeight: 663200, progressHeight: 663200)),
|
||||
latestScannedHeight: 663200,
|
||||
latestBlockHeight: 663200,
|
||||
latestScannedTime: 1
|
||||
),
|
||||
SynchronizerState(
|
||||
syncSessionID: uuids[1],
|
||||
shieldedBalance: WalletBalance(verified: Zatoshi(200000), total: Zatoshi(200000)),
|
||||
transparentBalance: WalletBalance(verified: Zatoshi(0), total: Zatoshi(0)),
|
||||
internalSyncStatus: .enhancing(
|
||||
EnhancementProgress(totalTransactions: 0, enhancedTransactions: 0, lastFoundTransaction: nil, range: 0...0, newlyMined: true)
|
||||
),
|
||||
latestScannedHeight: 663200,
|
||||
latestBlockHeight: 663200,
|
||||
latestScannedTime: 1
|
||||
),
|
||||
SynchronizerState(
|
||||
syncSessionID: uuids[1],
|
||||
shieldedBalance: WalletBalance(verified: Zatoshi(200000), total: Zatoshi(200000)),
|
||||
transparentBalance: WalletBalance(verified: Zatoshi(0), total: Zatoshi(0)),
|
||||
internalSyncStatus: .fetching(0),
|
||||
internalSyncStatus: .syncing(0.9),
|
||||
latestScannedHeight: 663200,
|
||||
latestBlockHeight: 663200,
|
||||
latestScannedTime: 1
|
||||
|
|
|
@ -33,7 +33,7 @@ final class SynchronizerTests: ZcashTestCase {
|
|||
walletBirthday: birthday + 50,
|
||||
network: network
|
||||
)
|
||||
try coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
|
||||
try await coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
|
||||
|
||||
let eventClosure: CompactBlockProcessor.EventClosure = { [weak self] event in
|
||||
switch event {
|
||||
|
@ -66,189 +66,189 @@ final class SynchronizerTests: ZcashTestCase {
|
|||
reorgExpectation.fulfill()
|
||||
}
|
||||
|
||||
func testSynchronizerStops() async throws {
|
||||
/*
|
||||
1. create fake chain
|
||||
*/
|
||||
let fullSyncLength = 100_000
|
||||
|
||||
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName, length: fullSyncLength)
|
||||
|
||||
try coordinator.applyStaged(blockheight: birthday + fullSyncLength)
|
||||
|
||||
sleep(10)
|
||||
|
||||
let syncStoppedExpectation = XCTestExpectation(description: "SynchronizerStopped Expectation")
|
||||
sdkSynchronizerInternalSyncStatusHandler.subscribe(
|
||||
to: coordinator.synchronizer.stateStream,
|
||||
expectations: [.stopped: syncStoppedExpectation]
|
||||
)
|
||||
|
||||
/*
|
||||
sync to latest height
|
||||
*/
|
||||
try await coordinator.sync(
|
||||
completion: { _ in
|
||||
XCTFail("Sync should have stopped")
|
||||
},
|
||||
error: self.handleError
|
||||
)
|
||||
|
||||
try await Task.sleep(nanoseconds: 5_000_000_000)
|
||||
self.coordinator.synchronizer.stop()
|
||||
|
||||
await fulfillment(of: [syncStoppedExpectation], timeout: 6)
|
||||
|
||||
let status = await coordinator.synchronizer.status
|
||||
XCTAssertEqual(status, .stopped)
|
||||
let state = await coordinator.synchronizer.blockProcessor.state
|
||||
XCTAssertEqual(state, .stopped)
|
||||
}
|
||||
// func testSynchronizerStops() async throws {
|
||||
// /*
|
||||
// 1. create fake chain
|
||||
// */
|
||||
// let fullSyncLength = 100_000
|
||||
//
|
||||
// try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName, length: fullSyncLength)
|
||||
//
|
||||
// try coordinator.applyStaged(blockheight: birthday + fullSyncLength)
|
||||
//
|
||||
// sleep(10)
|
||||
//
|
||||
// let syncStoppedExpectation = XCTestExpectation(description: "SynchronizerStopped Expectation")
|
||||
// sdkSynchronizerInternalSyncStatusHandler.subscribe(
|
||||
// to: coordinator.synchronizer.stateStream,
|
||||
// expectations: [.stopped: syncStoppedExpectation]
|
||||
// )
|
||||
//
|
||||
// /*
|
||||
// sync to latest height
|
||||
// */
|
||||
// try await coordinator.sync(
|
||||
// completion: { _ in
|
||||
// XCTFail("Sync should have stopped")
|
||||
// },
|
||||
// error: self.handleError
|
||||
// )
|
||||
//
|
||||
// try await Task.sleep(nanoseconds: 5_000_000_000)
|
||||
// self.coordinator.synchronizer.stop()
|
||||
//
|
||||
// await fulfillment(of: [syncStoppedExpectation], timeout: 6)
|
||||
//
|
||||
// let status = await coordinator.synchronizer.status
|
||||
// XCTAssertEqual(status, .stopped)
|
||||
// let state = await coordinator.synchronizer.blockProcessor.state
|
||||
// XCTAssertEqual(state, .stopped)
|
||||
// }
|
||||
|
||||
// MARK: Wipe tests
|
||||
|
||||
func testWipeCalledWhichSyncDoesntRun() async throws {
|
||||
/*
|
||||
create fake chain
|
||||
*/
|
||||
let fullSyncLength = 1000
|
||||
// func testWipeCalledWhichSyncDoesntRun() async throws {
|
||||
// /*
|
||||
// create fake chain
|
||||
// */
|
||||
// let fullSyncLength = 1000
|
||||
//
|
||||
// try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName, length: fullSyncLength)
|
||||
//
|
||||
// try coordinator.applyStaged(blockheight: birthday + fullSyncLength)
|
||||
//
|
||||
// sleep(2)
|
||||
//
|
||||
// let syncFinished = XCTestExpectation(description: "SynchronizerSyncFinished Expectation")
|
||||
//
|
||||
// /*
|
||||
// sync to latest height
|
||||
// */
|
||||
// try await coordinator.sync(
|
||||
// completion: { _ in
|
||||
// syncFinished.fulfill()
|
||||
// },
|
||||
// error: handleError
|
||||
// )
|
||||
//
|
||||
// await fulfillment(of: [syncFinished], timeout: 3)
|
||||
//
|
||||
// let wipeFinished = XCTestExpectation(description: "SynchronizerWipeFinished Expectation")
|
||||
//
|
||||
// /*
|
||||
// Call wipe
|
||||
// */
|
||||
// coordinator.synchronizer.wipe()
|
||||
// .sink(
|
||||
// receiveCompletion: { completion in
|
||||
// switch completion {
|
||||
// case .finished:
|
||||
// wipeFinished.fulfill()
|
||||
//
|
||||
// case .failure(let error):
|
||||
// XCTFail("Wipe should finish successfully. \(error)")
|
||||
// }
|
||||
// },
|
||||
// receiveValue: {
|
||||
// XCTFail("No no value should be received from wipe.")
|
||||
// }
|
||||
// )
|
||||
// .store(in: &cancellables)
|
||||
//
|
||||
// await fulfillment(of: [wipeFinished], timeout: 1)
|
||||
//
|
||||
// /*
|
||||
// Check that wipe cleared everything that is expected
|
||||
// */
|
||||
// await checkThatWipeWorked()
|
||||
// }
|
||||
|
||||
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName, length: fullSyncLength)
|
||||
// func testWipeCalledWhileSyncRuns() async throws {
|
||||
// /*
|
||||
// 1. create fake chain
|
||||
// */
|
||||
// let fullSyncLength = 50_000
|
||||
//
|
||||
// try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName, length: fullSyncLength)
|
||||
//
|
||||
// try coordinator.applyStaged(blockheight: birthday + fullSyncLength)
|
||||
//
|
||||
// sleep(5)
|
||||
//
|
||||
// /*
|
||||
// Start sync
|
||||
// */
|
||||
// try await coordinator.sync(
|
||||
// completion: { _ in
|
||||
// XCTFail("Sync should have stopped")
|
||||
// },
|
||||
// error: self.handleError
|
||||
// )
|
||||
//
|
||||
// try await Task.sleep(nanoseconds: 2_000_000_000)
|
||||
//
|
||||
// // Just to be sure that blockProcessor is still syncing and that this test does what it should.
|
||||
// let blockProcessorState = await coordinator.synchronizer.blockProcessor.state
|
||||
// XCTAssertEqual(blockProcessorState, .syncing)
|
||||
//
|
||||
// let wipeFinished = XCTestExpectation(description: "SynchronizerWipeFinished Expectation")
|
||||
// /*
|
||||
// Call wipe
|
||||
// */
|
||||
// coordinator.synchronizer.wipe()
|
||||
// .sink(
|
||||
// receiveCompletion: { completion in
|
||||
// switch completion {
|
||||
// case .finished:
|
||||
// wipeFinished.fulfill()
|
||||
//
|
||||
// case .failure(let error):
|
||||
// XCTFail("Wipe should finish successfully. \(error)")
|
||||
// }
|
||||
// },
|
||||
// receiveValue: {
|
||||
// XCTFail("No no value should be received from wipe.")
|
||||
// }
|
||||
// )
|
||||
// .store(in: &cancellables)
|
||||
//
|
||||
// await fulfillment(of: [wipeFinished], timeout: 6)
|
||||
//
|
||||
// /*
|
||||
// Check that wipe cleared everything that is expected
|
||||
// */
|
||||
// await checkThatWipeWorked()
|
||||
// }
|
||||
|
||||
try coordinator.applyStaged(blockheight: birthday + fullSyncLength)
|
||||
|
||||
sleep(2)
|
||||
|
||||
let syncFinished = XCTestExpectation(description: "SynchronizerSyncFinished Expectation")
|
||||
|
||||
/*
|
||||
sync to latest height
|
||||
*/
|
||||
try await coordinator.sync(
|
||||
completion: { _ in
|
||||
syncFinished.fulfill()
|
||||
},
|
||||
error: handleError
|
||||
)
|
||||
|
||||
await fulfillment(of: [syncFinished], timeout: 3)
|
||||
|
||||
let wipeFinished = XCTestExpectation(description: "SynchronizerWipeFinished Expectation")
|
||||
|
||||
/*
|
||||
Call wipe
|
||||
*/
|
||||
coordinator.synchronizer.wipe()
|
||||
.sink(
|
||||
receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case .finished:
|
||||
wipeFinished.fulfill()
|
||||
|
||||
case .failure(let error):
|
||||
XCTFail("Wipe should finish successfully. \(error)")
|
||||
}
|
||||
},
|
||||
receiveValue: {
|
||||
XCTFail("No no value should be received from wipe.")
|
||||
}
|
||||
)
|
||||
.store(in: &cancellables)
|
||||
|
||||
await fulfillment(of: [wipeFinished], timeout: 1)
|
||||
|
||||
/*
|
||||
Check that wipe cleared everything that is expected
|
||||
*/
|
||||
await checkThatWipeWorked()
|
||||
}
|
||||
|
||||
func testWipeCalledWhileSyncRuns() async throws {
|
||||
/*
|
||||
1. create fake chain
|
||||
*/
|
||||
let fullSyncLength = 50_000
|
||||
|
||||
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName, length: fullSyncLength)
|
||||
|
||||
try coordinator.applyStaged(blockheight: birthday + fullSyncLength)
|
||||
|
||||
sleep(5)
|
||||
|
||||
/*
|
||||
Start sync
|
||||
*/
|
||||
try await coordinator.sync(
|
||||
completion: { _ in
|
||||
XCTFail("Sync should have stopped")
|
||||
},
|
||||
error: self.handleError
|
||||
)
|
||||
|
||||
try await Task.sleep(nanoseconds: 2_000_000_000)
|
||||
|
||||
// Just to be sure that blockProcessor is still syncing and that this test does what it should.
|
||||
let blockProcessorState = await coordinator.synchronizer.blockProcessor.state
|
||||
XCTAssertEqual(blockProcessorState, .syncing)
|
||||
|
||||
let wipeFinished = XCTestExpectation(description: "SynchronizerWipeFinished Expectation")
|
||||
/*
|
||||
Call wipe
|
||||
*/
|
||||
coordinator.synchronizer.wipe()
|
||||
.sink(
|
||||
receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case .finished:
|
||||
wipeFinished.fulfill()
|
||||
|
||||
case .failure(let error):
|
||||
XCTFail("Wipe should finish successfully. \(error)")
|
||||
}
|
||||
},
|
||||
receiveValue: {
|
||||
XCTFail("No no value should be received from wipe.")
|
||||
}
|
||||
)
|
||||
.store(in: &cancellables)
|
||||
|
||||
await fulfillment(of: [wipeFinished], timeout: 6)
|
||||
|
||||
/*
|
||||
Check that wipe cleared everything that is expected
|
||||
*/
|
||||
await checkThatWipeWorked()
|
||||
}
|
||||
|
||||
private func checkThatWipeWorked() async {
|
||||
let storage = await self.coordinator.synchronizer.blockProcessor.storage as! FSCompactBlockRepository
|
||||
let fm = FileManager.default
|
||||
print(coordinator.synchronizer.initializer.dataDbURL.path)
|
||||
|
||||
XCTAssertFalse(fm.fileExists(atPath: coordinator.synchronizer.initializer.dataDbURL.path), "Data DB should be deleted.")
|
||||
XCTAssertTrue(fm.fileExists(atPath: storage.blocksDirectory.path), "FS Cache directory should exist")
|
||||
XCTAssertEqual(try fm.contentsOfDirectory(atPath: storage.blocksDirectory.path), [], "FS Cache directory should be empty")
|
||||
|
||||
let internalSyncProgress = InternalSyncProgress(
|
||||
alias: .default,
|
||||
storage: UserDefaults.standard,
|
||||
logger: logger
|
||||
)
|
||||
|
||||
let latestDownloadedBlockHeight = await internalSyncProgress.load(.latestDownloadedBlockHeight)
|
||||
let latestEnhancedHeight = await internalSyncProgress.load(.latestEnhancedHeight)
|
||||
let latestUTXOFetchedHeight = await internalSyncProgress.load(.latestUTXOFetchedHeight)
|
||||
|
||||
XCTAssertEqual(latestDownloadedBlockHeight, 0, "internalSyncProgress latestDownloadedBlockHeight should be 0")
|
||||
XCTAssertEqual(latestEnhancedHeight, 0, "internalSyncProgress latestEnhancedHeight should be 0")
|
||||
XCTAssertEqual(latestUTXOFetchedHeight, 0, "internalSyncProgress latestUTXOFetchedHeight should be 0")
|
||||
|
||||
let blockProcessorState = await coordinator.synchronizer.blockProcessor.state
|
||||
XCTAssertEqual(blockProcessorState, .stopped, "CompactBlockProcessor state should be stopped")
|
||||
|
||||
let status = await coordinator.synchronizer.status
|
||||
XCTAssertEqual(status, .unprepared, "SDKSynchronizer state should be unprepared")
|
||||
}
|
||||
// private func checkThatWipeWorked() async {
|
||||
// let storage = await self.coordinator.synchronizer.blockProcessor.storage as! FSCompactBlockRepository
|
||||
// let fm = FileManager.default
|
||||
// print(coordinator.synchronizer.initializer.dataDbURL.path)
|
||||
//
|
||||
// XCTAssertFalse(fm.fileExists(atPath: coordinator.synchronizer.initializer.dataDbURL.path), "Data DB should be deleted.")
|
||||
// XCTAssertTrue(fm.fileExists(atPath: storage.blocksDirectory.path), "FS Cache directory should exist")
|
||||
// XCTAssertEqual(try fm.contentsOfDirectory(atPath: storage.blocksDirectory.path), [], "FS Cache directory should be empty")
|
||||
//
|
||||
// let internalSyncProgress = InternalSyncProgress(
|
||||
// alias: .default,
|
||||
// storage: UserDefaults.standard,
|
||||
// logger: logger
|
||||
// )
|
||||
//
|
||||
// let latestDownloadedBlockHeight = await internalSyncProgress.load(.latestDownloadedBlockHeight)
|
||||
// let latestEnhancedHeight = await internalSyncProgress.load(.latestEnhancedHeight)
|
||||
// let latestUTXOFetchedHeight = await internalSyncProgress.load(.latestUTXOFetchedHeight)
|
||||
//
|
||||
// XCTAssertEqual(latestDownloadedBlockHeight, 0, "internalSyncProgress latestDownloadedBlockHeight should be 0")
|
||||
// XCTAssertEqual(latestEnhancedHeight, 0, "internalSyncProgress latestEnhancedHeight should be 0")
|
||||
// XCTAssertEqual(latestUTXOFetchedHeight, 0, "internalSyncProgress latestUTXOFetchedHeight should be 0")
|
||||
//
|
||||
// let blockProcessorState = await coordinator.synchronizer.blockProcessor.state
|
||||
// XCTAssertEqual(blockProcessorState, .stopped, "CompactBlockProcessor state should be stopped")
|
||||
//
|
||||
// let status = await coordinator.synchronizer.status
|
||||
// XCTAssertEqual(status, .unprepared, "SDKSynchronizer state should be unprepared")
|
||||
// }
|
||||
|
||||
func handleError(_ error: Error?) async {
|
||||
_ = try? await coordinator.stop()
|
||||
|
|
|
@ -33,7 +33,7 @@ class Z2TReceiveTests: ZcashTestCase {
|
|||
walletBirthday: birthday,
|
||||
network: network
|
||||
)
|
||||
try coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
|
||||
try await coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
|
||||
}
|
||||
|
||||
override func tearDown() async throws {
|
||||
|
|
|
@ -212,7 +212,7 @@ final class ComputeSyncRangesActionTests: ZcashTestCase {
|
|||
|
||||
return ComputeSyncRangesAction(
|
||||
container: mockContainer,
|
||||
config: config
|
||||
configProvider: CompactBlockProcessor.ConfigProvider(config: config)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ final class DownloadActionTests: ZcashTestCase {
|
|||
|
||||
return DownloadAction(
|
||||
container: mockContainer,
|
||||
config: config
|
||||
configProvider: CompactBlockProcessor.ConfigProvider(config: config)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -245,6 +245,71 @@ final class EnhanceActionTests: ZcashTestCase {
|
|||
XCTFail("testEnhanceAction_EnhancementOfBlocksCalled_minedTransaction is not expected to fail. \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func testEnhanceAction_EnhancementOfBlocksCalled_usingSmallRange_minedTransaction() async throws {
|
||||
let blockEnhancerMock = BlockEnhancerMock()
|
||||
let transactionRepositoryMock = TransactionRepositoryMock()
|
||||
let internalSyncProgressStorageMock = InternalSyncProgressStorageMock()
|
||||
|
||||
transactionRepositoryMock.lastScannedHeightReturnValue = 200
|
||||
internalSyncProgressStorageMock.integerForKeyReturnValue = 1
|
||||
|
||||
let transaction = ZcashTransaction.Overview(
|
||||
accountId: 0,
|
||||
blockTime: 1.0,
|
||||
expiryHeight: 663206,
|
||||
fee: Zatoshi(0),
|
||||
id: 2,
|
||||
index: 1,
|
||||
hasChange: false,
|
||||
memoCount: 1,
|
||||
minedHeight: 663188,
|
||||
raw: Data(),
|
||||
rawID: Data(),
|
||||
receivedNoteCount: 1,
|
||||
sentNoteCount: 0,
|
||||
value: Zatoshi(100000),
|
||||
isExpiredUmined: false
|
||||
)
|
||||
|
||||
blockEnhancerMock.enhanceAtDidEnhanceClosure = { _, didEnhance in
|
||||
await didEnhance(
|
||||
EnhancementProgress(
|
||||
totalTransactions: 0,
|
||||
enhancedTransactions: 0,
|
||||
lastFoundTransaction: transaction,
|
||||
range: 0...0,
|
||||
newlyMined: true
|
||||
)
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
let enhanceAction = setupAction(
|
||||
blockEnhancerMock,
|
||||
transactionRepositoryMock,
|
||||
internalSyncProgressStorageMock
|
||||
)
|
||||
|
||||
underlyingEnhanceRange = CompactBlockRange(uncheckedBounds: (100, 200))
|
||||
|
||||
let syncContext = await setupActionContext()
|
||||
|
||||
do {
|
||||
_ = try await enhanceAction.run(with: syncContext) { event in
|
||||
guard case .minedTransaction(let minedTransaction) = event else {
|
||||
XCTFail("Event is expected to be .minedTransaction but received \(event)")
|
||||
return
|
||||
}
|
||||
XCTAssertEqual(minedTransaction.expiryHeight, transaction.expiryHeight, "MinedTransaction differs from mocked one.")
|
||||
}
|
||||
XCTAssertTrue(transactionRepositoryMock.lastScannedHeightCalled, "transactionRepository.lastScannedHeight() is expected to be called.")
|
||||
XCTAssertTrue(internalSyncProgressStorageMock.integerForKeyCalled, "internalSyncProgress.load() is expected to be called.")
|
||||
XCTAssertTrue(blockEnhancerMock.enhanceAtDidEnhanceCalled, "blockEnhancer.enhance() is expected to be called.")
|
||||
} catch {
|
||||
XCTFail("testEnhanceAction_EnhancementOfBlocksCalled_minedTransaction is not expected to fail. \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
private func setupActionContext() async -> ActionContext {
|
||||
let syncContext: ActionContext = .init(state: .enhance)
|
||||
|
@ -285,7 +350,7 @@ final class EnhanceActionTests: ZcashTestCase {
|
|||
|
||||
return EnhanceAction(
|
||||
container: mockContainer,
|
||||
config: config
|
||||
configProvider: CompactBlockProcessor.ConfigProvider(config: config)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ final class ScanActionTests: ZcashTestCase {
|
|||
|
||||
return ScanAction(
|
||||
container: mockContainer,
|
||||
config: config
|
||||
configProvider: CompactBlockProcessor.ConfigProvider(config: config)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ final class ValidateServerActionTests: ZcashTestCase {
|
|||
|
||||
return ValidateServerAction(
|
||||
container: mockContainer,
|
||||
config: config
|
||||
configProvider: CompactBlockProcessor.ConfigProvider(config: config)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -209,29 +209,26 @@ extension TestCoordinator {
|
|||
try await service.latestBlockHeight()
|
||||
}
|
||||
|
||||
func reset(saplingActivation: BlockHeight, branchID: String, chainName: String) throws {
|
||||
Task {
|
||||
await self.synchronizer.blockProcessor.stop()
|
||||
// TODO: [#1102] review and potentially fix/remove commented code https://github.com/zcash/ZcashLightClientKit/issues/1102
|
||||
// let config = await self.synchronizer.blockProcessor.config
|
||||
//
|
||||
// let newConfig = CompactBlockProcessor.Configuration(
|
||||
// alias: config.alias,
|
||||
// fsBlockCacheRoot: config.fsBlockCacheRoot,
|
||||
// dataDb: config.dataDb,
|
||||
// spendParamsURL: config.spendParamsURL,
|
||||
// outputParamsURL: config.outputParamsURL,
|
||||
// saplingParamsSourceURL: config.saplingParamsSourceURL,
|
||||
// retries: config.retries,
|
||||
// maxBackoffInterval: config.maxBackoffInterval,
|
||||
// rewindDistance: config.rewindDistance,
|
||||
// walletBirthdayProvider: config.walletBirthdayProvider,
|
||||
// saplingActivation: saplingActivation,
|
||||
// network: config.network
|
||||
// )
|
||||
func reset(saplingActivation: BlockHeight, branchID: String, chainName: String) async throws {
|
||||
await self.synchronizer.blockProcessor.stop()
|
||||
|
||||
// await self.synchronizer.blockProcessor.update(config: newConfig)
|
||||
}
|
||||
let config = await self.synchronizer.blockProcessor.config
|
||||
let newConfig = CompactBlockProcessor.Configuration(
|
||||
alias: config.alias,
|
||||
fsBlockCacheRoot: config.fsBlockCacheRoot,
|
||||
dataDb: config.dataDb,
|
||||
spendParamsURL: config.spendParamsURL,
|
||||
outputParamsURL: config.outputParamsURL,
|
||||
saplingParamsSourceURL: config.saplingParamsSourceURL,
|
||||
retries: config.retries,
|
||||
maxBackoffInterval: config.maxBackoffInterval,
|
||||
rewindDistance: config.rewindDistance,
|
||||
walletBirthdayProvider: config.walletBirthdayProvider,
|
||||
saplingActivation: saplingActivation,
|
||||
network: config.network
|
||||
)
|
||||
|
||||
await self.synchronizer.blockProcessor.update(config: newConfig)
|
||||
|
||||
try service.reset(saplingActivation: saplingActivation, branchID: branchID, chainName: chainName)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue