Skip to content

Commit 8bd94fb

Browse files
committed
Add integration tests for ipc-extractor
1 parent c0d6f7d commit 8bd94fb

1 file changed

Lines changed: 152 additions & 4 deletions

File tree

Lines changed: 152 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,156 @@
1-
use shared::tokio;
1+
#![cfg(feature = "nats_integration_tests")]
2+
#![cfg(feature = "node_integration_tests")]
3+
4+
use ipc_extractor::{self, Args};
5+
use shared::{
6+
async_nats,
7+
bitcoin::hex::DisplayHex,
8+
corepc_node,
9+
futures::StreamExt,
10+
log::{self, info},
11+
nats_util::NatsArgs,
12+
prost::Message,
13+
protobuf::{
14+
event::{Event, event::PeerObserverEvent},
15+
ipc_extractor::ipc::IpcEvent::BlockTip,
16+
},
17+
simple_logger::SimpleLogger,
18+
testing::nats_server::NatsServerForTesting,
19+
tokio::{self, sync::watch, task::LocalSet, time::sleep},
20+
};
21+
use std::sync::Once;
22+
use std::time::Duration;
23+
24+
pub const QUERY_INTERVAL_SECONDS: u64 = 1;
25+
26+
// 5 second check() timeout.
27+
const TEST_TIMEOUT_SECONDS: u64 = 5;
28+
29+
pub fn make_test_args(nats_port: u16, ipc_socket_path: String) -> Args {
30+
Args::new(
31+
NatsArgs {
32+
address: format!("127.0.0.1:{}", nats_port),
33+
username: None,
34+
password: None,
35+
password_file: None,
36+
},
37+
log::Level::Trace,
38+
ipc_socket_path,
39+
QUERY_INTERVAL_SECONDS,
40+
)
41+
}
42+
43+
static INIT: Once = Once::new();
44+
45+
pub fn setup() {
46+
INIT.call_once(|| {
47+
SimpleLogger::new()
48+
.with_level(log::LevelFilter::Trace)
49+
.init()
50+
.unwrap();
51+
});
52+
}
53+
54+
pub fn setup_node(conf: corepc_node::Conf) -> corepc_node::Node {
55+
info!(
56+
"env BITCOIN_NODE_EXE={:?}",
57+
std::env::var("BITCOIN_NODE_EXE")
58+
);
59+
let exe_path = std::env::var("BITCOIN_NODE_EXE").unwrap();
60+
61+
info!("Using bitcoin-node at '{}'", exe_path);
62+
corepc_node::Node::with_conf(exe_path, &conf).unwrap()
63+
}
64+
65+
fn configure_node() -> corepc_node::Node {
66+
let mut node_conf = corepc_node::Conf::default();
67+
node_conf.args = vec!["-regtest", "-ipcbind=unix"];
68+
// enabling this is useful for debugging, but enabling this by default will
69+
// be quite spammy.
70+
node_conf.view_stdout = false;
71+
// node_conf.wallet is `true` by default, but since `bitcoin-node` binary doesn't
72+
// have wallet capabilities we disable it
73+
node_conf.wallet = None;
74+
75+
setup_node(node_conf)
76+
}
77+
78+
async fn check(check_expected: fn(PeerObserverEvent) -> ()) {
79+
setup();
80+
let node = configure_node();
81+
let nats_server = NatsServerForTesting::new(&[]).await;
82+
83+
let ipc_socket_path = node
84+
.workdir()
85+
.as_path()
86+
.join("regtest")
87+
.join("node.sock")
88+
.to_str()
89+
.unwrap()
90+
.into();
91+
92+
let args = make_test_args(nats_server.port, ipc_socket_path);
93+
94+
let local = LocalSet::new();
95+
local
96+
.run_until(async move {
97+
let (shutdown_tx, shutdown_rx) = watch::channel(false);
98+
99+
let ipc_extractor_future = ipc_extractor::run(args, shutdown_rx.clone());
100+
tokio::pin!(ipc_extractor_future);
101+
102+
let nc = async_nats::connect(format!("127.0.0.1:{}", nats_server.port))
103+
.await
104+
.unwrap();
105+
let mut sub = nc.subscribe("*").await.unwrap();
106+
107+
tokio::select! {
108+
_ = sleep(Duration::from_secs(TEST_TIMEOUT_SECONDS)) => {
109+
panic!("timed out waiting for check() to complete");
110+
}
111+
msg = sub.next() => {
112+
if let Some(msg) = msg {
113+
let unwrapped = Event::decode(msg.payload).unwrap();
114+
if let Some(event) = unwrapped.peer_observer_event {
115+
check_expected(event);
116+
}
117+
} else {
118+
panic!("subscription ended");
119+
}
120+
}
121+
result = &mut ipc_extractor_future => {
122+
panic!("ipc_extractor stopped unexpectedly: {:?}", result);
123+
}
124+
}
125+
126+
shutdown_tx.send(true).unwrap();
127+
ipc_extractor_future.await.unwrap();
128+
})
129+
.await;
130+
}
2131

3132
#[tokio::test]
4-
async fn test_integration_ipc_foo() {
5-
println!("test that we receive foo IPC events");
133+
#[ignore] // ignored until we have a proper CI setup for running a `bitcoin-node` process
134+
async fn test_integration_ipc() {
135+
println!("test that we receive BlockTip IPC events");
6136

7-
assert_eq!(1, 1)
137+
check(|event| match event {
138+
PeerObserverEvent::IpcExtractor(i) => {
139+
if let Some(ref e) = i.ipc_event {
140+
match e {
141+
BlockTip(t) => {
142+
assert_eq!(t.height, 0);
143+
assert_eq!(t.hash.len(), 32);
144+
assert_eq!(
145+
t.hash.to_lower_hex_string(),
146+
// genesis blockhash in Regtest
147+
"0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"
148+
);
149+
}
150+
}
151+
}
152+
}
153+
_ => panic!("unexpected event {:?}", event),
154+
})
155+
.await;
8156
}

0 commit comments

Comments
 (0)