Commit 58c1d98c14

Veikka Tuominen <git@vexu.eu>
2022-12-31 13:28:21
add tests for fixed stage1 bugs
Closes #4144 Closes #4255 Closes #4372 Closes #4375 Closes #4380 Closes #4417 Closes #4423 Closes #4476 Closes #4528 Closes #4562 Closes #4572 Closes #4597 Closes #4639 Closes #4672 Closes #4782 Closes #4955 Closes #4984 Closes #4997 Closes #5010 Closes #5114 Closes #5166 Closes #5173 Closes #5276
1 parent 1c711b0
lib/std/io/fixed_buffer_stream.zig
@@ -132,6 +132,17 @@ test "FixedBufferStream output" {
     try testing.expectEqualSlices(u8, "HelloWorld!", fbs.getWritten());
 }
 
+test "FixedBufferStream output at comptime" {
+    comptime {
+        var buf: [255]u8 = undefined;
+        var fbs = fixedBufferStream(&buf);
+        const stream = fbs.writer();
+
+        try stream.print("{s}{s}!", .{ "Hello", "World" });
+        try testing.expectEqualSlices(u8, "HelloWorld!", fbs.getWritten());
+    }
+}
+
 test "FixedBufferStream output 2" {
     var buffer: [10]u8 = undefined;
     var fbs = fixedBufferStream(&buffer);
lib/std/fmt.zig
@@ -2773,3 +2773,21 @@ test "runtime precision specifier" {
     try expectFmt("3.14e+00", "{:1.[1]}", .{ number, precision });
     try expectFmt("3.14e+00", "{:1.[precision]}", .{ .number = number, .precision = precision });
 }
+
+test "recursive format function" {
+    const R = union(enum) {
+        const R = @This();
+        Leaf: i32,
+        Branch: struct { left: *const R, right: *const R },
+
+        pub fn format(self: R, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
+            return switch (self) {
+                .Leaf => |n| std.fmt.format(writer, "Leaf({})", .{n}),
+                .Branch => |b| std.fmt.format(writer, "Branch({}, {})", .{ b.left, b.right }),
+            };
+        }
+    };
+
+    var r = R{ .Leaf = 1 };
+    try expectFmt("Leaf(1)\n", "{}\n", .{&r});
+}
test/behavior/array.zig
@@ -654,3 +654,11 @@ test "array init of container level array variable" {
     S.bar(5, 6);
     try expectEqual([2]usize{ 5, 6 }, S.pair);
 }
+
+test "runtime initialized sentinel-terminated array literal" {
+    var c: u16 = 300;
+    const f = &[_:0x9999]u16{c};
+    const g = @ptrCast(*[4]u8, f);
+    try std.testing.expect(g[2] == 0x99);
+    try std.testing.expect(g[3] == 0x99);
+}
test/behavior/call.zig
@@ -394,3 +394,20 @@ test "recursive inline call with comptime known argument" {
 
     try expect(S.foo(4) == 20);
 }
+
+test "inline while with @call" {
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+
+    const S = struct {
+        fn inc(a: *u32) void {
+            a.* += 1;
+        }
+    };
+    var a: u32 = 0;
+    comptime var i = 0;
+    inline while (i < 10) : (i += 1) {
+        @call(.auto, S.inc, .{&a});
+    }
+    try expect(a == 10);
+}
test/behavior/cast.zig
@@ -1528,3 +1528,19 @@ test "optional pointer coerced to optional allowzero pointer" {
     q = p;
     try expect(@ptrToInt(q.?) == 4);
 }
+
+test "ptrToInt on const inside comptime block" {
+    var a = comptime blk: {
+        const b: u8 = 1;
+        const c = @ptrToInt(&b);
+        break :blk c;
+    };
+    try expect(@intToPtr(*const u8, a).* == 1);
+}
+
+test "single item pointer to pointer to array to slice" {
+    var x: i32 = 1234;
+    try expect(@as([]const i32, @as(*[1]i32, &x))[0] == 1234);
+    const z1 = @as([]const i32, @as(*[1]i32, &x));
+    try expect(z1[0] == 1234);
+}
test/behavior/eval.zig
@@ -1621,3 +1621,38 @@ test "inline for loop of functions returning error unions" {
     }
     try expect(a == 3);
 }
+
+test "if inside a switch" {
+    var condition = true;
+    var wave_type: u32 = 0;
+    var sample: i32 = switch (wave_type) {
+        0 => if (condition) 2 else 3,
+        1 => 100,
+        2 => 200,
+        3 => 300,
+        else => unreachable,
+    };
+    try expect(sample == 2);
+}
+
+test "function has correct return type when previous return is casted to smaller type" {
+    const S = struct {
+        fn foo(b: bool) u16 {
+            if (b) return @as(u8, 0xFF);
+            return 0xFFFF;
+        }
+    };
+    try expect(S.foo(true) == 0xFF);
+}
+
+test "early exit in container level const" {
+    const S = struct {
+        const value = blk: {
+            if (true) {
+                break :blk @as(u32, 1);
+            }
+            break :blk @as(u32, 0);
+        };
+    };
+    try expect(S.value == 1);
+}
test/behavior/fn.zig
@@ -484,3 +484,36 @@ test "using @ptrCast on function pointers" {
     // https://github.com/ziglang/zig/issues/2626
     // try comptime S.run();
 }
+
+test "function returns function returning type" {
+    const S = struct {
+        fn a() fn () type {
+            return (struct {
+                fn b() type {
+                    return u32;
+                }
+            }).b;
+        }
+    };
+    try expect(S.a()() == u32);
+}
+
+test "peer type resolution of inferred error set with non-void payload" {
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+
+    const S = struct {
+        fn openDataFile(mode: enum { read, write }) !u32 {
+            return switch (mode) {
+                .read => foo(),
+                .write => bar(),
+            };
+        }
+        fn foo() error{ a, b }!u32 {
+            return 1;
+        }
+        fn bar() error{ c, d }!u32 {
+            return 2;
+        }
+    };
+    try expect(try S.openDataFile(.read) == 1);
+}
test/behavior/packed-struct.zig
@@ -588,3 +588,14 @@ test "overaligned pointer to packed struct" {
         },
     }
 }
+
+test "packed struct initialized in bitcast" {
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+
+    const T = packed struct { val: u8 };
+    var val: u8 = 123;
+    const t = @bitCast(u8, T{ .val = val });
+    try expect(t == val);
+}
test/behavior/slice.zig
@@ -737,3 +737,13 @@ test "empty slice ptr is non null" {
     const t = @ptrCast([*]i8, p);
     try expect(@ptrToInt(t) == @ptrToInt(empty_slice.ptr));
 }
+
+test "slice decays to many pointer" {
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+
+    var buf: [8]u8 = "abcdefg\x00".*;
+    const p: [*:0]const u8 = buf[0..7 :0];
+    try expectEqualStrings(buf[0..7], std.mem.span(p));
+}
test/behavior/struct.zig
@@ -1495,3 +1495,63 @@ test "function pointer in struct returns the struct" {
     var a = A.f();
     try expect(a.f == A.f);
 }
+
+test "no dependency loop on optional field wrapped in generic function" {
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+
+    const S = struct {
+        fn Atomic(comptime T: type) type {
+            return T;
+        }
+        const A = struct { b: Atomic(?*B) };
+        const B = struct { a: ?*A };
+    };
+    var a: S.A = .{ .b = null };
+    var b: S.B = .{ .a = &a };
+    a.b = &b;
+
+    try expect(a.b == &b);
+    try expect(b.a == &a);
+}
+
+test "optional field init with tuple" {
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+
+    const S = struct {
+        a: ?struct { b: u32 },
+    };
+    var a: u32 = 0;
+    var b = S{
+        .a = .{ .b = a },
+    };
+    try expect(b.a.?.b == a);
+}
+
+test "if inside struct init inside if" {
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+
+    const MyStruct = struct { x: u32 };
+    const b: u32 = 5;
+    var i: u32 = 1;
+    var my_var = if (i < 5)
+        MyStruct{
+            .x = 1 + if (i > 0) b else 0,
+        }
+    else
+        MyStruct{
+            .x = 1 + if (i > 0) b else 0,
+        };
+    try expect(my_var.x == 6);
+}
+
+test "optional generic function label struct field" {
+    const Options = struct {
+        isFoo: ?fn (type) u8 = defaultIsFoo,
+        fn defaultIsFoo(comptime _: type) u8 {
+            return 123;
+        }
+    };
+    try expect((Options{}).isFoo.?(u8) == 123);
+}
test/behavior/translate_c_macros.zig
@@ -221,3 +221,7 @@ test "Macro that uses remainder operator. Issue #13346" {
         ),
     );
 }
+
+test "@typeInfo on @cImport result" {
+    try expect(@typeInfo(h).Struct.decls.len > 1);
+}
test/behavior/tuple.zig
@@ -3,6 +3,7 @@ const std = @import("std");
 const testing = std.testing;
 const expect = testing.expect;
 const expectEqualStrings = std.testing.expectEqualStrings;
+const expectEqual = std.testing.expectEqual;
 
 test "tuple concatenation" {
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
@@ -233,31 +234,31 @@ test "fieldParentPtr of anon struct" {
 test "offsetOf tuple" {
     var x: u32 = 0;
     const T = @TypeOf(.{ x, x });
-    _ = @offsetOf(T, "1");
+    try expect(@offsetOf(T, "1") == @sizeOf(u32));
 }
 
 test "offsetOf anon struct" {
     var x: u32 = 0;
     const T = @TypeOf(.{ .foo = x, .bar = x });
-    _ = @offsetOf(T, "bar");
+    try expect(@offsetOf(T, "bar") == @sizeOf(u32));
 }
 
 test "initializing tuple with mixed comptime-runtime fields" {
-    if (true) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
 
     var x: u32 = 15;
     const T = @TypeOf(.{ @as(i32, -1234), @as(u32, 5678), x });
     var a: T = .{ -1234, 5678, x + 1 };
-    _ = a;
+    try expect(a[2] == 16);
 }
 
 test "initializing anon struct with mixed comptime-runtime fields" {
-    if (true) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
 
     var x: u32 = 15;
     const T = @TypeOf(.{ .foo = @as(i32, -1234), .bar = x });
     var a: T = .{ .foo = -1234, .bar = x + 1 };
-    _ = a;
+    try expect(a.bar == 16);
 }
 
 test "tuple in tuple passed to generic function" {
@@ -366,3 +367,33 @@ test "tuple initialized with a runtime known value" {
     const w = .{W{ .w = e }};
     try expectEqualStrings(w[0].w.e, "test");
 }
+
+test "tuple of struct concatenation and coercion to array" {
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+
+    const StructWithDefault = struct { value: f32 = 42 };
+    const SomeStruct = struct { array: [4]StructWithDefault };
+
+    const value1 = SomeStruct{ .array = .{StructWithDefault{}} ++ [_]StructWithDefault{.{}} ** 3 };
+    const value2 = SomeStruct{ .array = .{.{}} ++ [_]StructWithDefault{.{}} ** 3 };
+
+    try expectEqual(value1, value2);
+}
+
+test "nested runtime conditionals in tuple initializer" {
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+
+    var data: u8 = 0;
+    const x = .{
+        if (data != 0) "" else switch (@truncate(u1, data)) {
+            0 => "up",
+            1 => "down",
+        },
+    };
+    try expectEqualStrings("up", x[0]);
+}
test/behavior/union.zig
@@ -1482,6 +1482,8 @@ test "no dependency loop when function pointer in union returns the union" {
         b: *const fn (x: U) void,
         c: *const fn (x: U) U,
         d: *const fn (x: u8) U,
+        e: *const fn (x: *U) void,
+        f: *const fn (x: *U) U,
         fn foo(x: u8) U {
             return .{ .a = x };
         }
test/cases/compile_errors/comptime_slice-sentinel_does_not_match_target-sentinel.zig
@@ -53,6 +53,21 @@ export fn foo_slice() void {
         _ = slice;
     }
 }
+export fn undefined_slice() void {
+    const arr: [100]u16 = undefined;
+    const slice = arr[0..12 :0];
+    _ = slice;
+}
+export fn string_slice() void {
+    const str = "abcdefg";
+    const slice = str[0..1 :12];
+    _ = slice;
+}
+export fn typeName_slice() void {
+    const arr = @typeName(usize);
+    const slice = arr[0..2 :0];
+    _ = slice;
+}
 
 // error
 // backend=stage2
@@ -72,3 +87,9 @@ export fn foo_slice() void {
 // :44:29: note: expected '255', found '0'
 // :52:29: error: value in memory does not match slice sentinel
 // :52:29: note: expected '255', found '0'
+// :58:22: error: value in memory does not match slice sentinel
+// :58:22: note: expected '0', found 'undefined'
+// :63:22: error: value in memory does not match slice sentinel
+// :63:22: note: expected '12', found '98'
+// :68:22: error: value in memory does not match slice sentinel
+// :68:22: note: expected '0', found '105'