Skip to content

chore: refactor test utils #72

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all 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
5 changes: 4 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ pub mod tasks;
/// Utilities.
pub mod utils;

/// Test utilitites
pub mod test_utils;

// Anonymous import suppresses warnings about unused imports.
use openssl as _;
use tracing_subscriber as _;
use tracing_subscriber as _;
45 changes: 6 additions & 39 deletions src/tasks/oauth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,54 +122,21 @@ impl Authenticator {
}

mod tests {
use crate::config::BuilderConfig;
use alloy::primitives::Address;
use eyre::Result;

#[ignore = "integration test"]
#[tokio::test]
async fn test_authenticator() -> Result<()> {
async fn test_authenticator() -> eyre::Result<()> {
use super::*;
use crate::test_utils::setup_test_config;
use oauth2::TokenResponse;

let config = setup_test_config()?;
let auth = Authenticator::new(&config);
let token = auth.fetch_oauth_token().await?;
dbg!(&token);

let _ = auth.fetch_oauth_token().await?;

let token = auth.token().await.unwrap();
println!("{:?}", token);

assert!(!token.access_token().secret().is_empty());
Ok(())
}

#[allow(dead_code)]
fn setup_test_config() -> Result<BuilderConfig> {
let config = BuilderConfig {
host_chain_id: 17000,
ru_chain_id: 17001,
host_rpc_url: "host-rpc.example.com".into(),
ru_rpc_url: "ru-rpc.example.com".into(),
zenith_address: Address::default(),
quincey_url: "http://localhost:8080".into(),
builder_port: 8080,
sequencer_key: None,
builder_key: "0000000000000000000000000000000000000000000000000000000000000000".into(),
block_confirmation_buffer: 1,
chain_offset: 0,
target_slot_time: 1,
builder_rewards_address: Address::default(),
rollup_block_gas_limit: 100_000,
tx_pool_url: "http://localhost:9000/".into(),
tx_pool_cache_duration: 5,
oauth_client_id: "some_client_id".into(),
oauth_client_secret: "some_client_secret".into(),
oauth_authenticate_url: "http://localhost:9000".into(),
oauth_token_url: "http://localhost:9000".into(),
tx_broadcast_urls: vec!["http://localhost:9000".into()],
oauth_token_refresh_interval: 300, // 5 minutes
builder_helper_address: Address::default(),
concurrency_limit: 1000,
};
Ok(config)
}
}
72 changes: 72 additions & 0 deletions src/test_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//! Test utilities for testing builder tasks
use crate::{config::BuilderConfig, tasks::block::PECORINO_CHAIN_ID};
use alloy::{
consensus::{SignableTransaction, TxEip1559, TxEnvelope},
primitives::{Address, TxKind, U256},
signers::{SignerSync, local::PrivateKeySigner},
};
use eyre::Result;
use std::str::FromStr;
use tracing_subscriber::{EnvFilter, Layer, layer::SubscriberExt, util::SubscriberInitExt};

/// Sets up a block builder with test values
pub fn setup_test_config() -> Result<BuilderConfig> {
let config = BuilderConfig {
host_chain_id: 17000,
ru_chain_id: 17001,
host_rpc_url: "host-rpc.example.com".into(),
ru_rpc_url: "ru-rpc.example.com".into(),
tx_broadcast_urls: vec!["http://localhost:9000".into()],
zenith_address: Address::default(),
quincey_url: "http://localhost:8080".into(),
builder_port: 8080,
sequencer_key: None,
builder_key: "0000000000000000000000000000000000000000000000000000000000000000".into(),
block_confirmation_buffer: 1,
chain_offset: 0,
target_slot_time: 1,
builder_rewards_address: Address::default(),
rollup_block_gas_limit: 100_000,
tx_pool_url: "http://localhost:9000/".into(),
tx_pool_cache_duration: 5,
oauth_client_id: "some_client_id".into(),
oauth_client_secret: "some_client_secret".into(),
oauth_authenticate_url: "http://localhost:8080".into(),
oauth_token_url: "http://localhost:8080".into(),
oauth_token_refresh_interval: 300, // 5 minutes
builder_helper_address: Address::default(),
concurrency_limit: 1000,
start_timestamp: 1740681556, // pecorino start timestamp as sane default
};
Ok(config)
}

/// Returns a new signed test transaction with the provided nonce, value, and mpfpg.
pub fn new_signed_tx(
wallet: &PrivateKeySigner,
nonce: u64,
value: U256,
mpfpg: u128,
) -> Result<TxEnvelope> {
let tx = TxEip1559 {
chain_id: PECORINO_CHAIN_ID,
nonce,
max_fee_per_gas: 50_000,
max_priority_fee_per_gas: mpfpg,
to: TxKind::Call(Address::from_str("0x0000000000000000000000000000000000000000").unwrap()),
value,
gas_limit: 50_000,
..Default::default()
};
let signature = wallet.sign_hash_sync(&tx.signature_hash())?;
Ok(TxEnvelope::Eip1559(tx.into_signed(signature)))
}

/// Initializes a logger that prints during testing
pub fn setup_logging() {
// Initialize logging
let filter = EnvFilter::from_default_env();
let fmt = tracing_subscriber::fmt::layer().with_filter(filter);
let registry = tracing_subscriber::registry().with(fmt);
let _ = registry.try_init();
}
154 changes: 78 additions & 76 deletions tests/block_builder_test.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,30 @@
#[cfg(test)]
mod tests {
use alloy::{
consensus::{SignableTransaction, TxEip1559, TxEnvelope},
node_bindings::Anvil,
primitives::{Address, TxKind, U256},
providers::ProviderBuilder,
signers::{SignerSync, local::PrivateKeySigner},
node_bindings::Anvil, primitives::U256, providers::ProviderBuilder,
signers::local::PrivateKeySigner,
};
use builder::{
config::BuilderConfig,
tasks::{
block::{BlockBuilder, PECORINO_CHAIN_ID},
oauth::Authenticator,
},
tasks::block::{BlockBuilder, PECORINO_CHAIN_ID},
test_utils::{new_signed_tx, setup_logging, setup_test_config},
};
use eyre::Result;

use signet_sim::{SimCache, SimItem};
use std::str::FromStr;
use tracing_subscriber::{EnvFilter, Layer, layer::SubscriberExt, util::SubscriberInitExt};
use signet_types::SlotCalculator;
use std::{
sync::Arc,
time::{Duration, Instant, SystemTime, UNIX_EPOCH},
};
use tokio::{sync::mpsc::unbounded_channel, time::timeout};

#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn test_spawn() {
let filter = EnvFilter::from_default_env();
let fmt = tracing_subscriber::fmt::layer().with_filter(filter);
let registry = tracing_subscriber::registry().with(fmt);
registry.try_init().unwrap();
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_handle_build() {
setup_logging();

// Make a test config
let config = setup_test_config();
let config = setup_test_config().unwrap();
let constants = config.load_pecorino_constants();

// Create an authenticator for bundle integration testing
let authenticator = Authenticator::new(&config);

// Create an anvil instance for testing
let anvil_instance = Anvil::new().chain_id(PECORINO_CHAIN_ID).spawn();

Expand All @@ -44,8 +36,14 @@ mod tests {
// Create a rollup provider
let ru_provider = ProviderBuilder::new().on_http(anvil_instance.endpoint_url());

// Create a block builder
let block_builder = BlockBuilder::new(&config, authenticator, ru_provider.clone());
// Create a block builder with a slot calculator for testing
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Clock may have gone backwards")
.as_secs();
dbg!(now);
let slot_calculator = SlotCalculator::new(now, 0, 12);
let block_builder = BlockBuilder::new(&config, ru_provider.clone(), slot_calculator);

// Setup a sim cache
let sim_items = SimCache::new();
Expand All @@ -57,64 +55,68 @@ mod tests {
let tx_2 = new_signed_tx(&test_key_1, 0, U256::from(2_f64), 10_000).unwrap();
sim_items.add_item(SimItem::Tx(tx_2));

let finish_by = Instant::now() + Duration::from_secs(2);

// Spawn the block builder task
let got = block_builder.handle_build(constants, ru_provider, sim_items).await;
let got = block_builder.handle_build(constants, sim_items, finish_by).await;

// Assert on the built block
assert!(got.is_ok());
assert!(got.unwrap().tx_count() == 2);
}

fn setup_test_config() -> BuilderConfig {
let config = BuilderConfig {
host_chain_id: 1,
ru_chain_id: PECORINO_CHAIN_ID,
host_rpc_url: "https://host-rpc.example.com".into(),
ru_rpc_url: "https://rpc.pecorino.signet.sh".into(),
zenith_address: Address::default(),
quincey_url: "http://localhost:8080".into(),
builder_port: 8080,
sequencer_key: None,
builder_key: "0000000000000000000000000000000000000000000000000000000000000000".into(),
block_confirmation_buffer: 1,
chain_offset: 0,
target_slot_time: 1,
builder_rewards_address: Address::default(),
rollup_block_gas_limit: 100_000_000,
tx_pool_url: "http://localhost:9000/".into(),
tx_pool_cache_duration: 5,
oauth_client_id: "some_client_id".into(),
oauth_client_secret: "some_client_secret".into(),
oauth_authenticate_url: "http://localhost:9000".into(),
oauth_token_url: "http://localhost:9000".into(),
tx_broadcast_urls: vec!["http://localhost:9000".into()],
oauth_token_refresh_interval: 300, // 5 minutes
builder_helper_address: Address::default(),
concurrency_limit: 1000,
};
config
}
/// Tests the full block builder loop
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_spawn() {
setup_logging();

// Make a test config
let config = setup_test_config().unwrap();
let constants = config.load_pecorino_constants();

// Create an anvil instance for testing
let anvil_instance = Anvil::new().chain_id(PECORINO_CHAIN_ID).spawn();

// Create a wallet
let keys = anvil_instance.keys();
let test_key_0 = PrivateKeySigner::from_signing_key(keys[0].clone().into());
let test_key_1 = PrivateKeySigner::from_signing_key(keys[1].clone().into());

// Plumb inputs for the test setup
let (tx_sender, tx_receiver) = unbounded_channel();
let (_, bundle_receiver) = unbounded_channel();
let (block_sender, mut block_receiver) = unbounded_channel();

// Create a rollup provider
let ru_provider = ProviderBuilder::new().on_http(anvil_instance.endpoint_url());

// Create a builder with a test slot calculator
let slot_calculator = SlotCalculator::new(
config.start_timestamp,
config.chain_offset,
config.target_slot_time,
);
let sim_cache = SimCache::new();
let builder = Arc::new(BlockBuilder::new(&config, ru_provider.clone(), slot_calculator));

// Create a sim cache and start filling it with items
let _ =
builder.clone().spawn_cache_handler(tx_receiver, bundle_receiver, sim_cache.clone());

// Finally, Kick off the block builder task.
let _ = builder.clone().spawn_builder_task(constants, sim_cache.clone(), block_sender);

let tx_1 = new_signed_tx(&test_key_0, 0, U256::from(1_f64), 11_000).unwrap();
let tx_2 = new_signed_tx(&test_key_1, 0, U256::from(2_f64), 10_000).unwrap();
tx_sender.send(tx_1).unwrap();
tx_sender.send(tx_2).unwrap();

// Returns a new signed test transaction with default values
fn new_signed_tx(
wallet: &PrivateKeySigner,
nonce: u64,
value: U256,
mpfpg: u128,
) -> Result<TxEnvelope> {
let tx = TxEip1559 {
chain_id: PECORINO_CHAIN_ID,
nonce,
max_fee_per_gas: 50_000,
max_priority_fee_per_gas: mpfpg,
to: TxKind::Call(
Address::from_str("0x0000000000000000000000000000000000000000").unwrap(),
),
value,
gas_limit: 50_000,
..Default::default()
};
let signature = wallet.sign_hash_sync(&tx.signature_hash())?;
Ok(TxEnvelope::Eip1559(tx.into_signed(signature)))
// Wait for a block with timeout
let result = timeout(Duration::from_secs(5), block_receiver.recv()).await;
assert!(result.is_ok(), "Did not receive block within 5 seconds");
let block = result.unwrap();
dbg!(&block);
assert!(block.is_some(), "Block channel closed without receiving a block");
assert!(block.unwrap().tx_count() == 2); // TODO: Why is this failing? I'm seeing EVM errors but haven't tracked them down yet.
}
}
40 changes: 4 additions & 36 deletions tests/bundle_poller_test.rs
Original file line number Diff line number Diff line change
@@ -1,49 +1,17 @@
mod tests {
use alloy::primitives::Address;
use builder::{config::BuilderConfig, tasks::oauth::Authenticator};
use builder::{tasks::oauth::Authenticator, test_utils};
use eyre::Result;

#[ignore = "integration test"]
#[tokio::test]
async fn test_bundle_poller_roundtrip() -> Result<()> {
let config = setup_test_config().await.unwrap();
let config = test_utils::setup_test_config().unwrap();
let auth = Authenticator::new(&config);

let mut bundle_poller = builder::tasks::bundler::BundlePoller::new(&config, auth);

let got = bundle_poller.check_bundle_cache().await?;
dbg!(got);
let _ = bundle_poller.check_bundle_cache().await?;

Ok(())
}

async fn setup_test_config() -> Result<BuilderConfig> {
let config = BuilderConfig {
host_chain_id: 17000,
ru_chain_id: 17001,
host_rpc_url: "host-rpc.example.com".into(),
ru_rpc_url: "ru-rpc.example.com".into(),
zenith_address: Address::default(),
quincey_url: "http://localhost:8080".into(),
builder_port: 8080,
sequencer_key: None,
builder_key: "0000000000000000000000000000000000000000000000000000000000000000".into(),
block_confirmation_buffer: 1,
chain_offset: 0,
target_slot_time: 1,
builder_rewards_address: Address::default(),
rollup_block_gas_limit: 100_000,
tx_pool_url: "http://localhost:9000/".into(),
// tx_pool_url: "https://transactions.holesky.signet.sh".into(),
tx_pool_cache_duration: 5,
oauth_client_id: "some_client_id".into(),
oauth_client_secret: "some_client_secret".into(),
oauth_authenticate_url: "http://localhost:8080".into(),
oauth_token_url: "http://localhost:8080".into(),
tx_broadcast_urls: vec!["http://localhost:9000".into()],
oauth_token_refresh_interval: 300, // 5 minutes
builder_helper_address: Address::default(),
concurrency_limit: 1000,
};
Ok(config)
}
}
Loading
Loading