diff --git a/Cargo.lock b/Cargo.lock
index 11e29e1f..080a6a0b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -197,9 +197,9 @@ dependencies = [
[[package]]
name = "alloy-primitives"
-version = "0.8.8"
+version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38f35429a652765189c1c5092870d8360ee7b7769b09b06d89ebaefd34676446"
+checksum = "c71738eb20c42c5fb149571e76536a0f309d142f3957c28791662b96baf77a3d"
dependencies = [
"alloy-rlp",
"arbitrary",
@@ -282,7 +282,7 @@ checksum = "4d0f2d905ebd295e7effec65e5f6868d153936130ae718352771de3e7d03c75c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -396,23 +396,23 @@ dependencies = [
[[package]]
name = "alloy-sol-macro"
-version = "0.8.8"
+version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b2395336745358cc47207442127c47c63801a7065ecc0aa928da844f8bb5576"
+checksum = "b0900b83f4ee1f45c640ceee596afbc118051921b9438fdb5a3175c1a7e05f8b"
dependencies = [
"alloy-sol-macro-expander",
"alloy-sol-macro-input",
"proc-macro-error2",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
name = "alloy-sol-macro-expander"
-version = "0.8.8"
+version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ed5047c9a241df94327879c2b0729155b58b941eae7805a7ada2e19436e6b39"
+checksum = "a41b1e78dde06b5e12e6702fa8c1d30621bf07728ba75b801fb801c9c6a0ba10"
dependencies = [
"alloy-sol-macro-input",
"const-hex",
@@ -421,31 +421,31 @@ dependencies = [
"proc-macro-error2",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
"syn-solidity",
"tiny-keccak",
]
[[package]]
name = "alloy-sol-macro-input"
-version = "0.8.8"
+version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5dee02a81f529c415082235129f0df8b8e60aa1601b9c9298ffe54d75f57210b"
+checksum = "91dc311a561a306664393407b88d3e53ae58581624128afd8a15faa5de3627dc"
dependencies = [
"const-hex",
"dunce",
"heck",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
"syn-solidity",
]
[[package]]
name = "alloy-sol-types"
-version = "0.8.8"
+version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2841af22d99e2c0f82a78fe107b6481be3dd20b89bfb067290092794734343a"
+checksum = "086f41bc6ebcd8cb15f38ba20e47be38dd03692149681ce8061c35d960dbf850"
dependencies = [
"alloy-primitives",
"alloy-sol-macro",
@@ -733,7 +733,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -744,7 +744,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -771,7 +771,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -830,7 +830,7 @@ dependencies = [
"regex",
"rustc-hash 1.1.0",
"shlex",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -944,7 +944,7 @@ checksum = "523363cbe1df49b68215efdf500b103ac3b0fb4836aed6d15689a076eadb8fff"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -1108,7 +1108,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -1306,7 +1306,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -1317,7 +1317,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -1382,7 +1382,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -1403,7 +1403,7 @@ dependencies = [
"convert_case",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
"unicode-xid",
]
@@ -1496,7 +1496,7 @@ checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -1664,7 +1664,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -2216,7 +2216,7 @@ dependencies = [
"kona-common",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -2551,7 +2551,7 @@ checksum = "1bb5c1d8184f13f7d0ccbeeca0def2f9a181bce2624302793005f5ca8aa62e5e"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -2730,7 +2730,7 @@ checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -2848,7 +2848,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -2986,7 +2986,7 @@ checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -3130,7 +3130,7 @@ dependencies = [
"proc-macro-error-attr2",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -3210,7 +3210,7 @@ checksum = "6ff7ff745a347b87471d859a377a9a404361e7efc2a971d73424a6d183c0fc77"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -3236,7 +3236,7 @@ checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -3563,7 +3563,7 @@ checksum = "09cb82b74b4810f07e460852c32f522e979787691b0b7b7439fe473e49d49b2f"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -3867,14 +3867,14 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
name = "serde_json"
-version = "1.0.131"
+version = "1.0.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67d42a0bd4ac281beff598909bb56a86acaf979b84483e1c79c10dcaf98f8cf3"
+checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
dependencies = [
"indexmap 2.6.0",
"itoa",
@@ -3891,7 +3891,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -3933,7 +3933,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -4103,7 +4103,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -4161,9 +4161,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.79"
+version = "2.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
+checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021"
dependencies = [
"proc-macro2",
"quote",
@@ -4172,14 +4172,14 @@ dependencies = [
[[package]]
name = "syn-solidity"
-version = "0.8.8"
+version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebfc1bfd06acc78f16d8fd3ef846bc222ee7002468d10a7dce8d703d6eab89a3"
+checksum = "9d5e0c2ea8db64b2898b62ea2fbd60204ca95e0b2c6bdf53ff768bbe916fbe4d"
dependencies = [
"paste",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -4262,7 +4262,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -4272,7 +4272,7 @@ source = "git+https://github.com/quartiq/thiserror?branch=no-std#e779e1b70023cee
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -4385,7 +4385,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -4496,7 +4496,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -4712,7 +4712,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
"wasm-bindgen-shared",
]
@@ -4746,7 +4746,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -4969,7 +4969,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
[[package]]
@@ -4989,5 +4989,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.82",
]
diff --git a/crates/derive/src/stages/channel/channel_assembler.rs b/crates/derive/src/stages/channel/channel_assembler.rs
index 609ec7c7..2e48de48 100644
--- a/crates/derive/src/stages/channel/channel_assembler.rs
+++ b/crates/derive/src/stages/channel/channel_assembler.rs
@@ -200,7 +200,7 @@ mod test {
use super::ChannelAssembler;
use crate::{
prelude::PipelineError,
- stages::{frame_queue::tests::new_test_frames, ChannelReaderProvider},
+ stages::ChannelReaderProvider,
test_utils::{CollectingLayer, TestNextFrameProvider, TraceStorage},
};
use alloc::sync::Arc;
@@ -217,7 +217,10 @@ mod test {
let layer = CollectingLayer::new(trace_store.clone());
tracing_subscriber::Registry::default().with(layer).init();
- let frames = new_test_frames(2);
+ let frames = [
+ crate::frame!(0xFF, 0, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 1, vec![0xDD; 50], true),
+ ];
let mock = TestNextFrameProvider::new(frames.into_iter().rev().map(Ok).collect());
let cfg = Arc::new(RollupConfig::default());
let mut assembler = ChannelAssembler::new(cfg, mock);
@@ -255,7 +258,10 @@ mod test {
#[tokio::test]
async fn test_assembler_non_starting_frame() {
- let frames = new_test_frames(2);
+ let frames = [
+ crate::frame!(0xFF, 0, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 1, vec![0xDD; 50], true),
+ ];
let mock = TestNextFrameProvider::new(frames.into_iter().map(Ok).collect());
let cfg = Arc::new(RollupConfig::default());
let mut assembler = ChannelAssembler::new(cfg, mock);
@@ -273,7 +279,10 @@ mod test {
let layer = CollectingLayer::new(trace_store.clone());
tracing_subscriber::Registry::default().with(layer).init();
- let frames = new_test_frames(2);
+ let frames = [
+ crate::frame!(0xFF, 0, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 1, vec![0xDD; 50], true),
+ ];
let mock = TestNextFrameProvider::new(frames.clone().into_iter().rev().map(Ok).collect());
let cfg = Arc::new(RollupConfig::default());
let mut assembler = ChannelAssembler::new(cfg, mock);
@@ -308,7 +317,10 @@ mod test {
let layer = CollectingLayer::new(trace_store.clone());
tracing_subscriber::Registry::default().with(layer).init();
- let mut frames = new_test_frames(2);
+ let mut frames = [
+ crate::frame!(0xFF, 0, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 1, vec![0xDD; 50], true),
+ ];
frames[1].data = vec![0; MAX_RLP_BYTES_PER_CHANNEL_BEDROCK as usize];
let mock = TestNextFrameProvider::new(frames.into_iter().rev().map(Ok).collect());
let cfg = Arc::new(RollupConfig::default());
@@ -339,7 +351,10 @@ mod test {
let layer = CollectingLayer::new(trace_store.clone());
tracing_subscriber::Registry::default().with(layer).init();
- let mut frames = new_test_frames(2);
+ let mut frames = [
+ crate::frame!(0xFF, 0, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 1, vec![0xDD; 50], true),
+ ];
frames[1].data = vec![0; MAX_RLP_BYTES_PER_CHANNEL_FJORD as usize];
let mock = TestNextFrameProvider::new(frames.into_iter().rev().map(Ok).collect());
let cfg = Arc::new(RollupConfig { fjord_time: Some(0), ..Default::default() });
diff --git a/crates/derive/src/stages/channel/channel_bank.rs b/crates/derive/src/stages/channel/channel_bank.rs
index f2f4422f..7f2b05c6 100644
--- a/crates/derive/src/stages/channel/channel_bank.rs
+++ b/crates/derive/src/stages/channel/channel_bank.rs
@@ -276,7 +276,6 @@ where
mod tests {
use super::*;
use crate::{
- stages::frame_queue::tests::new_test_frames,
test_utils::{CollectingLayer, TestNextFrameProvider, TraceStorage},
traits::ResetSignal,
};
@@ -287,7 +286,7 @@ mod tests {
#[test]
fn test_channel_bank_into_prev() {
- let frames = new_test_frames(1);
+ let frames = [crate::frame!(0xFF, 0, vec![0xDD; 50], true)];
let mock = TestNextFrameProvider::new(frames.into_iter().map(Ok).collect());
let cfg = Arc::new(RollupConfig::default());
let channel_bank = ChannelBank::new(cfg, mock);
@@ -485,8 +484,7 @@ mod tests {
#[test]
fn test_ingest_and_prune_channel_bank() {
- use alloc::vec::Vec;
- let mut frames: Vec = new_test_frames(100000);
+ let mut frames = crate::frames!(0xFF, 0, vec![0xDD; 50], 100000);
let mock = TestNextFrameProvider::new(vec![]);
let cfg = Arc::new(RollupConfig::default());
let mut channel_bank = ChannelBank::new(cfg, mock);
@@ -511,8 +509,7 @@ mod tests {
#[test]
fn test_ingest_and_prune_channel_bank_fjord() {
- use alloc::vec::Vec;
- let mut frames: Vec = new_test_frames(100000);
+ let mut frames = crate::frames!(0xFF, 0, vec![0xDD; 50], 100000);
let mock = TestNextFrameProvider::new(vec![]);
let cfg = Arc::new(RollupConfig { fjord_time: Some(0), ..Default::default() });
let mut channel_bank = ChannelBank::new(cfg, mock);
@@ -537,7 +534,7 @@ mod tests {
#[tokio::test]
async fn test_read_empty_channel_bank() {
- let frames = new_test_frames(1);
+ let frames = [crate::frame!(0xFF, 0, vec![0xDD; 50], true)];
let mock = TestNextFrameProvider::new(vec![Ok(frames[0].clone())]);
let cfg = Arc::new(RollupConfig::default());
let mut channel_bank = ChannelBank::new(cfg, mock);
@@ -556,7 +553,10 @@ mod tests {
const ROLLUP_CONFIGS: [RollupConfig; 2] = [OP_MAINNET_CONFIG, BASE_MAINNET_CONFIG];
for cfg in ROLLUP_CONFIGS {
- let frames = new_test_frames(2);
+ let frames = [
+ crate::frame!(0xFF, 0, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 1, vec![0xDD; 50], true),
+ ];
let mock = TestNextFrameProvider::new(frames.into_iter().map(Ok).collect::>());
let cfg = Arc::new(cfg);
let mut channel_bank = ChannelBank::new(cfg.clone(), mock);
diff --git a/crates/derive/src/stages/channel/channel_provider.rs b/crates/derive/src/stages/channel/channel_provider.rs
index c51f68d4..6d6ad94b 100644
--- a/crates/derive/src/stages/channel/channel_provider.rs
+++ b/crates/derive/src/stages/channel/channel_provider.rs
@@ -31,7 +31,7 @@ mod test {
use super::{ActiveStage, ChannelProvider};
use crate::{
prelude::{OriginProvider, PipelineError},
- stages::{frame_queue::tests::new_test_frames, ChannelReaderProvider},
+ stages::ChannelReaderProvider,
test_utils::TestNextFrameProvider,
traits::{ResetSignal, SignalReceiver},
};
@@ -153,7 +153,10 @@ mod test {
#[tokio::test]
async fn test_channel_provider_reset_bank() {
- let frames = new_test_frames(2);
+ let frames = [
+ crate::frame!(0xFF, 0, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 1, vec![0xDD; 50], true),
+ ];
let provider = TestNextFrameProvider::new(frames.into_iter().rev().map(Ok).collect());
let cfg = Arc::new(RollupConfig::default());
let mut channel_provider = ChannelProvider::new(cfg.clone(), provider);
@@ -181,7 +184,10 @@ mod test {
#[tokio::test]
async fn test_channel_provider_reset_assembler() {
- let frames = new_test_frames(2);
+ let frames = [
+ crate::frame!(0xFF, 0, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 1, vec![0xDD; 50], true),
+ ];
let provider = TestNextFrameProvider::new(frames.into_iter().rev().map(Ok).collect());
let cfg = Arc::new(RollupConfig { holocene_time: Some(0), ..Default::default() });
let mut channel_provider = ChannelProvider::new(cfg.clone(), provider);
diff --git a/crates/derive/src/stages/frame_queue.rs b/crates/derive/src/stages/frame_queue.rs
index 23b358c7..945dedcd 100644
--- a/crates/derive/src/stages/frame_queue.rs
+++ b/crates/derive/src/stages/frame_queue.rs
@@ -199,33 +199,7 @@ where
pub(crate) mod tests {
use super::*;
use crate::{test_utils::TestFrameQueueProvider, traits::ResetSignal};
- use alloc::{vec, vec::Vec};
- use op_alloy_protocol::DERIVATION_VERSION_0;
-
- pub(crate) fn new_test_frames(count: usize) -> Vec {
- (0..count)
- .map(|i| Frame {
- id: [0xFF; 16],
- number: i as u16,
- data: vec![0xDD; 50],
- is_last: i == count - 1,
- })
- .collect()
- }
-
- pub(crate) fn encode_frames(frames: Vec) -> Bytes {
- let mut bytes = Vec::new();
- bytes.extend_from_slice(&[DERIVATION_VERSION_0]);
- for frame in frames.iter() {
- bytes.extend_from_slice(&frame.encode());
- }
- Bytes::from(bytes)
- }
-
- pub(crate) fn new_encoded_test_frames(count: usize) -> Bytes {
- let frames = new_test_frames(count);
- encode_frames(frames)
- }
+ use alloc::vec;
#[tokio::test]
async fn test_frame_queue_reset() {
@@ -261,321 +235,271 @@ pub(crate) mod tests {
#[tokio::test]
async fn test_frame_queue_wrong_derivation_version() {
- let data = vec![Ok(Bytes::from(vec![0x01]))];
- let mut mock = TestFrameQueueProvider::new(data);
- mock.set_origin(BlockInfo::default());
- let mut frame_queue = FrameQueue::new(mock, Default::default());
- assert!(!frame_queue.is_holocene_active(BlockInfo::default()));
- let err = frame_queue.next_frame().await.unwrap_err();
- assert_eq!(err, PipelineError::NotEnoughData.temp());
+ let assert = crate::test_utils::FrameQueueBuilder::new()
+ .with_origin(BlockInfo::default())
+ .with_raw_frames(Bytes::from(vec![0x01]))
+ .with_expected_err(PipelineError::NotEnoughData.temp())
+ .build();
+ assert.holocene_active(false);
+ assert.next_frames().await;
}
#[tokio::test]
async fn test_frame_queue_frame_too_short() {
- let data = vec![Ok(Bytes::from(vec![0x00, 0x01]))];
- let mut mock = TestFrameQueueProvider::new(data);
- mock.set_origin(BlockInfo::default());
- let mut frame_queue = FrameQueue::new(mock, Default::default());
- assert!(!frame_queue.is_holocene_active(BlockInfo::default()));
- let err = frame_queue.next_frame().await.unwrap_err();
- assert_eq!(err, PipelineError::NotEnoughData.temp());
+ let assert = crate::test_utils::FrameQueueBuilder::new()
+ .with_origin(BlockInfo::default())
+ .with_raw_frames(Bytes::from(vec![0x00, 0x01]))
+ .with_expected_err(PipelineError::NotEnoughData.temp())
+ .build();
+ assert.holocene_active(false);
+ assert.next_frames().await;
}
#[tokio::test]
async fn test_frame_queue_single_frame() {
- let data = new_encoded_test_frames(1);
- let mut mock = TestFrameQueueProvider::new(vec![Ok(data)]);
- mock.set_origin(BlockInfo::default());
- let mut frame_queue = FrameQueue::new(mock, Default::default());
- assert!(!frame_queue.is_holocene_active(BlockInfo::default()));
- let frame_decoded = frame_queue.next_frame().await.unwrap();
- let frame = new_test_frames(1);
- assert_eq!(frame[0], frame_decoded);
- let err = frame_queue.next_frame().await.unwrap_err();
- assert_eq!(err, PipelineError::Eof.temp());
+ let frames = [crate::frame!(0xFF, 0, vec![0xDD; 50], true)];
+ let assert = crate::test_utils::FrameQueueBuilder::new()
+ .with_expected_frames(&frames)
+ .with_origin(BlockInfo::default())
+ .with_frames(&frames)
+ .build();
+ assert.holocene_active(false);
+ assert.next_frames().await;
}
#[tokio::test]
async fn test_frame_queue_multiple_frames() {
- let data = new_encoded_test_frames(3);
- let mut mock = TestFrameQueueProvider::new(vec![Ok(data)]);
- mock.set_origin(BlockInfo::default());
- let mut frame_queue = FrameQueue::new(mock, Default::default());
- assert!(!frame_queue.is_holocene_active(BlockInfo::default()));
- for i in 0..3 {
- let frame_decoded = frame_queue.next_frame().await.unwrap();
- assert_eq!(frame_decoded.number, i);
- }
- let err = frame_queue.next_frame().await.unwrap_err();
- assert_eq!(err, PipelineError::Eof.temp());
+ let frames = [
+ crate::frame!(0xFF, 0, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 1, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 2, vec![0xDD; 50], true),
+ ];
+ let assert = crate::test_utils::FrameQueueBuilder::new()
+ .with_expected_frames(&frames)
+ .with_origin(BlockInfo::default())
+ .with_frames(&frames)
+ .build();
+ assert.holocene_active(false);
+ assert.next_frames().await;
}
#[tokio::test]
async fn test_frame_queue_missing_origin() {
- let data = new_encoded_test_frames(1);
- let mock = TestFrameQueueProvider::new(vec![Ok(data)]);
- let mut frame_queue = FrameQueue::new(mock, Default::default());
- let err = frame_queue.next_frame().await.unwrap_err();
- assert_eq!(err, PipelineError::MissingOrigin.crit());
+ let frames = [crate::frame!(0xFF, 0, vec![0xDD; 50], true)];
+ let assert = crate::test_utils::FrameQueueBuilder::new()
+ .with_expected_frames(&frames)
+ .with_frames(&frames)
+ .build();
+ assert.holocene_active(false);
+ assert.missing_origin().await;
}
#[tokio::test]
async fn test_holocene_valid_frames() {
- let channel = new_encoded_test_frames(3);
- let config = RollupConfig { holocene_time: Some(0), ..Default::default() };
- let mut mock = TestFrameQueueProvider::new(vec![Ok(channel)]);
- mock.set_origin(BlockInfo::default());
- let mut frame_queue = FrameQueue::new(mock, Arc::new(config));
- assert!(frame_queue.is_holocene_active(BlockInfo::default()));
- for i in 0..3 {
- let frame_decoded = frame_queue.next_frame().await.unwrap();
- assert_eq!(frame_decoded.number, i);
- }
- let err = frame_queue.next_frame().await.unwrap_err();
- assert_eq!(err, PipelineError::Eof.temp());
+ let frames = [
+ crate::frame!(0xFF, 0, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 1, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 2, vec![0xDD; 50], true),
+ ];
+ let assert = crate::test_utils::FrameQueueBuilder::new()
+ .with_rollup_config(&RollupConfig { holocene_time: Some(0), ..Default::default() })
+ .with_origin(BlockInfo::default())
+ .with_expected_frames(&frames)
+ .with_frames(&frames)
+ .build();
+ assert.holocene_active(true);
+ assert.next_frames().await;
}
#[tokio::test]
- async fn test_holocene_single_invalid_frame() {
- let frames = vec![Frame { id: [0xEE; 16], number: 1, data: vec![0xDD; 50], is_last: true }];
- let encoded = encode_frames(frames.clone());
- let config = RollupConfig { holocene_time: Some(0), ..Default::default() };
- let mut mock = TestFrameQueueProvider::new(vec![Ok(encoded)]);
- mock.set_origin(BlockInfo::default());
- let mut frame_queue = FrameQueue::new(mock, Arc::new(config));
- assert!(frame_queue.is_holocene_active(BlockInfo::default()));
- let decoded = frame_queue.next_frame().await.unwrap();
- assert_eq!(decoded, frames[0]);
- let err = frame_queue.next_frame().await.unwrap_err();
- assert_eq!(err, PipelineError::Eof.temp());
+ async fn test_holocene_single_frame() {
+ let frames = [crate::frame!(0xFF, 1, vec![0xDD; 50], true)];
+ let assert = crate::test_utils::FrameQueueBuilder::new()
+ .with_rollup_config(&RollupConfig { holocene_time: Some(0), ..Default::default() })
+ .with_origin(BlockInfo::default())
+ .with_expected_frames(&frames)
+ .with_frames(&frames)
+ .build();
+ assert.holocene_active(true);
+ assert.next_frames().await;
}
#[tokio::test]
async fn test_holocene_unordered_frames() {
- let frames = vec![
+ let frames = [
// -- First Channel --
- Frame { id: [0xEE; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xEE; 16], number: 1, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xEE; 16], number: 2, data: vec![0xDD; 50], is_last: true },
- // Frame with the same channel id, but after is_last should be dropped.
- Frame { id: [0xEE; 16], number: 3, data: vec![0xDD; 50], is_last: false },
+ crate::frame!(0xEE, 0, vec![0xDD; 50], false),
+ crate::frame!(0xEE, 1, vec![0xDD; 50], false),
+ crate::frame!(0xEE, 2, vec![0xDD; 50], true),
+ crate::frame!(0xEE, 3, vec![0xDD; 50], false), // Dropped
// -- Next Channel --
- Frame { id: [0xFF; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xFF; 16], number: 1, data: vec![0xDD; 50], is_last: true },
+ crate::frame!(0xFF, 0, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 1, vec![0xDD; 50], true),
];
- let encoded = encode_frames(frames.clone());
- let config = RollupConfig { holocene_time: Some(0), ..Default::default() };
- let mut mock = TestFrameQueueProvider::new(vec![Ok(encoded)]);
- mock.set_origin(BlockInfo::default());
- let mut frame_queue = FrameQueue::new(mock, Arc::new(config));
- assert!(frame_queue.is_holocene_active(BlockInfo::default()));
- for frame in frames.iter().take(3) {
- let frame_decoded = frame_queue.next_frame().await.unwrap();
- assert_eq!(frame_decoded, *frame);
- }
- for i in 0..2 {
- let frame_decoded = frame_queue.next_frame().await.unwrap();
- assert_eq!(frame_decoded, frames[i + 4]);
- }
- let err = frame_queue.next_frame().await.unwrap_err();
- assert_eq!(err, PipelineError::Eof.temp());
+ let assert = crate::test_utils::FrameQueueBuilder::new()
+ .with_rollup_config(&RollupConfig { holocene_time: Some(0), ..Default::default() })
+ .with_origin(BlockInfo::default())
+ .with_expected_frames(&[&frames[0..3], &frames[4..]].concat())
+ .with_frames(&frames)
+ .build();
+ assert.holocene_active(true);
+ assert.next_frames().await;
}
#[tokio::test]
async fn test_holocene_non_sequential_frames() {
- let frames = vec![
+ let frames = [
// -- First Channel --
- Frame { id: [0xEE; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xEE; 16], number: 1, data: vec![0xDD; 50], is_last: false },
- // Both this and the next frames should be dropped since neither will be
- // interpreted as having the next sequential frame number after 1.
- Frame { id: [0xEE; 16], number: 3, data: vec![0xDD; 50], is_last: true },
- Frame { id: [0xEE; 16], number: 4, data: vec![0xDD; 50], is_last: false },
+ crate::frame!(0xEE, 0, vec![0xDD; 50], false),
+ crate::frame!(0xEE, 1, vec![0xDD; 50], false),
+ crate::frame!(0xEE, 3, vec![0xDD; 50], true), // Dropped
+ crate::frame!(0xEE, 4, vec![0xDD; 50], false), // Dropped
];
- let encoded = encode_frames(frames.clone());
- let config = RollupConfig { holocene_time: Some(0), ..Default::default() };
- let mut mock = TestFrameQueueProvider::new(vec![Ok(encoded)]);
- mock.set_origin(BlockInfo::default());
- let mut frame_queue = FrameQueue::new(mock, Arc::new(config));
- assert!(frame_queue.is_holocene_active(BlockInfo::default()));
- for frame in frames.iter().take(2) {
- let frame_decoded = frame_queue.next_frame().await.unwrap();
- assert_eq!(frame_decoded, *frame);
- }
- let err = frame_queue.next_frame().await.unwrap_err();
- assert_eq!(err, PipelineError::Eof.temp());
+ let assert = crate::test_utils::FrameQueueBuilder::new()
+ .with_rollup_config(&RollupConfig { holocene_time: Some(0), ..Default::default() })
+ .with_origin(BlockInfo::default())
+ .with_expected_frames(&frames[0..2])
+ .with_frames(&frames)
+ .build();
+ assert.holocene_active(true);
+ assert.next_frames().await;
}
#[tokio::test]
async fn test_holocene_unclosed_channel() {
- let frames = vec![
+ let frames = [
// -- First Channel --
- // Since this channel isn't closed by a last frame it is entirely dropped
- Frame { id: [0xEE; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xEE; 16], number: 1, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xEE; 16], number: 2, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xEE; 16], number: 3, data: vec![0xDD; 50], is_last: false },
+ crate::frame!(0xEE, 0, vec![0xDD; 50], false),
+ crate::frame!(0xEE, 1, vec![0xDD; 50], false),
+ crate::frame!(0xEE, 2, vec![0xDD; 50], false),
+ crate::frame!(0xEE, 3, vec![0xDD; 50], false),
// -- Next Channel --
- Frame { id: [0xFF; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xFF; 16], number: 1, data: vec![0xDD; 50], is_last: true },
+ crate::frame!(0xFF, 0, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 1, vec![0xDD; 50], true),
];
- let encoded = encode_frames(frames.clone());
- let config = RollupConfig { holocene_time: Some(0), ..Default::default() };
- let mut mock = TestFrameQueueProvider::new(vec![Ok(encoded)]);
- mock.set_origin(BlockInfo::default());
- let mut frame_queue = FrameQueue::new(mock, Arc::new(config));
- assert!(frame_queue.is_holocene_active(BlockInfo::default()));
- for i in 0..2 {
- let frame_decoded = frame_queue.next_frame().await.unwrap();
- assert_eq!(frame_decoded, frames[i + 4]);
- }
- let err = frame_queue.next_frame().await.unwrap_err();
- assert_eq!(err, PipelineError::Eof.temp());
+ let assert = crate::test_utils::FrameQueueBuilder::new()
+ .with_rollup_config(&RollupConfig { holocene_time: Some(0), ..Default::default() })
+ .with_origin(BlockInfo::default())
+ .with_expected_frames(&frames[4..])
+ .with_frames(&frames)
+ .build();
+ assert.holocene_active(true);
+ assert.next_frames().await;
}
#[tokio::test]
async fn test_holocene_unstarted_channel() {
- let frames = vec![
+ let frames = [
// -- First Channel --
- Frame { id: [0xDD; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xDD; 16], number: 1, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xDD; 16], number: 2, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xDD; 16], number: 3, data: vec![0xDD; 50], is_last: true },
+ crate::frame!(0xDD, 0, vec![0xDD; 50], false),
+ crate::frame!(0xDD, 1, vec![0xDD; 50], false),
+ crate::frame!(0xDD, 2, vec![0xDD; 50], false),
+ crate::frame!(0xDD, 3, vec![0xDD; 50], true),
// -- Second Channel --
- // Since this channel doesn't have a starting frame where number == 0,
- // it is entirely dropped.
- Frame { id: [0xEE; 16], number: 1, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xEE; 16], number: 2, data: vec![0xDD; 50], is_last: true },
+ crate::frame!(0xEE, 1, vec![0xDD; 50], false), // Dropped
+ crate::frame!(0xEE, 2, vec![0xDD; 50], true), // Dropped
// -- Third Channel --
- Frame { id: [0xFF; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xFF; 16], number: 1, data: vec![0xDD; 50], is_last: true },
+ crate::frame!(0xFF, 0, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 1, vec![0xDD; 50], true),
];
- let encoded = encode_frames(frames.clone());
- let config = RollupConfig { holocene_time: Some(0), ..Default::default() };
- let mut mock = TestFrameQueueProvider::new(vec![Ok(encoded)]);
- mock.set_origin(BlockInfo::default());
- let mut frame_queue = FrameQueue::new(mock, Arc::new(config));
- assert!(frame_queue.is_holocene_active(BlockInfo::default()));
- for frame in frames.iter().take(4) {
- let frame_decoded = frame_queue.next_frame().await.unwrap();
- assert_eq!(frame_decoded, *frame);
- }
- for i in 0..2 {
- let frame_decoded = frame_queue.next_frame().await.unwrap();
- assert_eq!(frame_decoded, frames[i + 6]);
- }
- let err = frame_queue.next_frame().await.unwrap_err();
- assert_eq!(err, PipelineError::Eof.temp());
+ let assert = crate::test_utils::FrameQueueBuilder::new()
+ .with_rollup_config(&RollupConfig { holocene_time: Some(0), ..Default::default() })
+ .with_origin(BlockInfo::default())
+ .with_expected_frames(&[&frames[0..4], &frames[6..]].concat())
+ .with_frames(&frames)
+ .build();
+ assert.holocene_active(true);
+ assert.next_frames().await;
}
- // Notice: The first channel is **not** dropped here because there can still be
- // frames that come in to successfully close the channel.
#[tokio::test]
async fn test_holocene_unclosed_channel_with_invalid_start() {
- let frames = vec![
+ let frames = [
// -- First Channel --
- Frame { id: [0xEE; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xEE; 16], number: 1, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xEE; 16], number: 2, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xEE; 16], number: 3, data: vec![0xDD; 50], is_last: false },
+ crate::frame!(0xEE, 0, vec![0xDD; 50], false),
+ crate::frame!(0xEE, 1, vec![0xDD; 50], false),
+ crate::frame!(0xEE, 2, vec![0xDD; 50], false),
+ crate::frame!(0xEE, 3, vec![0xDD; 50], false),
// -- Next Channel --
- // This is also an invalid channel because it is never started
- // since there isn't a first frame with number == 0
- Frame { id: [0xFF; 16], number: 1, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xFF; 16], number: 2, data: vec![0xDD; 50], is_last: true },
+ crate::frame!(0xFF, 1, vec![0xDD; 50], false), // Dropped
+ crate::frame!(0xFF, 2, vec![0xDD; 50], true), // Dropped
];
- let encoded = encode_frames(frames.clone());
- let config = RollupConfig { holocene_time: Some(0), ..Default::default() };
- let mut mock = TestFrameQueueProvider::new(vec![Ok(encoded)]);
- mock.set_origin(BlockInfo::default());
- let mut frame_queue = FrameQueue::new(mock, Arc::new(config));
- assert!(frame_queue.is_holocene_active(BlockInfo::default()));
- for frame in frames.iter().take(4) {
- let frame_decoded = frame_queue.next_frame().await.unwrap();
- assert_eq!(frame_decoded, *frame);
- }
- let err = frame_queue.next_frame().await.unwrap_err();
- assert_eq!(err, PipelineError::Eof.temp());
+ let assert = crate::test_utils::FrameQueueBuilder::new()
+ .with_rollup_config(&RollupConfig { holocene_time: Some(0), ..Default::default() })
+ .with_origin(BlockInfo::default())
+ .with_expected_frames(&frames[0..4])
+ .with_frames(&frames)
+ .build();
+ assert.holocene_active(true);
+ assert.next_frames().await;
}
#[tokio::test]
async fn test_holocene_replace_channel() {
- let frames = vec![
+ let frames = [
// -- First Channel - VALID & CLOSED --
- Frame { id: [0xDD; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xDD; 16], number: 1, data: vec![0xDD; 50], is_last: true },
+ crate::frame!(0xDD, 0, vec![0xDD; 50], false),
+ crate::frame!(0xDD, 1, vec![0xDD; 50], true),
// -- Second Channel - VALID & NOT CLOSED / DROPPED --
- Frame { id: [0xEE; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xEE; 16], number: 1, data: vec![0xDD; 50], is_last: false },
+ crate::frame!(0xEE, 0, vec![0xDD; 50], false),
+ crate::frame!(0xEE, 1, vec![0xDD; 50], false),
// -- Third Channel - VALID & CLOSED / REPLACES CHANNEL #2 --
- Frame { id: [0xFF; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xFF; 16], number: 1, data: vec![0xDD; 50], is_last: true },
+ crate::frame!(0xFF, 0, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 1, vec![0xDD; 50], true),
];
- let encoded = encode_frames(frames.clone());
- let config = RollupConfig { holocene_time: Some(0), ..Default::default() };
- let mut mock = TestFrameQueueProvider::new(vec![Ok(encoded)]);
- mock.set_origin(BlockInfo::default());
- let mut frame_queue = FrameQueue::new(mock, Arc::new(config));
- assert!(frame_queue.is_holocene_active(BlockInfo::default()));
- for frame in frames.iter().filter(|f| f.id != [0xEE; 16]) {
- let frame_decoded = frame_queue.next_frame().await.unwrap();
- assert_eq!(frame_decoded, *frame);
- }
- let err = frame_queue.next_frame().await.unwrap_err();
- assert_eq!(err, PipelineError::Eof.temp());
+ let assert = crate::test_utils::FrameQueueBuilder::new()
+ .with_rollup_config(&RollupConfig { holocene_time: Some(0), ..Default::default() })
+ .with_origin(BlockInfo::default())
+ .with_expected_frames(&[&frames[0..2], &frames[4..]].concat())
+ .with_frames(&frames)
+ .build();
+ assert.holocene_active(true);
+ assert.next_frames().await;
}
#[tokio::test]
async fn test_holocene_interleaved_invalid_channel() {
- let frames = vec![
+ let frames = [
// -- First channel is dropped since it is replaced by the second channel --
// -- Second channel is dropped since it isn't closed --
- Frame { id: [0x01; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0x02; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0x01; 16], number: 1, data: vec![0xDD; 50], is_last: true },
- Frame { id: [0x02; 16], number: 1, data: vec![0xDD; 50], is_last: false },
+ crate::frame!(0x01, 0, vec![0xDD; 50], false),
+ crate::frame!(0x02, 0, vec![0xDD; 50], false),
+ crate::frame!(0x01, 1, vec![0xDD; 50], true),
+ crate::frame!(0x02, 1, vec![0xDD; 50], false),
// -- Third Channel - VALID & CLOSED --
- Frame { id: [0xFF; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xFF; 16], number: 1, data: vec![0xDD; 50], is_last: true },
+ crate::frame!(0xFF, 0, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 1, vec![0xDD; 50], true),
];
- let encoded = encode_frames(frames.clone());
- let config = RollupConfig { holocene_time: Some(0), ..Default::default() };
- let mut mock = TestFrameQueueProvider::new(vec![Ok(encoded)]);
- mock.set_origin(BlockInfo::default());
- let mut frame_queue = FrameQueue::new(mock, Arc::new(config));
- assert!(frame_queue.is_holocene_active(BlockInfo::default()));
- for frame in frames[4..].iter() {
- let frame_decoded = frame_queue.next_frame().await.unwrap();
- assert_eq!(frame_decoded, *frame);
- }
- let err = frame_queue.next_frame().await.unwrap_err();
- assert_eq!(err, PipelineError::Eof.temp());
+ let assert = crate::test_utils::FrameQueueBuilder::new()
+ .with_rollup_config(&RollupConfig { holocene_time: Some(0), ..Default::default() })
+ .with_origin(BlockInfo::default())
+ .with_expected_frames(&frames[4..])
+ .with_frames(&frames)
+ .build();
+ assert.holocene_active(true);
+ assert.next_frames().await;
}
#[tokio::test]
async fn test_holocene_interleaved_valid_channel() {
- let frames = vec![
+ let frames = [
// -- First channel is dropped since it is replaced by the second channel --
// -- Second channel is successfully closed so it's valid --
- Frame { id: [0x01; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0x02; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0x01; 16], number: 1, data: vec![0xDD; 50], is_last: true },
- Frame { id: [0x02; 16], number: 1, data: vec![0xDD; 50], is_last: true },
+ crate::frame!(0x01, 0, vec![0xDD; 50], false),
+ crate::frame!(0x02, 0, vec![0xDD; 50], false),
+ crate::frame!(0x01, 1, vec![0xDD; 50], true),
+ crate::frame!(0x02, 1, vec![0xDD; 50], true),
// -- Third Channel - VALID & CLOSED --
- Frame { id: [0xFF; 16], number: 0, data: vec![0xDD; 50], is_last: false },
- Frame { id: [0xFF; 16], number: 1, data: vec![0xDD; 50], is_last: true },
+ crate::frame!(0xFF, 0, vec![0xDD; 50], false),
+ crate::frame!(0xFF, 1, vec![0xDD; 50], true),
];
- let encoded = encode_frames(frames.clone());
- let config = RollupConfig { holocene_time: Some(0), ..Default::default() };
- let mut mock = TestFrameQueueProvider::new(vec![Ok(encoded)]);
- mock.set_origin(BlockInfo::default());
- let mut frame_queue = FrameQueue::new(mock, Arc::new(config));
- assert!(frame_queue.is_holocene_active(BlockInfo::default()));
- for frame in [&frames[1], &frames[3], &frames[4], &frames[5]].iter() {
- let frame_decoded = frame_queue.next_frame().await.unwrap();
- assert_eq!(frame_decoded, **frame);
- }
- let err = frame_queue.next_frame().await.unwrap_err();
- assert_eq!(err, PipelineError::Eof.temp());
+ let assert = crate::test_utils::FrameQueueBuilder::new()
+ .with_rollup_config(&RollupConfig { holocene_time: Some(0), ..Default::default() })
+ .with_origin(BlockInfo::default())
+ .with_expected_frames(&[&frames[1..2], &frames[3..]].concat())
+ .with_frames(&frames)
+ .build();
+ assert.holocene_active(true);
+ assert.next_frames().await;
}
}
diff --git a/crates/derive/src/test_utils/frames.rs b/crates/derive/src/test_utils/frames.rs
new file mode 100644
index 00000000..9c4a8eb0
--- /dev/null
+++ b/crates/derive/src/test_utils/frames.rs
@@ -0,0 +1,134 @@
+//! Frames
+
+use crate::{
+ errors::{PipelineError, PipelineErrorKind},
+ stages::{FrameQueue, NextFrameProvider},
+ test_utils::TestFrameQueueProvider,
+ traits::OriginProvider,
+};
+use alloc::{sync::Arc, vec, vec::Vec};
+use alloy_primitives::Bytes;
+use op_alloy_genesis::RollupConfig;
+use op_alloy_protocol::{BlockInfo, Frame, DERIVATION_VERSION_0};
+
+/// A [FrameQueue] builder.
+#[derive(Debug, Default)]
+pub struct FrameQueueBuilder {
+ origin: Option,
+ config: Option,
+ mock: Option,
+ expected_frames: Vec,
+ expected_err: Option,
+}
+
+fn encode_frames(frames: &[Frame]) -> Bytes {
+ let mut bytes = Vec::new();
+ bytes.extend_from_slice(&[DERIVATION_VERSION_0]);
+ for frame in frames.iter() {
+ bytes.extend_from_slice(&frame.encode());
+ }
+ Bytes::from(bytes)
+}
+
+impl FrameQueueBuilder {
+ /// Create a new [FrameQueueBuilder] instance.
+ pub const fn new() -> Self {
+ Self { origin: None, config: None, mock: None, expected_frames: vec![], expected_err: None }
+ }
+
+ /// Sets the rollup config.
+ pub fn with_rollup_config(mut self, config: &RollupConfig) -> Self {
+ self.config = Some(config.clone());
+ self
+ }
+
+ /// Set the origin block.
+ pub const fn with_origin(mut self, origin: BlockInfo) -> Self {
+ self.origin = Some(origin);
+ self
+ }
+
+ /// With expected frames.
+ pub fn with_expected_frames(mut self, frames: &[Frame]) -> Self {
+ self.expected_frames = frames.to_vec();
+ self
+ }
+
+ /// Sets the expected error type.
+ pub fn with_expected_err(mut self, err: PipelineErrorKind) -> Self {
+ self.expected_err = Some(err);
+ self
+ }
+
+ /// With raw frames.
+ pub fn with_raw_frames(mut self, raw: Bytes) -> Self {
+ let mock = self.mock.unwrap_or_else(|| TestFrameQueueProvider::new(vec![Ok(raw)]));
+ self.mock = Some(mock);
+ self
+ }
+
+ /// Adds frames to the mock provider.
+ pub fn with_frames(mut self, frames: &[Frame]) -> Self {
+ let encoded = encode_frames(frames);
+ let mock = self.mock.unwrap_or_else(|| TestFrameQueueProvider::new(vec![Ok(encoded)]));
+ self.mock = Some(mock);
+ self
+ }
+
+ /// Build the [FrameQueue].
+ pub fn build(self) -> FrameQueueAsserter {
+ let mut mock = self.mock.unwrap_or_else(|| TestFrameQueueProvider::new(vec![]));
+ if let Some(origin) = self.origin {
+ mock.set_origin(origin);
+ }
+ let config = self.config.unwrap_or_default();
+ let config = Arc::new(config);
+ let err = self.expected_err.unwrap_or_else(|| PipelineError::Eof.temp());
+ FrameQueueAsserter::new(FrameQueue::new(mock, config), self.expected_frames, err)
+ }
+}
+
+/// The [FrameQueueAsserter] validates frame queue outputs.
+#[derive(Debug)]
+pub struct FrameQueueAsserter {
+ inner: FrameQueue,
+ expected_frames: Vec,
+ expected_err: PipelineErrorKind,
+}
+
+impl FrameQueueAsserter {
+ /// Create a new [FrameQueueAsserter] instance.
+ pub const fn new(
+ inner: FrameQueue,
+ expected_frames: Vec,
+ expected_err: PipelineErrorKind,
+ ) -> Self {
+ Self { inner, expected_frames, expected_err }
+ }
+
+ /// Asserts that holocene is active.
+ pub fn holocene_active(&self, active: bool) {
+ let holocene = self.inner.is_holocene_active(self.inner.origin().unwrap_or_default());
+ if !active {
+ assert!(!holocene);
+ } else {
+ assert!(holocene);
+ }
+ }
+
+ /// Asserts that the frame queue returns with a missing origin error.
+ pub async fn missing_origin(mut self) {
+ let err = self.inner.next_frame().await.unwrap_err();
+ assert_eq!(err, PipelineError::MissingOrigin.crit());
+ }
+
+ /// Asserts that the frame queue produces the expected frames.
+ pub async fn next_frames(mut self) {
+ for eframe in self.expected_frames.into_iter() {
+ let frame = self.inner.next_frame().await.expect("unexpected frame");
+ assert_eq!(frame, eframe);
+ }
+ let err = self.inner.next_frame().await.unwrap_err();
+ assert_eq!(err, self.expected_err);
+ }
+}
diff --git a/crates/derive/src/test_utils/macros.rs b/crates/derive/src/test_utils/macros.rs
new file mode 100644
index 00000000..b629bf59
--- /dev/null
+++ b/crates/derive/src/test_utils/macros.rs
@@ -0,0 +1,19 @@
+//! Macros used across test utilities.
+
+/// A shorthand syntax for constructing [op_alloy_protocol::Frame]s.
+#[macro_export]
+macro_rules! frame {
+ ($id:expr, $number:expr, $data:expr, $is_last:expr) => {
+ op_alloy_protocol::Frame { id: [$id; 16], number: $number, data: $data, is_last: $is_last }
+ };
+}
+
+/// A shorthand syntax for constructing a list of [op_alloy_protocol::Frame]s.
+#[macro_export]
+macro_rules! frames {
+ ($id:expr, $number:expr, $data:expr, $count:expr) => {{
+ let mut frames = vec![$crate::frame!($id, $number, $data, false); $count];
+ frames[$count - 1].is_last = true;
+ frames
+ }};
+}
diff --git a/crates/derive/src/test_utils/mod.rs b/crates/derive/src/test_utils/mod.rs
index 4ee92875..0a4e7d2d 100644
--- a/crates/derive/src/test_utils/mod.rs
+++ b/crates/derive/src/test_utils/mod.rs
@@ -41,3 +41,8 @@ pub use tracing::{CollectingLayer, TraceStorage};
mod sys_config_fetcher;
pub use sys_config_fetcher::TestSystemConfigL2Fetcher;
+
+mod frames;
+pub use frames::{FrameQueueAsserter, FrameQueueBuilder};
+
+mod macros;