[#1044] Implement EnhanceAction
- EnhanceAction tests focused on 2 different methods: - decideWhatToDoNext covered separately, decisions where the state machine goes next - run tests for different cases - new mocks generated for enhacer - some typos fixed [#1044] Implement EnhanceAction (#1107) - empty assert messages fixed
This commit is contained in:
parent
d1dd251423
commit
6734af4bde
|
@ -45,8 +45,8 @@ extension EnhanceAction: Action {
|
|||
// This action is executed on each downloaded and scanned batch (typically each 100 blocks). But we want to run enhancement each 1000 blocks.
|
||||
// This action can use `InternalSyncProgress` and last scanned height to compute when it should do work.
|
||||
|
||||
// if latestScannedHeight == context.scanRanges.downloadAndScanRange?.upperBound then set state `enhance`. Everything is scanned.
|
||||
// If latestScannedHeight < context.scanRanges.downloadAndScanRange?.upperBound thne set state to `download` because there are blocks to
|
||||
// if latestScannedHeight == context.scanRanges.downloadAndScanRange?.upperBound then set state `clearCache`. Everything is scanned.
|
||||
// If latestScannedHeight < context.scanRanges.downloadAndScanRange?.upperBound then set state to `download` because there are blocks to
|
||||
// download and scan.
|
||||
|
||||
let lastScannedHeight = try await transactionRepository.lastScannedHeight()
|
||||
|
|
|
@ -52,7 +52,7 @@ public struct EnhancementProgress: Equatable {
|
|||
}
|
||||
|
||||
protocol BlockEnhancer {
|
||||
func enhance(at range: CompactBlockRange, didEnhance: (EnhancementProgress) async -> Void) async throws -> [ZcashTransaction.Overview]?
|
||||
func enhance(at range: CompactBlockRange, didEnhance: @escaping (EnhancementProgress) async -> Void) async throws -> [ZcashTransaction.Overview]?
|
||||
}
|
||||
|
||||
struct BlockEnhancerImpl {
|
||||
|
@ -82,7 +82,7 @@ struct BlockEnhancerImpl {
|
|||
}
|
||||
|
||||
extension BlockEnhancerImpl: BlockEnhancer {
|
||||
func enhance(at range: CompactBlockRange, didEnhance: (EnhancementProgress) async -> Void) async throws -> [ZcashTransaction.Overview]? {
|
||||
func enhance(at range: CompactBlockRange, didEnhance: @escaping (EnhancementProgress) async -> Void) async throws -> [ZcashTransaction.Overview]? {
|
||||
try Task.checkCancellation()
|
||||
|
||||
logger.debug("Started Enhancing range: \(range)")
|
||||
|
|
|
@ -47,6 +47,7 @@ protocol InternalSyncProgressStorage {
|
|||
func bool(forKey defaultName: String) -> Bool
|
||||
func integer(forKey defaultName: String) -> Int
|
||||
func set(_ value: Int, forKey defaultName: String)
|
||||
// sourcery: mockedName="setBool"
|
||||
func set(_ value: Bool, forKey defaultName: String)
|
||||
@discardableResult
|
||||
func synchronize() -> Bool
|
||||
|
|
|
@ -0,0 +1,285 @@
|
|||
//
|
||||
// EnhanceActionTests.swift
|
||||
//
|
||||
//
|
||||
// Created by Lukáš Korba on 19.05.2023.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import TestUtils
|
||||
@testable import ZcashLightClientKit
|
||||
|
||||
final class EnhanceActionTests: ZcashTestCase {
|
||||
var underlyingDownloadAndScanRange: CompactBlockRange?
|
||||
var underlyingEnhanceRange: CompactBlockRange?
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
|
||||
underlyingDownloadAndScanRange = nil
|
||||
underlyingEnhanceRange = nil
|
||||
}
|
||||
|
||||
func testEnhanceAction_decideWhatToDoNext_NoDownloadAndScanRange() async throws {
|
||||
let enhanceAction = setupAction()
|
||||
|
||||
let syncContext = await setupActionContext()
|
||||
let nextContext = await enhanceAction.decideWhatToDoNext(context: syncContext, lastScannedHeight: 1)
|
||||
let nextState = await nextContext.state
|
||||
|
||||
XCTAssertTrue(
|
||||
nextState == .clearCache,
|
||||
"testEnhanceAction_decideWhatToDoNext_NoDownloadAndScanRange is expected to be .clearCache but received \(nextState)"
|
||||
)
|
||||
}
|
||||
|
||||
func testEnhanceAction_decideWhatToDoNext_NothingToDownloadAndScanLeft() async throws {
|
||||
let enhanceAction = setupAction()
|
||||
underlyingDownloadAndScanRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
|
||||
let syncContext = await setupActionContext()
|
||||
let nextContext = await enhanceAction.decideWhatToDoNext(context: syncContext, lastScannedHeight: 2000)
|
||||
let nextState = await nextContext.state
|
||||
|
||||
XCTAssertTrue(
|
||||
nextState == .clearCache,
|
||||
"testEnhanceAction_decideWhatToDoNext_NothingToDownloadAndScanLeft is expected to be .clearCache but received \(nextState)"
|
||||
)
|
||||
}
|
||||
|
||||
func testEnhanceAction_decideWhatToDoNext_DownloadExpected() async throws {
|
||||
let enhanceAction = setupAction()
|
||||
underlyingDownloadAndScanRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
|
||||
let syncContext = await setupActionContext()
|
||||
let nextContext = await enhanceAction.decideWhatToDoNext(context: syncContext, lastScannedHeight: 1500)
|
||||
let nextState = await nextContext.state
|
||||
|
||||
XCTAssertTrue(
|
||||
nextState == .download,
|
||||
"testEnhanceAction_decideWhatToDoNext_DownloadExpected is expected to be .download but received \(nextState)"
|
||||
)
|
||||
}
|
||||
|
||||
func testEnhanceAction_NoEnhanceRange() async throws {
|
||||
let blockEnhancerMock = BlockEnhancerMock()
|
||||
let transactionRepositoryMock = TransactionRepositoryMock()
|
||||
let internalSyncProgressStorageMock = InternalSyncProgressStorageMock()
|
||||
|
||||
transactionRepositoryMock.lastScannedHeightReturnValue = 1
|
||||
|
||||
let enhanceAction = setupAction(
|
||||
blockEnhancerMock,
|
||||
transactionRepositoryMock,
|
||||
internalSyncProgressStorageMock
|
||||
)
|
||||
|
||||
let syncContext = await setupActionContext()
|
||||
|
||||
do {
|
||||
let _ = try await enhanceAction.run(with: syncContext) { _ in }
|
||||
XCTAssertTrue(transactionRepositoryMock.lastScannedHeightCalled, "transactionRepository.lastScannedHeight() is expected to be called.")
|
||||
XCTAssertFalse(blockEnhancerMock.enhanceAtDidEnhanceCalled, "blockEnhancer.enhance() is not expected to be called.")
|
||||
XCTAssertFalse(internalSyncProgressStorageMock.integerForKeyCalled, "internalSyncProgress.load() is not expected to be called.")
|
||||
} catch {
|
||||
XCTFail("testEnhanceAction_NoEnhanceRange is not expected to fail. \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func testEnhanceAction_1000BlocksConditionNotFulfilled() async throws {
|
||||
let blockEnhancerMock = BlockEnhancerMock()
|
||||
let transactionRepositoryMock = TransactionRepositoryMock()
|
||||
let internalSyncProgressStorageMock = InternalSyncProgressStorageMock()
|
||||
|
||||
transactionRepositoryMock.lastScannedHeightReturnValue = 1
|
||||
internalSyncProgressStorageMock.integerForKeyReturnValue = 1
|
||||
|
||||
let enhanceAction = setupAction(
|
||||
blockEnhancerMock,
|
||||
transactionRepositoryMock,
|
||||
internalSyncProgressStorageMock
|
||||
)
|
||||
|
||||
underlyingEnhanceRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
|
||||
let syncContext = await setupActionContext()
|
||||
|
||||
do {
|
||||
let _ = try await enhanceAction.run(with: syncContext) { _ in }
|
||||
XCTAssertTrue(transactionRepositoryMock.lastScannedHeightCalled, "transactionRepository.lastScannedHeight() is expected to be called.")
|
||||
XCTAssertTrue(internalSyncProgressStorageMock.integerForKeyCalled, "internalSyncProgress.load() is expected to be called.")
|
||||
XCTAssertFalse(blockEnhancerMock.enhanceAtDidEnhanceCalled, "blockEnhancer.enhance() is not expected to be called.")
|
||||
} catch {
|
||||
XCTFail("testEnhanceAction_1000BlocksConditionNotFulfilled is not expected to fail. \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func testEnhanceAction_EnhancementOfBlocksCalled_FoundTransactions() async throws {
|
||||
let blockEnhancerMock = BlockEnhancerMock()
|
||||
let transactionRepositoryMock = TransactionRepositoryMock()
|
||||
let internalSyncProgressStorageMock = InternalSyncProgressStorageMock()
|
||||
|
||||
transactionRepositoryMock.lastScannedHeightReturnValue = 1500
|
||||
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.zero)
|
||||
return [transaction]
|
||||
}
|
||||
|
||||
let enhanceAction = setupAction(
|
||||
blockEnhancerMock,
|
||||
transactionRepositoryMock,
|
||||
internalSyncProgressStorageMock
|
||||
)
|
||||
|
||||
underlyingEnhanceRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
|
||||
let syncContext = await setupActionContext()
|
||||
|
||||
do {
|
||||
let _ = try await enhanceAction.run(with: syncContext) { event in
|
||||
guard case let .foundTransactions(transactions, _) = event else {
|
||||
XCTFail("Event is expected to be .foundTransactions but received \(event)")
|
||||
return
|
||||
}
|
||||
XCTAssertTrue(transactions.count == 1)
|
||||
guard let receivedTransaction = transactions.first else {
|
||||
XCTFail("Transaction.first is expected to pass.")
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertEqual(receivedTransaction.expiryHeight, transaction.expiryHeight, "ReceivedTransaction 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_FoundTransactions is not expected to fail. \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func testEnhanceAction_EnhancementOfBlocksCalled_minedTransaction() async throws {
|
||||
let blockEnhancerMock = BlockEnhancerMock()
|
||||
let transactionRepositoryMock = TransactionRepositoryMock()
|
||||
let internalSyncProgressStorageMock = InternalSyncProgressStorageMock()
|
||||
|
||||
transactionRepositoryMock.lastScannedHeightReturnValue = 1500
|
||||
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: (1000, 2000))
|
||||
|
||||
let syncContext = await setupActionContext()
|
||||
|
||||
do {
|
||||
let _ = 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)")
|
||||
}
|
||||
}
|
||||
|
||||
func setupActionContext() async -> ActionContext {
|
||||
let syncContext: ActionContext = .init(state: .enhance)
|
||||
|
||||
let syncRanges = SyncRanges(
|
||||
latestBlockHeight: 0,
|
||||
downloadedButUnscannedRange: nil,
|
||||
downloadAndScanRange: underlyingDownloadAndScanRange,
|
||||
enhanceRange: underlyingEnhanceRange,
|
||||
fetchUTXORange: nil,
|
||||
latestScannedHeight: nil,
|
||||
latestDownloadedBlockHeight: nil
|
||||
)
|
||||
|
||||
await syncContext.update(syncRanges: syncRanges)
|
||||
await syncContext.update(totalProgressRange: CompactBlockRange(uncheckedBounds: (1000, 2000)))
|
||||
|
||||
return syncContext
|
||||
}
|
||||
|
||||
func setupAction(
|
||||
_ blockEnhancerMock: BlockEnhancerMock = BlockEnhancerMock(),
|
||||
_ transactionRepositoryMock: TransactionRepositoryMock = TransactionRepositoryMock(),
|
||||
_ internalSyncProgressStorageMock: InternalSyncProgressStorageMock = InternalSyncProgressStorageMock(),
|
||||
_ loggerMock: LoggerMock = LoggerMock()
|
||||
) -> EnhanceAction {
|
||||
mockContainer.register(type: InternalSyncProgress.self, isSingleton: true) { di in
|
||||
InternalSyncProgress(alias: .default, storage: internalSyncProgressStorageMock, logger: loggerMock)
|
||||
}
|
||||
|
||||
mockContainer.mock(type: BlockEnhancer.self, isSingleton: true) { _ in blockEnhancerMock }
|
||||
mockContainer.mock(type: TransactionRepository.self, isSingleton: true) { _ in transactionRepositoryMock }
|
||||
mockContainer.mock(type: Logger.self, isSingleton: true) { _ in loggerMock }
|
||||
|
||||
let config: CompactBlockProcessor.Configuration = .standard(
|
||||
for: ZcashNetworkBuilder.network(for: .testnet), walletBirthday: 0
|
||||
)
|
||||
|
||||
return EnhanceAction(
|
||||
container: mockContainer,
|
||||
config: config
|
||||
)
|
||||
}
|
||||
}
|
|
@ -55,9 +55,9 @@ final class ScanActionTests: ZcashTestCase {
|
|||
|
||||
do {
|
||||
_ = try await scanAction.run(with: syncContext) { _ in }
|
||||
XCTAssertFalse(transactionRepositoryMock.lastScannedHeightCalled, "transactionRepository.lastScannedHeight() is expected to be called.")
|
||||
XCTAssertFalse(loggerMock.debugFileFunctionLineCalled, "logger.debug(...) is expected to be called.")
|
||||
XCTAssertFalse(blockScannerMock.scanBlocksAtTotalProgressRangeDidScanCalled, "blockScanner.scanBlocks(...) is expected to be called.")
|
||||
XCTAssertFalse(transactionRepositoryMock.lastScannedHeightCalled, "transactionRepository.lastScannedHeight() is not expected to be called.")
|
||||
XCTAssertFalse(loggerMock.debugFileFunctionLineCalled, "logger.debug(...) is not expected to be called.")
|
||||
XCTAssertFalse(blockScannerMock.scanBlocksAtTotalProgressRangeDidScanCalled, "blockScanner.scanBlocks(...) is not expected to be called.")
|
||||
} catch {
|
||||
XCTFail("testScanAction_NextAction is not expected to fail. \(error)")
|
||||
}
|
||||
|
@ -76,8 +76,8 @@ final class ScanActionTests: ZcashTestCase {
|
|||
do {
|
||||
_ = try await scanAction.run(with: syncContext) { _ in }
|
||||
XCTAssertTrue(transactionRepositoryMock.lastScannedHeightCalled, "transactionRepository.lastScannedHeight() is expected to be called.")
|
||||
XCTAssertFalse(loggerMock.debugFileFunctionLineCalled, "logger.debug(...) is expected to be called.")
|
||||
XCTAssertFalse(blockScannerMock.scanBlocksAtTotalProgressRangeDidScanCalled, "blockScanner.scanBlocks(...) is expected to be called.")
|
||||
XCTAssertFalse(loggerMock.debugFileFunctionLineCalled, "logger.debug(...) is not expected to be called.")
|
||||
XCTAssertFalse(blockScannerMock.scanBlocksAtTotalProgressRangeDidScanCalled, "blockScanner.scanBlocks(...) is not expected to be called.")
|
||||
} catch {
|
||||
XCTFail("testScanAction_NextAction is not expected to fail. \(error)")
|
||||
}
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
|
||||
@testable import ZcashLightClientKit
|
||||
|
||||
extension BlockEnhancer { }
|
||||
extension BlockScanner { }
|
||||
extension BlockValidator { }
|
||||
extension InternalSyncProgressStorage { }
|
||||
extension LightWalletdInfo { }
|
||||
extension LightWalletService { }
|
||||
extension Logger { }
|
||||
|
@ -22,5 +24,4 @@ extension Synchronizer { }
|
|||
extension TransactionRepository { }
|
||||
extension UTXOFetcher { }
|
||||
extension ZcashRustBackendWelding { }
|
||||
|
||||
// sourcery:end:
|
||||
|
|
|
@ -7,6 +7,38 @@ import Foundation
|
|||
|
||||
|
||||
// MARK: - AutoMockable protocols
|
||||
class BlockEnhancerMock: BlockEnhancer {
|
||||
|
||||
|
||||
init(
|
||||
) {
|
||||
}
|
||||
|
||||
// MARK: - enhance
|
||||
|
||||
var enhanceAtDidEnhanceThrowableError: Error?
|
||||
var enhanceAtDidEnhanceCallsCount = 0
|
||||
var enhanceAtDidEnhanceCalled: Bool {
|
||||
return enhanceAtDidEnhanceCallsCount > 0
|
||||
}
|
||||
var enhanceAtDidEnhanceReceivedArguments: (range: CompactBlockRange, didEnhance: (EnhancementProgress) async -> Void)?
|
||||
var enhanceAtDidEnhanceReturnValue: [ZcashTransaction.Overview]?
|
||||
var enhanceAtDidEnhanceClosure: ((CompactBlockRange, @escaping (EnhancementProgress) async -> Void) async throws -> [ZcashTransaction.Overview]?)?
|
||||
|
||||
func enhance(at range: CompactBlockRange, didEnhance: @escaping (EnhancementProgress) async -> Void) async throws -> [ZcashTransaction.Overview]? {
|
||||
if let error = enhanceAtDidEnhanceThrowableError {
|
||||
throw error
|
||||
}
|
||||
enhanceAtDidEnhanceCallsCount += 1
|
||||
enhanceAtDidEnhanceReceivedArguments = (range: range, didEnhance: didEnhance)
|
||||
if let closure = enhanceAtDidEnhanceClosure {
|
||||
return try await closure(range, didEnhance)
|
||||
} else {
|
||||
return enhanceAtDidEnhanceReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
class BlockScannerMock: BlockScanner {
|
||||
|
||||
|
||||
|
@ -63,6 +95,102 @@ class BlockValidatorMock: BlockValidator {
|
|||
try await validateClosure!()
|
||||
}
|
||||
|
||||
}
|
||||
class InternalSyncProgressStorageMock: InternalSyncProgressStorage {
|
||||
|
||||
|
||||
init(
|
||||
) {
|
||||
}
|
||||
|
||||
// MARK: - bool
|
||||
|
||||
var boolForKeyCallsCount = 0
|
||||
var boolForKeyCalled: Bool {
|
||||
return boolForKeyCallsCount > 0
|
||||
}
|
||||
var boolForKeyReceivedDefaultName: String?
|
||||
var boolForKeyReturnValue: Bool!
|
||||
var boolForKeyClosure: ((String) -> Bool)?
|
||||
|
||||
func bool(forKey defaultName: String) -> Bool {
|
||||
boolForKeyCallsCount += 1
|
||||
boolForKeyReceivedDefaultName = defaultName
|
||||
if let closure = boolForKeyClosure {
|
||||
return closure(defaultName)
|
||||
} else {
|
||||
return boolForKeyReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - integer
|
||||
|
||||
var integerForKeyCallsCount = 0
|
||||
var integerForKeyCalled: Bool {
|
||||
return integerForKeyCallsCount > 0
|
||||
}
|
||||
var integerForKeyReceivedDefaultName: String?
|
||||
var integerForKeyReturnValue: Int!
|
||||
var integerForKeyClosure: ((String) -> Int)?
|
||||
|
||||
func integer(forKey defaultName: String) -> Int {
|
||||
integerForKeyCallsCount += 1
|
||||
integerForKeyReceivedDefaultName = defaultName
|
||||
if let closure = integerForKeyClosure {
|
||||
return closure(defaultName)
|
||||
} else {
|
||||
return integerForKeyReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - set
|
||||
|
||||
var setForKeyCallsCount = 0
|
||||
var setForKeyCalled: Bool {
|
||||
return setForKeyCallsCount > 0
|
||||
}
|
||||
var setForKeyReceivedArguments: (value: Int, defaultName: String)?
|
||||
var setForKeyClosure: ((Int, String) -> Void)?
|
||||
|
||||
func set(_ value: Int, forKey defaultName: String) {
|
||||
setForKeyCallsCount += 1
|
||||
setForKeyReceivedArguments = (value: value, defaultName: defaultName)
|
||||
setForKeyClosure!(value, defaultName)
|
||||
}
|
||||
|
||||
// MARK: - set
|
||||
|
||||
var setBoolCallsCount = 0
|
||||
var setBoolCalled: Bool {
|
||||
return setBoolCallsCount > 0
|
||||
}
|
||||
var setBoolReceivedArguments: (value: Bool, defaultName: String)?
|
||||
var setBoolClosure: ((Bool, String) -> Void)?
|
||||
|
||||
func set(_ value: Bool, forKey defaultName: String) {
|
||||
setBoolCallsCount += 1
|
||||
setBoolReceivedArguments = (value: value, defaultName: defaultName)
|
||||
setBoolClosure!(value, defaultName)
|
||||
}
|
||||
|
||||
// MARK: - synchronize
|
||||
|
||||
var synchronizeCallsCount = 0
|
||||
var synchronizeCalled: Bool {
|
||||
return synchronizeCallsCount > 0
|
||||
}
|
||||
var synchronizeReturnValue: Bool!
|
||||
var synchronizeClosure: (() -> Bool)?
|
||||
|
||||
func synchronize() -> Bool {
|
||||
synchronizeCallsCount += 1
|
||||
if let closure = synchronizeClosure {
|
||||
return closure()
|
||||
} else {
|
||||
return synchronizeReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
class LightWalletServiceMock: LightWalletService {
|
||||
|
||||
|
|
Loading…
Reference in New Issue