authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-30 10:01:40-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-01-30 10:01:40-05:00
log65b1a4953fd5b87f30260beb363d0e968dc8e291
treeab01d1b6699d103b4b075807f47c136926404f92
parente3a383a661aaf9b43016358e2951ff9d792f240e
parent9c196efa2afe0e337ac0b16bd1138e89393f6106
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #4324 from fengb/testing-allocator

Remove debug.global_allocator in favor of testing.allocator

41 files changed, 370 insertions(+), 271 deletions(-)

doc/docgen.zig+2-1
...@@ -672,7 +672,8 @@ const TermState = enum {...@@ -672,7 +672,8 @@ const TermState = enum {
672672
673test "term color" {673test "term color" {
674 const input_bytes = "A\x1b[32;1mgreen\x1b[0mB";674 const input_bytes = "A\x1b[32;1mgreen\x1b[0mB";
675 const result = try termColor(std.debug.global_allocator, input_bytes);675 const result = try termColor(std.testing.allocator, input_bytes);
676 defer std.testing.allocator.free(result);
676 testing.expectEqualSlices(u8, "A<span class=\"t32\">green</span>B", result);677 testing.expectEqualSlices(u8, "A<span class=\"t32\">green</span>B", result);
677}678}
678679
doc/langref.html.in+4-5
...@@ -5359,7 +5359,7 @@ const std = @import("std");...@@ -5359,7 +5359,7 @@ const std = @import("std");
5359const assert = std.debug.assert;5359const assert = std.debug.assert;
53605360
5361test "turn HashMap into a set with void" {5361test "turn HashMap into a set with void" {
5362 var map = std.HashMap(i32, void, hash_i32, eql_i32).init(std.debug.global_allocator);5362 var map = std.HashMap(i32, void, hash_i32, eql_i32).init(std.testing.allocator);
5363 defer map.deinit();5363 defer map.deinit();
53645364
5365 _ = try map.put(1, {});5365 _ = try map.put(1, {});
...@@ -9281,9 +9281,8 @@ fn concat(allocator: *Allocator, a: []const u8, b: []const u8) ![]u8 {...@@ -9281,9 +9281,8 @@ fn concat(allocator: *Allocator, a: []const u8, b: []const u8) ![]u8 {
9281 In the above example, 100 bytes of stack memory are used to initialize a9281 In the above example, 100 bytes of stack memory are used to initialize a
9282 {#syntax#}FixedBufferAllocator{#endsyntax#}, which is then passed to a function.9282 {#syntax#}FixedBufferAllocator{#endsyntax#}, which is then passed to a function.
9283 As a convenience there is a global {#syntax#}FixedBufferAllocator{#endsyntax#}9283 As a convenience there is a global {#syntax#}FixedBufferAllocator{#endsyntax#}
9284 available for quick tests at {#syntax#}std.debug.global_allocator{#endsyntax#},9284 available for quick tests at {#syntax#}std.testing.allocator{#endsyntax#},
9285 however it is deprecated and should be avoided in favor of directly using a9285 which will also do perform basic leak detection.
9286 {#syntax#}FixedBufferAllocator{#endsyntax#} as in the example above.
9287 </p>9286 </p>
9288 <p>9287 <p>
9289 Currently Zig has no general purpose allocator, but there is9288 Currently Zig has no general purpose allocator, but there is
...@@ -9341,7 +9340,7 @@ pub fn main() !void {...@@ -9341,7 +9340,7 @@ pub fn main() !void {
9341 </li>9340 </li>
9342 <li>9341 <li>
9343 Are you writing a test, and you want to make sure {#syntax#}error.OutOfMemory{#endsyntax#}9342 Are you writing a test, and you want to make sure {#syntax#}error.OutOfMemory{#endsyntax#}
9344 is handled correctly? In this case, use {#syntax#}std.debug.FailingAllocator{#endsyntax#}.9343 is handled correctly? In this case, use {#syntax#}std.testing.FailingAllocator{#endsyntax#}.
9345 </li>9344 </li>
9346 <li>9345 <li>
9347 Finally, if none of the above apply, you need a general purpose allocator. Zig does not9346 Finally, if none of the above apply, you need a general purpose allocator. Zig does not
lib/std/array_list.zig+8-7
...@@ -320,7 +320,7 @@ test "std.ArrayList.basic" {...@@ -320,7 +320,7 @@ test "std.ArrayList.basic" {
320}320}
321321
322test "std.ArrayList.orderedRemove" {322test "std.ArrayList.orderedRemove" {
323 var list = ArrayList(i32).init(debug.global_allocator);323 var list = ArrayList(i32).init(testing.allocator);
324 defer list.deinit();324 defer list.deinit();
325325
326 try list.append(1);326 try list.append(1);
...@@ -347,7 +347,7 @@ test "std.ArrayList.orderedRemove" {...@@ -347,7 +347,7 @@ test "std.ArrayList.orderedRemove" {
347}347}
348348
349test "std.ArrayList.swapRemove" {349test "std.ArrayList.swapRemove" {
350 var list = ArrayList(i32).init(debug.global_allocator);350 var list = ArrayList(i32).init(testing.allocator);
351 defer list.deinit();351 defer list.deinit();
352352
353 try list.append(1);353 try list.append(1);
...@@ -374,7 +374,7 @@ test "std.ArrayList.swapRemove" {...@@ -374,7 +374,7 @@ test "std.ArrayList.swapRemove" {
374}374}
375375
376test "std.ArrayList.swapRemoveOrError" {376test "std.ArrayList.swapRemoveOrError" {
377 var list = ArrayList(i32).init(debug.global_allocator);377 var list = ArrayList(i32).init(testing.allocator);
378 defer list.deinit();378 defer list.deinit();
379379
380 // Test just after initialization380 // Test just after initialization
...@@ -402,7 +402,7 @@ test "std.ArrayList.swapRemoveOrError" {...@@ -402,7 +402,7 @@ test "std.ArrayList.swapRemoveOrError" {
402}402}
403403
404test "std.ArrayList.insert" {404test "std.ArrayList.insert" {
405 var list = ArrayList(i32).init(debug.global_allocator);405 var list = ArrayList(i32).init(testing.allocator);
406 defer list.deinit();406 defer list.deinit();
407407
408 try list.append(1);408 try list.append(1);
...@@ -416,7 +416,7 @@ test "std.ArrayList.insert" {...@@ -416,7 +416,7 @@ test "std.ArrayList.insert" {
416}416}
417417
418test "std.ArrayList.insertSlice" {418test "std.ArrayList.insertSlice" {
419 var list = ArrayList(i32).init(debug.global_allocator);419 var list = ArrayList(i32).init(testing.allocator);
420 defer list.deinit();420 defer list.deinit();
421421
422 try list.append(1);422 try list.append(1);
...@@ -443,7 +443,8 @@ const Item = struct {...@@ -443,7 +443,8 @@ const Item = struct {
443};443};
444444
445test "std.ArrayList: ArrayList(T) of struct T" {445test "std.ArrayList: ArrayList(T) of struct T" {
446 var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(debug.global_allocator) };446 var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(testing.allocator) };
447 try root.sub_items.append(Item{ .integer = 42, .sub_items = ArrayList(Item).init(debug.global_allocator) });447 defer root.sub_items.deinit();
448 try root.sub_items.append(Item{ .integer = 42, .sub_items = ArrayList(Item).init(testing.allocator) });
448 testing.expect(root.sub_items.items[0].integer == 42);449 testing.expect(root.sub_items.items[0].integer == 42);
449}450}
lib/std/buf_map.zig+4-3
...@@ -43,9 +43,10 @@ pub const BufMap = struct {...@@ -43,9 +43,10 @@ pub const BufMap = struct {
43 pub fn set(self: *BufMap, key: []const u8, value: []const u8) !void {43 pub fn set(self: *BufMap, key: []const u8, value: []const u8) !void {
44 const value_copy = try self.copy(value);44 const value_copy = try self.copy(value);
45 errdefer self.free(value_copy);45 errdefer self.free(value_copy);
46 // Avoid copying key if it already exists
47 const get_or_put = try self.hash_map.getOrPut(key);46 const get_or_put = try self.hash_map.getOrPut(key);
48 if (!get_or_put.found_existing) {47 if (get_or_put.found_existing) {
48 self.free(get_or_put.kv.value);
49 } else {
49 get_or_put.kv.key = self.copy(key) catch |err| {50 get_or_put.kv.key = self.copy(key) catch |err| {
50 _ = self.hash_map.remove(key);51 _ = self.hash_map.remove(key);
51 return err;52 return err;
...@@ -83,7 +84,7 @@ pub const BufMap = struct {...@@ -83,7 +84,7 @@ pub const BufMap = struct {
83};84};
8485
85test "BufMap" {86test "BufMap" {
86 var bufmap = BufMap.init(std.heap.page_allocator);87 var bufmap = BufMap.init(std.testing.allocator);
87 defer bufmap.deinit();88 defer bufmap.deinit();
8889
89 try bufmap.set("x", "1");90 try bufmap.set("x", "1");
lib/std/buf_set.zig+1-1
...@@ -65,7 +65,7 @@ pub const BufSet = struct {...@@ -65,7 +65,7 @@ pub const BufSet = struct {
65};65};
6666
67test "BufSet" {67test "BufSet" {
68 var bufset = BufSet.init(std.heap.page_allocator);68 var bufset = BufSet.init(std.testing.allocator);
69 defer bufset.deinit();69 defer bufset.deinit();
7070
71 try bufset.put("x");71 try bufset.put("x");
lib/std/buffer.zig+8-3
...@@ -150,7 +150,9 @@ pub const Buffer = struct {...@@ -150,7 +150,9 @@ pub const Buffer = struct {
150};150};
151151
152test "simple Buffer" {152test "simple Buffer" {
153 var buf = try Buffer.init(debug.global_allocator, "");153 var buf = try Buffer.init(testing.allocator, "");
154 defer buf.deinit();
155
154 testing.expect(buf.len() == 0);156 testing.expect(buf.len() == 0);
155 try buf.append("hello");157 try buf.append("hello");
156 try buf.append(" ");158 try buf.append(" ");
...@@ -159,6 +161,7 @@ test "simple Buffer" {...@@ -159,6 +161,7 @@ test "simple Buffer" {
159 testing.expect(mem.eql(u8, mem.toSliceConst(u8, buf.toSliceConst().ptr), buf.toSliceConst()));161 testing.expect(mem.eql(u8, mem.toSliceConst(u8, buf.toSliceConst().ptr), buf.toSliceConst()));
160162
161 var buf2 = try Buffer.initFromBuffer(buf);163 var buf2 = try Buffer.initFromBuffer(buf);
164 defer buf2.deinit();
162 testing.expect(buf.eql(buf2.toSliceConst()));165 testing.expect(buf.eql(buf2.toSliceConst()));
163166
164 testing.expect(buf.startsWith("hell"));167 testing.expect(buf.startsWith("hell"));
...@@ -169,14 +172,16 @@ test "simple Buffer" {...@@ -169,14 +172,16 @@ test "simple Buffer" {
169}172}
170173
171test "Buffer.initSize" {174test "Buffer.initSize" {
172 var buf = try Buffer.initSize(debug.global_allocator, 3);175 var buf = try Buffer.initSize(testing.allocator, 3);
176 defer buf.deinit();
173 testing.expect(buf.len() == 3);177 testing.expect(buf.len() == 3);
174 try buf.append("hello");178 try buf.append("hello");
175 testing.expect(mem.eql(u8, buf.toSliceConst()[3..], "hello"));179 testing.expect(mem.eql(u8, buf.toSliceConst()[3..], "hello"));
176}180}
177181
178test "Buffer.initCapacity" {182test "Buffer.initCapacity" {
179 var buf = try Buffer.initCapacity(debug.global_allocator, 10);183 var buf = try Buffer.initCapacity(testing.allocator, 10);
184 defer buf.deinit();
180 testing.expect(buf.len() == 0);185 testing.expect(buf.len() == 0);
181 testing.expect(buf.capacity() >= 10);186 testing.expect(buf.capacity() >= 10);
182 const old_cap = buf.capacity();187 const old_cap = buf.capacity();
lib/std/build.zig+3
...@@ -1059,7 +1059,10 @@ pub const Builder = struct {...@@ -1059,7 +1059,10 @@ pub const Builder = struct {
1059};1059};
10601060
1061test "builder.findProgram compiles" {1061test "builder.findProgram compiles" {
1062 // TODO: uncomment and fix the leak
1063 // const builder = try Builder.create(std.testing.allocator, "zig", "zig-cache", "zig-cache");
1062 const builder = try Builder.create(std.heap.page_allocator, "zig", "zig-cache", "zig-cache");1064 const builder = try Builder.create(std.heap.page_allocator, "zig", "zig-cache", "zig-cache");
1065 defer builder.destroy();
1063 _ = builder.findProgram(&[_][]const u8{}, &[_][]const u8{}) catch null;1066 _ = builder.findProgram(&[_][]const u8{}, &[_][]const u8{}) catch null;
1064}1067}
10651068
lib/std/debug.zig+2-7
...@@ -19,8 +19,8 @@ const windows = std.os.windows;...@@ -19,8 +19,8 @@ const windows = std.os.windows;
1919
20pub const leb = @import("debug/leb128.zig");20pub const leb = @import("debug/leb128.zig");
2121
22pub const FailingAllocator = @import("debug/failing_allocator.zig").FailingAllocator;22pub const global_allocator = @compileError("Please switch to std.testing.allocator.");
23pub const failing_allocator = &FailingAllocator.init(global_allocator, 0).allocator;23pub const failing_allocator = @compileError("Please switch to std.testing.failing_allocator.");
2424
25pub const runtime_safety = switch (builtin.mode) {25pub const runtime_safety = switch (builtin.mode) {
26 .Debug, .ReleaseSafe => true,26 .Debug, .ReleaseSafe => true,
...@@ -2196,11 +2196,6 @@ fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool)...@@ -2196,11 +2196,6 @@ fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool)
2196 }2196 }
2197}2197}
21982198
2199/// This should only be used in temporary test programs.
2200pub const global_allocator = &global_fixed_allocator.allocator;
2201var global_fixed_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(global_allocator_mem[0..]);
2202var global_allocator_mem: [100 * 1024]u8 = undefined;
2203
2204/// TODO multithreaded awareness2199/// TODO multithreaded awareness
2205var debug_info_allocator: ?*mem.Allocator = null;2200var debug_info_allocator: ?*mem.Allocator = null;
2206var debug_info_arena_allocator: std.heap.ArenaAllocator = undefined;2201var debug_info_arena_allocator: std.heap.ArenaAllocator = undefined;
lib/std/debug/failing_allocator.zig deleted-81
...@@ -1,81 +0,0 @@
1const std = @import("../std.zig");
2const mem = std.mem;
3
4/// Allocator that fails after N allocations, useful for making sure out of
5/// memory conditions are handled correctly.
6///
7/// To use this, first initialize it and get an allocator with
8///
9/// `const failing_allocator = &FailingAllocator.init(<allocator>,
10/// <fail_index>).allocator;`
11///
12/// Then use `failing_allocator` anywhere you would have used a
13/// different allocator.
14pub const FailingAllocator = struct {
15 allocator: mem.Allocator,
16 index: usize,
17 fail_index: usize,
18 internal_allocator: *mem.Allocator,
19 allocated_bytes: usize,
20 freed_bytes: usize,
21 allocations: usize,
22 deallocations: usize,
23
24 /// `fail_index` is the number of successful allocations you can
25 /// expect from this allocator. The next allocation will fail.
26 /// For example, if this is called with `fail_index` equal to 2,
27 /// the following test will pass:
28 ///
29 /// var a = try failing_alloc.create(i32);
30 /// var b = try failing_alloc.create(i32);
31 /// testing.expectError(error.OutOfMemory, failing_alloc.create(i32));
32 pub fn init(allocator: *mem.Allocator, fail_index: usize) FailingAllocator {
33 return FailingAllocator{
34 .internal_allocator = allocator,
35 .fail_index = fail_index,
36 .index = 0,
37 .allocated_bytes = 0,
38 .freed_bytes = 0,
39 .allocations = 0,
40 .deallocations = 0,
41 .allocator = mem.Allocator{
42 .reallocFn = realloc,
43 .shrinkFn = shrink,
44 },
45 };
46 }
47
48 fn realloc(allocator: *mem.Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
49 const self = @fieldParentPtr(FailingAllocator, "allocator", allocator);
50 if (self.index == self.fail_index) {
51 return error.OutOfMemory;
52 }
53 const result = try self.internal_allocator.reallocFn(
54 self.internal_allocator,
55 old_mem,
56 old_align,
57 new_size,
58 new_align,
59 );
60 if (new_size < old_mem.len) {
61 self.freed_bytes += old_mem.len - new_size;
62 if (new_size == 0)
63 self.deallocations += 1;
64 } else if (new_size > old_mem.len) {
65 self.allocated_bytes += new_size - old_mem.len;
66 if (old_mem.len == 0)
67 self.allocations += 1;
68 }
69 self.index += 1;
70 return result;
71 }
72
73 fn shrink(allocator: *mem.Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
74 const self = @fieldParentPtr(FailingAllocator, "allocator", allocator);
75 const r = self.internal_allocator.shrinkFn(self.internal_allocator, old_mem, old_align, new_size, new_align);
76 self.freed_bytes += old_mem.len - r.len;
77 if (new_size == 0)
78 self.deallocations += 1;
79 return r;
80 }
81};
lib/std/fifo.zig+2-2
...@@ -347,7 +347,7 @@ pub fn LinearFifo(...@@ -347,7 +347,7 @@ pub fn LinearFifo(
347}347}
348348
349test "LinearFifo(u8, .Dynamic)" {349test "LinearFifo(u8, .Dynamic)" {
350 var fifo = LinearFifo(u8, .Dynamic).init(debug.global_allocator);350 var fifo = LinearFifo(u8, .Dynamic).init(testing.allocator);
351 defer fifo.deinit();351 defer fifo.deinit();
352352
353 try fifo.write("HELLO");353 try fifo.write("HELLO");
...@@ -422,7 +422,7 @@ test "LinearFifo" {...@@ -422,7 +422,7 @@ test "LinearFifo" {
422 var fifo = switch (bt) {422 var fifo = switch (bt) {
423 .Static => FifoType.init(),423 .Static => FifoType.init(),
424 .Slice => FifoType.init(buf[0..]),424 .Slice => FifoType.init(buf[0..]),
425 .Dynamic => FifoType.init(debug.global_allocator),425 .Dynamic => FifoType.init(testing.allocator),
426 };426 };
427 defer fifo.deinit();427 defer fifo.deinit();
428428
lib/std/fmt.zig+10-5
...@@ -1598,7 +1598,8 @@ test "hexToBytes" {...@@ -1598,7 +1598,8 @@ test "hexToBytes" {
1598test "formatIntValue with comptime_int" {1598test "formatIntValue with comptime_int" {
1599 const value: comptime_int = 123456789123456789;1599 const value: comptime_int = 123456789123456789;
16001600
1601 var buf = try std.Buffer.init(std.debug.global_allocator, "");1601 var buf = try std.Buffer.init(std.testing.allocator, "");
1602 defer buf.deinit();
1602 try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append);1603 try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append);
1603 std.testing.expect(mem.eql(u8, buf.toSlice(), "123456789123456789"));1604 std.testing.expect(mem.eql(u8, buf.toSlice(), "123456789123456789"));
1604}1605}
...@@ -1652,19 +1653,23 @@ test "formatType max_depth" {...@@ -1652,19 +1653,23 @@ test "formatType max_depth" {
1652 inst.a = &inst;1653 inst.a = &inst;
1653 inst.tu.ptr = &inst.tu;1654 inst.tu.ptr = &inst.tu;
16541655
1655 var buf0 = try std.Buffer.init(std.debug.global_allocator, "");1656 var buf0 = try std.Buffer.init(std.testing.allocator, "");
1657 defer buf0.deinit();
1656 try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 0);1658 try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 0);
1657 std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }"));1659 std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }"));
16581660
1659 var buf1 = try std.Buffer.init(std.debug.global_allocator, "");1661 var buf1 = try std.Buffer.init(std.testing.allocator, "");
1662 defer buf1.deinit();
1660 try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 1);1663 try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 1);
1661 std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));1664 std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
16621665
1663 var buf2 = try std.Buffer.init(std.debug.global_allocator, "");1666 var buf2 = try std.Buffer.init(std.testing.allocator, "");
1667 defer buf2.deinit();
1664 try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 2);1668 try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 2);
1665 std.testing.expect(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));1669 std.testing.expect(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));
16661670
1667 var buf3 = try std.Buffer.init(std.debug.global_allocator, "");1671 var buf3 = try std.Buffer.init(std.testing.allocator, "");
1672 defer buf3.deinit();
1668 try formatType(inst, "", FormatOptions{}, &buf3, @TypeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 3);1673 try formatType(inst, "", FormatOptions{}, &buf3, @TypeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 3);
1669 std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));1674 std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
1670}1675}
lib/std/fs/path.zig+87-79
...@@ -665,15 +665,16 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -665,15 +665,16 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
665}665}
666666
667test "resolve" {667test "resolve" {
668 const cwd = try process.getCwdAlloc(debug.global_allocator);668 const cwd = try process.getCwdAlloc(testing.allocator);
669 defer testing.allocator.free(cwd);
669 if (builtin.os == .windows) {670 if (builtin.os == .windows) {
670 if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {671 if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {
671 cwd[0] = asciiUpper(cwd[0]);672 cwd[0] = asciiUpper(cwd[0]);
672 }673 }
673 testing.expect(mem.eql(u8, testResolveWindows(&[_][]const u8{"."}), cwd));674 try testResolveWindows(&[_][]const u8{"."}, cwd);
674 } else {675 } else {
675 testing.expect(mem.eql(u8, testResolvePosix(&[_][]const u8{ "a/b/c/", "../../.." }), cwd));676 try testResolvePosix(&[_][]const u8{ "a/b/c/", "../../.." }, cwd);
676 testing.expect(mem.eql(u8, testResolvePosix(&[_][]const u8{"."}), cwd));677 try testResolvePosix(&[_][]const u8{"."}, cwd);
677 }678 }
678}679}
679680
...@@ -683,66 +684,71 @@ test "resolveWindows" {...@@ -683,66 +684,71 @@ test "resolveWindows" {
683 return error.SkipZigTest;684 return error.SkipZigTest;
684 }685 }
685 if (builtin.os == .windows) {686 if (builtin.os == .windows) {
686 const cwd = try process.getCwdAlloc(debug.global_allocator);687 const cwd = try process.getCwdAlloc(testing.allocator);
688 defer testing.allocator.free(cwd);
687 const parsed_cwd = windowsParsePath(cwd);689 const parsed_cwd = windowsParsePath(cwd);
688 {690 {
689 const result = testResolveWindows(&[_][]const u8{ "/usr/local", "lib\\zig\\std\\array_list.zig" });691 const expected = try join(testing.allocator, &[_][]const u8{
690 const expected = try join(debug.global_allocator, &[_][]const u8{
691 parsed_cwd.disk_designator,692 parsed_cwd.disk_designator,
692 "usr\\local\\lib\\zig\\std\\array_list.zig",693 "usr\\local\\lib\\zig\\std\\array_list.zig",
693 });694 });
695 defer testing.allocator.free(expected);
694 if (parsed_cwd.kind == WindowsPath.Kind.Drive) {696 if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
695 expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);697 expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);
696 }698 }
697 testing.expect(mem.eql(u8, result, expected));699 try testResolveWindows(&[_][]const u8{ "/usr/local", "lib\\zig\\std\\array_list.zig" }, expected);
698 }700 }
699 {701 {
700 const result = testResolveWindows(&[_][]const u8{ "usr/local", "lib\\zig" });702 const expected = try join(testing.allocator, &[_][]const u8{
701 const expected = try join(debug.global_allocator, &[_][]const u8{
702 cwd,703 cwd,
703 "usr\\local\\lib\\zig",704 "usr\\local\\lib\\zig",
704 });705 });
706 defer testing.allocator.free(expected);
705 if (parsed_cwd.kind == WindowsPath.Kind.Drive) {707 if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
706 expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);708 expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);
707 }709 }
708 testing.expect(mem.eql(u8, result, expected));710 try testResolveWindows(&[_][]const u8{ "usr/local", "lib\\zig" }, expected);
709 }711 }
710 }712 }
711713
712 testing.expect(mem.eql(u8, testResolveWindows(&[_][]const u8{ "c:\\a\\b\\c", "/hi", "ok" }), "C:\\hi\\ok"));714 try testResolveWindows(&[_][]const u8{ "c:\\a\\b\\c", "/hi", "ok" }, "C:\\hi\\ok");
713 testing.expect(mem.eql(u8, testResolveWindows(&[_][]const u8{ "c:/blah\\blah", "d:/games", "c:../a" }), "C:\\blah\\a"));715 try testResolveWindows(&[_][]const u8{ "c:/blah\\blah", "d:/games", "c:../a" }, "C:\\blah\\a");
714 testing.expect(mem.eql(u8, testResolveWindows(&[_][]const u8{ "c:/blah\\blah", "d:/games", "C:../a" }), "C:\\blah\\a"));716 try testResolveWindows(&[_][]const u8{ "c:/blah\\blah", "d:/games", "C:../a" }, "C:\\blah\\a");
715 testing.expect(mem.eql(u8, testResolveWindows(&[_][]const u8{ "c:/ignore", "d:\\a/b\\c/d", "\\e.exe" }), "D:\\e.exe"));717 try testResolveWindows(&[_][]const u8{ "c:/ignore", "d:\\a/b\\c/d", "\\e.exe" }, "D:\\e.exe");
716 testing.expect(mem.eql(u8, testResolveWindows(&[_][]const u8{ "c:/ignore", "c:/some/file" }), "C:\\some\\file"));718 try testResolveWindows(&[_][]const u8{ "c:/ignore", "c:/some/file" }, "C:\\some\\file");
717 testing.expect(mem.eql(u8, testResolveWindows(&[_][]const u8{ "d:/ignore", "d:some/dir//" }), "D:\\ignore\\some\\dir"));719 try testResolveWindows(&[_][]const u8{ "d:/ignore", "d:some/dir//" }, "D:\\ignore\\some\\dir");
718 testing.expect(mem.eql(u8, testResolveWindows(&[_][]const u8{ "//server/share", "..", "relative\\" }), "\\\\server\\share\\relative"));720 try testResolveWindows(&[_][]const u8{ "//server/share", "..", "relative\\" }, "\\\\server\\share\\relative");
719 testing.expect(mem.eql(u8, testResolveWindows(&[_][]const u8{ "c:/", "//" }), "C:\\"));721 try testResolveWindows(&[_][]const u8{ "c:/", "//" }, "C:\\");
720 testing.expect(mem.eql(u8, testResolveWindows(&[_][]const u8{ "c:/", "//dir" }), "C:\\dir"));722 try testResolveWindows(&[_][]const u8{ "c:/", "//dir" }, "C:\\dir");
721 testing.expect(mem.eql(u8, testResolveWindows(&[_][]const u8{ "c:/", "//server/share" }), "\\\\server\\share\\"));723 try testResolveWindows(&[_][]const u8{ "c:/", "//server/share" }, "\\\\server\\share\\");
722 testing.expect(mem.eql(u8, testResolveWindows(&[_][]const u8{ "c:/", "//server//share" }), "\\\\server\\share\\"));724 try testResolveWindows(&[_][]const u8{ "c:/", "//server//share" }, "\\\\server\\share\\");
723 testing.expect(mem.eql(u8, testResolveWindows(&[_][]const u8{ "c:/", "///some//dir" }), "C:\\some\\dir"));725 try testResolveWindows(&[_][]const u8{ "c:/", "///some//dir" }, "C:\\some\\dir");
724 testing.expect(mem.eql(u8, testResolveWindows(&[_][]const u8{ "C:\\foo\\tmp.3\\", "..\\tmp.3\\cycles\\root.js" }), "C:\\foo\\tmp.3\\cycles\\root.js"));726 try testResolveWindows(&[_][]const u8{ "C:\\foo\\tmp.3\\", "..\\tmp.3\\cycles\\root.js" }, "C:\\foo\\tmp.3\\cycles\\root.js");
725}727}
726728
727test "resolvePosix" {729test "resolvePosix" {
728 testing.expect(mem.eql(u8, testResolvePosix(&[_][]const u8{ "/a/b", "c" }), "/a/b/c"));730 try testResolvePosix(&[_][]const u8{ "/a/b", "c" }, "/a/b/c");
729 testing.expect(mem.eql(u8, testResolvePosix(&[_][]const u8{ "/a/b", "c", "//d", "e///" }), "/d/e"));731 try testResolvePosix(&[_][]const u8{ "/a/b", "c", "//d", "e///" }, "/d/e");
730 testing.expect(mem.eql(u8, testResolvePosix(&[_][]const u8{ "/a/b/c", "..", "../" }), "/a"));732 try testResolvePosix(&[_][]const u8{ "/a/b/c", "..", "../" }, "/a");
731 testing.expect(mem.eql(u8, testResolvePosix(&[_][]const u8{ "/", "..", ".." }), "/"));733 try testResolvePosix(&[_][]const u8{ "/", "..", ".." }, "/");
732 testing.expect(mem.eql(u8, testResolvePosix(&[_][]const u8{"/a/b/c/"}), "/a/b/c"));734 try testResolvePosix(&[_][]const u8{"/a/b/c/"}, "/a/b/c");
733735
734 testing.expect(mem.eql(u8, testResolvePosix(&[_][]const u8{ "/var/lib", "../", "file/" }), "/var/file"));736 try testResolvePosix(&[_][]const u8{ "/var/lib", "../", "file/" }, "/var/file");
735 testing.expect(mem.eql(u8, testResolvePosix(&[_][]const u8{ "/var/lib", "/../", "file/" }), "/file"));737 try testResolvePosix(&[_][]const u8{ "/var/lib", "/../", "file/" }, "/file");
736 testing.expect(mem.eql(u8, testResolvePosix(&[_][]const u8{ "/some/dir", ".", "/absolute/" }), "/absolute"));738 try testResolvePosix(&[_][]const u8{ "/some/dir", ".", "/absolute/" }, "/absolute");
737 testing.expect(mem.eql(u8, testResolvePosix(&[_][]const u8{ "/foo/tmp.3/", "../tmp.3/cycles/root.js" }), "/foo/tmp.3/cycles/root.js"));739 try testResolvePosix(&[_][]const u8{ "/foo/tmp.3/", "../tmp.3/cycles/root.js" }, "/foo/tmp.3/cycles/root.js");
738}740}
739741
740fn testResolveWindows(paths: []const []const u8) []u8 {742fn testResolveWindows(paths: []const []const u8, expected: []const u8) !void {
741 return resolveWindows(debug.global_allocator, paths) catch unreachable;743 const actual = try resolveWindows(testing.allocator, paths);
744 defer testing.allocator.free(actual);
745 return testing.expect(mem.eql(u8, actual, expected));
742}746}
743747
744fn testResolvePosix(paths: []const []const u8) []u8 {748fn testResolvePosix(paths: []const []const u8, expected: []const u8) !void {
745 return resolvePosix(debug.global_allocator, paths) catch unreachable;749 const actual = try resolvePosix(testing.allocator, paths);
750 defer testing.allocator.free(actual);
751 return testing.expect(mem.eql(u8, actual, expected));
746}752}
747753
748/// If the path is a file in the current directory (no directory component)754/// If the path is a file in the current directory (no directory component)
...@@ -1126,51 +1132,53 @@ test "relative" {...@@ -1126,51 +1132,53 @@ test "relative" {
1126 // TODO https://github.com/ziglang/zig/issues/32881132 // TODO https://github.com/ziglang/zig/issues/3288
1127 return error.SkipZigTest;1133 return error.SkipZigTest;
1128 }1134 }
1129 testRelativeWindows("c:/blah\\blah", "d:/games", "D:\\games");1135 try testRelativeWindows("c:/blah\\blah", "d:/games", "D:\\games");
1130 testRelativeWindows("c:/aaaa/bbbb", "c:/aaaa", "..");1136 try testRelativeWindows("c:/aaaa/bbbb", "c:/aaaa", "..");
1131 testRelativeWindows("c:/aaaa/bbbb", "c:/cccc", "..\\..\\cccc");1137 try testRelativeWindows("c:/aaaa/bbbb", "c:/cccc", "..\\..\\cccc");
1132 testRelativeWindows("c:/aaaa/bbbb", "c:/aaaa/bbbb", "");1138 try testRelativeWindows("c:/aaaa/bbbb", "c:/aaaa/bbbb", "");
1133 testRelativeWindows("c:/aaaa/bbbb", "c:/aaaa/cccc", "..\\cccc");1139 try testRelativeWindows("c:/aaaa/bbbb", "c:/aaaa/cccc", "..\\cccc");
1134 testRelativeWindows("c:/aaaa/", "c:/aaaa/cccc", "cccc");1140 try testRelativeWindows("c:/aaaa/", "c:/aaaa/cccc", "cccc");
1135 testRelativeWindows("c:/", "c:\\aaaa\\bbbb", "aaaa\\bbbb");1141 try testRelativeWindows("c:/", "c:\\aaaa\\bbbb", "aaaa\\bbbb");
1136 testRelativeWindows("c:/aaaa/bbbb", "d:\\", "D:\\");1142 try testRelativeWindows("c:/aaaa/bbbb", "d:\\", "D:\\");
1137 testRelativeWindows("c:/AaAa/bbbb", "c:/aaaa/bbbb", "");1143 try testRelativeWindows("c:/AaAa/bbbb", "c:/aaaa/bbbb", "");
1138 testRelativeWindows("c:/aaaaa/", "c:/aaaa/cccc", "..\\aaaa\\cccc");1144 try testRelativeWindows("c:/aaaaa/", "c:/aaaa/cccc", "..\\aaaa\\cccc");
1139 testRelativeWindows("C:\\foo\\bar\\baz\\quux", "C:\\", "..\\..\\..\\..");1145 try testRelativeWindows("C:\\foo\\bar\\baz\\quux", "C:\\", "..\\..\\..\\..");
1140 testRelativeWindows("C:\\foo\\test", "C:\\foo\\test\\bar\\package.json", "bar\\package.json");1146 try testRelativeWindows("C:\\foo\\test", "C:\\foo\\test\\bar\\package.json", "bar\\package.json");
1141 testRelativeWindows("C:\\foo\\bar\\baz-quux", "C:\\foo\\bar\\baz", "..\\baz");1147 try testRelativeWindows("C:\\foo\\bar\\baz-quux", "C:\\foo\\bar\\baz", "..\\baz");
1142 testRelativeWindows("C:\\foo\\bar\\baz", "C:\\foo\\bar\\baz-quux", "..\\baz-quux");1148 try testRelativeWindows("C:\\foo\\bar\\baz", "C:\\foo\\bar\\baz-quux", "..\\baz-quux");
1143 testRelativeWindows("\\\\foo\\bar", "\\\\foo\\bar\\baz", "baz");1149 try testRelativeWindows("\\\\foo\\bar", "\\\\foo\\bar\\baz", "baz");
1144 testRelativeWindows("\\\\foo\\bar\\baz", "\\\\foo\\bar", "..");1150 try testRelativeWindows("\\\\foo\\bar\\baz", "\\\\foo\\bar", "..");
1145 testRelativeWindows("\\\\foo\\bar\\baz-quux", "\\\\foo\\bar\\baz", "..\\baz");1151 try testRelativeWindows("\\\\foo\\bar\\baz-quux", "\\\\foo\\bar\\baz", "..\\baz");
1146 testRelativeWindows("\\\\foo\\bar\\baz", "\\\\foo\\bar\\baz-quux", "..\\baz-quux");1152 try testRelativeWindows("\\\\foo\\bar\\baz", "\\\\foo\\bar\\baz-quux", "..\\baz-quux");
1147 testRelativeWindows("C:\\baz-quux", "C:\\baz", "..\\baz");1153 try testRelativeWindows("C:\\baz-quux", "C:\\baz", "..\\baz");
1148 testRelativeWindows("C:\\baz", "C:\\baz-quux", "..\\baz-quux");1154 try testRelativeWindows("C:\\baz", "C:\\baz-quux", "..\\baz-quux");
1149 testRelativeWindows("\\\\foo\\baz-quux", "\\\\foo\\baz", "..\\baz");1155 try testRelativeWindows("\\\\foo\\baz-quux", "\\\\foo\\baz", "..\\baz");
1150 testRelativeWindows("\\\\foo\\baz", "\\\\foo\\baz-quux", "..\\baz-quux");1156 try testRelativeWindows("\\\\foo\\baz", "\\\\foo\\baz-quux", "..\\baz-quux");
1151 testRelativeWindows("C:\\baz", "\\\\foo\\bar\\baz", "\\\\foo\\bar\\baz");1157 try testRelativeWindows("C:\\baz", "\\\\foo\\bar\\baz", "\\\\foo\\bar\\baz");
1152 testRelativeWindows("\\\\foo\\bar\\baz", "C:\\baz", "C:\\baz");1158 try testRelativeWindows("\\\\foo\\bar\\baz", "C:\\baz", "C:\\baz");
11531159
1154 testRelativePosix("/var/lib", "/var", "..");1160 try testRelativePosix("/var/lib", "/var", "..");
1155 testRelativePosix("/var/lib", "/bin", "../../bin");1161 try testRelativePosix("/var/lib", "/bin", "../../bin");
1156 testRelativePosix("/var/lib", "/var/lib", "");1162 try testRelativePosix("/var/lib", "/var/lib", "");
1157 testRelativePosix("/var/lib", "/var/apache", "../apache");1163 try testRelativePosix("/var/lib", "/var/apache", "../apache");
1158 testRelativePosix("/var/", "/var/lib", "lib");1164 try testRelativePosix("/var/", "/var/lib", "lib");
1159 testRelativePosix("/", "/var/lib", "var/lib");1165 try testRelativePosix("/", "/var/lib", "var/lib");
1160 testRelativePosix("/foo/test", "/foo/test/bar/package.json", "bar/package.json");1166 try testRelativePosix("/foo/test", "/foo/test/bar/package.json", "bar/package.json");
1161 testRelativePosix("/Users/a/web/b/test/mails", "/Users/a/web/b", "../..");1167 try testRelativePosix("/Users/a/web/b/test/mails", "/Users/a/web/b", "../..");
1162 testRelativePosix("/foo/bar/baz-quux", "/foo/bar/baz", "../baz");1168 try testRelativePosix("/foo/bar/baz-quux", "/foo/bar/baz", "../baz");
1163 testRelativePosix("/foo/bar/baz", "/foo/bar/baz-quux", "../baz-quux");1169 try testRelativePosix("/foo/bar/baz", "/foo/bar/baz-quux", "../baz-quux");
1164 testRelativePosix("/baz-quux", "/baz", "../baz");1170 try testRelativePosix("/baz-quux", "/baz", "../baz");
1165 testRelativePosix("/baz", "/baz-quux", "../baz-quux");1171 try testRelativePosix("/baz", "/baz-quux", "../baz-quux");
1166}1172}
11671173
1168fn testRelativePosix(from: []const u8, to: []const u8, expected_output: []const u8) void {1174fn testRelativePosix(from: []const u8, to: []const u8, expected_output: []const u8) !void {
1169 const result = relativePosix(debug.global_allocator, from, to) catch unreachable;1175 const result = try relativePosix(testing.allocator, from, to);
1176 defer testing.allocator.free(result);
1170 testing.expectEqualSlices(u8, expected_output, result);1177 testing.expectEqualSlices(u8, expected_output, result);
1171}1178}
11721179
1173fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []const u8) void {1180fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []const u8) !void {
1174 const result = relativeWindows(debug.global_allocator, from, to) catch unreachable;1181 const result = try relativeWindows(testing.allocator, from, to);
1182 defer testing.allocator.free(result);
1175 testing.expectEqualSlices(u8, expected_output, result);1183 testing.expectEqualSlices(u8, expected_output, result);
1176}1184}
lib/std/hash/auto_hash.zig+5-5
...@@ -234,8 +234,8 @@ test "hash pointer" {...@@ -234,8 +234,8 @@ test "hash pointer" {
234test "hash slice shallow" {234test "hash slice shallow" {
235 // Allocate one array dynamically so that we're assured it is not merged235 // Allocate one array dynamically so that we're assured it is not merged
236 // with the other by the optimization passes.236 // with the other by the optimization passes.
237 const array1 = try std.heap.page_allocator.create([6]u32);237 const array1 = try std.testing.allocator.create([6]u32);
238 defer std.heap.page_allocator.destroy(array1);238 defer std.testing.allocator.destroy(array1);
239 array1.* = [_]u32{ 1, 2, 3, 4, 5, 6 };239 array1.* = [_]u32{ 1, 2, 3, 4, 5, 6 };
240 const array2 = [_]u32{ 1, 2, 3, 4, 5, 6 };240 const array2 = [_]u32{ 1, 2, 3, 4, 5, 6 };
241 const a = array1[0..];241 const a = array1[0..];
...@@ -250,8 +250,8 @@ test "hash slice shallow" {...@@ -250,8 +250,8 @@ test "hash slice shallow" {
250test "hash slice deep" {250test "hash slice deep" {
251 // Allocate one array dynamically so that we're assured it is not merged251 // Allocate one array dynamically so that we're assured it is not merged
252 // with the other by the optimization passes.252 // with the other by the optimization passes.
253 const array1 = try std.heap.page_allocator.create([6]u32);253 const array1 = try std.testing.allocator.create([6]u32);
254 defer std.heap.page_allocator.destroy(array1);254 defer std.testing.allocator.destroy(array1);
255 array1.* = [_]u32{ 1, 2, 3, 4, 5, 6 };255 array1.* = [_]u32{ 1, 2, 3, 4, 5, 6 };
256 const array2 = [_]u32{ 1, 2, 3, 4, 5, 6 };256 const array2 = [_]u32{ 1, 2, 3, 4, 5, 6 };
257 const a = array1[0..];257 const a = array1[0..];
...@@ -278,7 +278,7 @@ test "hash struct deep" {...@@ -278,7 +278,7 @@ test "hash struct deep" {
278 }278 }
279 };279 };
280280
281 const allocator = std.heap.page_allocator;281 const allocator = std.testing.allocator;
282 const foo = try Foo.init(allocator, 123, 1.0, true);282 const foo = try Foo.init(allocator, 123, 1.0, true);
283 const bar = try Foo.init(allocator, 123, 1.0, true);283 const bar = try Foo.init(allocator, 123, 1.0, true);
284 const baz = try Foo.init(allocator, 123, 1.0, false);284 const baz = try Foo.init(allocator, 123, 1.0, false);
lib/std/hash_map.zig+3-3
...@@ -419,7 +419,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3...@@ -419,7 +419,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
419}419}
420420
421test "basic hash map usage" {421test "basic hash map usage" {
422 var map = AutoHashMap(i32, i32).init(std.heap.page_allocator);422 var map = AutoHashMap(i32, i32).init(std.testing.allocator);
423 defer map.deinit();423 defer map.deinit();
424424
425 testing.expect((try map.put(1, 11)) == null);425 testing.expect((try map.put(1, 11)) == null);
...@@ -463,7 +463,7 @@ test "basic hash map usage" {...@@ -463,7 +463,7 @@ test "basic hash map usage" {
463}463}
464464
465test "iterator hash map" {465test "iterator hash map" {
466 var reset_map = AutoHashMap(i32, i32).init(std.heap.page_allocator);466 var reset_map = AutoHashMap(i32, i32).init(std.testing.allocator);
467 defer reset_map.deinit();467 defer reset_map.deinit();
468468
469 try reset_map.putNoClobber(1, 11);469 try reset_map.putNoClobber(1, 11);
...@@ -509,7 +509,7 @@ test "iterator hash map" {...@@ -509,7 +509,7 @@ test "iterator hash map" {
509}509}
510510
511test "ensure capacity" {511test "ensure capacity" {
512 var map = AutoHashMap(i32, i32).init(std.heap.page_allocator);512 var map = AutoHashMap(i32, i32).init(std.testing.allocator);
513 defer map.deinit();513 defer map.deinit();
514514
515 try map.ensureCapacity(20);515 try map.ensureCapacity(20);
lib/std/heap.zig+4
...@@ -711,6 +711,10 @@ pub const ThreadSafeFixedBufferAllocator = blk: {...@@ -711,6 +711,10 @@ pub const ThreadSafeFixedBufferAllocator = blk: {
711 fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {711 fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
712 return old_mem[0..new_size];712 return old_mem[0..new_size];
713 }713 }
714
715 pub fn reset(self: *ThreadSafeFixedBufferAllocator) void {
716 self.end_index = 0;
717 }
714 };718 };
715 }719 }
716};720};
lib/std/heap/logging_allocator.zig+1-1
...@@ -57,7 +57,7 @@ test "LoggingAllocator" {...@@ -57,7 +57,7 @@ test "LoggingAllocator" {
57 var slice_stream = std.io.SliceOutStream.init(buf[0..]);57 var slice_stream = std.io.SliceOutStream.init(buf[0..]);
58 const stream = &slice_stream.stream;58 const stream = &slice_stream.stream;
5959
60 const allocator = &LoggingAllocator.init(std.heap.page_allocator, @ptrCast(*AnyErrorOutStream, stream)).allocator;60 const allocator = &LoggingAllocator.init(std.testing.allocator, @ptrCast(*AnyErrorOutStream, stream)).allocator;
6161
62 const ptr = try allocator.alloc(u8, 10);62 const ptr = try allocator.alloc(u8, 10);
63 allocator.free(ptr);63 allocator.free(ptr);
lib/std/io.zig+1-1
...@@ -891,7 +891,7 @@ pub fn readLineSlice(slice: []u8) ![]u8 {...@@ -891,7 +891,7 @@ pub fn readLineSlice(slice: []u8) ![]u8 {
891pub fn readLineSliceFrom(stream: var, slice: []u8) ![]u8 {891pub fn readLineSliceFrom(stream: var, slice: []u8) ![]u8 {
892 // We cannot use Buffer.fromOwnedSlice, as it wants to append a null byte892 // We cannot use Buffer.fromOwnedSlice, as it wants to append a null byte
893 // after taking ownership, which would always require an allocation.893 // after taking ownership, which would always require an allocation.
894 var buf = std.Buffer{ .list = std.ArrayList(u8).fromOwnedSlice(debug.failing_allocator, slice) };894 var buf = std.Buffer{ .list = std.ArrayList(u8).fromOwnedSlice(testing.failing_allocator, slice) };
895 try buf.resize(0);895 try buf.resize(0);
896 return try readLineFrom(stream, &buf);896 return try readLineFrom(stream, &buf);
897}897}
lib/std/linked_list.zig+3-3
...@@ -143,7 +143,7 @@ pub fn SinglyLinkedList(comptime T: type) type {...@@ -143,7 +143,7 @@ pub fn SinglyLinkedList(comptime T: type) type {
143}143}
144144
145test "basic SinglyLinkedList test" {145test "basic SinglyLinkedList test" {
146 const allocator = debug.global_allocator;146 const allocator = testing.allocator;
147 var list = SinglyLinkedList(u32).init();147 var list = SinglyLinkedList(u32).init();
148148
149 var one = try list.createNode(1, allocator);149 var one = try list.createNode(1, allocator);
...@@ -404,7 +404,7 @@ pub fn TailQueue(comptime T: type) type {...@@ -404,7 +404,7 @@ pub fn TailQueue(comptime T: type) type {
404}404}
405405
406test "basic TailQueue test" {406test "basic TailQueue test" {
407 const allocator = debug.global_allocator;407 const allocator = testing.allocator;
408 var list = TailQueue(u32).init();408 var list = TailQueue(u32).init();
409409
410 var one = try list.createNode(1, allocator);410 var one = try list.createNode(1, allocator);
...@@ -456,7 +456,7 @@ test "basic TailQueue test" {...@@ -456,7 +456,7 @@ test "basic TailQueue test" {
456}456}
457457
458test "TailQueue concatenation" {458test "TailQueue concatenation" {
459 const allocator = debug.global_allocator;459 const allocator = testing.allocator;
460 var list1 = TailQueue(u32).init();460 var list1 = TailQueue(u32).init();
461 var list2 = TailQueue(u32).init();461 var list2 = TailQueue(u32).init();
462462
lib/std/mutex.zig-6
...@@ -306,12 +306,6 @@ const TestContext = struct {...@@ -306,12 +306,6 @@ const TestContext = struct {
306};306};
307307
308test "std.Mutex" {308test "std.Mutex" {
309 var plenty_of_memory = try std.heap.page_allocator.alloc(u8, 300 * 1024);
310 defer std.heap.page_allocator.free(plenty_of_memory);
311
312 var fixed_buffer_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(plenty_of_memory);
313 var a = &fixed_buffer_allocator.allocator;
314
315 var mutex = Mutex.init();309 var mutex = Mutex.init();
316 defer mutex.deinit();310 defer mutex.deinit();
317311
lib/std/os/test.zig+3-3
...@@ -9,7 +9,7 @@ const elf = std.elf;...@@ -9,7 +9,7 @@ const elf = std.elf;
9const File = std.fs.File;9const File = std.fs.File;
10const Thread = std.Thread;10const Thread = std.Thread;
1111
12const a = std.debug.global_allocator;12const a = std.testing.allocator;
1313
14const builtin = @import("builtin");14const builtin = @import("builtin");
15const AtomicRmwOp = builtin.AtomicRmwOp;15const AtomicRmwOp = builtin.AtomicRmwOp;
...@@ -235,8 +235,8 @@ test "pipe" {...@@ -235,8 +235,8 @@ test "pipe" {
235}235}
236236
237test "argsAlloc" {237test "argsAlloc" {
238 var args = try std.process.argsAlloc(std.heap.page_allocator);238 var args = try std.process.argsAlloc(std.testing.allocator);
239 std.process.argsFree(std.heap.page_allocator, args);239 std.process.argsFree(std.testing.allocator, args);
240}240}
241241
242test "memfd_create" {242test "memfd_create" {
lib/std/packed_int_array.zig+2-2
...@@ -604,7 +604,7 @@ test "PackedIntArray at end of available memory" {...@@ -604,7 +604,7 @@ test "PackedIntArray at end of available memory" {
604 p: PackedArray,604 p: PackedArray,
605 };605 };
606606
607 const allocator = std.heap.page_allocator;607 const allocator = std.testing.allocator;
608608
609 var pad = try allocator.create(Padded);609 var pad = try allocator.create(Padded);
610 defer allocator.destroy(pad);610 defer allocator.destroy(pad);
...@@ -618,7 +618,7 @@ test "PackedIntSlice at end of available memory" {...@@ -618,7 +618,7 @@ test "PackedIntSlice at end of available memory" {
618 }618 }
619 const PackedSlice = PackedIntSlice(u11);619 const PackedSlice = PackedIntSlice(u11);
620620
621 const allocator = std.heap.page_allocator;621 const allocator = std.testing.allocator;
622622
623 var page = try allocator.alloc(u8, std.mem.page_size);623 var page = try allocator.alloc(u8, std.mem.page_size);
624 defer allocator.free(page);624 defer allocator.free(page);
lib/std/priority_queue.zig+19-19
...@@ -1,10 +1,10 @@...@@ -1,10 +1,10 @@
1const std = @import("std.zig");1const std = @import("std.zig");
2const Allocator = std.mem.Allocator;2const Allocator = std.mem.Allocator;
3const debug = std.debug;3const assert = std.debug.assert;
4const assert = debug.assert;4const testing = std.testing;
5const expect = std.testing.expect;5const expect = testing.expect;
6const expectEqual = std.testing.expectEqual;6const expectEqual = testing.expectEqual;
7const expectError = std.testing.expectError;7const expectError = testing.expectError;
88
9/// Priority queue for storing generic data. Initialize with `init`.9/// Priority queue for storing generic data. Initialize with `init`.
10pub fn PriorityQueue(comptime T: type) type {10pub fn PriorityQueue(comptime T: type) type {
...@@ -239,7 +239,7 @@ fn greaterThan(a: u32, b: u32) bool {...@@ -239,7 +239,7 @@ fn greaterThan(a: u32, b: u32) bool {
239const PQ = PriorityQueue(u32);239const PQ = PriorityQueue(u32);
240240
241test "std.PriorityQueue: add and remove min heap" {241test "std.PriorityQueue: add and remove min heap" {
242 var queue = PQ.init(debug.global_allocator, lessThan);242 var queue = PQ.init(testing.allocator, lessThan);
243 defer queue.deinit();243 defer queue.deinit();
244244
245 try queue.add(54);245 try queue.add(54);
...@@ -257,7 +257,7 @@ test "std.PriorityQueue: add and remove min heap" {...@@ -257,7 +257,7 @@ test "std.PriorityQueue: add and remove min heap" {
257}257}
258258
259test "std.PriorityQueue: add and remove same min heap" {259test "std.PriorityQueue: add and remove same min heap" {
260 var queue = PQ.init(debug.global_allocator, lessThan);260 var queue = PQ.init(testing.allocator, lessThan);
261 defer queue.deinit();261 defer queue.deinit();
262262
263 try queue.add(1);263 try queue.add(1);
...@@ -275,14 +275,14 @@ test "std.PriorityQueue: add and remove same min heap" {...@@ -275,14 +275,14 @@ test "std.PriorityQueue: add and remove same min heap" {
275}275}
276276
277test "std.PriorityQueue: removeOrNull on empty" {277test "std.PriorityQueue: removeOrNull on empty" {
278 var queue = PQ.init(debug.global_allocator, lessThan);278 var queue = PQ.init(testing.allocator, lessThan);
279 defer queue.deinit();279 defer queue.deinit();
280280
281 expect(queue.removeOrNull() == null);281 expect(queue.removeOrNull() == null);
282}282}
283283
284test "std.PriorityQueue: edge case 3 elements" {284test "std.PriorityQueue: edge case 3 elements" {
285 var queue = PQ.init(debug.global_allocator, lessThan);285 var queue = PQ.init(testing.allocator, lessThan);
286 defer queue.deinit();286 defer queue.deinit();
287287
288 try queue.add(9);288 try queue.add(9);
...@@ -294,7 +294,7 @@ test "std.PriorityQueue: edge case 3 elements" {...@@ -294,7 +294,7 @@ test "std.PriorityQueue: edge case 3 elements" {
294}294}
295295
296test "std.PriorityQueue: peek" {296test "std.PriorityQueue: peek" {
297 var queue = PQ.init(debug.global_allocator, lessThan);297 var queue = PQ.init(testing.allocator, lessThan);
298 defer queue.deinit();298 defer queue.deinit();
299299
300 expect(queue.peek() == null);300 expect(queue.peek() == null);
...@@ -306,7 +306,7 @@ test "std.PriorityQueue: peek" {...@@ -306,7 +306,7 @@ test "std.PriorityQueue: peek" {
306}306}
307307
308test "std.PriorityQueue: sift up with odd indices" {308test "std.PriorityQueue: sift up with odd indices" {
309 var queue = PQ.init(debug.global_allocator, lessThan);309 var queue = PQ.init(testing.allocator, lessThan);
310 defer queue.deinit();310 defer queue.deinit();
311 const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };311 const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
312 for (items) |e| {312 for (items) |e| {
...@@ -320,7 +320,7 @@ test "std.PriorityQueue: sift up with odd indices" {...@@ -320,7 +320,7 @@ test "std.PriorityQueue: sift up with odd indices" {
320}320}
321321
322test "std.PriorityQueue: addSlice" {322test "std.PriorityQueue: addSlice" {
323 var queue = PQ.init(debug.global_allocator, lessThan);323 var queue = PQ.init(testing.allocator, lessThan);
324 defer queue.deinit();324 defer queue.deinit();
325 const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };325 const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
326 try queue.addSlice(items[0..]);326 try queue.addSlice(items[0..]);
...@@ -333,8 +333,8 @@ test "std.PriorityQueue: addSlice" {...@@ -333,8 +333,8 @@ test "std.PriorityQueue: addSlice" {
333333
334test "std.PriorityQueue: fromOwnedSlice" {334test "std.PriorityQueue: fromOwnedSlice" {
335 const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };335 const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
336 const heap_items = try std.mem.dupe(debug.global_allocator, u32, items[0..]);336 const heap_items = try std.mem.dupe(testing.allocator, u32, items[0..]);
337 var queue = PQ.fromOwnedSlice(debug.global_allocator, lessThan, heap_items[0..]);337 var queue = PQ.fromOwnedSlice(testing.allocator, lessThan, heap_items[0..]);
338 defer queue.deinit();338 defer queue.deinit();
339339
340 const sorted_items = [_]u32{ 1, 2, 5, 6, 7, 7, 11, 12, 13, 14, 15, 15, 16, 21, 22, 24, 24, 25 };340 const sorted_items = [_]u32{ 1, 2, 5, 6, 7, 7, 11, 12, 13, 14, 15, 15, 16, 21, 22, 24, 24, 25 };
...@@ -344,7 +344,7 @@ test "std.PriorityQueue: fromOwnedSlice" {...@@ -344,7 +344,7 @@ test "std.PriorityQueue: fromOwnedSlice" {
344}344}
345345
346test "std.PriorityQueue: add and remove max heap" {346test "std.PriorityQueue: add and remove max heap" {
347 var queue = PQ.init(debug.global_allocator, greaterThan);347 var queue = PQ.init(testing.allocator, greaterThan);
348 defer queue.deinit();348 defer queue.deinit();
349349
350 try queue.add(54);350 try queue.add(54);
...@@ -362,7 +362,7 @@ test "std.PriorityQueue: add and remove max heap" {...@@ -362,7 +362,7 @@ test "std.PriorityQueue: add and remove max heap" {
362}362}
363363
364test "std.PriorityQueue: add and remove same max heap" {364test "std.PriorityQueue: add and remove same max heap" {
365 var queue = PQ.init(debug.global_allocator, greaterThan);365 var queue = PQ.init(testing.allocator, greaterThan);
366 defer queue.deinit();366 defer queue.deinit();
367367
368 try queue.add(1);368 try queue.add(1);
...@@ -380,8 +380,8 @@ test "std.PriorityQueue: add and remove same max heap" {...@@ -380,8 +380,8 @@ test "std.PriorityQueue: add and remove same max heap" {
380}380}
381381
382test "std.PriorityQueue: iterator" {382test "std.PriorityQueue: iterator" {
383 var queue = PQ.init(debug.global_allocator, lessThan);383 var queue = PQ.init(testing.allocator, lessThan);
384 var map = std.AutoHashMap(u32, void).init(debug.global_allocator);384 var map = std.AutoHashMap(u32, void).init(testing.allocator);
385 defer {385 defer {
386 queue.deinit();386 queue.deinit();
387 map.deinit();387 map.deinit();
...@@ -402,7 +402,7 @@ test "std.PriorityQueue: iterator" {...@@ -402,7 +402,7 @@ test "std.PriorityQueue: iterator" {
402}402}
403403
404test "std.PriorityQueue: remove at index" {404test "std.PriorityQueue: remove at index" {
405 var queue = PQ.init(debug.global_allocator, lessThan);405 var queue = PQ.init(testing.allocator, lessThan);
406 defer queue.deinit();406 defer queue.deinit();
407407
408 try queue.add(3);408 try queue.add(3);
lib/std/process.zig+6-5
...@@ -79,7 +79,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -79,7 +79,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
79 // https://github.com/WebAssembly/WASI/issues/2779 // https://github.com/WebAssembly/WASI/issues/27
80 var environ = try allocator.alloc(?[*:0]u8, environ_count + 1);80 var environ = try allocator.alloc(?[*:0]u8, environ_count + 1);
81 defer allocator.free(environ);81 defer allocator.free(environ);
82 var environ_buf = try std.heap.page_allocator.alloc(u8, environ_buf_size);82 var environ_buf = try allocator.alloc(u8, environ_buf_size);
83 defer allocator.free(environ_buf);83 defer allocator.free(environ_buf);
8484
85 const environ_get_ret = os.wasi.environ_get(environ.ptr, environ_buf.ptr);85 const environ_get_ret = os.wasi.environ_get(environ.ptr, environ_buf.ptr);
...@@ -114,7 +114,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -114,7 +114,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
114}114}
115115
116test "os.getEnvMap" {116test "os.getEnvMap" {
117 var env = try getEnvMap(std.debug.global_allocator);117 var env = try getEnvMap(std.testing.allocator);
118 defer env.deinit();118 defer env.deinit();
119}119}
120120
...@@ -165,7 +165,7 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned...@@ -165,7 +165,7 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned
165}165}
166166
167test "os.getEnvVarOwned" {167test "os.getEnvVarOwned" {
168 var ga = std.debug.global_allocator;168 var ga = std.testing.allocator;
169 testing.expectError(error.EnvironmentVariableNotFound, getEnvVarOwned(ga, "BADENV"));169 testing.expectError(error.EnvironmentVariableNotFound, getEnvVarOwned(ga, "BADENV"));
170}170}
171171
...@@ -492,10 +492,11 @@ test "windows arg parsing" {...@@ -492,10 +492,11 @@ test "windows arg parsing" {
492fn testWindowsCmdLine(input_cmd_line: [*]const u8, expected_args: []const []const u8) void {492fn testWindowsCmdLine(input_cmd_line: [*]const u8, expected_args: []const []const u8) void {
493 var it = ArgIteratorWindows.initWithCmdLine(input_cmd_line);493 var it = ArgIteratorWindows.initWithCmdLine(input_cmd_line);
494 for (expected_args) |expected_arg| {494 for (expected_args) |expected_arg| {
495 const arg = it.next(std.debug.global_allocator).? catch unreachable;495 const arg = it.next(std.testing.allocator).? catch unreachable;
496 defer std.testing.allocator.free(arg);
496 testing.expectEqualSlices(u8, expected_arg, arg);497 testing.expectEqualSlices(u8, expected_arg, arg);
497 }498 }
498 testing.expect(it.next(std.debug.global_allocator) == null);499 testing.expect(it.next(std.testing.allocator) == null);
499}500}
500501
501pub const UserInfo = struct {502pub const UserInfo = struct {
lib/std/segmented_list.zig+1-1
...@@ -339,7 +339,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type...@@ -339,7 +339,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
339}339}
340340
341test "std.SegmentedList" {341test "std.SegmentedList" {
342 var a = std.heap.page_allocator;342 var a = std.testing.allocator;
343343
344 try testSegmentedList(0, a);344 try testSegmentedList(0, a);
345 try testSegmentedList(1, a);345 try testSegmentedList(1, a);
lib/std/special/test_runner.zig+6
...@@ -13,6 +13,8 @@ pub fn main() anyerror!void {...@@ -13,6 +13,8 @@ pub fn main() anyerror!void {
13 };13 };
1414
15 for (test_fn_list) |test_fn, i| {15 for (test_fn_list) |test_fn, i| {
16 std.testing.base_allocator_instance.reset();
17
16 var test_node = root_node.start(test_fn.name, null);18 var test_node = root_node.start(test_fn.name, null);
17 test_node.activate();19 test_node.activate();
18 progress.refresh();20 progress.refresh();
...@@ -22,6 +24,10 @@ pub fn main() anyerror!void {...@@ -22,6 +24,10 @@ pub fn main() anyerror!void {
22 if (test_fn.func()) |_| {24 if (test_fn.func()) |_| {
23 ok_count += 1;25 ok_count += 1;
24 test_node.end();26 test_node.end();
27 std.testing.allocator_instance.validate() catch |err| switch (err) {
28 error.Leak => std.debug.panic("", .{}),
29 else => std.debug.panic("error.{}", .{@errorName(err)}),
30 };
25 if (progress.terminal == null) std.debug.warn("OK\n", .{});31 if (progress.terminal == null) std.debug.warn("OK\n", .{});
26 } else |err| switch (err) {32 } else |err| switch (err) {
27 error.SkipZigTest => {33 error.SkipZigTest => {
lib/std/testing.zig+12
...@@ -2,6 +2,18 @@ const builtin = @import("builtin");...@@ -2,6 +2,18 @@ const builtin = @import("builtin");
2const TypeId = builtin.TypeId;2const TypeId = builtin.TypeId;
3const std = @import("std.zig");3const std = @import("std.zig");
44
5pub const LeakCountAllocator = @import("testing/leak_count_allocator.zig").LeakCountAllocator;
6pub const FailingAllocator = @import("testing/failing_allocator.zig").FailingAllocator;
7
8/// This should only be used in temporary test programs.
9pub const allocator = &allocator_instance.allocator;
10pub var allocator_instance = LeakCountAllocator.init(&base_allocator_instance.allocator);
11
12pub const failing_allocator = &FailingAllocator.init(&base_allocator_instance.allocator, 0).allocator;
13
14pub var base_allocator_instance = std.heap.ThreadSafeFixedBufferAllocator.init(allocator_mem[0..]);
15var allocator_mem: [512 * 1024]u8 = undefined;
16
5/// This function is intended to be used only in tests. It prints diagnostics to stderr17/// This function is intended to be used only in tests. It prints diagnostics to stderr
6/// and then aborts when actual_error_union is not expected_error.18/// and then aborts when actual_error_union is not expected_error.
7pub fn expectError(expected_error: anyerror, actual_error_union: var) void {19pub fn expectError(expected_error: anyerror, actual_error_union: var) void {
lib/std/testing/failing_allocator.zig created+81
...@@ -0,0 +1,81 @@
1const std = @import("../std.zig");
2const mem = std.mem;
3
4/// Allocator that fails after N allocations, useful for making sure out of
5/// memory conditions are handled correctly.
6///
7/// To use this, first initialize it and get an allocator with
8///
9/// `const failing_allocator = &FailingAllocator.init(<allocator>,
10/// <fail_index>).allocator;`
11///
12/// Then use `failing_allocator` anywhere you would have used a
13/// different allocator.
14pub const FailingAllocator = struct {
15 allocator: mem.Allocator,
16 index: usize,
17 fail_index: usize,
18 internal_allocator: *mem.Allocator,
19 allocated_bytes: usize,
20 freed_bytes: usize,
21 allocations: usize,
22 deallocations: usize,
23
24 /// `fail_index` is the number of successful allocations you can
25 /// expect from this allocator. The next allocation will fail.
26 /// For example, if this is called with `fail_index` equal to 2,
27 /// the following test will pass:
28 ///
29 /// var a = try failing_alloc.create(i32);
30 /// var b = try failing_alloc.create(i32);
31 /// testing.expectError(error.OutOfMemory, failing_alloc.create(i32));
32 pub fn init(allocator: *mem.Allocator, fail_index: usize) FailingAllocator {
33 return FailingAllocator{
34 .internal_allocator = allocator,
35 .fail_index = fail_index,
36 .index = 0,
37 .allocated_bytes = 0,
38 .freed_bytes = 0,
39 .allocations = 0,
40 .deallocations = 0,
41 .allocator = mem.Allocator{
42 .reallocFn = realloc,
43 .shrinkFn = shrink,
44 },
45 };
46 }
47
48 fn realloc(allocator: *mem.Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
49 const self = @fieldParentPtr(FailingAllocator, "allocator", allocator);
50 if (self.index == self.fail_index) {
51 return error.OutOfMemory;
52 }
53 const result = try self.internal_allocator.reallocFn(
54 self.internal_allocator,
55 old_mem,
56 old_align,
57 new_size,
58 new_align,
59 );
60 if (new_size < old_mem.len) {
61 self.freed_bytes += old_mem.len - new_size;
62 if (new_size == 0)
63 self.deallocations += 1;
64 } else if (new_size > old_mem.len) {
65 self.allocated_bytes += new_size - old_mem.len;
66 if (old_mem.len == 0)
67 self.allocations += 1;
68 }
69 self.index += 1;
70 return result;
71 }
72
73 fn shrink(allocator: *mem.Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
74 const self = @fieldParentPtr(FailingAllocator, "allocator", allocator);
75 const r = self.internal_allocator.shrinkFn(self.internal_allocator, old_mem, old_align, new_size, new_align);
76 self.freed_bytes += old_mem.len - r.len;
77 if (new_size == 0)
78 self.deallocations += 1;
79 return r;
80 }
81};
lib/std/testing/leak_count_allocator.zig created+50
...@@ -0,0 +1,50 @@
1const std = @import("../std.zig");
2
3/// This allocator is used in front of another allocator and counts the numbers of allocs and frees.
4/// The test runner asserts every alloc has a corresponding free at the end of each test.
5///
6/// The detection algorithm is incredibly primitive and only accounts for number of calls.
7/// This should be replaced by the general purpose debug allocator.
8pub const LeakCountAllocator = struct {
9 count: usize,
10 allocator: std.mem.Allocator,
11 internal_allocator: *std.mem.Allocator,
12
13 pub fn init(allocator: *std.mem.Allocator) LeakCountAllocator {
14 return .{
15 .count = 0,
16 .allocator = .{
17 .reallocFn = realloc,
18 .shrinkFn = shrink,
19 },
20 .internal_allocator = allocator,
21 };
22 }
23
24 fn realloc(allocator: *std.mem.Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
25 const self = @fieldParentPtr(LeakCountAllocator, "allocator", allocator);
26 var data = try self.internal_allocator.reallocFn(self.internal_allocator, old_mem, old_align, new_size, new_align);
27 if (old_mem.len == 0) {
28 self.count += 1;
29 }
30 return data;
31 }
32
33 fn shrink(allocator: *std.mem.Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
34 const self = @fieldParentPtr(LeakCountAllocator, "allocator", allocator);
35 if (new_size == 0) {
36 if (self.count == 0) {
37 std.debug.panic("error - too many calls to free, most likely double free", .{});
38 }
39 self.count -= 1;
40 }
41 return self.internal_allocator.shrinkFn(self.internal_allocator, old_mem, old_align, new_size, new_align);
42 }
43
44 pub fn validate(self: LeakCountAllocator) !void {
45 if (self.count > 0) {
46 std.debug.warn("error - detected leaked allocations without matching free: {}\n", .{self.count});
47 return error.Leak;
48 }
49 }
50};
lib/std/unicode.zig+12-6
...@@ -501,14 +501,16 @@ test "utf16leToUtf8" {...@@ -501,14 +501,16 @@ test "utf16leToUtf8" {
501 {501 {
502 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 'A');502 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 'A');
503 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 'a');503 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 'a');
504 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, &utf16le);504 const utf8 = try utf16leToUtf8Alloc(std.testing.allocator, &utf16le);
505 defer std.testing.allocator.free(utf8);
505 testing.expect(mem.eql(u8, utf8, "Aa"));506 testing.expect(mem.eql(u8, utf8, "Aa"));
506 }507 }
507508
508 {509 {
509 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0x80);510 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0x80);
510 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xffff);511 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xffff);
511 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, &utf16le);512 const utf8 = try utf16leToUtf8Alloc(std.testing.allocator, &utf16le);
513 defer std.testing.allocator.free(utf8);
512 testing.expect(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf"));514 testing.expect(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf"));
513 }515 }
514516
...@@ -516,7 +518,8 @@ test "utf16leToUtf8" {...@@ -516,7 +518,8 @@ test "utf16leToUtf8" {
516 // the values just outside the surrogate half range518 // the values just outside the surrogate half range
517 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd7ff);519 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd7ff);
518 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xe000);520 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xe000);
519 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, &utf16le);521 const utf8 = try utf16leToUtf8Alloc(std.testing.allocator, &utf16le);
522 defer std.testing.allocator.free(utf8);
520 testing.expect(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80"));523 testing.expect(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80"));
521 }524 }
522525
...@@ -524,7 +527,8 @@ test "utf16leToUtf8" {...@@ -524,7 +527,8 @@ test "utf16leToUtf8" {
524 // smallest surrogate pair527 // smallest surrogate pair
525 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd800);528 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd800);
526 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00);529 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00);
527 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, &utf16le);530 const utf8 = try utf16leToUtf8Alloc(std.testing.allocator, &utf16le);
531 defer std.testing.allocator.free(utf8);
528 testing.expect(mem.eql(u8, utf8, "\xf0\x90\x80\x80"));532 testing.expect(mem.eql(u8, utf8, "\xf0\x90\x80\x80"));
529 }533 }
530534
...@@ -532,14 +536,16 @@ test "utf16leToUtf8" {...@@ -532,14 +536,16 @@ test "utf16leToUtf8" {
532 // largest surrogate pair536 // largest surrogate pair
533 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff);537 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff);
534 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdfff);538 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdfff);
535 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, &utf16le);539 const utf8 = try utf16leToUtf8Alloc(std.testing.allocator, &utf16le);
540 defer std.testing.allocator.free(utf8);
536 testing.expect(mem.eql(u8, utf8, "\xf4\x8f\xbf\xbf"));541 testing.expect(mem.eql(u8, utf8, "\xf4\x8f\xbf\xbf"));
537 }542 }
538543
539 {544 {
540 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff);545 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff);
541 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00);546 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00);
542 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, &utf16le);547 const utf8 = try utf16leToUtf8Alloc(std.testing.allocator, &utf16le);
548 defer std.testing.allocator.free(utf8);
543 testing.expect(mem.eql(u8, utf8, "\xf4\x8f\xb0\x80"));549 testing.expect(mem.eql(u8, utf8, "\xf4\x8f\xb0\x80"));
544 }550 }
545}551}
lib/std/zig/ast.zig+1-1
...@@ -2287,7 +2287,7 @@ pub const Node = struct {...@@ -2287,7 +2287,7 @@ pub const Node = struct {
2287test "iterate" {2287test "iterate" {
2288 var root = Node.Root{2288 var root = Node.Root{
2289 .base = Node{ .id = Node.Id.Root },2289 .base = Node{ .id = Node.Id.Root },
2290 .decls = Node.Root.DeclList.init(std.debug.global_allocator),2290 .decls = Node.Root.DeclList.init(std.testing.allocator),
2291 .eof_token = 0,2291 .eof_token = 0,
2292 };2292 };
2293 var base = &root.base;2293 var base = &root.base;
lib/std/zig/parser_test.zig+2-2
...@@ -2773,7 +2773,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {...@@ -2773,7 +2773,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {
2773 const needed_alloc_count = x: {2773 const needed_alloc_count = x: {
2774 // Try it once with unlimited memory, make sure it works2774 // Try it once with unlimited memory, make sure it works
2775 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);2775 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
2776 var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, maxInt(usize));2776 var failing_allocator = std.testing.FailingAllocator.init(&fixed_allocator.allocator, maxInt(usize));
2777 var anything_changed: bool = undefined;2777 var anything_changed: bool = undefined;
2778 const result_source = try testParse(source, &failing_allocator.allocator, &anything_changed);2778 const result_source = try testParse(source, &failing_allocator.allocator, &anything_changed);
2779 if (!mem.eql(u8, result_source, expected_source)) {2779 if (!mem.eql(u8, result_source, expected_source)) {
...@@ -2797,7 +2797,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {...@@ -2797,7 +2797,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {
2797 var fail_index: usize = 0;2797 var fail_index: usize = 0;
2798 while (fail_index < needed_alloc_count) : (fail_index += 1) {2798 while (fail_index < needed_alloc_count) : (fail_index += 1) {
2799 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);2799 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
2800 var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, fail_index);2800 var failing_allocator = std.testing.FailingAllocator.init(&fixed_allocator.allocator, fail_index);
2801 var anything_changed: bool = undefined;2801 var anything_changed: bool = undefined;
2802 if (testParse(source, &failing_allocator.allocator, &anything_changed)) |_| {2802 if (testParse(source, &failing_allocator.allocator, &anything_changed)) |_| {
2803 return error.NondeterministicMemoryUsage;2803 return error.NondeterministicMemoryUsage;
src-self-hosted/c_tokenizer.zig+2-2
...@@ -866,7 +866,7 @@ fn expectTokens(tl: *TokenList, src: [*:0]const u8, expected: []CToken) void {...@@ -866,7 +866,7 @@ fn expectTokens(tl: *TokenList, src: [*:0]const u8, expected: []CToken) void {
866}866}
867867
868test "tokenize macro" {868test "tokenize macro" {
869 var tl = TokenList.init(std.heap.page_allocator);869 var tl = TokenList.init(std.testing.allocator);
870 defer tl.deinit();870 defer tl.deinit();
871871
872 expectTokens(&tl, "TEST(0\n", &[_]CToken{872 expectTokens(&tl, "TEST(0\n", &[_]CToken{
...@@ -904,7 +904,7 @@ test "tokenize macro" {...@@ -904,7 +904,7 @@ test "tokenize macro" {
904}904}
905905
906test "tokenize macro ops" {906test "tokenize macro ops" {
907 var tl = TokenList.init(std.heap.page_allocator);907 var tl = TokenList.init(std.testing.allocator);
908 defer tl.deinit();908 defer tl.deinit();
909909
910 expectTokens(&tl, "ADD A + B", &[_]CToken{910 expectTokens(&tl, "ADD A + B", &[_]CToken{
test/cli.zig+1-1
...@@ -8,7 +8,7 @@ const ChildProcess = std.ChildProcess;...@@ -8,7 +8,7 @@ const ChildProcess = std.ChildProcess;
8var a: *std.mem.Allocator = undefined;8var a: *std.mem.Allocator = undefined;
99
10pub fn main() !void {10pub fn main() !void {
11 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);11 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
12 defer arena.deinit();12 defer arena.deinit();
1313
14 var arg_it = process.args();14 var arg_it = process.args();
test/compare_output.zig+2-2
...@@ -445,7 +445,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -445,7 +445,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
445 \\const std = @import("std");445 \\const std = @import("std");
446 \\const io = std.io;446 \\const io = std.io;
447 \\const os = std.os;447 \\const os = std.os;
448 \\const allocator = std.debug.global_allocator;448 \\const allocator = std.testing.allocator;
449 \\449 \\
450 \\pub fn main() !void {450 \\pub fn main() !void {
451 \\ var args_it = std.process.args();451 \\ var args_it = std.process.args();
...@@ -486,7 +486,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -486,7 +486,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
486 \\const std = @import("std");486 \\const std = @import("std");
487 \\const io = std.io;487 \\const io = std.io;
488 \\const os = std.os;488 \\const os = std.os;
489 \\const allocator = std.debug.global_allocator;489 \\const allocator = std.testing.allocator;
490 \\490 \\
491 \\pub fn main() !void {491 \\pub fn main() !void {
492 \\ var args_it = std.process.args();492 \\ var args_it = std.process.args();
test/compile_errors.zig+1-1
...@@ -5765,7 +5765,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5765,7 +5765,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5765 \\5765 \\
5766 \\export fn entry() void {5766 \\export fn entry() void {
5767 \\ const a = MdNode.Header {5767 \\ const a = MdNode.Header {
5768 \\ .text = MdText.init(&std.debug.global_allocator),5768 \\ .text = MdText.init(&std.testing.allocator),
5769 \\ .weight = HeaderWeight.H1,5769 \\ .weight = HeaderWeight.H1,
5770 \\ };5770 \\ };
5771 \\}5771 \\}
test/stage1/behavior/async_fn.zig+5-5
...@@ -410,8 +410,8 @@ test "heap allocated async function frame" {...@@ -410,8 +410,8 @@ test "heap allocated async function frame" {
410 var x: i32 = 42;410 var x: i32 = 42;
411411
412 fn doTheTest() !void {412 fn doTheTest() !void {
413 const frame = try std.heap.page_allocator.create(@Frame(someFunc));413 const frame = try std.testing.allocator.create(@Frame(someFunc));
414 defer std.heap.page_allocator.destroy(frame);414 defer std.testing.allocator.destroy(frame);
415415
416 expect(x == 42);416 expect(x == 42);
417 frame.* = async someFunc();417 frame.* = async someFunc();
...@@ -671,7 +671,7 @@ fn testAsyncAwaitTypicalUsage(...@@ -671,7 +671,7 @@ fn testAsyncAwaitTypicalUsage(
671 }671 }
672672
673 fn amain() !void {673 fn amain() !void {
674 const allocator = std.heap.page_allocator; // TODO once we have the debug allocator, use that, so that this can detect leaks674 const allocator = std.testing.allocator;
675 var download_frame = async fetchUrl(allocator, "https://example.com/");675 var download_frame = async fetchUrl(allocator, "https://example.com/");
676 var download_awaited = false;676 var download_awaited = false;
677 errdefer if (!download_awaited) {677 errdefer if (!download_awaited) {
...@@ -935,12 +935,12 @@ fn recursiveAsyncFunctionTest(comptime suspending_implementation: bool) type {...@@ -935,12 +935,12 @@ fn recursiveAsyncFunctionTest(comptime suspending_implementation: bool) type {
935 _ = async amain(&result);935 _ = async amain(&result);
936 return result;936 return result;
937 } else {937 } else {
938 return fib(std.heap.page_allocator, 10) catch unreachable;938 return fib(std.testing.allocator, 10) catch unreachable;
939 }939 }
940 }940 }
941941
942 fn amain(result: *u32) void {942 fn amain(result: *u32) void {
943 var x = async fib(std.heap.page_allocator, 10);943 var x = async fib(std.testing.allocator, 10);
944 result.* = (await x) catch unreachable;944 result.* = (await x) catch unreachable;
945 }945 }
946 };946 };
test/stage1/behavior/const_slice_child.zig+4-2
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const std = @import("std");1const std = @import("std");
2const debug = std.debug;2const debug = std.debug;
3const expect = std.testing.expect;3const testing = std.testing;
4const expect = testing.expect;
45
5var argv: [*]const [*]const u8 = undefined;6var argv: [*]const [*]const u8 = undefined;
67
...@@ -22,7 +23,8 @@ fn foo(args: [][]const u8) void {...@@ -22,7 +23,8 @@ fn foo(args: [][]const u8) void {
22}23}
2324
24fn bar(argc: usize) void {25fn bar(argc: usize) void {
25 const args = debug.global_allocator.alloc([]const u8, argc) catch unreachable;26 const args = testing.allocator.alloc([]const u8, argc) catch unreachable;
27 defer testing.allocator.free(args);
26 for (args) |_, i| {28 for (args) |_, i| {
27 const ptr = argv[i];29 const ptr = argv[i];
28 args[i] = ptr[0..strlen(ptr)];30 args[i] = ptr[0..strlen(ptr)];
test/standalone/brace_expansion/main.zig+8-2
...@@ -201,7 +201,10 @@ pub fn main() !void {...@@ -201,7 +201,10 @@ pub fn main() !void {
201}201}
202202
203test "invalid inputs" {203test "invalid inputs" {
204 global_allocator = std.debug.global_allocator;204 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
205 defer arena.deinit();
206
207 global_allocator = &arena.allocator;
205208
206 expectError("}ABC", error.InvalidInput);209 expectError("}ABC", error.InvalidInput);
207 expectError("{ABC", error.InvalidInput);210 expectError("{ABC", error.InvalidInput);
...@@ -222,7 +225,10 @@ fn expectError(test_input: []const u8, expected_err: anyerror) void {...@@ -222,7 +225,10 @@ fn expectError(test_input: []const u8, expected_err: anyerror) void {
222}225}
223226
224test "valid inputs" {227test "valid inputs" {
225 global_allocator = std.debug.global_allocator;228 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
229 defer arena.deinit();
230
231 global_allocator = &arena.allocator;
226232
227 expectExpansion("{x,y,z}", "x y z");233 expectExpansion("{x,y,z}", "x y z");
228 expectExpansion("{A,B}{x,y}", "Ax Ay Bx By");234 expectExpansion("{A,B}{x,y}", "Ax Ay Bx By");
test/standalone/cat/main.zig+1-1
...@@ -4,7 +4,7 @@ const process = std.process;...@@ -4,7 +4,7 @@ const process = std.process;
4const fs = std.fs;4const fs = std.fs;
5const mem = std.mem;5const mem = std.mem;
6const warn = std.debug.warn;6const warn = std.debug.warn;
7const allocator = std.debug.global_allocator;7const allocator = std.testing.allocator;
88
9pub fn main() !void {9pub fn main() !void {
10 var args_it = process.args();10 var args_it = process.args();
test/standalone/empty_env/main.zig+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("std");1const std = @import("std");
22
3pub fn main() void {3pub fn main() void {
4 const env_map = std.process.getEnvMap(std.debug.global_allocator) catch @panic("unable to get env map");4 const env_map = std.process.getEnvMap(std.testing.allocator) catch @panic("unable to get env map");
5 std.testing.expect(env_map.count() == 0);5 std.testing.expect(env_map.count() == 0);
6}6}
test/standalone/load_dynamic_library/main.zig+2-2
...@@ -1,8 +1,8 @@...@@ -1,8 +1,8 @@
1const std = @import("std");1const std = @import("std");
22
3pub fn main() !void {3pub fn main() !void {
4 const args = try std.process.argsAlloc(std.debug.global_allocator);4 const args = try std.process.argsAlloc(std.testing.allocator);
5 defer std.process.argsFree(std.debug.global_allocator, args);5 defer std.process.argsFree(std.testing.allocator, args);
66
7 const dynlib_name = args[1];7 const dynlib_name = args[1];
88