ZcashLightClientKit/Tests/DarksideTests/SynchronizerTests.swift

121 lines
4.2 KiB
Swift

//
// SynchronizerTests.swift
// DarksideTests
//
// Created by Francisco Gindre on 9/16/22.
//
import Combine
import XCTest
@testable import TestUtils
@testable import ZcashLightClientKit
final class SynchronizerTests: XCTestCase {
let sendAmount = Zatoshi(1000)
var birthday: BlockHeight = 663150
let defaultLatestHeight: BlockHeight = 663175
var coordinator: TestCoordinator!
var syncedExpectation = XCTestExpectation(description: "synced")
var sentTransactionExpectation = XCTestExpectation(description: "sent")
var expectedReorgHeight: BlockHeight = 665188
var expectedRewindHeight: BlockHeight = 665188
var reorgExpectation = XCTestExpectation(description: "reorg")
let branchID = "2bb40e60"
let chainName = "main"
let network = DarksideWalletDNetwork()
var cancellables: [AnyCancellable] = []
var processorEventHandler: CompactBlockProcessorEventHandler! = CompactBlockProcessorEventHandler()
override func setUpWithError() throws {
try super.setUpWithError()
self.coordinator = try TestCoordinator(
seed: Environment.seedPhrase,
walletBirthday: self.birthday + 50, // don't use an exact birthday, users never do.
network: self.network
)
try coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
var stream: AnyPublisher<CompactBlockProcessor.Event, Never>!
XCTestCase.wait { await stream = self.coordinator.synchronizer.blockProcessor.eventStream }
stream
.sink { [weak self] event in
switch event {
case .handledReorg: self?.handleReorg(event: event)
default: break
}
}
.store(in: &cancellables)
}
override func tearDownWithError() throws {
try super.tearDownWithError()
NotificationCenter.default.removeObserver(self)
try coordinator.stop()
try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot)
try? FileManager.default.removeItem(at: coordinator.databases.dataDB)
try? FileManager.default.removeItem(at: coordinator.databases.pendingDB)
coordinator = nil
cancellables = []
processorEventHandler = nil
}
func handleReorg(event: CompactBlockProcessor.Event) {
guard case let .handledReorg(reorgHeight, rewindHeight) = event else { return XCTFail("empty reorg notification") }
logger!.debug("--- REORG DETECTED \(reorgHeight)--- RewindHeight: \(rewindHeight)", file: #file, function: #function, line: #line)
XCTAssertEqual(reorgHeight, expectedReorgHeight)
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")
syncStoppedExpectation.subscribe(to: .synchronizerStopped, object: nil)
/*
sync to latest height
*/
try coordinator.sync(completion: { _ in
XCTFail("Sync should have stopped")
}, error: { error in
_ = try? self.coordinator.stop()
guard let testError = error else {
XCTFail("failed with nil error")
return
}
XCTFail("Failed with error: \(testError)")
})
try await Task.sleep(nanoseconds: 5_000_000_000)
self.coordinator.synchronizer.stop()
wait(for: [syncStoppedExpectation], timeout: 6, enforceOrder: true)
XCTAssertEqual(coordinator.synchronizer.status, .stopped)
let state = await coordinator.synchronizer.blockProcessor.state
XCTAssertEqual(state, .stopped)
}
func handleError(_ error: Error?) {
_ = try? coordinator.stop()
guard let testError = error else {
XCTFail("failed with nil error")
return
}
XCTFail("Failed with error: \(testError)")
}
}