[#1043] Implement DownloadAction
- DownloadAction tests - BlockDownloader mock [#1043] Implement DownloadAction (#1110) - support functions set to private
This commit is contained in:
parent
2541fe5a8a
commit
cff734201b
|
@ -0,0 +1,178 @@
|
||||||
|
//
|
||||||
|
// DownloadActionTests.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Lukáš Korba on 21.05.2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
@testable import TestUtils
|
||||||
|
@testable import ZcashLightClientKit
|
||||||
|
|
||||||
|
final class DownloadActionTests: ZcashTestCase {
|
||||||
|
var underlyingDownloadAndScanRange: CompactBlockRange?
|
||||||
|
|
||||||
|
func testDownloadAction_NextAction() async throws {
|
||||||
|
let blockDownloaderMock = BlockDownloaderMock()
|
||||||
|
let transactionRepositoryMock = TransactionRepositoryMock()
|
||||||
|
|
||||||
|
transactionRepositoryMock.lastScannedHeightReturnValue = 1
|
||||||
|
blockDownloaderMock.setSyncRangeBatchSizeClosure = { _, _ in }
|
||||||
|
blockDownloaderMock.setDownloadLimitClosure = { _ in }
|
||||||
|
blockDownloaderMock.startDownloadMaxBlockBufferSizeClosure = { _ in }
|
||||||
|
blockDownloaderMock.waitUntilRequestedBlocksAreDownloadedInClosure = { _ in }
|
||||||
|
|
||||||
|
let downloadAction = setupAction(
|
||||||
|
blockDownloaderMock,
|
||||||
|
transactionRepositoryMock
|
||||||
|
)
|
||||||
|
|
||||||
|
underlyingDownloadAndScanRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||||
|
|
||||||
|
let syncContext = await setupActionContext()
|
||||||
|
|
||||||
|
do {
|
||||||
|
let nextContext = try await downloadAction.run(with: syncContext) { _ in }
|
||||||
|
|
||||||
|
XCTAssertTrue(transactionRepositoryMock.lastScannedHeightCalled, "transactionRepository.lastScannedHeight() is expected to be called.")
|
||||||
|
XCTAssertTrue(blockDownloaderMock.setSyncRangeBatchSizeCalled, "downloader.setSyncRange() is expected to be called.")
|
||||||
|
XCTAssertTrue(blockDownloaderMock.setDownloadLimitCalled, "downloader.setDownloadLimit() is expected to be called.")
|
||||||
|
XCTAssertTrue(blockDownloaderMock.startDownloadMaxBlockBufferSizeCalled, "downloader.startDownload() is expected to be called.")
|
||||||
|
XCTAssertTrue(
|
||||||
|
blockDownloaderMock.waitUntilRequestedBlocksAreDownloadedInCalled,
|
||||||
|
"downloader.waitUntilRequestedBlocksAreDownloaded() is expected to be called."
|
||||||
|
)
|
||||||
|
|
||||||
|
let nextState = await nextContext.state
|
||||||
|
XCTAssertTrue(
|
||||||
|
nextState == .validate,
|
||||||
|
"nextContext after .download is expected to be .validate but received \(nextState)"
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
XCTFail("testDownloadAction_NextAction is not expected to fail. \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDownloadAction_NoDownloadAndScanRange() async throws {
|
||||||
|
let blockDownloaderMock = BlockDownloaderMock()
|
||||||
|
let transactionRepositoryMock = TransactionRepositoryMock()
|
||||||
|
|
||||||
|
let downloadAction = setupAction(
|
||||||
|
blockDownloaderMock,
|
||||||
|
transactionRepositoryMock
|
||||||
|
)
|
||||||
|
|
||||||
|
let syncContext = await setupActionContext()
|
||||||
|
|
||||||
|
do {
|
||||||
|
let nextContext = try await downloadAction.run(with: syncContext) { _ in }
|
||||||
|
|
||||||
|
XCTAssertFalse(transactionRepositoryMock.lastScannedHeightCalled, "transactionRepository.lastScannedHeight() is not expected to be called.")
|
||||||
|
XCTAssertFalse(blockDownloaderMock.setSyncRangeBatchSizeCalled, "downloader.setSyncRange() is not expected to be called.")
|
||||||
|
XCTAssertFalse(blockDownloaderMock.setDownloadLimitCalled, "downloader.setDownloadLimit() is not expected to be called.")
|
||||||
|
XCTAssertFalse(blockDownloaderMock.startDownloadMaxBlockBufferSizeCalled, "downloader.startDownload() is not expected to be called.")
|
||||||
|
XCTAssertFalse(
|
||||||
|
blockDownloaderMock.waitUntilRequestedBlocksAreDownloadedInCalled,
|
||||||
|
"downloader.waitUntilRequestedBlocksAreDownloaded() is not expected to be called."
|
||||||
|
)
|
||||||
|
|
||||||
|
let nextState = await nextContext.state
|
||||||
|
XCTAssertTrue(
|
||||||
|
nextState == .validate,
|
||||||
|
"nextContext after .download is expected to be .validate but received \(nextState)"
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
XCTFail("testDownloadAction_NoDownloadAndScanRange is not expected to fail. \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDownloadAction_NothingMoreToDownload() async throws {
|
||||||
|
let blockDownloaderMock = BlockDownloaderMock()
|
||||||
|
let transactionRepositoryMock = TransactionRepositoryMock()
|
||||||
|
|
||||||
|
transactionRepositoryMock.lastScannedHeightReturnValue = 2001
|
||||||
|
|
||||||
|
let downloadAction = setupAction(
|
||||||
|
blockDownloaderMock,
|
||||||
|
transactionRepositoryMock
|
||||||
|
)
|
||||||
|
|
||||||
|
underlyingDownloadAndScanRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||||
|
|
||||||
|
let syncContext = await setupActionContext()
|
||||||
|
|
||||||
|
do {
|
||||||
|
let nextContext = try await downloadAction.run(with: syncContext) { _ in }
|
||||||
|
|
||||||
|
XCTAssertTrue(transactionRepositoryMock.lastScannedHeightCalled, "transactionRepository.lastScannedHeight() is expected to be called.")
|
||||||
|
XCTAssertFalse(blockDownloaderMock.setSyncRangeBatchSizeCalled, "downloader.setSyncRange() is not expected to be called.")
|
||||||
|
XCTAssertFalse(blockDownloaderMock.setDownloadLimitCalled, "downloader.setDownloadLimit() is not expected to be called.")
|
||||||
|
XCTAssertFalse(blockDownloaderMock.startDownloadMaxBlockBufferSizeCalled, "downloader.startDownload() is not expected to be called.")
|
||||||
|
XCTAssertFalse(
|
||||||
|
blockDownloaderMock.waitUntilRequestedBlocksAreDownloadedInCalled,
|
||||||
|
"downloader.waitUntilRequestedBlocksAreDownloaded() is not expected to be called."
|
||||||
|
)
|
||||||
|
|
||||||
|
let nextState = await nextContext.state
|
||||||
|
XCTAssertTrue(
|
||||||
|
nextState == .validate,
|
||||||
|
"nextContext after .download is expected to be .validate but received \(nextState)"
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
XCTFail("testDownloadAction_NoDownloadAndScanRange is not expected to fail. \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDownloadAction_DownloadStops() async throws {
|
||||||
|
let blockDownloaderMock = BlockDownloaderMock()
|
||||||
|
|
||||||
|
blockDownloaderMock.stopDownloadClosure = { }
|
||||||
|
|
||||||
|
let downloadAction = setupAction(
|
||||||
|
blockDownloaderMock
|
||||||
|
)
|
||||||
|
|
||||||
|
await downloadAction.stop()
|
||||||
|
|
||||||
|
XCTAssertTrue(blockDownloaderMock.stopDownloadCalled, "downloader.stopDownload() is expected to be called.")
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupActionContext() async -> ActionContext {
|
||||||
|
let syncContext: ActionContext = .init(state: .download)
|
||||||
|
|
||||||
|
let syncRanges = SyncRanges(
|
||||||
|
latestBlockHeight: 0,
|
||||||
|
downloadedButUnscannedRange: nil,
|
||||||
|
downloadAndScanRange: underlyingDownloadAndScanRange,
|
||||||
|
enhanceRange: nil,
|
||||||
|
fetchUTXORange: nil,
|
||||||
|
latestScannedHeight: nil,
|
||||||
|
latestDownloadedBlockHeight: nil
|
||||||
|
)
|
||||||
|
|
||||||
|
await syncContext.update(syncRanges: syncRanges)
|
||||||
|
|
||||||
|
return syncContext
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupAction(
|
||||||
|
_ blockDownloaderMock: BlockDownloaderMock = BlockDownloaderMock(),
|
||||||
|
_ transactionRepositoryMock: TransactionRepositoryMock = TransactionRepositoryMock(),
|
||||||
|
_ loggerMock: LoggerMock = LoggerMock()
|
||||||
|
) -> DownloadAction {
|
||||||
|
mockContainer.mock(type: BlockDownloader.self, isSingleton: true) { _ in blockDownloaderMock }
|
||||||
|
mockContainer.mock(type: TransactionRepository.self, isSingleton: true) { _ in transactionRepositoryMock }
|
||||||
|
mockContainer.mock(type: Logger.self, isSingleton: true) { _ in loggerMock }
|
||||||
|
|
||||||
|
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
|
||||||
|
|
||||||
|
let config: CompactBlockProcessor.Configuration = .standard(
|
||||||
|
for: ZcashNetworkBuilder.network(for: .testnet), walletBirthday: 0
|
||||||
|
)
|
||||||
|
|
||||||
|
return DownloadAction(
|
||||||
|
container: mockContainer,
|
||||||
|
config: config
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
@testable import ZcashLightClientKit
|
@testable import ZcashLightClientKit
|
||||||
|
|
||||||
|
extension BlockDownloader { }
|
||||||
extension BlockEnhancer { }
|
extension BlockEnhancer { }
|
||||||
extension BlockScanner { }
|
extension BlockScanner { }
|
||||||
extension BlockValidator { }
|
extension BlockValidator { }
|
||||||
|
|
|
@ -7,6 +7,95 @@ import Foundation
|
||||||
|
|
||||||
|
|
||||||
// MARK: - AutoMockable protocols
|
// MARK: - AutoMockable protocols
|
||||||
|
class BlockDownloaderMock: BlockDownloader {
|
||||||
|
|
||||||
|
|
||||||
|
init(
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - setDownloadLimit
|
||||||
|
|
||||||
|
var setDownloadLimitCallsCount = 0
|
||||||
|
var setDownloadLimitCalled: Bool {
|
||||||
|
return setDownloadLimitCallsCount > 0
|
||||||
|
}
|
||||||
|
var setDownloadLimitReceivedLimit: BlockHeight?
|
||||||
|
var setDownloadLimitClosure: ((BlockHeight) async -> Void)?
|
||||||
|
|
||||||
|
func setDownloadLimit(_ limit: BlockHeight) async {
|
||||||
|
setDownloadLimitCallsCount += 1
|
||||||
|
setDownloadLimitReceivedLimit = limit
|
||||||
|
await setDownloadLimitClosure!(limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - setSyncRange
|
||||||
|
|
||||||
|
var setSyncRangeBatchSizeThrowableError: Error?
|
||||||
|
var setSyncRangeBatchSizeCallsCount = 0
|
||||||
|
var setSyncRangeBatchSizeCalled: Bool {
|
||||||
|
return setSyncRangeBatchSizeCallsCount > 0
|
||||||
|
}
|
||||||
|
var setSyncRangeBatchSizeReceivedArguments: (range: CompactBlockRange, batchSize: Int)?
|
||||||
|
var setSyncRangeBatchSizeClosure: ((CompactBlockRange, Int) async throws -> Void)?
|
||||||
|
|
||||||
|
func setSyncRange(_ range: CompactBlockRange, batchSize: Int) async throws {
|
||||||
|
if let error = setSyncRangeBatchSizeThrowableError {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
setSyncRangeBatchSizeCallsCount += 1
|
||||||
|
setSyncRangeBatchSizeReceivedArguments = (range: range, batchSize: batchSize)
|
||||||
|
try await setSyncRangeBatchSizeClosure!(range, batchSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - startDownload
|
||||||
|
|
||||||
|
var startDownloadMaxBlockBufferSizeCallsCount = 0
|
||||||
|
var startDownloadMaxBlockBufferSizeCalled: Bool {
|
||||||
|
return startDownloadMaxBlockBufferSizeCallsCount > 0
|
||||||
|
}
|
||||||
|
var startDownloadMaxBlockBufferSizeReceivedMaxBlockBufferSize: Int?
|
||||||
|
var startDownloadMaxBlockBufferSizeClosure: ((Int) async -> Void)?
|
||||||
|
|
||||||
|
func startDownload(maxBlockBufferSize: Int) async {
|
||||||
|
startDownloadMaxBlockBufferSizeCallsCount += 1
|
||||||
|
startDownloadMaxBlockBufferSizeReceivedMaxBlockBufferSize = maxBlockBufferSize
|
||||||
|
await startDownloadMaxBlockBufferSizeClosure!(maxBlockBufferSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - stopDownload
|
||||||
|
|
||||||
|
var stopDownloadCallsCount = 0
|
||||||
|
var stopDownloadCalled: Bool {
|
||||||
|
return stopDownloadCallsCount > 0
|
||||||
|
}
|
||||||
|
var stopDownloadClosure: (() async -> Void)?
|
||||||
|
|
||||||
|
func stopDownload() async {
|
||||||
|
stopDownloadCallsCount += 1
|
||||||
|
await stopDownloadClosure!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - waitUntilRequestedBlocksAreDownloaded
|
||||||
|
|
||||||
|
var waitUntilRequestedBlocksAreDownloadedInThrowableError: Error?
|
||||||
|
var waitUntilRequestedBlocksAreDownloadedInCallsCount = 0
|
||||||
|
var waitUntilRequestedBlocksAreDownloadedInCalled: Bool {
|
||||||
|
return waitUntilRequestedBlocksAreDownloadedInCallsCount > 0
|
||||||
|
}
|
||||||
|
var waitUntilRequestedBlocksAreDownloadedInReceivedRange: CompactBlockRange?
|
||||||
|
var waitUntilRequestedBlocksAreDownloadedInClosure: ((CompactBlockRange) async throws -> Void)?
|
||||||
|
|
||||||
|
func waitUntilRequestedBlocksAreDownloaded(in range: CompactBlockRange) async throws {
|
||||||
|
if let error = waitUntilRequestedBlocksAreDownloadedInThrowableError {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
waitUntilRequestedBlocksAreDownloadedInCallsCount += 1
|
||||||
|
waitUntilRequestedBlocksAreDownloadedInReceivedRange = range
|
||||||
|
try await waitUntilRequestedBlocksAreDownloadedInClosure!(range)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
class BlockEnhancerMock: BlockEnhancer {
|
class BlockEnhancerMock: BlockEnhancer {
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue