Commit c06fecd466
Changed files (1)
lib
std
testing
lib/std/testing/FailingAllocator.zig
@@ -1,13 +1,5 @@
//! Allocator that fails after N allocations, useful for making sure out of
//! memory conditions are handled correctly.
-//!
-//! To use this, first initialize it and get an allocator with
-//!
-//! `const failing_allocator = &FailingAllocator.init(<allocator>,
-//! <config>).allocator;`
-//!
-//! Then use `failing_allocator` anywhere you would have used a
-//! different allocator.
const std = @import("../std.zig");
const mem = std.mem;
const FailingAllocator = @This();
@@ -28,12 +20,7 @@ const num_stack_frames = if (std.debug.sys_can_stack_trace) 16 else 0;
pub const Config = struct {
/// The number of successful allocations you can expect from this allocator.
- /// The next allocation will fail. For example, with `fail_index` equal to
- /// 2, the following test will pass:
- ///
- /// var a = try failing_alloc.create(i32);
- /// var b = try failing_alloc.create(i32);
- /// testing.expectError(error.OutOfMemory, failing_alloc.create(i32));
+ /// The next allocation will fail.
fail_index: usize = std.math.maxInt(usize),
/// Number of successful resizes to expect from this allocator. The next resize will fail.
@@ -159,3 +146,40 @@ pub fn getStackTrace(self: *FailingAllocator) std.builtin.StackTrace {
.index = len,
};
}
+
+test FailingAllocator {
+ // Fail on allocation
+ {
+ var failing_allocator_state = FailingAllocator.init(std.testing.allocator, .{
+ .fail_index = 2,
+ });
+ const failing_alloc = failing_allocator_state.allocator();
+
+ const a = try failing_alloc.create(i32);
+ defer failing_alloc.destroy(a);
+ const b = try failing_alloc.create(i32);
+ defer failing_alloc.destroy(b);
+ try std.testing.expectError(error.OutOfMemory, failing_alloc.create(i32));
+ }
+ // Fail on resize
+ {
+ var failing_allocator_state = FailingAllocator.init(std.testing.allocator, .{
+ .resize_fail_index = 1,
+ });
+ const failing_alloc = failing_allocator_state.allocator();
+
+ const resized_slice = blk: {
+ const slice = try failing_alloc.alloc(u8, 8);
+ errdefer failing_alloc.free(slice);
+
+ break :blk failing_alloc.remap(slice, 6) orelse return error.UnexpectedRemapFailure;
+ };
+ defer failing_alloc.free(resized_slice);
+
+ // Remap and resize should fail from here on out
+ try std.testing.expectEqual(null, failing_alloc.remap(resized_slice, 4));
+ try std.testing.expectEqual(false, failing_alloc.resize(resized_slice, 4));
+
+ // Note: realloc could succeed because it falls back to free+alloc
+ }
+}