diff --git a/src/payload/ext/span.rs b/src/payload/ext/span.rs index a6bdedb..5f03f3e 100644 --- a/src/payload/ext/span.rs +++ b/src/payload/ext/span.rs @@ -106,3 +106,90 @@ impl SpanExt

for Span

{ } } } + +#[cfg(test)] +mod span_ext_tests { + use { + crate::{ + payload::{Span, SpanExt}, + prelude::{BlockContext, Checkpoint, Ethereum}, + test_utils::{BlockContextMocked, transfer_tx}, + }, + alloy::primitives::U256, + rblib::{alloy, test_utils::FundedAccounts}, + }; + + #[test] + fn gas_and_blob_gas_used_sum_correctly() { + let block = BlockContext::::mocked(); + + let root = block.start(); + let c1: Checkpoint = root.barrier(); + let c2: Checkpoint = c1.barrier(); + + let span = Span::::between(&root, &c2).unwrap(); + + assert_eq!(span.gas_used(), 0); + assert_eq!(span.blob_gas_used(), 0); + } + + #[test] + fn contains_transaction_hash_works() { + let block = BlockContext::::mocked(); + + let root = block.start(); + let c1: Checkpoint = root.barrier(); + + let tx1 = transfer_tx::( + &FundedAccounts::signer(0), + 0, + U256::from(50_000u64), + ); + + let c2 = c1.apply(tx1.clone()).unwrap(); + + let span = Span::::between(&root, &c2).unwrap(); + + assert!(span.contains(*tx1.hash())); + } + + #[test] + fn split_at_produces_valid_halves() { + let block = BlockContext::::mocked(); + + let root = block.start(); + let c1: Checkpoint = root.barrier(); + let c2: Checkpoint = c1.barrier(); + + let span = Span::::between(&root, &c2).unwrap(); + + let (left, right) = span.split_at(1); + assert_eq!(left.len(), 1); + assert_eq!(right.len(), 2); + + let (left_all, right_empty) = span.split_at(10); + assert_eq!(left_all.len(), span.len()); + assert!(right_empty.is_empty()); + } + + #[test] + fn take_and_skip_are_consistent_with_split_at() { + let block = BlockContext::::mocked(); + + let root = block.start(); + let c1: Checkpoint = root.barrier(); + let c2: Checkpoint = c1.barrier(); + + let span = Span::::between(&root, &c2).unwrap(); + + let take_1 = span.take(1); + let skip_1 = span.skip(1); + + assert_eq!(take_1.len(), 1); + assert_eq!(skip_1.len(), 2); + + let (left, right) = span.split_at(1); + assert_eq!(take_1.len(), left.len()); + assert_eq!(skip_1.len(), right.len()); + } +} diff --git a/src/payload/span.rs b/src/payload/span.rs index 9393e50..cace757 100644 --- a/src/payload/span.rs +++ b/src/payload/span.rs @@ -181,3 +181,72 @@ impl Display for Span

{ ) } } + +#[cfg(test)] +mod tests { + use crate::{ + payload::Span, + prelude::{BlockContext, Checkpoint, Ethereum}, + test_utils::BlockContextMocked, + }; + + #[test] + fn span_between_linear_history() { + let block = BlockContext::::mocked(); + + let checkpoint = block.start(); + let c1: Checkpoint = checkpoint.barrier(); + let c2: Checkpoint = c1.barrier(); + + // Direct ancestor-descendant pair + let mut span = Span::::between(&checkpoint, &c2).unwrap(); + assert_eq!(span.len(), 3); + assert_eq!(span.pop_first().unwrap(), checkpoint); + assert_eq!(span.len(), 2); + assert_eq!(span.pop_last().unwrap(), c2); + assert_eq!(span.len(), 1); + } + + #[test] + fn test_empty_span() { + let block = BlockContext::::mocked(); + + let checkpoint = block.start(); + + let span = Span::::between(&checkpoint, &checkpoint).unwrap(); + + assert_eq!(span.len(), 1); + } + + #[test] + fn test_between_nonlinear_history() { + let block = BlockContext::::mocked(); + + let checkpoint1 = block.start(); + let checkpoint2 = block.start(); + + let result = Span::between(&checkpoint1, &checkpoint2); + assert!(result.is_err()); + } + + #[test] + fn into_iter_and_iterators_work() { + let block = BlockContext::::mocked(); + + let root = block.start(); + let c1: Checkpoint = root.barrier(); + let c2: Checkpoint = c1.barrier(); + + let span = Span::::between(&root, &c2).unwrap(); + + // iter() + let ids_from_iter: Vec<_> = span.iter().map(|c| c.to_owned()).collect(); + assert_eq!(ids_from_iter.len(), 3); + assert_eq!(ids_from_iter[0], root); + assert_eq!(ids_from_iter[2], c2); + + // into_iter() + let ids_from_into_iter: Vec<_> = span.clone().into_iter().collect(); + assert_eq!(ids_from_iter, ids_from_into_iter); + } +}