pub struct Check { /* private fields */ }Expand description
Configuration for an allocation-failure check.
Implementations§
Source§impl Check
impl Check
Sourcepub const fn new() -> Self
pub const fn new() -> Self
Creates a check with no failure limit, no early stop, and one baseline run.
Examples found in repository?
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}Sourcepub const fn max_failures(self, max_failures: usize) -> Self
pub const fn max_failures(self, max_failures: usize) -> Self
Limits the number of allocation attempts that will be failed.
This is useful when a baseline run performs many allocations and a full
exhaustive check would be too expensive. A limited report is considered
truncated, so Report::assert_success will fail unless the limit still
covers every observed baseline allocation.
Examples found in repository?
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}Sourcepub const fn unlimited_failures(self) -> Self
pub const fn unlimited_failures(self) -> Self
Removes a previously configured failure limit.
Sourcepub fn only_failure(self, target: usize) -> Self
pub fn only_failure(self, target: usize) -> Self
Tests exactly one zero-based allocation attempt.
This is primarily a reproduction and debugging aid after a full check
has identified an interesting allocation number. A single-target report
is considered truncated when the baseline contains any other allocation
attempts, so Report::assert_success remains exhaustive by default.
§Panics
Panics if target is usize::MAX.
Examples found in repository?
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}Sourcepub fn failure_range(self, range: Range<usize>) -> Self
pub fn failure_range(self, range: Range<usize>) -> Self
Tests a zero-based half-open range of allocation attempts.
For example, failure_range(30..40) tests allocation attempts 30
through 39. Ranges that do not cover every observed baseline
allocation produce truncated reports.
§Panics
Panics if range.start > range.end.
Sourcepub const fn all_failures(self) -> Self
pub const fn all_failures(self) -> Self
Restores the default target selection, which tests every observed baseline allocation attempt.
Sourcepub const fn stability_runs(self, runs: usize) -> Self
pub const fn stability_runs(self, runs: usize) -> Self
Configures how many baseline counting runs are used to check allocation sequence stability before injection begins.
The default is 1, which performs no extra stability comparison. Values
greater than 1 rerun the closure in counting mode and require every
baseline run to complete with the same allocation count. Passing 0 is
treated as 1.
Examples found in repository?
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}Sourcepub const fn stop_on_failure(self, enabled: bool) -> Self
pub const fn stop_on_failure(self, enabled: bool) -> Self
Stops after the first failed iteration.
A failed iteration is one that panics or does not reach the selected allocation attempt. Early-stop reports are considered truncated unless the stopped attempt was the final observed allocation.
Sourcepub fn run<F>(self, f: F) -> Reportwhere
F: Fn(),
pub fn run<F>(self, f: F) -> Reportwhere
F: Fn(),
Runs this check.
§Panics
Panics if another check is already active in the process. Use
Check::try_run to handle that case explicitly.
Examples found in repository?
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}Sourcepub fn try_run<F>(self, f: F) -> Result<Report, AlreadyRunning>where
F: Fn(),
pub fn try_run<F>(self, f: F) -> Result<Report, AlreadyRunning>where
F: Fn(),
Fallible variant of Check::run.