Skip to content

FailingAllocator: remove outdated doc comments, move doc comment example to decltest #23613

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 23, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 38 additions & 14 deletions lib/std/testing/FailingAllocator.zig
Original file line number Diff line number Diff line change
@@ -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();
Expand All @@ -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.
Expand Down Expand Up @@ -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
}
}
Loading