diff options
| author | Benjamin Feng <benjamin.feng@glassdoor.com> | 2020-01-29 17:26:10 -0600 |
|---|---|---|
| committer | Benjamin Feng <benjamin.feng@glassdoor.com> | 2020-01-29 17:38:42 -0600 |
| commit | 0c137934cbd10528c2dced898b6c5485ab528e6d (patch) | |
| tree | bb55926127481fa0a81b0c858ceeec42b8526c29 /lib/std/testing/leak_count_allocator.zig | |
| parent | ffd30dbe28efce0b971d69df06ab684ceef0f881 (diff) | |
| download | zig-0c137934cbd10528c2dced898b6c5485ab528e6d.tar.gz zig-0c137934cbd10528c2dced898b6c5485ab528e6d.zip | |
Move FailingAllocator to testing
Diffstat (limited to 'lib/std/testing/leak_count_allocator.zig')
| -rw-r--r-- | lib/std/testing/leak_count_allocator.zig | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/lib/std/testing/leak_count_allocator.zig b/lib/std/testing/leak_count_allocator.zig new file mode 100644 index 0000000000..84c3248178 --- /dev/null +++ b/lib/std/testing/leak_count_allocator.zig @@ -0,0 +1,46 @@ +const std = @import("../std.zig"); + +/// This allocator is used in front of another allocator and counts the numbers of allocs and frees. +/// The test runner asserts every alloc has a corresponding free at the end of each test. +/// +/// The detection algorithm is incredibly primitive and only accounts for number of calls. +/// This should be replaced by the general purpose debug allocator. +pub const LeakCountAllocator = struct { + count: usize, + allocator: std.mem.Allocator, + internal_allocator: *std.mem.Allocator, + + pub fn init(allocator: *std.mem.Allocator) LeakCountAllocator { + return .{ + .count = 0, + .allocator = .{ + .reallocFn = realloc, + .shrinkFn = shrink, + }, + .internal_allocator = allocator, + }; + } + + fn realloc(allocator: *std.mem.Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 { + const self = @fieldParentPtr(LeakCountAllocator, "allocator", allocator); + if (old_mem.len == 0) { + self.count += 1; + } + return self.internal_allocator.reallocFn(self.internal_allocator, old_mem, old_align, new_size, new_align); + } + + fn shrink(allocator: *std.mem.Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 { + const self = @fieldParentPtr(LeakCountAllocator, "allocator", allocator); + if (new_size == 0) { + self.count -= 1; + } + return self.internal_allocator.shrinkFn(self.internal_allocator, old_mem, old_align, new_size, new_align); + } + + pub fn validate(self: LeakCountAllocator) !void { + if (self.count > 0) { + std.debug.warn("Detected leaked allocations without matching free: {}\n", .{self.count}); + return error.Leak; + } + } +}; |
