From 30ae93236a3022e062e8ab9a1db066f3165cec34 Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Sat, 19 Apr 2025 15:37:08 -0700 Subject: [PATCH] FailingAllocator: remove outdated doc comments, move doc comment example to decltest Note: The decltests for files-as-a-struct don't show up in autodoc currently --- lib/std/testing/FailingAllocator.zig | 52 ++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/lib/std/testing/FailingAllocator.zig b/lib/std/testing/FailingAllocator.zig index c7767ae02fec..c1f9791e39a9 100644 --- a/lib/std/testing/FailingAllocator.zig +++ b/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;` -//! -//! 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 + } +}