alloc_test/alloc/
compare.rs

1use derive_builder::Builder;
2use thiserror::Error;
3
4use super::measure::MemoryStats;
5use crate::threshold::{Threshold, ThresholdError, ThresholdFor};
6
7/// Limits for each allocation statistics parameter.
8#[derive(Debug, Builder)]
9pub struct AllocThresholds {
10    #[builder(default)]
11    pub current: Threshold<usize>,
12    #[builder(default)]
13    pub peak: Threshold<usize>,
14    #[builder(default)]
15    pub total_size: Threshold<usize>,
16    #[builder(default)]
17    pub total_num: Threshold<usize>,
18    #[builder(default)]
19    pub reallocs: Threshold<usize>,
20}
21
22#[derive(Debug, Error)]
23#[error("Allocation parameter `{param}`: {error}")]
24pub struct AllocThresholdsError {
25    error: ThresholdError<usize>,
26    param: &'static str,
27}
28
29macro_rules! check {
30    ($f:ident, $l:expr, $v:expr, $r:expr) => {
31        $l.$f
32            .check(&$v.$f, &$r.$f)
33            .map_err(|e| AllocThresholdsError {
34                error: e,
35                param: stringify!($f),
36            })
37    };
38}
39
40impl ThresholdFor<MemoryStats> for AllocThresholds {
41    type Error = AllocThresholdsError;
42
43    fn check_threshold(
44        &self,
45        value: &MemoryStats,
46        ref_value: &MemoryStats,
47    ) -> Result<(), Self::Error> {
48        self.check(value, ref_value)
49    }
50}
51
52impl AllocThresholds {
53    pub fn check(
54        &self,
55        value: &MemoryStats,
56        ref_value: &MemoryStats,
57    ) -> Result<(), AllocThresholdsError> {
58        check!(current, self, value, ref_value)?;
59        check!(peak, self, value, ref_value)?;
60        check!(total_size, self, value, ref_value)?;
61        check!(total_num, self, value, ref_value)?;
62        check!(reallocs, self, value, ref_value)?;
63        Ok(())
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn limits() {
73        let rs = MemoryStats {
74            current: 100,
75            peak: 1000,
76            total_size: 2000,
77            total_num: 100,
78            reallocs: 0,
79        };
80        let vs = MemoryStats {
81            current: 110,
82            peak: 1100,
83            total_size: 2200,
84            total_num: 110,
85            reallocs: 1,
86        };
87
88        let ls = AllocThresholdsBuilder::default().build().unwrap();
89        assert!(ls.check_threshold(&rs, &rs).is_ok());
90        assert!(ls.check_threshold(&vs, &rs).is_ok());
91
92        let ls = AllocThresholdsBuilder::default()
93            .current(Threshold::Cap(1))
94            .build()
95            .unwrap();
96        let r = ls.check(&vs, &rs);
97        assert!(r.unwrap_err().param == "current");
98
99        let ls = AllocThresholdsBuilder::default()
100            .reallocs(Threshold::Cap(0))
101            .build()
102            .unwrap();
103        let r = ls.check(&vs, &rs);
104        assert!(r.unwrap_err().param == "reallocs");
105    }
106}