Skip to content

Commit 4229b1d

Browse files
committed
Report memory leaks when using std.testing.allocator
Fix leaks in storage bottle
1 parent 2c4661a commit 4229b1d

File tree

2 files changed

+31
-18
lines changed

2 files changed

+31
-18
lines changed

src/main_tests.zig

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,14 @@ pub fn main() !void {
223223
try parser.init();
224224
defer parser.deinit();
225225

226+
std.testing.allocator_instance = .{};
226227
try test_fn.func();
227-
std.debug.print("{s}\tOK\n", .{test_fn.name});
228+
229+
if (std.testing.allocator_instance.deinit() == .leak) {
230+
std.debug.print("======Memory Leak: {s}======\n", .{test_fn.name});
231+
} else {
232+
std.debug.print("{s}\tOK\n", .{test_fn.name});
233+
}
228234
}
229235
}
230236
}

src/storage/storage.zig

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -149,20 +149,22 @@ pub const Bottle = struct {
149149
}
150150

151151
pub fn _setItem(self: *Bottle, k: []const u8, v: []const u8) !void {
152-
const old = self.map.get(k);
153-
if (old != null and std.mem.eql(u8, v, old.?)) return;
154-
155-
// owns k and v by copying them.
156-
const kk = try self.alloc.dupe(u8, k);
157-
errdefer self.alloc.free(kk);
158-
const vv = try self.alloc.dupe(u8, v);
159-
errdefer self.alloc.free(vv);
160-
161-
self.map.put(self.alloc, kk, vv) catch |e| {
152+
const gop = self.map.getOrPut(self.alloc, k) catch |e| {
162153
log.debug("set item: {any}", .{e});
163154
return DOMError.QuotaExceeded;
164155
};
165156

157+
if (gop.found_existing == false) {
158+
gop.key_ptr.* = try self.alloc.dupe(u8, k);
159+
gop.value_ptr.* = try self.alloc.dupe(u8, v);
160+
return;
161+
}
162+
163+
if (std.mem.eql(u8, v, gop.value_ptr.*) == false) {
164+
self.alloc.free(gop.value_ptr.*);
165+
gop.value_ptr.* = try self.alloc.dupe(u8, v);
166+
}
167+
166168
// > Broadcast this with key, oldValue, and value.
167169
// https://html.spec.whatwg.org/multipage/webstorage.html#the-storageevent-interface
168170
//
@@ -175,8 +177,10 @@ pub const Bottle = struct {
175177
}
176178

177179
pub fn _removeItem(self: *Bottle, k: []const u8) !void {
178-
const old = self.map.fetchRemove(k);
179-
if (old == null) return;
180+
if (self.map.fetchRemove(k)) |kv| {
181+
self.alloc.free(kv.key);
182+
self.alloc.free(kv.value);
183+
}
180184

181185
// > Broadcast this with key, oldValue, and null.
182186
// https://html.spec.whatwg.org/multipage/webstorage.html#the-storageevent-interface
@@ -235,14 +239,17 @@ test "storage bottle" {
235239
var bottle = Bottle.init(std.testing.allocator);
236240
defer bottle.deinit();
237241

238-
try std.testing.expect(0 == bottle.get_length());
239-
try std.testing.expect(null == bottle._getItem("foo"));
242+
try std.testing.expectEqual(0, bottle.get_length());
243+
try std.testing.expectEqual(null, bottle._getItem("foo"));
240244

241245
try bottle._setItem("foo", "bar");
242-
try std.testing.expect(std.mem.eql(u8, "bar", bottle._getItem("foo").?));
246+
try std.testing.expectEqualStrings("bar", bottle._getItem("foo").?);
247+
248+
try bottle._setItem("foo", "other");
249+
try std.testing.expectEqualStrings("other", bottle._getItem("foo").?);
243250

244251
try bottle._removeItem("foo");
245252

246-
try std.testing.expect(0 == bottle.get_length());
247-
try std.testing.expect(null == bottle._getItem("foo"));
253+
try std.testing.expectEqual(0, bottle.get_length());
254+
try std.testing.expectEqual(null, bottle._getItem("foo"));
248255
}

0 commit comments

Comments
 (0)