Commit 5a3eca5d4c

Dominic <4678790+dweiller@users.noreply.github.com>
2023-05-08 09:59:06
Disallow named test decls with duplicate names
1 parent bac3a28
lib/std/io/reader.zig
@@ -553,10 +553,18 @@ test "Reader.readUntilDelimiter returns StreamTooLong, then bytes read until the
 }
 
 test "Reader.readUntilDelimiter returns EndOfStream" {
-    var buf: [5]u8 = undefined;
-    var fis = std.io.fixedBufferStream("");
-    const reader = fis.reader();
-    try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
+    {
+        var buf: [5]u8 = undefined;
+        var fis = std.io.fixedBufferStream("");
+        const reader = fis.reader();
+        try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
+    }
+    {
+        var buf: [5]u8 = undefined;
+        var fis = std.io.fixedBufferStream("1234");
+        const reader = fis.reader();
+        try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
+    }
 }
 
 test "Reader.readUntilDelimiter returns bytes read until delimiter, then EndOfStream" {
@@ -567,13 +575,6 @@ test "Reader.readUntilDelimiter returns bytes read until delimiter, then EndOfSt
     try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
 }
 
-test "Reader.readUntilDelimiter returns EndOfStream" {
-    var buf: [5]u8 = undefined;
-    var fis = std.io.fixedBufferStream("1234");
-    const reader = fis.reader();
-    try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
-}
-
 test "Reader.readUntilDelimiter returns StreamTooLong, then EndOfStream" {
     var buf: [5]u8 = undefined;
     var fis = std.io.fixedBufferStream("12345");
lib/std/math/big/int_test.zig
@@ -2012,15 +2012,10 @@ test "big.int shift-right negative" {
     defer arg2.deinit();
     try a.shiftRight(&arg2, 10);
     try testing.expect((try a.to(i32)) == -1); // -5 >> 10 == -1
-}
 
-test "big.int shift-right negative" {
-    var a = try Managed.init(testing.allocator);
-    defer a.deinit();
-
-    var arg = try Managed.initSet(testing.allocator, -10);
-    defer arg.deinit();
-    try a.shiftRight(&arg, 1232);
+    var arg3 = try Managed.initSet(testing.allocator, -10);
+    defer arg3.deinit();
+    try a.shiftRight(&arg3, 1232);
     try testing.expect((try a.to(i32)) == -1); // -10 >> 1232 == -1
 }
 
@@ -2483,7 +2478,7 @@ test "big.int gcd non-one small" {
     try testing.expect((try r.to(u32)) == 1);
 }
 
-test "big.int gcd non-one small" {
+test "big.int gcd non-one medium" {
     var a = try Managed.initSet(testing.allocator, 4864);
     defer a.deinit();
     var b = try Managed.initSet(testing.allocator, 3458);
lib/std/math/big/rational.zig
@@ -782,36 +782,38 @@ test "big.rational mul" {
 }
 
 test "big.rational div" {
-    var a = try Rational.init(testing.allocator);
-    defer a.deinit();
-    var b = try Rational.init(testing.allocator);
-    defer b.deinit();
-    var r = try Rational.init(testing.allocator);
-    defer r.deinit();
+    {
+        var a = try Rational.init(testing.allocator);
+        defer a.deinit();
+        var b = try Rational.init(testing.allocator);
+        defer b.deinit();
+        var r = try Rational.init(testing.allocator);
+        defer r.deinit();
 
-    try a.setRatio(78923, 23341);
-    try b.setRatio(123097, 12441414);
-    try a.div(a, b);
+        try a.setRatio(78923, 23341);
+        try b.setRatio(123097, 12441414);
+        try a.div(a, b);
 
-    try r.setRatio(75531824394, 221015929);
-    try testing.expect((try a.order(r)) == .eq);
-}
+        try r.setRatio(75531824394, 221015929);
+        try testing.expect((try a.order(r)) == .eq);
+    }
 
-test "big.rational div" {
-    var a = try Rational.init(testing.allocator);
-    defer a.deinit();
-    var r = try Rational.init(testing.allocator);
-    defer r.deinit();
+    {
+        var a = try Rational.init(testing.allocator);
+        defer a.deinit();
+        var r = try Rational.init(testing.allocator);
+        defer r.deinit();
 
-    try a.setRatio(78923, 23341);
-    a.invert();
+        try a.setRatio(78923, 23341);
+        a.invert();
 
-    try r.setRatio(23341, 78923);
-    try testing.expect((try a.order(r)) == .eq);
+        try r.setRatio(23341, 78923);
+        try testing.expect((try a.order(r)) == .eq);
 
-    try a.setRatio(-78923, 23341);
-    a.invert();
+        try a.setRatio(-78923, 23341);
+        a.invert();
 
-    try r.setRatio(-23341, 78923);
-    try testing.expect((try a.order(r)) == .eq);
+        try r.setRatio(-23341, 78923);
+        try testing.expect((try a.order(r)) == .eq);
+    }
 }
lib/std/net/test.zig
@@ -182,7 +182,7 @@ test "listen on a port, send bytes, receive bytes" {
     try testing.expectEqualSlices(u8, "Hello world!", buf[0..n]);
 }
 
-test "listen on a port, send bytes, receive bytes" {
+test "listen on a port, send bytes, receive bytes, async-only" {
     if (!std.io.is_async) return error.SkipZigTest;
 
     if (builtin.os.tag != .linux and !builtin.os.tag.isDarwin()) {
lib/std/zig/parser_test.zig
@@ -1240,7 +1240,7 @@ test "zig fmt: infix operator and then multiline string literal" {
     );
 }
 
-test "zig fmt: infix operator and then multiline string literal" {
+test "zig fmt: infix operator and then multiline string literal over multiple lines" {
     try testCanonical(
         \\const x = "" ++
         \\    \\ hi0
@@ -4310,7 +4310,7 @@ test "zig fmt: comptime before comptime field" {
     });
 }
 
-test "zig fmt: invalid else branch statement" {
+test "zig fmt: invalid doc comments on comptime and test blocks" {
     try testError(
         \\/// This is a doc comment for a comptime block.
         \\comptime {}
@@ -5191,7 +5191,7 @@ test "zig fmt: preserve container doc comment in container without trailing comm
     );
 }
 
-test "zig fmt: make single-line if no trailing comma" {
+test "zig fmt: make single-line if no trailing comma, fmt: off" {
     try testCanonical(
         \\// Test trailing comma syntax
         \\// zig fmt: off
@@ -5270,7 +5270,7 @@ test "zig fmt: variable initialized with ==" {
     , &.{.wrong_equal_var_decl});
 }
 
-test "zig fmt: missing const/var before local variable" {
+test "zig fmt: missing const/var before local variable in comptime block" {
     try testError(
         \\comptime {
         \\    z: u32;
lib/std/fmt.zig
@@ -2244,8 +2244,8 @@ test "struct" {
             field: u8,
         };
         const value = Struct{ .field = 42 };
-        try expectFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value});
-        try expectFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
+        try expectFmt("struct: fmt.test.struct.Struct{ .field = 42 }\n", "struct: {}\n", .{value});
+        try expectFmt("struct: fmt.test.struct.Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
     }
     {
         const Struct = struct {
@@ -2253,8 +2253,24 @@ test "struct" {
             b: u1,
         };
         const value = Struct{ .a = 0, .b = 1 };
-        try expectFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});
+        try expectFmt("struct: fmt.test.struct.Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});
     }
+
+    const S = struct {
+        a: u32,
+        b: anyerror,
+    };
+
+    const inst = S{
+        .a = 456,
+        .b = error.Unused,
+    };
+
+    try expectFmt("fmt.test.struct.S{ .a = 456, .b = error.Unused }", "{}", .{inst});
+    // Tuples
+    try expectFmt("{ }", "{}", .{.{}});
+    try expectFmt("{ -1 }", "{}", .{.{-1}});
+    try expectFmt("{ -1, 42, 2.5e+04 }", "{}", .{.{ -1, 42, 0.25e5 }});
 }
 
 test "enum" {
@@ -2263,13 +2279,26 @@ test "enum" {
         Two,
     };
     const value = Enum.Two;
-    try expectFmt("enum: Enum.Two\n", "enum: {}\n", .{value});
-    try expectFmt("enum: Enum.Two\n", "enum: {}\n", .{&value});
-    try expectFmt("enum: Enum.One\n", "enum: {}\n", .{Enum.One});
-    try expectFmt("enum: Enum.Two\n", "enum: {}\n", .{Enum.Two});
+    try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{value});
+    try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{&value});
+    try expectFmt("enum: fmt.test.enum.Enum.One\n", "enum: {}\n", .{Enum.One});
+    try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{Enum.Two});
 
     // test very large enum to verify ct branch quota is large enough
-    try expectFmt("enum: os.windows.win32error.Win32Error.INVALID_FUNCTION\n", "enum: {}\n", .{std.os.windows.Win32Error.INVALID_FUNCTION});
+    // TODO: https://github.com/ziglang/zig/issues/15609
+    if (!((builtin.cpu.arch == .wasm32) and builtin.mode == .Debug)) {
+        try expectFmt("enum: os.windows.win32error.Win32Error.INVALID_FUNCTION\n", "enum: {}\n", .{std.os.windows.Win32Error.INVALID_FUNCTION});
+    }
+
+    const E = enum {
+        One,
+        Two,
+        Three,
+    };
+
+    const inst = E.Two;
+
+    try expectFmt("fmt.test.enum.E.Two", "{}", .{inst});
 }
 
 test "non-exhaustive enum" {
@@ -2445,24 +2474,6 @@ test "custom" {
     try expectFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
 }
 
-test "struct" {
-    const S = struct {
-        a: u32,
-        b: anyerror,
-    };
-
-    const inst = S{
-        .a = 456,
-        .b = error.Unused,
-    };
-
-    try expectFmt("fmt.test.struct.S{ .a = 456, .b = error.Unused }", "{}", .{inst});
-    // Tuples
-    try expectFmt("{ }", "{}", .{.{}});
-    try expectFmt("{ -1 }", "{}", .{.{-1}});
-    try expectFmt("{ -1, 42, 2.5e+04 }", "{}", .{.{ -1, 42, 0.25e5 }});
-}
-
 test "union" {
     const TU = union(enum) {
         float: f32,
@@ -2493,18 +2504,6 @@ test "union" {
     try std.testing.expect(mem.eql(u8, eu_result[0..18], "fmt.test.union.EU@"));
 }
 
-test "enum" {
-    const E = enum {
-        One,
-        Two,
-        Three,
-    };
-
-    const inst = E.Two;
-
-    try expectFmt("fmt.test.enum.E.Two", "{}", .{inst});
-}
-
 test "struct.self-referential" {
     const S = struct {
         const SelfType = @This();
lib/std/hash_map.zig
@@ -1741,6 +1741,22 @@ test "std.hash_map clone" {
     try expectEqual(b.get(1).?, 1);
     try expectEqual(b.get(2).?, 2);
     try expectEqual(b.get(3).?, 3);
+
+    var original = AutoHashMap(i32, i32).init(std.testing.allocator);
+    defer original.deinit();
+
+    var i: u8 = 0;
+    while (i < 10) : (i += 1) {
+        try original.putNoClobber(i, i * 10);
+    }
+
+    var copy = try original.clone();
+    defer copy.deinit();
+
+    i = 0;
+    while (i < 10) : (i += 1) {
+        try testing.expect(copy.get(i).? == i * 10);
+    }
 }
 
 test "std.hash_map ensureTotalCapacity with existing elements" {
@@ -2072,24 +2088,6 @@ test "std.hash_map basic hash map usage" {
     try testing.expect(map.remove(3) == true);
 }
 
-test "std.hash_map clone" {
-    var original = AutoHashMap(i32, i32).init(std.testing.allocator);
-    defer original.deinit();
-
-    var i: u8 = 0;
-    while (i < 10) : (i += 1) {
-        try original.putNoClobber(i, i * 10);
-    }
-
-    var copy = try original.clone();
-    defer copy.deinit();
-
-    i = 0;
-    while (i < 10) : (i += 1) {
-        try testing.expect(copy.get(i).? == i * 10);
-    }
-}
-
 test "std.hash_map getOrPutAdapted" {
     const AdaptedContext = struct {
         fn eql(self: @This(), adapted_key: []const u8, test_key: u64) bool {
lib/std/priority_dequeue.zig
@@ -633,7 +633,7 @@ test "std.PriorityDequeue: peekMax" {
     try expect(queue.peekMax().? == 9);
 }
 
-test "std.PriorityDequeue: sift up with odd indices" {
+test "std.PriorityDequeue: sift up with odd indices, removeMin" {
     var queue = PDQ.init(testing.allocator, {});
     defer queue.deinit();
     const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
@@ -647,7 +647,7 @@ test "std.PriorityDequeue: sift up with odd indices" {
     }
 }
 
-test "std.PriorityDequeue: sift up with odd indices" {
+test "std.PriorityDequeue: sift up with odd indices, removeMax" {
     var queue = PDQ.init(testing.allocator, {});
     defer queue.deinit();
     const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
src/Module.zig
@@ -5280,6 +5280,9 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
             }
         },
     };
+    var must_free_decl_name = true;
+    defer if (must_free_decl_name) gpa.free(decl_name);
+
     const is_exported = export_bit and decl_name_index != 0;
     if (kind == .@"usingnamespace") try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1);
 
@@ -5296,6 +5299,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
         const new_decl = mod.declPtr(new_decl_index);
         new_decl.kind = kind;
         new_decl.name = decl_name;
+        must_free_decl_name = false;
         if (kind == .@"usingnamespace") {
             namespace.usingnamespace_set.putAssumeCapacity(new_decl_index, is_pub);
         }
@@ -5339,9 +5343,29 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
         new_decl.alive = true; // This Decl corresponds to an AST node and therefore always alive.
         return;
     }
-    gpa.free(decl_name);
     const decl_index = gop.key_ptr.*;
     const decl = mod.declPtr(decl_index);
+    if (kind == .@"test") {
+        const src_loc = SrcLoc{
+            .file_scope = decl.getFileScope(),
+            .parent_decl_node = decl.src_node,
+            .lazy = .{ .token_offset = 1 },
+        };
+        const msg = try ErrorMsg.create(
+            gpa,
+            src_loc,
+            "found test declaration with duplicate name: {s}",
+            .{decl_name},
+        );
+        errdefer msg.destroy(gpa);
+        try mod.failed_decls.putNoClobber(gpa, decl_index, msg);
+        const other_src_loc = SrcLoc{
+            .file_scope = namespace.file_scope,
+            .parent_decl_node = decl_node,
+            .lazy = .{ .token_offset = 1 },
+        };
+        try mod.errNoteNonLazy(other_src_loc, msg, "other test here", .{});
+    }
     log.debug("scan existing {*} ({s}) of {*}", .{ decl, decl.name, namespace });
     // Update the AST node of the decl; even if its contents are unchanged, it may
     // have been re-ordered.
test/behavior/basic.zig
@@ -203,7 +203,7 @@ test "multiline string comments at multiple places" {
     try expect(mem.eql(u8, s1, s2));
 }
 
-test "string concatenation" {
+test "string concatenation simple" {
     try expect(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
 }
 
test/behavior/comptime_memory.zig
@@ -45,7 +45,7 @@ test "type pun signed and unsigned as offset many pointer" {
     }
 }
 
-test "type pun signed and unsigned as array pointer" {
+test "type pun signed and unsigned as array pointer with pointer arithemtic" {
     if (true) {
         // TODO https://github.com/ziglang/zig/issues/9646
         return error.SkipZigTest;
test/behavior/duplicated_test_names.zig
@@ -0,0 +1,17 @@
+const Namespace = struct {
+    test "thingy" {}
+};
+
+fn thingy(a: usize, b: usize) usize {
+    return a + b;
+}
+
+comptime {
+    _ = Namespace;
+}
+
+test "thingy" {}
+
+test thingy {
+    if (thingy(1, 2) != 3) unreachable;
+}
test/behavior/vector.zig
@@ -1129,20 +1129,6 @@ test "array of vectors is copied" {
     try std.testing.expectEqual(points2[6], Vec3{ -345, -311, 381 });
 }
 
-test "byte vector initialized in inline function" {
-    const S = struct {
-        inline fn boolx4(e0: bool, e1: bool, e2: bool, e3: bool) @Vector(4, bool) {
-            return .{ e0, e1, e2, e3 };
-        }
-
-        fn all(vb: @Vector(4, bool)) bool {
-            return @reduce(.And, vb);
-        }
-    };
-
-    try expect(S.all(S.boolx4(true, true, true, true)));
-}
-
 test "byte vector initialized in inline function" {
     if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
test/cases/compile_errors/invalid_duplicate_test_decl_name.zig
@@ -0,0 +1,10 @@
+test "thingy" {}
+test "thingy" {}
+
+// error
+// backend=stage2
+// target=native
+// is_test=1
+//
+// :1:6: error: found test declaration with duplicate name: test.thingy
+// :2:6: note: other test here
test/behavior.zig
@@ -150,6 +150,7 @@ test {
     _ = @import("behavior/comptime_memory.zig");
     _ = @import("behavior/const_slice_child.zig");
     _ = @import("behavior/decltest.zig");
+    _ = @import("behavior/duplicated_test_names.zig");
     _ = @import("behavior/defer.zig");
     _ = @import("behavior/empty_tuple_fields.zig");
     _ = @import("behavior/empty_union.zig");