Move FailingAllocator to testing

This commit is contained in:
Benjamin Feng 2020-01-29 17:26:10 -06:00
parent ffd30dbe28
commit 0c137934cb
6 changed files with 56 additions and 51 deletions

View File

@ -19,8 +19,8 @@ const windows = std.os.windows;
pub const leb = @import("debug/leb128.zig");
pub const FailingAllocator = @import("debug/failing_allocator.zig").FailingAllocator;
pub const failing_allocator = &FailingAllocator.init(&global_fixed_allocator.allocator, 0).allocator;
pub const global_allocator = @compileError("Please switch to std.testing.leak_count_allocator.");
pub const failing_allocator = @compileError("Please switch to std.testing.failing_allocator.");
pub const runtime_safety = switch (builtin.mode) {
.Debug, .ReleaseSafe => true,
@ -2192,12 +2192,6 @@ fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool)
}
}
pub const global_allocator = blk: {
@compileError("Please switch to std.testing.leak_count_allocator.");
};
var global_fixed_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(global_allocator_mem[0..]);
var global_allocator_mem: [100 * 1024]u8 = undefined;
/// TODO multithreaded awareness
var debug_info_allocator: ?*mem.Allocator = null;
var debug_info_arena_allocator: std.heap.ArenaAllocator = undefined;

View File

@ -891,7 +891,7 @@ pub fn readLineSlice(slice: []u8) ![]u8 {
pub fn readLineSliceFrom(stream: var, slice: []u8) ![]u8 {
// We cannot use Buffer.fromOwnedSlice, as it wants to append a null byte
// after taking ownership, which would always require an allocation.
var buf = std.Buffer{ .list = std.ArrayList(u8).fromOwnedSlice(debug.failing_allocator, slice) };
var buf = std.Buffer{ .list = std.ArrayList(u8).fromOwnedSlice(testing.failing_allocator, slice) };
try buf.resize(0);
return try readLineFrom(stream, &buf);
}

View File

@ -7,47 +7,12 @@ pub const allocator = &allocator_instance.allocator;
pub var allocator_instance = std.heap.ThreadSafeFixedBufferAllocator.init(allocator_mem[0..]);
var allocator_mem: [100 * 1024]u8 = undefined;
pub const leak_count_allocator = &leak_count_allocator_instance.allocator;
pub const FailingAllocator = @import("testing/failing_allocator.zig").FailingAllocator;
pub const failing_allocator = &FailingAllocator.init(allocator, 0).allocator;
pub const LeakCountAllocator = @import("testing/leak_count_allocator.zig").LeakCountAllocator;
pub var leak_count_allocator_instance = LeakCountAllocator.init(allocator);
const LeakCountAllocator = struct {
count: usize,
allocator: std.mem.Allocator,
internal_allocator: *std.mem.Allocator,
fn init(allo: *std.mem.Allocator) LeakCountAllocator {
return .{
.count = 0,
.allocator = .{
.reallocFn = realloc,
.shrinkFn = shrink,
},
.internal_allocator = allo,
};
}
fn realloc(allo: *std.mem.Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
const self = @fieldParentPtr(LeakCountAllocator, "allocator", allo);
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(allo: *std.mem.Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
const self = @fieldParentPtr(LeakCountAllocator, "allocator", allo);
if (new_size == 0) {
self.count -= 1;
}
return self.internal_allocator.shrinkFn(self.internal_allocator, old_mem, old_align, new_size, new_align);
}
fn validate(self: LeakCountAllocator) !void {
if (self.count > 0) {
std.debug.warn("Detected leaked allocations without matching free: {}\n", .{self.count});
return error.Leak;
}
}
};
pub const leak_count_allocator = &leak_count_allocator_instance.allocator;
/// This function is intended to be used only in tests. It prints diagnostics to stderr
/// and then aborts when actual_error_union is not expected_error.

View File

@ -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;
}
}
};

View File

@ -2773,7 +2773,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {
const needed_alloc_count = x: {
// Try it once with unlimited memory, make sure it works
var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, maxInt(usize));
var failing_allocator = std.testing.FailingAllocator.init(&fixed_allocator.allocator, maxInt(usize));
var anything_changed: bool = undefined;
const result_source = try testParse(source, &failing_allocator.allocator, &anything_changed);
if (!mem.eql(u8, result_source, expected_source)) {
@ -2797,7 +2797,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {
var fail_index: usize = 0;
while (fail_index < needed_alloc_count) : (fail_index += 1) {
var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, fail_index);
var failing_allocator = std.testing.FailingAllocator.init(&fixed_allocator.allocator, fail_index);
var anything_changed: bool = undefined;
if (testParse(source, &failing_allocator.allocator, &anything_changed)) |_| {
return error.NondeterministicMemoryUsage;