Merge pull request #1124 from LukasKorba/1122-Implement-FileManager-protocol-and-dependency
- ZcashFileManager protocol - MigrateLegacyCacheDBAction refactored to be dependent on ZcashFileManager - ZcashFileManager mock added
This commit is contained in:
commit
e267435d84
|
@ -12,12 +12,14 @@ final class MigrateLegacyCacheDBAction {
|
|||
private let internalSyncProgress: InternalSyncProgress
|
||||
private let storage: CompactBlockRepository
|
||||
private let transactionRepository: TransactionRepository
|
||||
private let fileManager: ZcashFileManager
|
||||
|
||||
init(container: DIContainer, config: CompactBlockProcessor.Configuration) {
|
||||
self.config = config
|
||||
internalSyncProgress = container.resolve(InternalSyncProgress.self)
|
||||
storage = container.resolve(CompactBlockRepository.self)
|
||||
transactionRepository = container.resolve(TransactionRepository.self)
|
||||
fileManager = container.resolve(ZcashFileManager.self)
|
||||
}
|
||||
|
||||
private func updateState(_ context: ActionContext) async -> ActionContext {
|
||||
|
@ -48,13 +50,13 @@ extension MigrateLegacyCacheDBAction: Action {
|
|||
// if the URL provided is not readable, it means that the client has a reference
|
||||
// to the cacheDb file but it has been deleted in a prior sync cycle. there's
|
||||
// nothing to do here.
|
||||
guard FileManager.default.isReadableFile(atPath: legacyCacheDbURL.path) else {
|
||||
guard fileManager.isReadableFile(atPath: legacyCacheDbURL.path) else {
|
||||
return await updateState(context)
|
||||
}
|
||||
|
||||
do {
|
||||
// if there's a readable file at the provided URL, delete it.
|
||||
try FileManager.default.removeItem(at: legacyCacheDbURL)
|
||||
try fileManager.removeItem(at: legacyCacheDbURL)
|
||||
} catch {
|
||||
throw ZcashError.compactBlockProcessorCacheDbMigrationFailedToDeleteLegacyDb(error)
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ actor CompactBlockProcessor {
|
|||
private let service: LightWalletService
|
||||
private let storage: CompactBlockRepository
|
||||
private let transactionRepository: TransactionRepository
|
||||
private let fileManager: ZcashFileManager
|
||||
|
||||
private var retryAttempts: Int = 0
|
||||
private var backoffTimer: Timer?
|
||||
|
@ -195,6 +196,7 @@ actor CompactBlockProcessor {
|
|||
self.config = config
|
||||
self.transactionRepository = container.resolve(TransactionRepository.self)
|
||||
self.accountRepository = accountRepository
|
||||
self.fileManager = container.resolve(ZcashFileManager.self)
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
@ -372,8 +374,8 @@ extension CompactBlockProcessor {
|
|||
|
||||
private func wipeLegacyCacheDbIfNeeded() {
|
||||
guard let cacheDbURL = config.cacheDbURL else { return }
|
||||
guard FileManager.default.isDeletableFile(atPath: cacheDbURL.pathExtension) else { return }
|
||||
try? FileManager.default.removeItem(at: cacheDbURL)
|
||||
guard fileManager.isDeletableFile(atPath: cacheDbURL.pathExtension) else { return }
|
||||
try? fileManager.removeItem(at: cacheDbURL)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,10 @@ enum Dependencies {
|
|||
let logger = di.resolve(Logger.self)
|
||||
return InternalSyncProgress(alias: alias, storage: UserDefaults.standard, logger: logger)
|
||||
}
|
||||
|
||||
container.register(type: ZcashFileManager.self, isSingleton: true) { _ in
|
||||
FileManager.default
|
||||
}
|
||||
}
|
||||
|
||||
static func setupCompactBlockProcessor(
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
//
|
||||
// ZcashFileManager.swift
|
||||
//
|
||||
//
|
||||
// Created by Lukáš Korba on 23.05.2023.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol ZcashFileManager {
|
||||
func isReadableFile(atPath path: String) -> Bool
|
||||
func removeItem(at URL: URL) throws
|
||||
func isDeletableFile(atPath path: String) -> Bool
|
||||
}
|
||||
|
||||
extension FileManager: ZcashFileManager { }
|
|
@ -124,7 +124,7 @@ final class ChecksBeforeSyncActionTests: ZcashTestCase {
|
|||
_ internalSyncProgressStorageMock: InternalSyncProgressStorageMock = InternalSyncProgressStorageMock(),
|
||||
_ loggerMock: LoggerMock = LoggerMock()
|
||||
) -> ChecksBeforeSyncAction {
|
||||
mockContainer.register(type: InternalSyncProgress.self, isSingleton: true) { di in
|
||||
mockContainer.register(type: InternalSyncProgress.self, isSingleton: true) { _ in
|
||||
InternalSyncProgress(alias: .default, storage: internalSyncProgressStorageMock, logger: loggerMock)
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ final class ComputeSyncRangesActionTests: ZcashTestCase {
|
|||
underlyingScanRange = nil
|
||||
}
|
||||
|
||||
func testComputeSyncRangesActionTests_computeTotalProgressRange_noDownloadNoScanRange() async throws {
|
||||
func testComputeSyncRangesAction_computeTotalProgressRange_noDownloadNoScanRange() async throws {
|
||||
let computeSyncRangesAction = setupAction()
|
||||
|
||||
let syncRanges = setupSyncRanges()
|
||||
|
@ -29,11 +29,11 @@ final class ComputeSyncRangesActionTests: ZcashTestCase {
|
|||
|
||||
XCTAssertTrue(
|
||||
totalProgressRange == 0...0,
|
||||
"testComputeSyncRangesActionTests_computeTotalProgressRange_A is expected to be 0...0 but received \(totalProgressRange)"
|
||||
"testComputeSyncRangesAction_computeTotalProgressRange_noDownloadNoScanRange is expected to be 0...0 but received \(totalProgressRange)"
|
||||
)
|
||||
}
|
||||
|
||||
func testComputeSyncRangesActionTests_computeTotalProgressRange_ValidRange() async throws {
|
||||
func testComputeSyncRangesAction_computeTotalProgressRange_ValidRange() async throws {
|
||||
let computeSyncRangesAction = setupAction()
|
||||
|
||||
underlyingDownloadRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
|
||||
|
@ -45,11 +45,11 @@ final class ComputeSyncRangesActionTests: ZcashTestCase {
|
|||
|
||||
XCTAssertTrue(
|
||||
totalProgressRange == expectedRange,
|
||||
"testComputeSyncRangesActionTests_computeTotalProgressRange_ValidRange is expected to be \(expectedRange) but received \(totalProgressRange)"
|
||||
"testComputeSyncRangesAction_computeTotalProgressRange_ValidRange is expected to be \(expectedRange) but received \(totalProgressRange)"
|
||||
)
|
||||
}
|
||||
|
||||
func testComputeSyncRangesActionTests_finishProcessingCase() async throws {
|
||||
func testComputeSyncRangesAction_finishProcessingCase() async throws {
|
||||
let blockDownloaderServiceMock = BlockDownloaderServiceMock()
|
||||
let latestBlocksDataProviderMock = LatestBlocksDataProviderMock()
|
||||
let internalSyncProgressStorageMock = InternalSyncProgressStorageMock()
|
||||
|
@ -67,8 +67,14 @@ final class ComputeSyncRangesActionTests: ZcashTestCase {
|
|||
do {
|
||||
let nextContext = try await computeSyncRangesAction.run(with: syncContext) { _ in }
|
||||
|
||||
XCTAssertTrue(blockDownloaderServiceMock.lastDownloadedBlockHeightCalled, "downloaderService.lastDownloadedBlockHeight() is expected to be called.")
|
||||
XCTAssertTrue(latestBlocksDataProviderMock.updateScannedDataCalled, "latestBlocksDataProvider.updateScannedData() is expected to be called.")
|
||||
XCTAssertTrue(
|
||||
blockDownloaderServiceMock.lastDownloadedBlockHeightCalled,
|
||||
"downloaderService.lastDownloadedBlockHeight() is expected to be called."
|
||||
)
|
||||
XCTAssertTrue(
|
||||
latestBlocksDataProviderMock.updateScannedDataCalled,
|
||||
"latestBlocksDataProvider.updateScannedData() is expected to be called."
|
||||
)
|
||||
XCTAssertTrue(latestBlocksDataProviderMock.updateBlockDataCalled, "latestBlocksDataProvider.updateBlockData() is expected to be called.")
|
||||
XCTAssertFalse(loggerMock.infoFileFunctionLineCalled, "logger.info() is not expected to be called.")
|
||||
|
||||
|
@ -78,11 +84,11 @@ final class ComputeSyncRangesActionTests: ZcashTestCase {
|
|||
"nextContext after .computeSyncRanges is expected to be .finished but received \(nextState)"
|
||||
)
|
||||
} catch {
|
||||
XCTFail("testComputeSyncRangesActionTests_FinishProcessing is not expected to fail. \(error)")
|
||||
XCTFail("testComputeSyncRangesAction_finishProcessingCase is not expected to fail. \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func testComputeSyncRangesActionTests_checksBeforeSyncCase() async throws {
|
||||
func testComputeSyncRangesAction_checksBeforeSyncCase() async throws {
|
||||
let blockDownloaderServiceMock = BlockDownloaderServiceMock()
|
||||
let latestBlocksDataProviderMock = LatestBlocksDataProviderMock()
|
||||
let internalSyncProgressStorageMock = InternalSyncProgressStorageMock()
|
||||
|
@ -101,8 +107,14 @@ final class ComputeSyncRangesActionTests: ZcashTestCase {
|
|||
do {
|
||||
let nextContext = try await computeSyncRangesAction.run(with: syncContext) { _ in }
|
||||
|
||||
XCTAssertTrue(blockDownloaderServiceMock.lastDownloadedBlockHeightCalled, "downloaderService.lastDownloadedBlockHeight() is expected to be called.")
|
||||
XCTAssertTrue(latestBlocksDataProviderMock.updateScannedDataCalled, "latestBlocksDataProvider.updateScannedData() is expected to be called.")
|
||||
XCTAssertTrue(
|
||||
blockDownloaderServiceMock.lastDownloadedBlockHeightCalled,
|
||||
"downloaderService.lastDownloadedBlockHeight() is expected to be called."
|
||||
)
|
||||
XCTAssertTrue(
|
||||
latestBlocksDataProviderMock.updateScannedDataCalled,
|
||||
"latestBlocksDataProvider.updateScannedData() is expected to be called."
|
||||
)
|
||||
XCTAssertTrue(latestBlocksDataProviderMock.updateBlockDataCalled, "latestBlocksDataProvider.updateBlockData() is expected to be called.")
|
||||
XCTAssertFalse(loggerMock.infoFileFunctionLineCalled, "logger.info() is not expected to be called.")
|
||||
|
||||
|
@ -112,11 +124,11 @@ final class ComputeSyncRangesActionTests: ZcashTestCase {
|
|||
"nextContext after .computeSyncRanges is expected to be .checksBeforeSync but received \(nextState)"
|
||||
)
|
||||
} catch {
|
||||
XCTFail("testComputeSyncRangesActionTests_checksBeforeSyncCase is not expected to fail. \(error)")
|
||||
XCTFail("testComputeSyncRangesAction_checksBeforeSyncCase is not expected to fail. \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func testComputeSyncRangesActionTests_waitCase() async throws {
|
||||
func testComputeSyncRangesAction_waitCase() async throws {
|
||||
let blockDownloaderServiceMock = BlockDownloaderServiceMock()
|
||||
let latestBlocksDataProviderMock = LatestBlocksDataProviderMock()
|
||||
let internalSyncProgressStorageMock = InternalSyncProgressStorageMock()
|
||||
|
@ -138,8 +150,14 @@ final class ComputeSyncRangesActionTests: ZcashTestCase {
|
|||
do {
|
||||
let nextContext = try await computeSyncRangesAction.run(with: syncContext) { _ in }
|
||||
|
||||
XCTAssertTrue(blockDownloaderServiceMock.lastDownloadedBlockHeightCalled, "downloaderService.lastDownloadedBlockHeight() is expected to be called.")
|
||||
XCTAssertTrue(latestBlocksDataProviderMock.updateScannedDataCalled, "latestBlocksDataProvider.updateScannedData() is expected to be called.")
|
||||
XCTAssertTrue(
|
||||
blockDownloaderServiceMock.lastDownloadedBlockHeightCalled,
|
||||
"downloaderService.lastDownloadedBlockHeight() is expected to be called."
|
||||
)
|
||||
XCTAssertTrue(
|
||||
latestBlocksDataProviderMock.updateScannedDataCalled,
|
||||
"latestBlocksDataProvider.updateScannedData() is expected to be called."
|
||||
)
|
||||
XCTAssertTrue(latestBlocksDataProviderMock.updateBlockDataCalled, "latestBlocksDataProvider.updateBlockData() is expected to be called.")
|
||||
XCTAssertTrue(loggerMock.infoFileFunctionLineCalled, "logger.info() is expected to be called.")
|
||||
|
||||
|
@ -149,7 +167,7 @@ final class ComputeSyncRangesActionTests: ZcashTestCase {
|
|||
"nextContext after .computeSyncRanges is expected to be .finished but received \(nextState)"
|
||||
)
|
||||
} catch {
|
||||
XCTFail("testComputeSyncRangesActionTests_waitCase is not expected to fail. \(error)")
|
||||
XCTFail("testComputeSyncRangesAction_waitCase is not expected to fail. \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,7 +198,7 @@ final class ComputeSyncRangesActionTests: ZcashTestCase {
|
|||
_ internalSyncProgressStorageMock: InternalSyncProgressStorageMock = InternalSyncProgressStorageMock(),
|
||||
_ loggerMock: LoggerMock = LoggerMock()
|
||||
) -> ComputeSyncRangesAction {
|
||||
mockContainer.register(type: InternalSyncProgress.self, isSingleton: true) { di in
|
||||
mockContainer.register(type: InternalSyncProgress.self, isSingleton: true) { _ in
|
||||
InternalSyncProgress(alias: .default, storage: internalSyncProgressStorageMock, logger: loggerMock)
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ final class DownloadActionTests: ZcashTestCase {
|
|||
transactionRepositoryMock.lastScannedHeightReturnValue = 1
|
||||
blockDownloaderMock.setSyncRangeBatchSizeClosure = { _, _ in }
|
||||
blockDownloaderMock.setDownloadLimitClosure = { _ in }
|
||||
blockDownloaderMock.startDownloadMaxBlockBufferSizeClosure = { _ in }
|
||||
blockDownloaderMock.startDownloadMaxBlockBufferSizeClosure = { _ in }
|
||||
blockDownloaderMock.waitUntilRequestedBlocksAreDownloadedInClosure = { _ in }
|
||||
|
||||
let downloadAction = setupAction(
|
||||
|
@ -69,7 +69,10 @@ final class DownloadActionTests: ZcashTestCase {
|
|||
do {
|
||||
let nextContext = try await downloadAction.run(with: syncContext) { _ in }
|
||||
|
||||
XCTAssertFalse(transactionRepositoryMock.lastScannedHeightCalled, "transactionRepository.lastScannedHeight() is not expected to be called.")
|
||||
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.")
|
||||
|
|
|
@ -27,6 +27,7 @@ extension SaplingParametersHandler { }
|
|||
extension Synchronizer { }
|
||||
extension TransactionRepository { }
|
||||
extension UTXOFetcher { }
|
||||
extension ZcashFileManager { }
|
||||
extension ZcashRustBackendWelding { }
|
||||
|
||||
// sourcery:end:
|
||||
|
|
|
@ -2012,6 +2012,73 @@ class UTXOFetcherMock: UTXOFetcher {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
class ZcashFileManagerMock: ZcashFileManager {
|
||||
|
||||
|
||||
init(
|
||||
) {
|
||||
}
|
||||
|
||||
// MARK: - isReadableFile
|
||||
|
||||
var isReadableFileAtPathCallsCount = 0
|
||||
var isReadableFileAtPathCalled: Bool {
|
||||
return isReadableFileAtPathCallsCount > 0
|
||||
}
|
||||
var isReadableFileAtPathReceivedPath: String?
|
||||
var isReadableFileAtPathReturnValue: Bool!
|
||||
var isReadableFileAtPathClosure: ((String) -> Bool)?
|
||||
|
||||
func isReadableFile(atPath path: String) -> Bool {
|
||||
isReadableFileAtPathCallsCount += 1
|
||||
isReadableFileAtPathReceivedPath = path
|
||||
if let closure = isReadableFileAtPathClosure {
|
||||
return closure(path)
|
||||
} else {
|
||||
return isReadableFileAtPathReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - removeItem
|
||||
|
||||
var removeItemAtThrowableError: Error?
|
||||
var removeItemAtCallsCount = 0
|
||||
var removeItemAtCalled: Bool {
|
||||
return removeItemAtCallsCount > 0
|
||||
}
|
||||
var removeItemAtReceivedURL: URL?
|
||||
var removeItemAtClosure: ((URL) throws -> Void)?
|
||||
|
||||
func removeItem(at URL: URL) throws {
|
||||
if let error = removeItemAtThrowableError {
|
||||
throw error
|
||||
}
|
||||
removeItemAtCallsCount += 1
|
||||
removeItemAtReceivedURL = URL
|
||||
try removeItemAtClosure!(URL)
|
||||
}
|
||||
|
||||
// MARK: - isDeletableFile
|
||||
|
||||
var isDeletableFileAtPathCallsCount = 0
|
||||
var isDeletableFileAtPathCalled: Bool {
|
||||
return isDeletableFileAtPathCallsCount > 0
|
||||
}
|
||||
var isDeletableFileAtPathReceivedPath: String?
|
||||
var isDeletableFileAtPathReturnValue: Bool!
|
||||
var isDeletableFileAtPathClosure: ((String) -> Bool)?
|
||||
|
||||
func isDeletableFile(atPath path: String) -> Bool {
|
||||
isDeletableFileAtPathCallsCount += 1
|
||||
isDeletableFileAtPathReceivedPath = path
|
||||
if let closure = isDeletableFileAtPathClosure {
|
||||
return closure(path)
|
||||
} else {
|
||||
return isDeletableFileAtPathReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
actor ZcashRustBackendWeldingMock: ZcashRustBackendWelding {
|
||||
|
||||
|
|
Loading…
Reference in New Issue