Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(composer): add missing blackbox tests #1834

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
645 changes: 0 additions & 645 deletions crates/astria-composer/src/executor/tests.rs

This file was deleted.

4 changes: 2 additions & 2 deletions crates/astria-composer/tests/blackbox/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ async fn readyz_with_one_rollup() {
// spawn_composer hits `/readyz` as part of starting the test
// environment. If this future return then `readyz` must have
// returned `status: ok`.
let _test_composer = spawn_composer(&["test1"]).await;
let _test_composer = spawn_composer(&["test1"], None, true).await;
}

#[tokio::test]
async fn readyz_with_two_rollups() {
// spawn_composer hits `/readyz` as part of starting the test
// environment. If this future return then `readyz` must have
// returned `status: ok`.
let _test_composer = spawn_composer(&["test1", "test2"]).await;
let _test_composer = spawn_composer(&["test1", "test2"], None, true).await;
}
224 changes: 224 additions & 0 deletions crates/astria-composer/tests/blackbox/executor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
use std::time::Duration;

use astria_core::{
generated::composer::v1::{
grpc_collector_service_client::GrpcCollectorServiceClient,
SubmitRollupTransactionRequest,
},
primitive::v1::{
RollupId,
ROLLUP_ID_LEN,
},
protocol::transaction::v1::action::RollupDataSubmission,
};
use tokio::time;

use crate::helper::{
mount_broadcast_tx_sync_rollup_data_submissions_mock,
signed_tx_from_request,
spawn_composer,
};

/// Test to check that the executor sends a signed transaction to the sequencer after its
/// `block_timer` has ticked
#[tokio::test]
async fn bundle_triggered_by_block_timer() {
let test_composer = spawn_composer(&["test1"], None, true).await;
let mut composer_client = GrpcCollectorServiceClient::connect(format!(
"http://{}",
test_composer.grpc_collector_addr
))
.await
.unwrap();

let response_guard =
mount_broadcast_tx_sync_rollup_data_submissions_mock(&test_composer.sequencer).await;

// send two sequence actions to the executor, both small enough to fit in a single bundle
// without filling it
let rollup_id = RollupId::new([0; ROLLUP_ID_LEN]);
let data = vec![0u8; 1000];

let seq0 = RollupDataSubmission {
data: data.clone().into(),
rollup_id,
fee_asset: "nria".parse().unwrap(),
};

// make sure at least one block has passed so that the executor will submit the bundle
// despite it not being full
time::pause();
time::timeout(Duration::from_millis(1000), async {
composer_client
.submit_rollup_transaction(SubmitRollupTransactionRequest {
rollup_id: Some(rollup_id.into_raw()),
data: data.into(),
})
.await
.expect("rollup transactions should have been submitted successfully to grpc collector")
})
.await
.unwrap();
time::advance(Duration::from_millis(2000)).await;
time::resume();

// wait for the mock sequencer to receive the signed transaction
tokio::time::timeout(
Duration::from_millis(100),
response_guard.wait_until_satisfied(),
)
.await
.unwrap();

// verify only one signed transaction was received by the mock sequencer
let expected_rollup_data_submissions = [seq0];
let requests = response_guard.received_requests().await;
assert_eq!(requests.len(), 1);

// verify the expected sequence actions were received
let signed_tx = signed_tx_from_request(&requests[0]);
let actions = signed_tx.actions();

assert_eq!(
actions.len(),
expected_rollup_data_submissions.len(),
"received more than one action, one was supposed to fill the bundle"
);

for (action, expected_rollup_data_submission) in
actions.iter().zip(expected_rollup_data_submissions.iter())
{
let rollup_data_submission = action.as_rollup_data_submission().unwrap();
assert_eq!(
rollup_data_submission.rollup_id, expected_rollup_data_submission.rollup_id,
"chain id does not match. actual {:?} expected {:?}",
rollup_data_submission.rollup_id, expected_rollup_data_submission.rollup_id
);
assert_eq!(
rollup_data_submission.data, expected_rollup_data_submission.data,
"data does not match expected data for action with rollup_id {:?}",
rollup_data_submission.rollup_id,
);
}
}

/// Test to check that the executor sends a signed transaction with two sequence actions to the
/// sequencer.
#[tokio::test]
async fn two_rollup_data_submissions_single_bundle() {
let test_composer = spawn_composer(&["test1"], None, true).await;
let mut composer_client = GrpcCollectorServiceClient::connect(format!(
"http://{}",
test_composer.grpc_collector_addr
))
.await
.unwrap();

let response_guard =
mount_broadcast_tx_sync_rollup_data_submissions_mock(&test_composer.sequencer).await;

// send two sequence actions to the executor, both small enough to fit in a single bundle
// without filling it
let seq0 = RollupDataSubmission {
rollup_id: RollupId::new([0; ROLLUP_ID_LEN]),
data: vec![0u8; 1000].into(),
fee_asset: "nria".parse().unwrap(),
};

let seq1 = RollupDataSubmission {
rollup_id: RollupId::new([1; ROLLUP_ID_LEN]),
data: vec![1u8; 1000].into(),
fee_asset: "nria".parse().unwrap(),
};

// make sure at least one block has passed so that the executor will submit the bundle
// despite it not being full
time::pause();
time::timeout(Duration::from_millis(1000), async {
composer_client
.submit_rollup_transaction(SubmitRollupTransactionRequest {
rollup_id: Some(seq0.rollup_id.into_raw()),
data: seq0.data.clone(),
})
.await
.expect("rollup transactions should have been submitted successfully to grpc collector")
})
.await
.unwrap();
time::timeout(Duration::from_millis(1000), async {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sometimes times out, even when increasing the timeout time. Unsure as to if this is a problem with the test or something flaky about composer.

composer_client
.submit_rollup_transaction(SubmitRollupTransactionRequest {
rollup_id: Some(seq1.rollup_id.into_raw()),
data: seq1.data.clone(),
})
.await
.expect("rollup transactions should have been submitted successfully to grpc collector")
})
.await
.unwrap();
time::advance(Duration::from_millis(2000)).await;
time::resume();

// wait for the mock sequencer to receive the signed transaction
tokio::time::timeout(
Duration::from_millis(100),
response_guard.wait_until_satisfied(),
)
.await
.unwrap();

// verify only one signed transaction was received by the mock sequencer
let expected_rollup_data_submissions = [seq0, seq1];
let requests = response_guard.received_requests().await;
assert_eq!(requests.len(), 1);

// verify the expected sequence actions were received
let signed_tx = signed_tx_from_request(&requests[0]);
let actions = signed_tx.actions();

assert_eq!(
actions.len(),
expected_rollup_data_submissions.len(),
"received more than one action, one was supposed to fill the bundle"
);

for (action, expected_rollup_data_submission) in
actions.iter().zip(expected_rollup_data_submissions.iter())
{
let rollup_data_submission = action.as_rollup_data_submission().unwrap();
assert_eq!(
rollup_data_submission.rollup_id, expected_rollup_data_submission.rollup_id,
"chain id does not match. actual {:?} expected {:?}",
rollup_data_submission.rollup_id, expected_rollup_data_submission.rollup_id
);
assert_eq!(
rollup_data_submission.data, expected_rollup_data_submission.data,
"data does not match expected data for action with rollup_id {:?}",
rollup_data_submission.rollup_id,
);
}
}

/// Test to check that executor's chain ID check is properly checked against the sequencer's chain
/// ID
#[tokio::test]
async fn chain_id_mismatch_returns_error() {
// TODO(https://github.com/astriaorg/astria/issues/1833): this test will currently succeed if
// the executor fails for any reason on startup, not just if the chain ID is incorrect. This is
// a symptom of the current implementation of executor, though, which should be propagating
// errors. As such, I think it is out of the scope for the following test-only changes and
// should be fixed in a followup.

let bad_chain_id = "bad_id";
let test_composer = spawn_composer(&["test1"], Some(bad_chain_id), false).await;
let err = test_composer.composer.await.unwrap().unwrap_err();
for cause in err.chain() {
if cause
.to_string()
.contains("executor failed while waiting for it to become ready")
{
return;
}
}
panic!("did not find expected executor error message")
}
14 changes: 7 additions & 7 deletions crates/astria-composer/tests/blackbox/geth_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::helper::{
async fn tx_from_one_rollup_is_received_by_sequencer() {
// Spawn a composer with a mock sequencer and a mock rollup node
// Initial nonce is 0
let test_composer = spawn_composer(&["test1"]).await;
let test_composer = spawn_composer(&["test1"], None, true).await;

let expected_rollup_ids = vec![RollupId::from_unhashed_bytes("test1")];
let mock_guard =
Expand All @@ -37,7 +37,7 @@ async fn tx_from_one_rollup_is_received_by_sequencer() {
async fn collector_restarts_after_exit() {
// Spawn a composer with a mock sequencer and a mock rollup node
// Initial nonce is 0
let test_composer = spawn_composer(&["test1"]).await;
let test_composer = spawn_composer(&["test1"], None, true).await;

// get rollup node
let rollup_node = test_composer.rollup_nodes.get("test1").unwrap();
Expand Down Expand Up @@ -71,7 +71,7 @@ async fn collector_restarts_after_exit() {
async fn invalid_nonce_causes_resubmission_under_different_nonce() {
// Spawn a composer with a mock sequencer and a mock rollup node
// Initial nonce is 0
let test_composer = spawn_composer(&["test1"]).await;
let test_composer = spawn_composer(&["test1"], None, true).await;

// Reject the first transaction for invalid nonce
let invalid_nonce_guard = mount_broadcast_tx_sync_invalid_nonce_mock(
Expand All @@ -88,7 +88,7 @@ async fn invalid_nonce_causes_resubmission_under_different_nonce() {
// Mount a response of 1 to a nonce query
test_composer
.sequencer_mock
.mount_pending_nonce_response(1, "setup correct nonce")
.mount_pending_nonce_response(1, "setup correct nonce", 1)
.await;

// Push a tx to the rollup node so that it is picked up by the composer and submitted with the
Expand Down Expand Up @@ -117,7 +117,7 @@ async fn invalid_nonce_causes_resubmission_under_different_nonce() {
async fn nonce_taken_causes_resubmission_under_different_nonce() {
// Spawn a composer with a mock sequencer and a mock rollup node
// Initial nonce is 0
let test_composer = spawn_composer(&["test1"]).await;
let test_composer = spawn_composer(&["test1"], None, true).await;

// Reject the first transaction for taken nonce
let invalid_nonce_guard = mount_broadcast_tx_sync_invalid_nonce_mock(
Expand All @@ -134,7 +134,7 @@ async fn nonce_taken_causes_resubmission_under_different_nonce() {
// Mount a response of 1 to a nonce query
test_composer
.sequencer_mock
.mount_pending_nonce_response(1, "setup correct nonce")
.mount_pending_nonce_response(1, "setup correct nonce", 1)
.await;

// Push a tx to the rollup node so that it is picked up by the composer and submitted with the
Expand Down Expand Up @@ -163,7 +163,7 @@ async fn nonce_taken_causes_resubmission_under_different_nonce() {
async fn single_rollup_tx_payload_integrity() {
// Spawn a composer with a mock sequencer and a mock rollup node
// Initial nonce is 0
let test_composer = spawn_composer(&["test1"]).await;
let test_composer = spawn_composer(&["test1"], None, true).await;

let tx: Transaction = serde_json::from_str(TEST_ETH_TX_JSON).unwrap();
let mock_guard =
Expand Down
8 changes: 4 additions & 4 deletions crates/astria-composer/tests/blackbox/grpc_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::helper::{

#[tokio::test]
async fn tx_from_one_rollup_is_received_by_sequencer() {
let test_composer = spawn_composer(&[]).await;
let test_composer = spawn_composer(&[], None, true).await;
let rollup_id = RollupId::from_unhashed_bytes("test1");
let expected_chain_ids = vec![rollup_id];
let mock_guard =
Expand Down Expand Up @@ -56,7 +56,7 @@ async fn invalid_nonce_causes_resubmission_under_different_nonce() {
// Spawn a composer with a mock sequencer and a mock rollup node
// Initial nonce is 0
let rollup_id = RollupId::from_unhashed_bytes("test1");
let test_composer = spawn_composer(&[]).await;
let test_composer = spawn_composer(&[], None, true).await;

// Reject the first transaction for invalid nonce
let invalid_nonce_guard =
Expand All @@ -65,7 +65,7 @@ async fn invalid_nonce_causes_resubmission_under_different_nonce() {
// Mount a response of 1 to a nonce query
test_composer
.sequencer_mock
.mount_pending_nonce_response(1, "setup correct nonce")
.mount_pending_nonce_response(1, "setup correct nonce", 1)
.await;

let expected_chain_ids = vec![rollup_id];
Expand Down Expand Up @@ -112,7 +112,7 @@ async fn single_rollup_tx_payload_integrity() {
// Spawn a composer with a mock sequencer and a mock rollup node
// Initial nonce is 0
let rollup_id = RollupId::from_unhashed_bytes("test1");
let test_composer = spawn_composer(&[]).await;
let test_composer = spawn_composer(&[], None, true).await;

let tx: Transaction = serde_json::from_str(TEST_ETH_TX_JSON).unwrap();
let mock_guard =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ use wiremock::{
ResponseTemplate,
};

pub async fn start() -> MockServer {
use super::TEST_CHAIN_ID;

pub async fn start(chain_id: Option<&str>) -> MockServer {
let server = MockServer::start().await;
mount_genesis(&server, "test-chain-1").await;
mount_genesis(&server, chain_id.unwrap_or(TEST_CHAIN_ID)).await;
server
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ impl MockGrpcSequencer {
&self,
nonce_to_mount: u32,
debug_name: impl Into<String>,
expected_requests: u64,
) {
let resp = GetPendingNonceResponse {
inner: nonce_to_mount,
Expand All @@ -86,7 +87,7 @@ impl MockGrpcSequencer {
)
.respond_with(constant_response(resp))
.up_to_n_times(1)
.expect(1)
.expect(expected_requests)
.with_name(debug_name)
.mount(&self.mock_server)
.await;
Expand Down
Loading
Loading