Skip to main content

Report

Struct Report 

Source
pub struct Report { /* private fields */ }
Expand description

Result of a full allocation-failure check.

Implementations§

Source§

impl Report

Source

pub fn baseline(&self) -> &Baseline

Returns the primary baseline run.

Source

pub fn stability_baselines(&self) -> &[Baseline]

Returns extra baseline runs used to validate allocation-count stability.

Source

pub fn baseline_is_stable(&self) -> bool

Returns whether every baseline run completed with the same allocation count as the primary baseline run.

Examples found in repository?
examples/scenarios.rs (line 129)
119fn unstable_baseline_diagnostic() {
120    let runs = AtomicUsize::new(0);
121
122    let report = alloc_chaos::Check::new().stability_runs(2).run(|| {
123        if runs.fetch_add(1, Ordering::SeqCst) == 0 {
124            checked_packet_builder();
125        }
126    });
127
128    print_report("unstable baseline", &report);
129    assert!(!report.baseline_is_stable());
130    assert!(report.attempts().is_empty());
131    assert!(!report.is_success());
132}
Source

pub fn baseline_allocations(&self) -> usize

Returns the number of allocation attempts observed during the primary baseline run.

Source

pub fn attempts(&self) -> &[Attempt]

Returns all injected-failure runs.

Examples found in repository?
examples/scenarios.rs (line 101)
96fn reproduce_one_failure_and_show_metadata() {
97    let full_report = alloc_chaos::check(checked_packet_builder);
98    full_report.assert_success();
99
100    let target = full_report
101        .attempts()
102        .first()
103        .map(alloc_chaos::Attempt::target_allocation)
104        .expect("packet builder should allocate during the baseline run");
105
106    let report = alloc_chaos::Check::new()
107        .only_failure(target)
108        .run(checked_packet_builder);
109
110    print_report("single-target reproduction", &report);
111    print_allocation_metadata(&report);
112
113    assert!(report.is_truncated());
114    assert_eq!(report.tested_failures(), 1);
115    assert!(report.attempts()[0].is_success());
116    assert!(!report.is_success());
117}
118
119fn unstable_baseline_diagnostic() {
120    let runs = AtomicUsize::new(0);
121
122    let report = alloc_chaos::Check::new().stability_runs(2).run(|| {
123        if runs.fetch_add(1, Ordering::SeqCst) == 0 {
124            checked_packet_builder();
125        }
126    });
127
128    print_report("unstable baseline", &report);
129    assert!(!report.baseline_is_stable());
130    assert!(report.attempts().is_empty());
131    assert!(!report.is_success());
132}
133
134fn mishandled_oom_diagnostic() {
135    with_quiet_expected_panics(|| {
136        let report = alloc_chaos::Check::new()
137            .max_failures(1)
138            .run(|| match build_packet() {
139                Ok(packet) => assert_eq!(packet.body.len(), 256),
140                Err(BuildError::OutOfMemory) => panic!("allocation failure was not handled"),
141            });
142
143        print_report("mishandled OOM path", &report);
144        assert!(report.first_failure().is_some());
145        assert!(!report.is_success());
146    });
147}
148
149fn print_report(title: &str, report: &alloc_chaos::Report) {
150    println!("\n=== {title} ===");
151    println!("{report}");
152}
153
154fn print_allocation_metadata(report: &alloc_chaos::Report) {
155    for attempt in report.attempts() {
156        if let Some(allocation) = attempt.injected_allocation() {
157            println!(
158                "metadata: target #{} -> {} size={} align={} new_size={:?}",
159                allocation.index(),
160                allocation.operation(),
161                allocation.size(),
162                allocation.align(),
163                allocation.new_size(),
164            );
165        }
166    }
167}
Source

pub fn failed_attempts(&self) -> impl Iterator<Item = &Attempt>

Returns all injected-failure runs that did not complete successfully.

Source

pub fn first_failure(&self) -> Option<&Attempt>

Returns the first injected-failure run that did not complete successfully.

Examples found in repository?
examples/scenarios.rs (line 144)
134fn mishandled_oom_diagnostic() {
135    with_quiet_expected_panics(|| {
136        let report = alloc_chaos::Check::new()
137            .max_failures(1)
138            .run(|| match build_packet() {
139                Ok(packet) => assert_eq!(packet.body.len(), 256),
140                Err(BuildError::OutOfMemory) => panic!("allocation failure was not handled"),
141            });
142
143        print_report("mishandled OOM path", &report);
144        assert!(report.first_failure().is_some());
145        assert!(!report.is_success());
146    });
147}
Source

pub fn tested_failures(&self) -> usize

Returns the number of selected failure targets that were executed.

Examples found in repository?
examples/scenarios.rs (line 92)
85fn range_diagnostic_run() {
86    let report = alloc_chaos::Check::new()
87        .failure_range(1..2)
88        .run(checked_packet_builder);
89
90    print_report("selected failure range", &report);
91    assert!(report.is_truncated());
92    assert_eq!(report.tested_failures(), 1);
93    assert!(!report.is_success());
94}
95
96fn reproduce_one_failure_and_show_metadata() {
97    let full_report = alloc_chaos::check(checked_packet_builder);
98    full_report.assert_success();
99
100    let target = full_report
101        .attempts()
102        .first()
103        .map(alloc_chaos::Attempt::target_allocation)
104        .expect("packet builder should allocate during the baseline run");
105
106    let report = alloc_chaos::Check::new()
107        .only_failure(target)
108        .run(checked_packet_builder);
109
110    print_report("single-target reproduction", &report);
111    print_allocation_metadata(&report);
112
113    assert!(report.is_truncated());
114    assert_eq!(report.tested_failures(), 1);
115    assert!(report.attempts()[0].is_success());
116    assert!(!report.is_success());
117}
Source

pub fn injected_failures(&self) -> usize

Returns the number of executed runs that actually reached and failed the selected allocation attempt.

Source

pub fn untested_failures(&self) -> usize

Returns the number of observed baseline allocation attempts that did not have a corresponding injected failure.

Source

pub fn is_truncated(&self) -> bool

Returns true if not every observed baseline allocation was tested.

This can happen when the baseline run panics, when the baseline is unstable, when Check::max_failures limits the run count, when Check::only_failure or Check::failure_range selects a subset, or when Check::stop_on_failure stops the check early.

Examples found in repository?
examples/scenarios.rs (line 81)
74fn bounded_diagnostic_run() {
75    let report = alloc_chaos::Check::new()
76        .max_failures(1)
77        .stop_on_failure(true)
78        .run(checked_packet_builder);
79
80    print_report("bounded diagnostic run", &report);
81    assert!(report.is_truncated());
82    assert!(!report.is_success());
83}
84
85fn range_diagnostic_run() {
86    let report = alloc_chaos::Check::new()
87        .failure_range(1..2)
88        .run(checked_packet_builder);
89
90    print_report("selected failure range", &report);
91    assert!(report.is_truncated());
92    assert_eq!(report.tested_failures(), 1);
93    assert!(!report.is_success());
94}
95
96fn reproduce_one_failure_and_show_metadata() {
97    let full_report = alloc_chaos::check(checked_packet_builder);
98    full_report.assert_success();
99
100    let target = full_report
101        .attempts()
102        .first()
103        .map(alloc_chaos::Attempt::target_allocation)
104        .expect("packet builder should allocate during the baseline run");
105
106    let report = alloc_chaos::Check::new()
107        .only_failure(target)
108        .run(checked_packet_builder);
109
110    print_report("single-target reproduction", &report);
111    print_allocation_metadata(&report);
112
113    assert!(report.is_truncated());
114    assert_eq!(report.tested_failures(), 1);
115    assert!(report.attempts()[0].is_success());
116    assert!(!report.is_success());
117}
Source

pub fn allocator_installed(&self) -> bool

Returns whether the ChaosAllocator was observed during an explicit allocator-installation probe at the start of the check.

false usually means the global allocator wrapper was not installed.

Source

pub fn is_success(&self) -> bool

Returns true only for an exhaustive, valid, fully successful check.

Success requires all of the following:

  • the global allocator wrapper was installed;
  • the primary baseline completed;
  • all configured stability baseline runs matched the primary baseline;
  • the report is not truncated;
  • every observed baseline allocation was tested; and
  • every injected run reached its target allocation and completed without panic.
Examples found in repository?
examples/scenarios.rs (line 82)
74fn bounded_diagnostic_run() {
75    let report = alloc_chaos::Check::new()
76        .max_failures(1)
77        .stop_on_failure(true)
78        .run(checked_packet_builder);
79
80    print_report("bounded diagnostic run", &report);
81    assert!(report.is_truncated());
82    assert!(!report.is_success());
83}
84
85fn range_diagnostic_run() {
86    let report = alloc_chaos::Check::new()
87        .failure_range(1..2)
88        .run(checked_packet_builder);
89
90    print_report("selected failure range", &report);
91    assert!(report.is_truncated());
92    assert_eq!(report.tested_failures(), 1);
93    assert!(!report.is_success());
94}
95
96fn reproduce_one_failure_and_show_metadata() {
97    let full_report = alloc_chaos::check(checked_packet_builder);
98    full_report.assert_success();
99
100    let target = full_report
101        .attempts()
102        .first()
103        .map(alloc_chaos::Attempt::target_allocation)
104        .expect("packet builder should allocate during the baseline run");
105
106    let report = alloc_chaos::Check::new()
107        .only_failure(target)
108        .run(checked_packet_builder);
109
110    print_report("single-target reproduction", &report);
111    print_allocation_metadata(&report);
112
113    assert!(report.is_truncated());
114    assert_eq!(report.tested_failures(), 1);
115    assert!(report.attempts()[0].is_success());
116    assert!(!report.is_success());
117}
118
119fn unstable_baseline_diagnostic() {
120    let runs = AtomicUsize::new(0);
121
122    let report = alloc_chaos::Check::new().stability_runs(2).run(|| {
123        if runs.fetch_add(1, Ordering::SeqCst) == 0 {
124            checked_packet_builder();
125        }
126    });
127
128    print_report("unstable baseline", &report);
129    assert!(!report.baseline_is_stable());
130    assert!(report.attempts().is_empty());
131    assert!(!report.is_success());
132}
133
134fn mishandled_oom_diagnostic() {
135    with_quiet_expected_panics(|| {
136        let report = alloc_chaos::Check::new()
137            .max_failures(1)
138            .run(|| match build_packet() {
139                Ok(packet) => assert_eq!(packet.body.len(), 256),
140                Err(BuildError::OutOfMemory) => panic!("allocation failure was not handled"),
141            });
142
143        print_report("mishandled OOM path", &report);
144        assert!(report.first_failure().is_some());
145        assert!(!report.is_success());
146    });
147}
Source

pub fn assert_success(&self)

Panics with a human-readable report if Report::is_success is false.

Examples found in repository?
examples/scenarios.rs (line 71)
67fn strict_success() {
68    let report = alloc_chaos::check(checked_packet_builder);
69
70    print_report("strict exhaustive check", &report);
71    report.assert_success();
72}
73
74fn bounded_diagnostic_run() {
75    let report = alloc_chaos::Check::new()
76        .max_failures(1)
77        .stop_on_failure(true)
78        .run(checked_packet_builder);
79
80    print_report("bounded diagnostic run", &report);
81    assert!(report.is_truncated());
82    assert!(!report.is_success());
83}
84
85fn range_diagnostic_run() {
86    let report = alloc_chaos::Check::new()
87        .failure_range(1..2)
88        .run(checked_packet_builder);
89
90    print_report("selected failure range", &report);
91    assert!(report.is_truncated());
92    assert_eq!(report.tested_failures(), 1);
93    assert!(!report.is_success());
94}
95
96fn reproduce_one_failure_and_show_metadata() {
97    let full_report = alloc_chaos::check(checked_packet_builder);
98    full_report.assert_success();
99
100    let target = full_report
101        .attempts()
102        .first()
103        .map(alloc_chaos::Attempt::target_allocation)
104        .expect("packet builder should allocate during the baseline run");
105
106    let report = alloc_chaos::Check::new()
107        .only_failure(target)
108        .run(checked_packet_builder);
109
110    print_report("single-target reproduction", &report);
111    print_allocation_metadata(&report);
112
113    assert!(report.is_truncated());
114    assert_eq!(report.tested_failures(), 1);
115    assert!(report.attempts()[0].is_success());
116    assert!(!report.is_success());
117}
More examples
Hide additional examples
examples/try_reserve.rs (line 33)
25fn main() {
26    let report = alloc_chaos::check(|| {
27        if let Ok(bytes) = build_payload(4096) {
28            assert_eq!(bytes.len(), 4096)
29        }
30    });
31
32    println!("{report}");
33    report.assert_success();
34}

Trait Implementations§

Source§

impl Clone for Report

Source§

fn clone(&self) -> Report

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Report

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for Report

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for Report

Source§

fn eq(&self, other: &Report) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for Report

Source§

impl StructuralPartialEq for Report

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.