Browse Source

Merge #875

875: Reduce boilerplate in tests r=klochowicz a=klochowicz

See commit messages for details

Co-authored-by: Mariusz Klochowicz <mariusz@klochowicz.com>
test-force-close-without-fake-clock
bors[bot] 3 years ago
committed by GitHub
parent
commit
2ece32874a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      daemon/src/projection.rs
  2. 95
      daemon/tests/happy_path.rs
  3. 14
      daemon/tests/harness/maia.rs
  4. 10
      daemon/tests/harness/mocks/oracle.rs
  5. 41
      daemon/tests/harness/mod.rs

2
daemon/src/projection.rs

@ -354,7 +354,7 @@ impl From<model::Identity> for Identity {
}
}
#[derive(Debug, Clone, Serialize)]
#[derive(Debug, Clone, PartialEq, Serialize)]
pub enum CfdState {
OutgoingOrderRequest,
IncomingOrderRequest,

95
daemon/tests/happy_path.rs

@ -1,7 +1,3 @@
use std::time::Duration;
use crate::harness::deliver_close_finality_event;
use crate::harness::deliver_lock_finality_event;
use crate::harness::dummy_new_order;
use crate::harness::flow::is_next_none;
use crate::harness::flow::next;
@ -17,13 +13,30 @@ use crate::harness::TakerConfig;
use daemon::connection::ConnectionStatus;
use daemon::model::cfd::OrderId;
use daemon::model::Usd;
use daemon::monitor::Event;
use daemon::projection::CfdState;
use daemon::projection::Identity;
use maia::secp256k1_zkp::schnorrsig;
use rust_decimal_macros::dec;
use std::time::Duration;
use tokio::time::sleep;
mod harness;
/// Assert the next state of the single cfd present at both maker and taker
macro_rules! assert_next_state {
($state:expr, $maker:expr, $taker:expr, $id:expr) => {
// TODO: Allow fetching cfd with the specified id if there is more than
// one on the cfd feed
let (taker_cfd, maker_cfd) = next_cfd($taker.cfd_feed(), $maker.cfd_feed())
.await
.unwrap();
assert_eq!(taker_cfd.order_id, $id);
assert_eq!(maker_cfd.order_id, $id);
assert_eq!(taker_cfd.state, $state);
assert_eq!(maker_cfd.state, $state);
};
}
#[tokio::test]
async fn taker_receives_order_from_maker_on_publication() {
let _guard = init_tracing();
@ -59,23 +72,12 @@ async fn taker_takes_order_and_maker_rejects() {
let (taker_cfd, maker_cfd) = next_cfd(taker.cfd_feed(), maker.cfd_feed()).await.unwrap();
assert_eq!(taker_cfd.order_id, received.id);
assert_eq!(maker_cfd.order_id, received.id);
assert!(matches!(
taker_cfd.state,
CfdState::OutgoingOrderRequest { .. }
));
assert!(matches!(
maker_cfd.state,
CfdState::IncomingOrderRequest { .. }
));
assert_eq!(taker_cfd.state, CfdState::OutgoingOrderRequest);
assert_eq!(maker_cfd.state, CfdState::IncomingOrderRequest);
maker.reject_take_request(received.clone()).await;
let (taker_cfd, maker_cfd) = next_cfd(taker.cfd_feed(), maker.cfd_feed()).await.unwrap();
// TODO: More elaborate Cfd assertions
assert_eq!(taker_cfd.order_id, received.id);
assert_eq!(maker_cfd.order_id, received.id);
assert!(matches!(taker_cfd.state, CfdState::Rejected { .. }));
assert!(matches!(maker_cfd.state, CfdState::Rejected { .. }));
assert_next_state!(CfdState::Rejected, maker, taker, received.id);
}
#[tokio::test]
@ -112,28 +114,16 @@ async fn taker_takes_order_and_maker_accepts_and_contract_setup() {
maker.accept_take_request(received.clone()).await;
let (taker_cfd, maker_cfd) = next_cfd(taker.cfd_feed(), maker.cfd_feed()).await.unwrap();
// TODO: More elaborate Cfd assertions
assert_eq!(taker_cfd.order_id, received.id);
assert_eq!(maker_cfd.order_id, received.id);
assert!(matches!(taker_cfd.state, CfdState::ContractSetup { .. }));
assert!(matches!(maker_cfd.state, CfdState::ContractSetup { .. }));
assert_next_state!(CfdState::ContractSetup, maker, taker, received.id);
maker.mocks.mock_wallet_sign_and_broadcast().await;
taker.mocks.mock_wallet_sign_and_broadcast().await;
let (taker_cfd, maker_cfd) = next_cfd(taker.cfd_feed(), maker.cfd_feed()).await.unwrap();
// TODO: More elaborate Cfd assertions
assert_eq!(taker_cfd.order_id, received.id);
assert_eq!(maker_cfd.order_id, received.id);
assert!(matches!(taker_cfd.state, CfdState::PendingOpen { .. }));
assert!(matches!(maker_cfd.state, CfdState::PendingOpen { .. }));
assert_next_state!(CfdState::PendingOpen, maker, taker, received.id);
deliver_lock_finality_event(&maker, &taker, received.id).await;
deliver_event!(maker, taker, Event::LockFinality(received.id));
let (taker_cfd, maker_cfd) = next_cfd(taker.cfd_feed(), maker.cfd_feed()).await.unwrap();
assert!(matches!(taker_cfd.state, CfdState::Open { .. }));
assert!(matches!(maker_cfd.state, CfdState::Open { .. }));
assert_next_state!(CfdState::Open, maker, taker, received.id);
}
#[tokio::test]
@ -144,14 +134,8 @@ async fn collaboratively_close_an_open_cfd() {
taker.propose_settlement(order_id).await;
let (taker_cfd, maker_cfd) = next_cfd(taker.cfd_feed(), maker.cfd_feed()).await.unwrap();
assert!(matches!(
taker_cfd.state,
CfdState::OutgoingSettlementProposal { .. }
));
assert!(matches!(
maker_cfd.state,
CfdState::IncomingSettlementProposal { .. }
));
assert_eq!(taker_cfd.state, CfdState::OutgoingSettlementProposal);
assert_eq!(maker_cfd.state, CfdState::IncomingSettlementProposal);
maker.mocks.mock_monitor_collaborative_settlement().await;
taker.mocks.mock_monitor_collaborative_settlement().await;
@ -159,16 +143,13 @@ async fn collaboratively_close_an_open_cfd() {
maker.accept_settlement_proposal(order_id).await;
sleep(Duration::from_secs(5)).await; // need to wait a bit until both transition
let (taker_cfd, maker_cfd) = next_cfd(taker.cfd_feed(), maker.cfd_feed()).await.unwrap();
assert!(matches!(taker_cfd.state, CfdState::PendingClose { .. }));
assert!(matches!(maker_cfd.state, CfdState::PendingClose { .. }));
assert_next_state!(CfdState::PendingClose, maker, taker, order_id);
deliver_event!(maker, taker, Event::CloseFinality(order_id));
deliver_close_finality_event(&maker, &taker, order_id).await;
sleep(Duration::from_secs(5)).await; // need to wait a bit until both transition
let (taker_cfd, maker_cfd) = next_cfd(taker.cfd_feed(), maker.cfd_feed()).await.unwrap();
assert!(matches!(taker_cfd.state, CfdState::Closed { .. }));
assert!(matches!(maker_cfd.state, CfdState::Closed { .. }));
assert_next_state!(CfdState::Closed, maker, taker, order_id);
}
#[tokio::test]
@ -279,21 +260,15 @@ async fn start_from_open_cfd_state() -> (Maker, Taker, OrderId) {
maker.accept_take_request(received.clone()).await;
let (taker_cfd, maker_cfd) = next_cfd(taker.cfd_feed(), maker.cfd_feed()).await.unwrap();
assert!(matches!(taker_cfd.state, CfdState::ContractSetup { .. }));
assert!(matches!(maker_cfd.state, CfdState::ContractSetup { .. }));
assert_next_state!(CfdState::ContractSetup, maker, taker, received.id);
maker.mocks.mock_wallet_sign_and_broadcast().await;
taker.mocks.mock_wallet_sign_and_broadcast().await;
let (taker_cfd, maker_cfd) = next_cfd(taker.cfd_feed(), maker.cfd_feed()).await.unwrap();
assert!(matches!(taker_cfd.state, CfdState::PendingOpen { .. }));
assert!(matches!(maker_cfd.state, CfdState::PendingOpen { .. }));
assert_next_state!(CfdState::PendingOpen, maker, taker, received.id);
deliver_lock_finality_event(&maker, &taker, received.id).await;
deliver_event!(maker, taker, Event::LockFinality(received.id));
assert_next_state!(CfdState::Open, maker, taker, received.id);
let (taker_cfd, maker_cfd) = next_cfd(taker.cfd_feed(), maker.cfd_feed()).await.unwrap();
assert!(matches!(taker_cfd.state, CfdState::Open { .. }));
assert!(matches!(maker_cfd.state, CfdState::Open { .. }));
(maker, taker, received.id)
}

14
daemon/tests/harness/maia.rs

@ -1,11 +1,12 @@
use daemon::model::BitMexPriceEventId;
use daemon::oracle::{self};
use maia::secp256k1_zkp::schnorrsig;
use maia::secp256k1_zkp::SecretKey;
use maia::Announcement;
use std::str::FromStr;
#[allow(dead_code)]
pub struct OliviaData {
id: String,
id: BitMexPriceEventId,
pk: schnorrsig::PublicKey,
nonce_pks: Vec<schnorrsig::PublicKey>,
price: u64,
@ -29,7 +30,7 @@ impl OliviaData {
fn example(id: &str, price: u64, nonce_pks: &[&str], attestations: &[&str]) -> Self {
let oracle_pk = schnorrsig::PublicKey::from_str(Self::OLIVIA_PK).unwrap();
let id = id.to_string();
let id = id.parse().unwrap();
let nonce_pks = nonce_pks
.iter()
@ -50,9 +51,10 @@ impl OliviaData {
}
}
pub fn announcement(&self) -> Announcement {
Announcement {
id: self.id.clone(),
pub fn announcement(&self) -> oracle::Announcement {
oracle::Announcement {
id: self.id,
expected_outcome_time: self.id.timestamp(),
nonce_pks: self.nonce_pks.clone(),
}
}

10
daemon/tests/harness/mocks/oracle.rs

@ -1,9 +1,7 @@
use crate::harness::maia::OliviaData;
use daemon::model::BitMexPriceEventId;
use daemon::oracle;
use mockall::*;
use std::sync::Arc;
use time::OffsetDateTime;
use tokio::sync::Mutex;
use xtra_productivity::xtra_productivity;
@ -53,11 +51,5 @@ pub trait Oracle {
}
pub fn dummy_announcement() -> oracle::Announcement {
let announcement = OliviaData::example_0().announcement();
oracle::Announcement {
id: BitMexPriceEventId::new(OffsetDateTime::UNIX_EPOCH, 0),
expected_outcome_time: OffsetDateTime::now_utc(),
nonce_pks: announcement.nonce_pks,
}
OliviaData::example_0().announcement()
}

41
daemon/tests/harness/mod.rs

@ -24,6 +24,7 @@ use daemon::MakerActorSystem;
use daemon::Tasks;
use daemon::HEARTBEAT_INTERVAL;
use daemon::N_PAYOUTS;
use daemon::SETTLEMENT_INTERVAL;
use rust_decimal_macros::dec;
use sqlx::SqlitePool;
use std::net::SocketAddr;
@ -149,7 +150,7 @@ impl Maker {
let (wallet_addr, wallet_fut) = wallet.create(None).run();
tasks.add(wallet_fut);
let settlement_interval = time::Duration::hours(24);
let settlement_interval = SETTLEMENT_INTERVAL;
let (identity_pk, identity_sk) = config.seed.derive_identity();
@ -353,36 +354,14 @@ impl Taker {
}
}
/// Deliver the event that provokes the transition to cfd's "Open" state
pub async fn deliver_lock_finality_event(maker: &Maker, taker: &Taker, id: OrderId) {
maker
.system
.cfd_actor_addr
.send(daemon::monitor::Event::LockFinality(id))
.await
.unwrap();
taker
.system
.cfd_actor_addr
.send(daemon::monitor::Event::LockFinality(id))
.await
.unwrap();
}
/// Deliver the event that provokes the transition to cfd's "Close" state
pub async fn deliver_close_finality_event(maker: &Maker, taker: &Taker, id: OrderId) {
taker
.system
.cfd_actor_addr
.send(daemon::monitor::Event::CloseFinality(id))
.await
.unwrap();
maker
.system
.cfd_actor_addr
.send(daemon::monitor::Event::CloseFinality(id))
.await
.unwrap();
/// Deliver monitor event to both actor systems
#[macro_export]
macro_rules! deliver_event {
($maker:expr, $taker:expr, $event:expr) => {
tracing::debug!("Delivering event: {:?}", $event);
$taker.system.cfd_actor_addr.send($event).await.unwrap();
$maker.system.cfd_actor_addr.send($event).await.unwrap();
};
}
async fn in_memory_db() -> SqlitePool {

Loading…
Cancel
Save