[#1049] Implement ValidateAction

- synchronizer offline tests updated so it compiles, review is requested in a different ticket
- ValidateAction tests added
- BlockValidator mock generated
This commit is contained in:
Lukas Korba 2023-05-17 16:50:44 +02:00 committed by Michal Fousek
parent 1b0e9e00f5
commit d4abae7fa2
8 changed files with 78 additions and 92 deletions

View File

@ -0,0 +1,33 @@
//
// ValidateActionTests.swift
//
//
// Created by Lukáš Korba on 17.05.2023.
//
import XCTest
@testable import TestUtils
@testable import ZcashLightClientKit
final class ValidateActionTests: ZcashTestCase {
func testValidateAction_NextAction() async throws {
let blockValidatorMock = BlockValidatorMock()
mockContainer.mock(type: BlockValidator.self, isSingleton: true) { _ in blockValidatorMock }
let validateAction = ValidateAction(
container: mockContainer
)
do {
let nextContext = try await validateAction.run(with: .init(state: .validate)) { _ in }
let nextState = await nextContext.state
XCTAssertTrue(
nextState == .scan,
"nextContext after .validate is expected to be .scan but received \(nextState)"
)
} catch {
XCTFail("testValidateAction_NextAction is not expected to fail. \(error)")
}
}
}

View File

@ -35,7 +35,7 @@ final class ValidateServerActionTests: ZcashTestCase {
"nextContext after .validateServer is expected to be .computeSyncRanges but received \(nextState)"
)
} catch {
XCTFail("testValidateServerActionNextAction is not expected to fail. \(error)")
XCTFail("testValidateServerAction_NextAction is not expected to fail. \(error)")
}
}
@ -50,7 +50,7 @@ final class ValidateServerActionTests: ZcashTestCase {
} catch ZcashError.compactBlockProcessorChainName(let chainName) {
XCTAssertEqual(chainName, "invalid")
} catch {
XCTFail("testValidateServerActionNextAction is expected to fail but error \(error) doesn't match ZcashError.compactBlockProcessorChainName")
XCTFail("testValidateServerAction_ChainNameError is expected to fail but error \(error) doesn't match ZcashError.compactBlockProcessorChainName")
}
}

View File

@ -11,6 +11,8 @@ import Foundation
import XCTest
@testable import ZcashLightClientKit
// TODO: [1098] review tests, after progress reporting some of them may not have a sense anymore
// https://github.com/zcash/ZcashLightClientKit/issues/1098
class SynchronizerOfflineTests: ZcashTestCase {
let data = TestsData(networkType: .testnet)
var network: ZcashNetwork!
@ -366,7 +368,7 @@ class SynchronizerOfflineTests: ZcashTestCase {
}
func testIsNewSessionOnUnpreparedToValidTransition() {
XCTAssertTrue(SessionTicker.live.isNewSyncSession(.unprepared, .syncing(.nullProgress)))
XCTAssertTrue(SessionTicker.live.isNewSyncSession(.unprepared, .syncing(0)))
}
func testIsNotNewSessionOnUnpreparedToStateThatWontSync() {
@ -376,18 +378,16 @@ class SynchronizerOfflineTests: ZcashTestCase {
func testIsNotNewSessionOnUnpreparedToInvalidOrUnexpectedTransitions() {
XCTAssertFalse(SessionTicker.live.isNewSyncSession(.unprepared, .synced))
XCTAssertFalse(SessionTicker.live.isNewSyncSession(.unprepared, .fetching(0)))
XCTAssertFalse(SessionTicker.live.isNewSyncSession(.unprepared, .enhancing(.zero)))
}
func testIsNotNewSyncSessionOnSameSession() {
XCTAssertFalse(
SessionTicker.live.isNewSyncSession(
.syncing(
BlockProgress(startHeight: 1, targetHeight: 10, progressHeight: 3)
0.5
),
.syncing(
BlockProgress(startHeight: 1, targetHeight: 10, progressHeight: 4)
0.6
)
)
)
@ -398,7 +398,7 @@ class SynchronizerOfflineTests: ZcashTestCase {
SessionTicker.live.isNewSyncSession(
.synced,
.syncing(
BlockProgress(startHeight: 1, targetHeight: 10, progressHeight: 4)
0.6
)
)
)
@ -409,7 +409,7 @@ class SynchronizerOfflineTests: ZcashTestCase {
SessionTicker.live.isNewSyncSession(
.disconnected,
.syncing(
BlockProgress(startHeight: 1, targetHeight: 10, progressHeight: 4)
0.6
)
)
)
@ -420,7 +420,7 @@ class SynchronizerOfflineTests: ZcashTestCase {
SessionTicker.live.isNewSyncSession(
.stopped,
.syncing(
BlockProgress(startHeight: 1, targetHeight: 10, progressHeight: 4)
0.6
)
)
)
@ -428,17 +428,16 @@ class SynchronizerOfflineTests: ZcashTestCase {
func testInternalSyncStatusesDontDifferWhenOuterStatusIsTheSame() {
XCTAssertFalse(InternalSyncStatus.disconnected.isDifferent(from: .disconnected))
XCTAssertFalse(InternalSyncStatus.fetching(0).isDifferent(from: .fetching(0)))
XCTAssertFalse(InternalSyncStatus.syncing(0).isDifferent(from: .syncing(0)))
XCTAssertFalse(InternalSyncStatus.stopped.isDifferent(from: .stopped))
XCTAssertFalse(InternalSyncStatus.synced.isDifferent(from: .synced))
XCTAssertFalse(InternalSyncStatus.syncing(.nullProgress).isDifferent(from: .syncing(.nullProgress)))
XCTAssertFalse(InternalSyncStatus.unprepared.isDifferent(from: .unprepared))
}
func testInternalSyncStatusMap_SyncingLowerBound() {
let synchronizerState = synchronizerState(
for:
InternalSyncStatus.syncing(BlockProgress(startHeight: 0, targetHeight: 100, progressHeight: 0))
InternalSyncStatus.syncing(0)
)
if case let .syncing(data) = synchronizerState.syncStatus, data != nextafter(0.0, data) {
@ -449,7 +448,7 @@ class SynchronizerOfflineTests: ZcashTestCase {
func testInternalSyncStatusMap_SyncingInTheMiddle() {
let synchronizerState = synchronizerState(
for:
InternalSyncStatus.syncing(BlockProgress(startHeight: 0, targetHeight: 100, progressHeight: 50))
InternalSyncStatus.syncing(0.45)
)
if case let .syncing(data) = synchronizerState.syncStatus, data != nextafter(0.45, data) {
@ -460,89 +459,16 @@ class SynchronizerOfflineTests: ZcashTestCase {
func testInternalSyncStatusMap_SyncingUpperBound() {
let synchronizerState = synchronizerState(
for:
InternalSyncStatus.syncing(BlockProgress(startHeight: 0, targetHeight: 100, progressHeight: 100))
InternalSyncStatus.syncing(0.9)
)
if case let .syncing(data) = synchronizerState.syncStatus, data != nextafter(0.9, data) {
XCTFail("Syncing is expected to be 90% (0.9) but received \(data).")
}
}
func testInternalSyncStatusMap_EnhancingLowerBound() {
let synchronizerState = synchronizerState(
for:
InternalSyncStatus.enhancing(
EnhancementProgress(
totalTransactions: 100,
enhancedTransactions: 0,
lastFoundTransaction: nil,
range: CompactBlockRange(uncheckedBounds: (0, 100)),
newlyMined: false
)
)
)
if case let .syncing(data) = synchronizerState.syncStatus, data != nextafter(0.9, data) {
XCTFail("Syncing is expected to be 90% (0.9) but received \(data).")
}
}
func testInternalSyncStatusMap_EnhancingInTheMiddle() {
let synchronizerState = synchronizerState(
for:
InternalSyncStatus.enhancing(
EnhancementProgress(
totalTransactions: 100,
enhancedTransactions: 50,
lastFoundTransaction: nil,
range: CompactBlockRange(uncheckedBounds: (0, 100)),
newlyMined: false
)
)
)
if case let .syncing(data) = synchronizerState.syncStatus, data != nextafter(0.94, data) {
XCTFail("Syncing is expected to be 94% (0.94) but received \(data).")
}
}
func testInternalSyncStatusMap_EnhancingUpperBound() {
let synchronizerState = synchronizerState(
for:
InternalSyncStatus.enhancing(
EnhancementProgress(
totalTransactions: 100,
enhancedTransactions: 100,
lastFoundTransaction: nil,
range: CompactBlockRange(uncheckedBounds: (0, 100)),
newlyMined: false
)
)
)
if case let .syncing(data) = synchronizerState.syncStatus, data != nextafter(0.98, data) {
XCTFail("Syncing is expected to be 98% (0.98) but received \(data).")
}
}
func testInternalSyncStatusMap_FetchingLowerBound() {
let synchronizerState = synchronizerState(for: InternalSyncStatus.fetching(0))
if case let .syncing(data) = synchronizerState.syncStatus, data != nextafter(0.98, data) {
XCTFail("Syncing is expected to be 98% (0.98) but received \(data).")
}
}
func testInternalSyncStatusMap_FetchingInTheMiddle() {
let synchronizerState = synchronizerState(for: InternalSyncStatus.fetching(0.5))
if case let .syncing(data) = synchronizerState.syncStatus, data != nextafter(0.99, data) {
XCTFail("Syncing is expected to be 99% (0.99) but received \(data).")
}
}
func testInternalSyncStatusMap_FetchingUpperBound() {
let synchronizerState = synchronizerState(for: InternalSyncStatus.fetching(1))
let synchronizerState = synchronizerState(for: InternalSyncStatus.syncing(1))
if case let .syncing(data) = synchronizerState.syncStatus, data != nextafter(1.0, data) {
XCTFail("Syncing is expected to be 100% (1.0) but received \(data).")

View File

@ -18,6 +18,7 @@ class CompactBlockProcessorEventHandler {
case minedTransaction
case handleReorg
case progressUpdated
case progressPartialUpdate
case storedUTXOs
case startedEnhancing
case startedFetching
@ -63,6 +64,8 @@ extension CompactBlockProcessor.Event {
return .stopped
case .minedTransaction:
return .minedTransaction
case .progressPartialUpdate:
return .progressPartialUpdate
}
}
}

View File

@ -39,8 +39,6 @@ extension InternalSyncStatus {
switch self {
case .unprepared: return .unprepared
case .syncing: return .syncing
case .enhancing: return .enhancing
case .fetching: return .fetching
case .synced: return .synced
case .stopped: return .stopped
case .disconnected: return .disconnected

View File

@ -16,5 +16,6 @@ extension ZcashRustBackendWelding { }
extension Synchronizer { }
extension LightWalletService { }
extension LightWalletdInfo { }
extension BlockValidator { }
// sourcery:end:

View File

@ -7,6 +7,31 @@ import Foundation
// MARK: - AutoMockable protocols
class BlockValidatorMock: BlockValidator {
init(
) {
}
// MARK: - validate
var validateThrowableError: Error?
var validateCallsCount = 0
var validateCalled: Bool {
return validateCallsCount > 0
}
var validateClosure: (() async throws -> Void)?
func validate() async throws {
if let error = validateThrowableError {
throw error
}
validateCallsCount += 1
try await validateClosure?()
}
}
class LightWalletServiceMock: LightWalletService {

View File

@ -209,7 +209,7 @@ extension SynchronizerState {
syncSessionID: .nullID,
shieldedBalance: WalletBalance(verified: Zatoshi(100), total: Zatoshi(200)),
transparentBalance: WalletBalance(verified: Zatoshi(200), total: Zatoshi(300)),
internalSyncStatus: .fetching(0),
internalSyncStatus: .syncing(0),
latestScannedHeight: 111111,
latestBlockHeight: 222222,
latestScannedTime: 12345678