Skip to content

Commit 5761a0d

Browse files
committed
Add tests
1 parent 1193cbc commit 5761a0d

File tree

3 files changed

+187
-71
lines changed

3 files changed

+187
-71
lines changed

tests/bitcoin.rs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
use std::time::Duration;
2+
3+
use anyhow::bail;
4+
use async_trait::async_trait;
5+
use bitcoincore_rpc::{json::IndexStatus, RpcApi};
6+
use citrea_e2e::{
7+
config::{BitcoinConfig, TestCaseConfig},
8+
framework::TestFramework,
9+
test_case::{TestCase, TestCaseRunner},
10+
traits::Restart,
11+
Result,
12+
};
13+
14+
struct BasicSyncTest;
15+
16+
#[async_trait]
17+
impl TestCase for BasicSyncTest {
18+
fn test_config() -> TestCaseConfig {
19+
TestCaseConfig {
20+
with_sequencer: false,
21+
n_nodes: 2,
22+
timeout: Duration::from_secs(60),
23+
..Default::default()
24+
}
25+
}
26+
27+
async fn run_test(&mut self, f: &mut TestFramework) -> Result<()> {
28+
let (Some(da0), Some(da1)) = (f.bitcoin_nodes.get(0), f.bitcoin_nodes.get(1)) else {
29+
bail!("bitcoind not running. Test should run with two da nodes")
30+
};
31+
let initial_height = f.initial_da_height;
32+
33+
// Generate some blocks on node0
34+
da0.generate(5, None).await?;
35+
36+
let height0 = da0.get_block_count().await?;
37+
let height1 = da1.get_block_count().await?;
38+
39+
// Nodes are now out of sync
40+
assert_eq!(height0, initial_height + 5);
41+
assert_eq!(height1, 0);
42+
43+
// Sync both nodes
44+
f.bitcoin_nodes
45+
.wait_for_sync(Some(Duration::from_secs(30)))
46+
.await?;
47+
48+
let height0 = da0.get_block_count().await?;
49+
let height1 = da1.get_block_count().await?;
50+
51+
// Assert that nodes are in sync
52+
assert_eq!(height0, height1, "Block heights don't match");
53+
54+
Ok(())
55+
}
56+
}
57+
58+
#[tokio::test]
59+
async fn test_basic_sync() -> Result<()> {
60+
TestCaseRunner::new(BasicSyncTest).run().await
61+
}
62+
63+
struct RestartBitcoinTest;
64+
65+
#[async_trait]
66+
impl TestCase for RestartBitcoinTest {
67+
fn test_config() -> TestCaseConfig {
68+
TestCaseConfig {
69+
with_sequencer: false,
70+
..Default::default()
71+
}
72+
}
73+
74+
fn bitcoin_config() -> BitcoinConfig {
75+
BitcoinConfig {
76+
extra_args: vec!["-txindex=0"],
77+
..Default::default()
78+
}
79+
}
80+
81+
async fn run_test(&mut self, f: &mut TestFramework) -> Result<()> {
82+
let da = f.bitcoin_nodes.get_mut(0).unwrap();
83+
// Add txindex flag to check that restart takes into account the extra args
84+
let new_conf = BitcoinConfig {
85+
extra_args: vec!["-txindex=1"],
86+
..da.config.clone()
87+
};
88+
89+
let block_before = da.get_block_count().await?;
90+
let info = da.get_index_info().await?;
91+
92+
assert_eq!(info.txindex, None);
93+
94+
// Restart node with txindex
95+
da.restart(Some(new_conf)).await?;
96+
97+
let block_after = da.get_block_count().await?;
98+
let info = da.get_index_info().await?;
99+
100+
assert!(matches!(
101+
info.txindex,
102+
Some(IndexStatus { synced: true, .. })
103+
));
104+
// Assert that state is kept between restarts
105+
assert_eq!(block_before, block_after);
106+
107+
Ok(())
108+
}
109+
}
110+
111+
#[tokio::test]
112+
async fn test_restart_bitcoin() -> Result<()> {
113+
TestCaseRunner::new(RestartBitcoinTest).run().await
114+
}

tests/docker.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use async_trait::async_trait;
2+
use bitcoincore_rpc::RpcApi;
3+
use citrea_e2e::{
4+
bitcoin::FINALITY_DEPTH,
5+
config::{TestCaseConfig, TestCaseDockerConfig},
6+
framework::TestFramework,
7+
test_case::{TestCase, TestCaseRunner},
8+
Result,
9+
};
10+
11+
struct DockerIntegrationTest;
12+
13+
#[async_trait]
14+
impl TestCase for DockerIntegrationTest {
15+
fn test_config() -> TestCaseConfig {
16+
TestCaseConfig {
17+
with_batch_prover: true,
18+
with_full_node: true,
19+
docker: TestCaseDockerConfig {
20+
bitcoin: true,
21+
citrea: true,
22+
},
23+
..Default::default()
24+
}
25+
}
26+
27+
async fn run_test(&mut self, f: &mut TestFramework) -> Result<()> {
28+
let sequencer = f.sequencer.as_ref().unwrap();
29+
let batch_prover = f.batch_prover.as_ref().unwrap();
30+
let full_node = f.full_node.as_ref().unwrap();
31+
let da = f.bitcoin_nodes.get(0).unwrap();
32+
33+
let min_soft_confirmations_per_commitment =
34+
sequencer.min_soft_confirmations_per_commitment();
35+
36+
for _ in 0..min_soft_confirmations_per_commitment {
37+
sequencer.client.send_publish_batch_request().await?;
38+
}
39+
40+
// Wait for blob inscribe tx to be in mempool
41+
da.wait_mempool_len(1, None).await?;
42+
43+
da.generate(FINALITY_DEPTH, None).await?;
44+
let finalized_height = da.get_finalized_height().await?;
45+
46+
batch_prover
47+
.wait_for_l1_height(finalized_height, None)
48+
.await?;
49+
50+
let commitments = full_node
51+
.wait_for_sequencer_commitments(finalized_height, None)
52+
.await?;
53+
54+
assert_eq!(commitments.len(), 1);
55+
56+
let unspent_sequencer = sequencer
57+
.da
58+
.list_unspent(None, None, None, None, None)
59+
.await?;
60+
let unspent_da = da.list_unspent(None, None, None, None, None).await?;
61+
// Make sure sequencer.da and da don't hit the same wallet
62+
assert_ne!(unspent_sequencer, unspent_da);
63+
64+
Ok(())
65+
}
66+
}
67+
68+
#[tokio::test]
69+
async fn test_docker_integration() -> Result<()> {
70+
TestCaseRunner::new(DockerIntegrationTest).run().await
71+
}

tests/mod.rs

Lines changed: 2 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,2 @@
1-
use async_trait::async_trait;
2-
use bitcoincore_rpc::RpcApi;
3-
use citrea_e2e::{
4-
bitcoin::FINALITY_DEPTH,
5-
config::{TestCaseConfig, TestCaseDockerConfig},
6-
framework::TestFramework,
7-
test_case::{TestCase, TestCaseRunner},
8-
Result,
9-
};
10-
11-
struct DockerIntegrationTest;
12-
13-
#[async_trait]
14-
impl TestCase for DockerIntegrationTest {
15-
fn test_config() -> TestCaseConfig {
16-
TestCaseConfig {
17-
with_batch_prover: true,
18-
with_full_node: true,
19-
docker: TestCaseDockerConfig {
20-
bitcoin: true,
21-
citrea: true,
22-
},
23-
..Default::default()
24-
}
25-
}
26-
27-
async fn run_test(&mut self, f: &mut TestFramework) -> Result<()> {
28-
let sequencer = f.sequencer.as_ref().unwrap();
29-
let batch_prover = f.batch_prover.as_ref().unwrap();
30-
let full_node = f.full_node.as_ref().unwrap();
31-
let da = f.bitcoin_nodes.get(0).unwrap();
32-
33-
let min_soft_confirmations_per_commitment =
34-
sequencer.min_soft_confirmations_per_commitment();
35-
36-
for _ in 0..min_soft_confirmations_per_commitment {
37-
sequencer.client.send_publish_batch_request().await?;
38-
}
39-
40-
// Wait for blob inscribe tx to be in mempool
41-
da.wait_mempool_len(1, None).await?;
42-
43-
da.generate(FINALITY_DEPTH, None).await?;
44-
let finalized_height = da.get_finalized_height().await?;
45-
46-
batch_prover
47-
.wait_for_l1_height(finalized_height, None)
48-
.await?;
49-
50-
let commitments = full_node
51-
.wait_for_sequencer_commitments(finalized_height, None)
52-
.await?;
53-
54-
assert_eq!(commitments.len(), 1);
55-
56-
let unspent_sequencer = sequencer
57-
.da
58-
.list_unspent(None, None, None, None, None)
59-
.await?;
60-
let unspent_da = da.list_unspent(None, None, None, None, None).await?;
61-
// Make sure sequencer.da and da don't hit the same wallet
62-
assert_ne!(unspent_sequencer, unspent_da);
63-
64-
Ok(())
65-
}
66-
}
67-
68-
#[tokio::test]
69-
async fn test_docker_integration() -> Result<()> {
70-
TestCaseRunner::new(DockerIntegrationTest).run().await
71-
}
1+
mod bitcoin;
2+
mod docker;

0 commit comments

Comments
 (0)