Skip to content

Commit

Permalink
feat: test context improvements (#606)
Browse files Browse the repository at this point in the history
* test context improvements

* add .with_mocked_clients() convenience method to reduce boilerplate

* pr comments
  • Loading branch information
cylewitruk authored Oct 3, 2024
1 parent 8f35f57 commit 2fa9ce6
Show file tree
Hide file tree
Showing 15 changed files with 627 additions and 256 deletions.
23 changes: 13 additions & 10 deletions signer/src/api/new_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,9 @@ mod tests {
use rand::rngs::OsRng;
use test_case::test_case;

use crate::config::Settings;
use crate::storage::in_memory::Store;
use crate::storage::model::StacksPrincipal;
use crate::testing::NoopSignerContext;
use crate::testing::context::*;

/// These were generated from a stacks node after running the
/// "complete-deposit standard recipient", "accept-withdrawal",
Expand Down Expand Up @@ -159,13 +158,15 @@ mod tests {
where
F: Fn(tokio::sync::MutexGuard<'_, Store>) -> bool,
{
let db = Store::new_shared();

let ctx = NoopSignerContext::init(Settings::new_from_default_config().unwrap(), db.clone())
.expect("failed to init context");
let ctx = TestContext::builder()
.with_in_memory_storage()
.with_mocked_clients()
.build();

let api = ApiState { ctx: ctx.clone() };

let db = ctx.inner_storage();

// Hey look, there is nothing here!
assert!(table_is_empty(db.lock().await));

Expand All @@ -188,13 +189,15 @@ mod tests {
where
F: Fn(tokio::sync::MutexGuard<'_, Store>) -> bool,
{
let db = Store::new_shared();

let ctx = NoopSignerContext::init(Settings::new_from_default_config().unwrap(), db.clone())
.expect("failed to init context");
let ctx = TestContext::builder()
.with_in_memory_storage()
.with_mocked_clients()
.build();

let api = ApiState { ctx: ctx.clone() };

let db = ctx.inner_storage();

// Hey look, there is nothing here!
assert!(table_is_empty(db.lock().await));

Expand Down
13 changes: 5 additions & 8 deletions signer/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,8 @@ mod tests {
use tokio::sync::Notify;

use crate::{
config::Settings,
context::{Context as _, SignerEvent, SignerSignal},
storage::in_memory::Store,
testing::NoopSignerContext,
testing::context::*,
};

/// This test shows that cloning a context and signalling on the original
Expand All @@ -185,11 +183,10 @@ mod tests {
#[tokio::test]
async fn context_clone_signalling_works() {
// Create a context.
let context = NoopSignerContext::init(
Settings::new_from_default_config().unwrap(),
Store::new_shared(),
)
.unwrap();
let context = TestContext::builder()
.with_in_memory_storage()
.with_mocked_clients()
.build();

// Clone the context.
let context_clone = context.clone();
Expand Down
9 changes: 6 additions & 3 deletions signer/src/network/libp2p/swarm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ impl SignerSwarm {

#[cfg(test)]
mod tests {
use crate::{config::Settings, storage::in_memory::Store, testing::NoopSignerContext};
use crate::testing::context::*;

use super::*;

Expand Down Expand Up @@ -246,8 +246,11 @@ mod tests {
let builder = SignerSwarmBuilder::new(&private_key);
let mut swarm = builder.build().unwrap();

let settings = Settings::new_from_default_config().unwrap();
let ctx = NoopSignerContext::init(settings, Store::new_shared()).unwrap();
let ctx = TestContext::builder()
.with_in_memory_storage()
.with_mocked_clients()
.build();

let term = ctx.get_termination_handle();

let timeout = tokio::time::timeout(Duration::from_secs(10), async {
Expand Down
15 changes: 9 additions & 6 deletions signer/src/network/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,8 @@ mod tests {
use super::*;

use crate::{
config::Settings,
keys::PrivateKey,
storage::in_memory::Store,
testing::{self, clear_env, NoopSignerContext},
testing::{self, clear_env, context::*},
};

#[tokio::test]
Expand All @@ -143,10 +141,15 @@ mod tests {
let key1 = PrivateKey::new(&mut rand::thread_rng());
let key2 = PrivateKey::new(&mut rand::thread_rng());

let settings = Settings::new_from_default_config().unwrap();
let context1 = TestContext::builder()
.with_in_memory_storage()
.with_mocked_clients()
.build();

let context1 = NoopSignerContext::init(settings.clone(), Store::new_shared()).unwrap();
let context2 = NoopSignerContext::init(settings, Store::new_shared()).unwrap();
let context2 = TestContext::builder()
.with_in_memory_storage()
.with_mocked_clients()
.build();

let term1 = context1.get_termination_handle();
let term2 = context2.get_termination_handle();
Expand Down
2 changes: 2 additions & 0 deletions signer/src/stacks/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ pub enum FeePriority {
}

/// A trait detailing the interface with the Stacks API and Stacks Nodes.
#[cfg_attr(any(test, feature = "testing"), mockall::automock)]
pub trait StacksInteract {
/// Retrieve the current signer set from the `sbtc-registry` contract.
///
Expand Down Expand Up @@ -127,6 +128,7 @@ pub trait StacksInteract {
///
/// This function usually uses the POST /v2/fees/transaction endpoint
/// of a stacks node.
#[cfg_attr(any(test, feature = "testing"), mockall::concretize)]
fn estimate_fees<T>(
&self,
payload: &T,
Expand Down
2 changes: 1 addition & 1 deletion signer/src/storage/postgres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ fn contract_transaction_kinds() -> &'static HashMap<&'static str, TransactionTyp

/// This function extracts the signer relevant sBTC related transactions
/// from the given blocks.
///
///
/// Here the deployer is the address that deployed the sBTC smart
/// contracts.
pub fn extract_relevant_transactions(
Expand Down
140 changes: 0 additions & 140 deletions signer/src/testing/api_clients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,148 +2,8 @@

use url::Url;

use crate::bitcoin::rpc::BitcoinTxInfo;
use crate::bitcoin::rpc::GetTxResponse;
use crate::bitcoin::BitcoinInteract;
use crate::bitcoin::MockBitcoinInteract;
use crate::blocklist_client::BlocklistChecker;
use crate::config::Settings;
use crate::emily_client::EmilyInteract;
use crate::error::Error;
use crate::stacks::api::StacksInteract;

/// A no-op API client that doesn't do anything. It will panic if you
/// attempt to use it, but can be useful for fillers in testing.
#[derive(Clone)]
pub struct NoopApiClient;

impl TryFrom<&[Url]> for NoopApiClient {
type Error = Error;
fn try_from(_value: &[Url]) -> Result<Self, Self::Error> {
Ok(NoopApiClient)
}
}

impl TryFrom<&Settings> for NoopApiClient {
type Error = Error;
fn try_from(_value: &Settings) -> Result<Self, Self::Error> {
Ok(NoopApiClient)
}
}

/// Noop implementation of the BitcoinInteract trait.
impl BitcoinInteract for NoopApiClient {
async fn get_tx(&self, _: &bitcoin::Txid) -> Result<Option<GetTxResponse>, Error> {
unimplemented!()
}

async fn get_tx_info(
&self,
_: &bitcoin::Txid,
_: &bitcoin::BlockHash,
) -> Result<Option<BitcoinTxInfo>, Error> {
unimplemented!()
}

async fn get_block(
&self,
_block_hash: &bitcoin::BlockHash,
) -> Result<Option<bitcoin::Block>, Error> {
unimplemented!()
}

async fn estimate_fee_rate(&self) -> Result<f64, Error> {
unimplemented!()
}

async fn get_last_fee(
&self,
_utxo: bitcoin::OutPoint,
) -> Result<Option<crate::bitcoin::utxo::Fees>, Error> {
unimplemented!()
}

async fn broadcast_transaction(&self, _tx: &bitcoin::Transaction) -> Result<(), Error> {
unimplemented!()
}
}

/// Noop implementation of the StacksInteract trait.
impl StacksInteract for NoopApiClient {
async fn get_current_signer_set(
&self,
_contract_principal: &clarity::types::chainstate::StacksAddress,
) -> Result<Vec<crate::keys::PublicKey>, Error> {
unimplemented!()
}

async fn get_account(
&self,
_address: &clarity::types::chainstate::StacksAddress,
) -> Result<crate::stacks::api::AccountInfo, Error> {
unimplemented!()
}

async fn submit_tx(
&self,
_tx: &blockstack_lib::chainstate::stacks::StacksTransaction,
) -> Result<crate::stacks::api::SubmitTxResponse, Error> {
unimplemented!()
}

async fn get_block(
&self,
_block_id: clarity::types::chainstate::StacksBlockId,
) -> Result<blockstack_lib::chainstate::nakamoto::NakamotoBlock, Error> {
unimplemented!()
}

async fn get_tenure(
&self,
_block_id: clarity::types::chainstate::StacksBlockId,
) -> Result<Vec<blockstack_lib::chainstate::nakamoto::NakamotoBlock>, Error> {
unimplemented!()
}

async fn get_tenure_info(
&self,
) -> Result<blockstack_lib::net::api::gettenureinfo::RPCGetTenureInfo, Error> {
unimplemented!()
}

async fn estimate_fees<T>(
&self,
_payload: &T,
_priority: crate::stacks::api::FeePriority,
) -> Result<u64, Error>
where
T: crate::stacks::contracts::AsTxPayload + Send + Sync,
{
unimplemented!()
}

fn nakamoto_start_height(&self) -> u64 {
unimplemented!()
}
}

/// Noop implementation of the EmilyInteract trait.
impl EmilyInteract for NoopApiClient {
async fn get_deposits(&self) -> Result<Vec<sbtc::deposits::CreateDepositRequest>, Error> {
todo!()
}
}

/// Noop implementation of the BlocklistChecker trait.
impl BlocklistChecker for NoopApiClient {
async fn can_accept(
&self,
_address: &str,
) -> Result<bool, blocklist_api::apis::Error<blocklist_api::apis::address_api::CheckAddressError>>
{
todo!()
}
}

impl TryFrom<&[Url]> for MockBitcoinInteract {
type Error = Error;
Expand Down
Loading

0 comments on commit 2fa9ce6

Please sign in to comment.