ZcashLightClientKit/ZcashLightClientKitTests/OutboundTransactionManagerT...

263 lines
9.6 KiB
Swift

//
// OutboundTransactionManagerTests.swift
// ZcashLightClientKit-Unit-Tests
//
// Created by Francisco Gindre on 11/26/19.
//
import XCTest
@testable import ZcashLightClientKit
class OutboundTransactionManagerTests: XCTestCase {
var transactionManager: OutboundTransactionManager!
var encoder: TransactionEncoder!
var pendingRespository: PendingTransactionSQLDAO!
var dataDbHandle = TestDbHandle(originalDb: TestDbBuilder.prePopulatedDataDbURL()!)
var cacheDbHandle = TestDbHandle(originalDb: TestDbBuilder.prePopulatedCacheDbURL()!)
var pendingDbhandle = TestDbHandle(originalDb: try! TestDbBuilder.pendingTransactionsDbURL())
var service: LightWalletService!
var initializer: Initializer!
let spendingKey = "secret-extended-key-test1qvpevftsqqqqpqy52ut2vv24a2qh7nsukew7qg9pq6djfwyc3xt5vaxuenshp2hhspp9qmqvdh0gs2ljpwxders5jkwgyhgln0drjqaguaenfhehz4esdl4kwlm5t9q0l6wmzcrvcf5ed6dqzvct3e2ge7f6qdvzhp02m7sp5a0qjssrwpdh7u6tq89hl3wchuq8ljq8r8rwd6xdwh3nry9at80z7amnj3s6ah4jevnvfr08gxpws523z95g6dmn4wm6l3658kd4xcq9rc0qn"
let recipientAddress = "ztestsapling1ctuamfer5xjnnrdr3xdazenljx0mu0gutcf9u9e74tr2d3jwjnt0qllzxaplu54hgc2tyjdc2p6"
let zpend: Int = 500_000
override func setUp() {
try! dataDbHandle.setUp()
try! cacheDbHandle.setUp()
pendingRespository = PendingTransactionSQLDAO(dbProvider: pendingDbhandle.connectionProvider(readwrite: true))
try! pendingRespository.createrTableIfNeeded()
initializer = Initializer(cacheDbURL: cacheDbHandle.readWriteDb,
dataDbURL: dataDbHandle.readWriteDb,
pendingDbURL: try! TestDbBuilder.pendingTransactionsDbURL(),
endpoint: LightWalletEndpointBuilder.default,
spendParamsURL: try! __spendParamsURL(),
outputParamsURL: try! __outputParamsURL())
encoder = WalletTransactionEncoder(initializer: initializer)
transactionManager = PersistentTransactionManager(encoder: encoder, service: MockLightWalletService(latestBlockHeight: 620999), repository: pendingRespository)
}
override func tearDown() {
transactionManager = nil
encoder = nil
service = nil
initializer = nil
pendingRespository = nil
dataDbHandle.dispose()
cacheDbHandle.dispose()
pendingDbhandle.dispose()
}
func testInitSpend() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
var tx: PendingTransactionEntity?
XCTAssertNoThrow(try { tx = try transactionManager.initSpend(zatoshi: zpend, toAddress: recipientAddress, memo: nil, from: 0) }())
guard let pendingTx = tx else {
XCTFail("failed to create pending transaction")
return
}
XCTAssertEqual(pendingTx.toAddress, recipientAddress)
XCTAssertEqual(pendingTx.memo, nil)
XCTAssertEqual(pendingTx.value, zpend)
}
func testEncodeSpendSucess() {
let expect = XCTestExpectation(description: self.description)
var tx: PendingTransactionEntity?
XCTAssertNoThrow(try { tx = try transactionManager.initSpend(zatoshi: zpend, toAddress: recipientAddress, memo: nil, from: 0) }())
guard let pendingTx = tx else {
XCTFail("failed to create pending transaction")
return
}
transactionManager.encode(spendingKey: spendingKey, pendingTransaction: pendingTx) { (result) in
expect.fulfill()
switch result {
case .failure(let error):
XCTFail("failed with error: \(error)")
case .success(let tx):
XCTAssertEqual(tx.id, pendingTx.id)
XCTAssertTrue(tx.encodeAttempts > 0)
XCTAssertFalse(tx.isFailedEncoding)
}
}
wait(for: [expect], timeout: 20)
}
func testSubmitFailed() {
transactionManager = PersistentTransactionManager(encoder: encoder, service: SlightlyBadLightWalletService(latestBlockHeight: 620999), repository: pendingRespository)
let submitExpect = XCTestExpectation(description: "submit")
guard let tx = submittableTx() else {
XCTFail("failed to encode and all that")
return
}
transactionManager.submit(pendingTransaction: tx) { (result) in
submitExpect.fulfill()
switch result {
case .failure(_):
let failedTx = try? self.pendingRespository.find(by: tx.id!)
XCTAssertTrue(failedTx?.isFailedSubmit ?? false)
case .success(_):
XCTFail("test should have failed but succeeeded!")
}
}
wait(for: [submitExpect], timeout: 5)
}
private func submittableTx() -> PendingTransactionEntity? {
let encodeExpect = XCTestExpectation(description: "encode")
var tx: PendingTransactionEntity?
XCTAssertNoThrow(try { tx = try transactionManager.initSpend(zatoshi: zpend, toAddress: recipientAddress, memo: nil, from: 0) }())
guard let pendingTx = tx else {
XCTFail("failed to create pending transaction")
return nil
}
var encodedTx: PendingTransactionEntity?
transactionManager.encode(spendingKey: spendingKey, pendingTransaction: pendingTx) { (result) in
encodeExpect.fulfill()
switch result {
case .failure(let error):
XCTFail("failed with error: \(error)")
case .success(let tx):
XCTAssertEqual(tx.id, pendingTx.id)
encodedTx = tx
}
}
wait(for: [encodeExpect], timeout: 20)
guard let submittableTx = encodedTx else {
XCTFail("failed to encode tx")
return nil
}
return submittableTx
}
func testSubmit() {
let submitExpect = XCTestExpectation(description: "submit")
guard let tx = submittableTx() else {
XCTFail("failed to encode and all that")
return
}
transactionManager.submit(pendingTransaction: tx) { (result) in
submitExpect.fulfill()
switch result {
case .failure(let error):
XCTFail("submission failed with error: \(error)")
let failedTx = try? self.pendingRespository.find(by: tx.id!)
XCTAssertTrue(failedTx?.isFailedSubmit ?? false)
case .success(let successfulTx):
XCTAssertEqual(tx.id, successfulTx.id)
XCTAssertTrue(successfulTx.isSubmitted)
XCTAssertTrue(successfulTx.isSubmitSuccess)
}
}
wait(for: [submitExpect], timeout: 5)
}
func testApplyMinedHeight() {
var tx: PendingTransactionEntity?
let minedHeight = 789_000
XCTAssertNoThrow(try { tx = try transactionManager.initSpend(zatoshi: zpend, toAddress: recipientAddress, memo: nil, from: 0) }())
guard let pendingTx = tx else {
XCTFail("failed to create pending transaction")
return
}
var minedTransaction: PendingTransactionEntity?
XCTAssertNoThrow(try { minedTransaction = try transactionManager.applyMinedHeight(pendingTransaction: pendingTx, minedHeight: minedHeight)}())
guard let minedTx = minedTransaction else {
XCTFail("failed to apply mined height")
return
}
XCTAssertTrue(minedTx.isMined)
XCTAssertEqual(minedTx.minedHeight, minedHeight)
}
func testCancel() {
var tx: PendingTransactionEntity?
XCTAssertNoThrow(try { tx = try transactionManager.initSpend(zatoshi: zpend, toAddress: recipientAddress, memo: nil, from: 0) }())
guard let pendingTx = tx else {
XCTFail("failed to create pending transaction")
return
}
let cancellationResult = transactionManager.cancel(pendingTransaction: pendingTx)
guard let id = pendingTx.id else {
XCTFail("transaction with no id")
return
}
guard let retrievedTransaction = try! pendingRespository.find(by: id) else {
XCTFail("failed to retrieve previously created transation")
return
}
XCTAssertEqual(cancellationResult, retrievedTransaction.isCancelled)
}
func testAllPendingTransactions() {
let txCount = 100
for i in 0 ..< txCount {
var tx: PendingTransactionEntity?
XCTAssertNoThrow(try { tx = try transactionManager.initSpend(zatoshi: zpend, toAddress: recipientAddress, memo: nil, from: 0) }())
guard tx != nil else {
XCTFail("failed to create pending transaction \(i)")
return
}
}
guard let allPending = try! transactionManager.allPendingTransactions() else {
XCTFail("failed to retrieve all pending transactions")
return
}
XCTAssertEqual(allPending.count, txCount)
}
}