Skip to main content

memalloc/
testing.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! A utility for test environments.
6//!
7//! This module exposes the [`NormalizedRangeCheckingIterator`] to assist in constructing a
8//! validated iterator over collections of ranges used for testing.
9
10/// An iterator which verifies that the underlying `iter` is a [`NormalizedRangeIterator`].
11#[derive(Clone)]
12pub struct NormalizedRangeCheckingIterator<I> {
13    iter: I,
14    prev: Option<crate::Range>,
15}
16
17impl<I> NormalizedRangeCheckingIterator<I>
18where
19    I: Iterator<Item = crate::Range>,
20{
21    pub fn new(ranges: impl IntoIterator<IntoIter = I>) -> Self {
22        Self { iter: ranges.into_iter(), prev: None }
23    }
24}
25
26impl<I> Iterator for NormalizedRangeCheckingIterator<I>
27where
28    I: Iterator<Item = crate::Range>,
29{
30    type Item = crate::Range;
31
32    fn next(&mut self) -> Option<crate::Range> {
33        let cur = self.iter.next()?;
34        if let Some(prev) = self.prev {
35            assert!(prev.end() < cur.addr() || (prev.end() == cur.addr() && prev.ty() != cur.ty()));
36        }
37        self.prev = Some(cur);
38        Some(cur)
39    }
40}
41
42// Safety: `NormalizedRangeCheckingIterator` will panic if it violates the normalized invariant.
43unsafe impl<I> crate::NormalizedRangeIterator for NormalizedRangeCheckingIterator<I> where
44    I: Iterator<Item = crate::Range>
45{
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    // Panic when the underlying iterator has two adjacent ranges of the same type.
53    #[test]
54    #[should_panic]
55    fn normalized_range_checking_iterator_test_maximally_contiguous() {
56        let mut ranges = NormalizedRangeCheckingIterator::new([
57            crate::Range::new(0, 0x1000, crate::Type::FreeRam),
58            crate::Range::new(0x1000, 0x1000, crate::Type::FreeRam),
59        ]);
60
61        ranges.next();
62        ranges.next();
63    }
64
65    // Panic when underlying iterator is not lexicographically sorted.
66    #[test]
67    #[should_panic]
68    fn normalized_range_checking_iterator_test_lexicographically_sorted() {
69        let mut ranges = NormalizedRangeCheckingIterator::new([
70            crate::Range::new(0x5000, 0x1000, crate::Type::FreeRam),
71            crate::Range::new(0, 0x1000, crate::Type::FreeRam),
72        ]);
73
74        ranges.next();
75        ranges.next();
76    }
77
78    // Panic when underlying iterator has overlapping ranges.
79    #[test]
80    #[should_panic]
81    fn normalized_range_checking_iterator_test_non_overlapping() {
82        let mut ranges = NormalizedRangeCheckingIterator::new([
83            crate::Range::new(0, 0x1000, crate::Type::FreeRam),
84            crate::Range::new(0, 0x1000, crate::Type::FreeRam),
85        ]);
86
87        ranges.next();
88        ranges.next();
89    }
90}