Skip to content

Commit

Permalink
test: add excluded-in-CI live tests
Browse files Browse the repository at this point in the history
  • Loading branch information
thunderbiscuit committed Nov 6, 2023
1 parent 13c751c commit d37b2f3
Show file tree
Hide file tree
Showing 24 changed files with 393 additions and 189 deletions.
11 changes: 6 additions & 5 deletions .github/workflows/test-android.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,12 @@ jobs:
- name: "Build Android library"
run: |
cd bdk-android
./gradlew buildAndroidLib
./gradlew buildAndroidLib --console=plain
# There are currently no unit tests for bdk-android and the integration tests require the macOS image
# which is not working with the older NDK version we are using, so for now we just make sure that the library builds.
# - name: "Run Android unit tests"
# There are currently no unit tests for bdk-android (see the tests in bdk-jvm instead) and the
# integration tests require the macOS image which is not working with the older NDK version we
# are using, so for now we just make sure that the library builds and omit the connectedTest
# - name: "Run Android connected tests"
# run: |
# cd bdk-android
# ./gradlew test --console=rich
# ./gradlew connectedAndroidTest --console=plain
2 changes: 1 addition & 1 deletion .github/workflows/test-jvm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ jobs:
- name: "Run JVM tests"
run: |
cd bdk-jvm
./gradlew test
./gradlew test -P excludeConnectedTests
8 changes: 4 additions & 4 deletions .github/workflows/test-python.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
run: ${PYBIN}/pip install ./dist/*.whl

- name: "Run tests"
run: ${PYBIN}/python -m unittest tests/test_bdk.py --verbose
run: ${PYBIN}/python -m unittest discover --start "./tests/" --pattern "test_offline_*.py" --verbose

- name: "Upload artifact test"
uses: actions/upload-artifact@v3
Expand Down Expand Up @@ -97,7 +97,7 @@ jobs:
# - name: "Install wheel and run tests"
# run: |
# pip3 install ./dist/*.whl
# python3 -m unittest tests/test_bdk.py --verbose
# python3 -m unittest discover --start "./tests/" --pattern "test_offline_*.py" --verbose

- name: "Upload artifact test"
uses: actions/upload-artifact@v3
Expand Down Expand Up @@ -138,7 +138,7 @@ jobs:
run: pip3 install ./dist/*.whl

- name: "Run tests"
run: python3 -m unittest tests/test_bdk.py --verbose
run: python3 -m unittest discover --start "./tests/" --pattern "test_offline_*.py" --verbose

- name: "Upload artifact test"
uses: actions/upload-artifact@v3
Expand Down Expand Up @@ -186,4 +186,4 @@ jobs:
shell: powershell

- name: "Run tests"
run: python -m unittest tests/test_bdk.py --verbose
run: python -m unittest discover --start "./tests/" --pattern "test_offline_*.py" --verbose
2 changes: 1 addition & 1 deletion .github/workflows/test-swift.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ jobs:

- name: "Run Swift tests"
working-directory: bdk-swift
run: swift test
run: swift test --skip LiveWalletTests --skip LiveTxBuilderTests
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.bitcoindevkit

import org.junit.Test
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.runner.RunWith
import kotlin.test.assertTrue

@RunWith(AndroidJUnit4::class)
class LiveTxBuilderTest {
@Test
fun testTxBuilder() {
val descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.TESTNET)
val wallet = Wallet.newNoPersist(descriptor, null, Network.TESTNET)
val esploraClient = EsploraClient("https://mempool.space/testnet/api")
val update = esploraClient.scan(wallet, 10uL, 1uL)
wallet.applyUpdate(update)
println("Balance: ${wallet.getBalance().total()}")

assert(wallet.getBalance().total() > 0uL)

val recipient: Address = Address("tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", Network.TESTNET)
val psbt: PartiallySignedTransaction = TxBuilder()
.addRecipient(recipient.scriptPubkey(), 4200uL)
.feeRate(2.0f)
.finish(wallet)

println(psbt.serialize())
assertTrue(psbt.serialize().startsWith("cHNi"), "PSBT should start with 'cHNi'")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.bitcoindevkit

import org.junit.Test
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class LiveWalletTest {
@Test
fun testSyncedBalance() {
val descriptor: Descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.TESTNET)
val wallet: Wallet = Wallet.newNoPersist(descriptor, null, Network.TESTNET)
val esploraClient: EsploraClient = EsploraClient("https://mempool.space/testnet/api")
// val esploraClient = EsploraClient("https://blockstream.info/testnet/api")
val update = esploraClient.scan(wallet, 10uL, 1uL)
wallet.applyUpdate(update)
println("Balance: ${wallet.getBalance().total()}")

assert(wallet.getBalance().total() > 0uL)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.bitcoindevkit

import kotlin.test.Test
import kotlin.test.assertTrue
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class OfflineDescriptorTest {
@Test
fun testDescriptorBip86() {
val mnemonic: Mnemonic = Mnemonic.fromString("space echo position wrist orient erupt relief museum myself grain wisdom tumble")
val descriptorSecretKey: DescriptorSecretKey = DescriptorSecretKey(Network.TESTNET, mnemonic, null)
val descriptor: Descriptor = Descriptor.newBip86(descriptorSecretKey, KeychainKind.EXTERNAL, Network.TESTNET)

assertEquals(
expected = "tr([be1eec8f/86'/1'/0']tpubDCTtszwSxPx3tATqDrsSyqScPNnUChwQAVAkanuDUCJQESGBbkt68nXXKRDifYSDbeMa2Xg2euKbXaU3YphvGWftDE7ozRKPriT6vAo3xsc/0/*)#m7puekcx",
actual = descriptor.asString()
)
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
package org.bitcoindevkit

import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.runner.RunWith
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.runner.RunWith

/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class WalletTest {

class OfflineWalletTest {
@Test
fun testDescriptorBip86() {
val mnemonic: Mnemonic = Mnemonic(WordCount.WORDS12)
Expand All @@ -36,7 +30,10 @@ class WalletTest {
)
val addressInfo: AddressInfo = wallet.getAddress(AddressIndex.New)

assertEquals("tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", addressInfo.address.asString())
assertEquals(
expected = "tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e",
actual = addressInfo.address.asString()
)
}

@Test
Expand All @@ -51,7 +48,9 @@ class WalletTest {
Network.TESTNET
)

assertEquals(0uL, wallet.getBalance().total())
assertEquals(
expected = 0uL,
actual = wallet.getBalance().total()
)
}

}
}
4 changes: 4 additions & 0 deletions bdk-ffi/src/bdk.udl
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,14 @@ interface Wallet {

AddressInfo get_address(AddressIndex address_index);

AddressInfo get_internal_address(AddressIndex address_index);

Network network();

Balance get_balance();

boolean is_mine(Script script);

[Throws=BdkError]
void apply_update(Update update);
};
Expand Down
83 changes: 10 additions & 73 deletions bdk-ffi/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,28 +38,22 @@ impl Wallet {
self.inner_mutex.lock().expect("wallet")
}

// pub fn get_address(&self, address_index: AddressIndex) -> Result<AddressInfo, BdkError> {
pub fn get_address(&self, address_index: AddressIndex) -> AddressInfo {
self.get_wallet().get_address(address_index.into()).into()
// NOTE: I prefer this:
// AddressInfo::from(
// self.get_wallet().get_address(address_index.into())
// )
}

pub fn network(&self) -> Network {
self.get_wallet().network().into()
}

// fn get_internal_address(&mut self, address_index: AddressIndex) -> AddressInfo {
// self.get_wallet()
// .get_internal_address(address_index.into())
// .into()
// }
pub fn get_internal_address(&self, address_index: AddressIndex) -> AddressInfo {
self.get_wallet()
.get_internal_address(address_index.into())
.into()
}

// TODO 16: Why is the Arc required here?
pub fn get_balance(&self) -> Arc<Balance> {
// Arc::new(self.get_wallet().get_balance().into())
let bdk_balance = self.get_wallet().get_balance();
let balance = Balance { inner: bdk_balance };
Arc::new(balance)
Expand All @@ -71,11 +65,11 @@ impl Wallet {
.map_err(|e| BdkError::Generic(e.to_string()))
}

// pub fn commit(&self) -> Result<(), BdkError> {}

// fn is_mine(&self, script: Arc<Script>) -> bool {
// self.get_wallet().is_mine(&script.inner)
// }
pub fn is_mine(&self, script: Arc<Script>) -> bool {
// TODO: Both of the following lines work. Which is better?
self.get_wallet().is_mine(&script.0)
// self.get_wallet().is_mine(script.0.clone().as_script())
}
}

pub struct Update(pub(crate) BdkUpdate);
Expand All @@ -98,63 +92,6 @@ pub struct Update(pub(crate) BdkUpdate);
// }
// }

// impl Wallet {
// // pub(crate) fn new(
// // descriptor: Arc<Descriptor>,
// // change_descriptor: Option<Arc<Descriptor>>,
// // db: PersistBackend<ChangeSet>,
// // network: Network,
// // ) -> Result<Self, BdkError> {
// // let any_database_config = match database_config {
// // DatabaseConfig::Memory => AnyDatabaseConfig::Memory(()),
// // DatabaseConfig::Sled { config } => AnyDatabaseConfig::Sled(config),
// // DatabaseConfig::Sqlite { config } => AnyDatabaseConfig::Sqlite(config),
// // };
// // let database = AnyDatabase::from_config(&any_database_config)?;
// // let descriptor: String = descriptor.as_string_private();
// // let change_descriptor: Option<String> = change_descriptor.map(|d| d.as_string_private());
// //
// // let wallet_mutex = Mutex::new(BdkWallet::new(
// // &descriptor,
// // change_descriptor.as_ref(),
// // network,
// // database,
// // )?);
// // Ok(Wallet {
// // inner_mutex: wallet_mutex,
// // })
// // }
//
// pub(crate) fn new_no_persist(
// descriptor: Arc<Descriptor>,
// change_descriptor: Option<Arc<Descriptor>>,
// network: Network,
// ) -> Result<Self, BdkError> {
// let descriptor: String = descriptor.as_string_private();
// let change_descriptor: Option<String> = change_descriptor.map(|d| d.as_string_private());
//
// let wallet = BdkWallet::new_no_persist(
// &descriptor,
// change_descriptor.as_ref(),
// network,
// )?;
//
// Ok(Wallet {
// inner: wallet,
// })
// }
//
// // MIGRATION 1.0: This function is no longer needed right? If I remove the mutex on the wallet,
// // I can just access the wallet directly without causing trouble me thinks.
// pub(crate) fn get_wallet(&self) -> MutexGuard<BdkWallet<AnyDatabase>> {
// self.inner_mutex.lock().expect("wallet")
// }
//
// /// Get the Bitcoin network the wallet is using.
// pub(crate) fn network(&self) -> Network {
// self.inner.network()
// }
//
// /// Return whether or not a script is part of this wallet (either internal or external).
// pub(crate) fn is_mine(&self, script: Arc<Script>) -> bool {
// self.inner.is_mine(&script.inner)
Expand Down
12 changes: 12 additions & 0 deletions bdk-jvm/lib/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ java {
withJavadocJar()
}

// This block ensures that the tests that require access to a blockchain are not
// run if the -P excludeConnectedTests flag is passed to gradle.
// This ensures our CI runs are not fickle by not requiring access to testnet.
// This is a workaround until we have a proper regtest setup for the CI.
// Note that the command in the CI is ./gradlew test -P excludeConnectedTests
tasks.test {
if (project.hasProperty("excludeConnectedTests")) {
exclude("**/LiveWalletTest.class")
exclude("**/LiveTxBuilderTest.class")
}
}

testing {
suites {
val test by getting(JvmTestSuite::class) {
Expand Down
29 changes: 29 additions & 0 deletions bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveTxBuilderTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.bitcoindevkit

import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class LiveTxBuilderTest {
@Test
fun testTxBuilder() {
val descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.TESTNET)
val wallet = Wallet.newNoPersist(descriptor, null, Network.TESTNET)
val esploraClient = EsploraClient("https://mempool.space/testnet/api")
val update = esploraClient.scan(wallet, 10uL, 1uL)
wallet.applyUpdate(update)
println("Balance: ${wallet.getBalance().total()}")

assert(wallet.getBalance().total() > 0uL)

val recipient: Address = Address("tb1qrnfslnrve9uncz9pzpvf83k3ukz22ljgees989", Network.TESTNET)
val psbt: PartiallySignedTransaction = TxBuilder()
.addRecipient(recipient.scriptPubkey(), 4200uL)
.feeRate(2.0f)
.finish(wallet)

println(psbt.serialize())

assertTrue(psbt.serialize().startsWith("cHNi"), "PSBT should start with 'cHNi'")
}
}
18 changes: 18 additions & 0 deletions bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveWalletTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.bitcoindevkit

import kotlin.test.Test

class LiveWalletTest {
@Test
fun testSyncedBalance() {
val descriptor: Descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.TESTNET)
val wallet: Wallet = Wallet.newNoPersist(descriptor, null, Network.TESTNET)
val esploraClient: EsploraClient = EsploraClient("https://mempool.space/testnet/api")
// val esploraClient = EsploraClient("https://blockstream.info/testnet/api")
val update = esploraClient.scan(wallet, 10uL, 1uL)
wallet.applyUpdate(update)
println("Balance: ${wallet.getBalance().total()}")

assert(wallet.getBalance().total() > 0uL)
}
}
Loading

0 comments on commit d37b2f3

Please sign in to comment.