blob: c5e3af33f75c151523ef2a7d574990591e44ccef [file]
// Copyright 2026 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! A utility for test environments.
//!
//! This module exposes the [`NormalizedRangeCheckingIterator`] to assist in constructing a
//! validated iterator over collections of ranges used for testing.
/// An iterator which verifies that the underlying `iter` is a [`NormalizedRangeIterator`].
pub struct NormalizedRangeCheckingIterator<I> {
iter: I,
prev: Option<crate::Range>,
}
impl<I> NormalizedRangeCheckingIterator<I>
where
I: Iterator<Item = crate::Range>,
{
pub fn new(ranges: impl IntoIterator<IntoIter = I>) -> Self {
Self { iter: ranges.into_iter(), prev: None }
}
}
impl<I> Iterator for NormalizedRangeCheckingIterator<I>
where
I: Iterator<Item = crate::Range>,
{
type Item = crate::Range;
fn next(&mut self) -> Option<crate::Range> {
let cur = self.iter.next()?;
if let Some(prev) = self.prev {
assert!(prev.end() < cur.addr() || (prev.end() == cur.addr() && prev.ty() != cur.ty()));
}
self.prev = Some(cur);
Some(cur)
}
}
// Safety: `NormalizedRangeCheckingIterator` will panic if it violates the normalized invariant.
unsafe impl<I> crate::NormalizedRangeIterator for NormalizedRangeCheckingIterator<I> where
I: Iterator<Item = crate::Range>
{
}
#[cfg(test)]
mod tests {
use super::*;
// Panic when the underlying iterator has two adjacent ranges of the same type.
#[test]
#[should_panic]
fn normalized_range_checking_iterator_test_maximally_contiguous() {
let mut ranges = NormalizedRangeCheckingIterator::new([
crate::Range::new(0, 0x1000, crate::Type::FreeRam),
crate::Range::new(0x1000, 0x1000, crate::Type::FreeRam),
]);
ranges.next();
ranges.next();
}
// Panic when underlying iterator is not lexicographically sorted.
#[test]
#[should_panic]
fn normalized_range_checking_iterator_test_lexicographically_sorted() {
let mut ranges = NormalizedRangeCheckingIterator::new([
crate::Range::new(0x5000, 0x1000, crate::Type::FreeRam),
crate::Range::new(0, 0x1000, crate::Type::FreeRam),
]);
ranges.next();
ranges.next();
}
// Panic when underlying iterator has overlapping ranges.
#[test]
#[should_panic]
fn normalized_range_checking_iterator_test_non_overlapping() {
let mut ranges = NormalizedRangeCheckingIterator::new([
crate::Range::new(0, 0x1000, crate::Type::FreeRam),
crate::Range::new(0, 0x1000, crate::Type::FreeRam),
]);
ranges.next();
ranges.next();
}
}