[#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
|
||||
|
||||
extension BlockDownloader { }
|
||||
extension BlockEnhancer { }
|
||||
extension BlockScanner { }
|
||||
extension BlockValidator { }
|
||||
|
|
|
@ -7,6 +7,95 @@ import Foundation
|
|||
|
||||
|
||||
// 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 {
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue