I have a logic that conditionally allocates.
Is there a clean way to have a tests where I can confirm that allocation occurs in the path that should allocate?
I have a logic that conditionally allocates.
Is there a clean way to have a tests where I can confirm that allocation occurs in the path that should allocate?
I use the std.testing.allocator
, and while testing the path that should not allocate, I do not call the necessary denit function in the test.
So if tests runs, and no leak is detected, I assume that means no allocation happened.
Not sure if there is a better/cleaner way
There is a std.testing.checkAllAllocationFailures(…) that you could use. This doesn’t do exactly what you want, but might be something to read and base a solution off it. Another option would be to write your own allocator that can track allocations like you want.
I am curious as to why you would need to assert that one particular allocation succeds. Of we had more context, there might be another option for what you are trying to verify.
If you only want to know if an allocation occured, you should be able to check that std.testing.allocator_instance.total_requested_bytes
is non zero
There is also std.testing.FailingAllocator
. You can set fail_index
to 1
, call your function and then expect the next allocation to fail:
test {
var failer = std.testing.FailingAllocator.init(std.testing.allocator, .{ .fail_index = 1 });
const allocator = failer.allocator();
const cond = true;
// Your function that conditionally allocates
foo(allocator, cond);
try std.testing.expectError(error.OutOfMemory, allocator.create(u8));
}
failer
also keeps track of allocated_bytes
.
I like this strategy, but I think it might be more intuitive/readable to not set a fail point and just check the allocation count:
test {
var failer = std.testing.FailingAllocator.init(std.testing.allocator, .{});
const allocator = failer.allocator();
const cond = true;
// Your function that conditionally allocates
foo(allocator, cond);
try std.testing.expectEqual(failer.allocations, 1);
// you could also do expect(failer.allocations > 0)
}
Yeah sure, that might be a better way to express intent here.
You could also use a pattern similiar to this test from std
:
test {
// Should allocate
try testing.expectError(error.OutOfMemory, foo(std.testing.failing_allocator, true));
// Should not allocate
try foo(std.testing.failing_allocator, false);
}
Yeah, I like that for the negative case (no allocation) because it gives an error trace pointing to where the allocation happened.