migrate runtime safety tests to the new test harness

* migrate runtime safety tests to the new test harness
   - this required adding compare output / execution support for stage1
     to the test harness.
 * rename `zig build test-stage2` to `zig build test-cases` since it now
   does quite a bit of stage1 testing actually. I named it this way
   since the main directory in the source tree associated with these
   tests is "test/cases/".
 * add some documentation for the test manifest format.
This commit is contained in:
Andrew Kelley 2022-05-13 00:00:20 -07:00
parent f32928c50d
commit 66f3efb63b
76 changed files with 1410 additions and 1243 deletions

View file

@ -40,10 +40,10 @@ pub fn build(b: *Builder) !void {
const toolchain_step = b.step("test-toolchain", "Run the tests for the toolchain");
var test_stage2 = b.addTest("src/test.zig");
test_stage2.setBuildMode(mode);
test_stage2.addPackagePath("test_cases", "test/cases.zig");
test_stage2.single_threaded = single_threaded;
var test_cases = b.addTest("src/test.zig");
test_cases.setBuildMode(mode);
test_cases.addPackagePath("test_cases", "test/cases.zig");
test_cases.single_threaded = single_threaded;
const fmt_build_zig = b.addFmt(&[_][]const u8{"build.zig"});
@ -158,7 +158,7 @@ pub fn build(b: *Builder) !void {
if (target.isWindows() and target.getAbi() == .gnu) {
// LTO is currently broken on mingw, this can be removed when it's fixed.
exe.want_lto = false;
test_stage2.want_lto = false;
test_cases.want_lto = false;
}
const exe_options = b.addOptions();
@ -175,7 +175,7 @@ pub fn build(b: *Builder) !void {
if (link_libc) {
exe.linkLibC();
test_stage2.linkLibC();
test_cases.linkLibC();
}
const is_debug = mode == .Debug;
@ -258,7 +258,7 @@ pub fn build(b: *Builder) !void {
zig0.defineCMacro("ZIG_VERSION_PATCH", b.fmt("{d}", .{zig_version.patch}));
zig0.defineCMacro("ZIG_VERSION_STRING", b.fmt("\"{s}\"", .{version}));
for ([_]*std.build.LibExeObjStep{ zig0, exe, test_stage2 }) |artifact| {
for ([_]*std.build.LibExeObjStep{ zig0, exe, test_cases }) |artifact| {
artifact.addIncludePath("src");
artifact.addIncludePath("deps/SoftFloat-3e/source/include");
artifact.addIncludePath("deps/SoftFloat-3e-prebuilt");
@ -335,11 +335,11 @@ pub fn build(b: *Builder) !void {
}
try addCmakeCfgOptionsToExe(b, cfg, exe, use_zig_libcxx);
try addCmakeCfgOptionsToExe(b, cfg, test_stage2, use_zig_libcxx);
try addCmakeCfgOptionsToExe(b, cfg, test_cases, use_zig_libcxx);
} else {
// Here we are -Denable-llvm but no cmake integration.
try addStaticLlvmOptionsToExe(exe);
try addStaticLlvmOptionsToExe(test_stage2);
try addStaticLlvmOptionsToExe(test_cases);
}
}
@ -381,7 +381,7 @@ pub fn build(b: *Builder) !void {
const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter");
const test_stage2_options = b.addOptions();
test_stage2.addOptions("build_options", test_stage2_options);
test_cases.addOptions("build_options", test_stage2_options);
test_stage2_options.addOption(bool, "enable_logging", enable_logging);
test_stage2_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots);
@ -404,10 +404,10 @@ pub fn build(b: *Builder) !void {
test_stage2_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version));
test_stage2_options.addOption(std.SemanticVersion, "semver", semver);
const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests");
test_stage2_step.dependOn(&test_stage2.step);
const test_cases_step = b.step("test-cases", "Run the main compiler test cases");
test_cases_step.dependOn(&test_cases.step);
if (!skip_stage2_tests) {
toolchain_step.dependOn(test_stage2_step);
toolchain_step.dependOn(test_cases_step);
}
var chosen_modes: [4]builtin.Mode = undefined;
@ -485,7 +485,6 @@ pub fn build(b: *Builder) !void {
toolchain_step.dependOn(tests.addStackTraceTests(b, test_filter, modes));
toolchain_step.dependOn(tests.addCliTests(b, test_filter, modes));
toolchain_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes));
toolchain_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes));
toolchain_step.dependOn(tests.addTranslateCTests(b, test_filter));
if (!skip_run_translated_c) {
toolchain_step.dependOn(tests.addRunTranslatedCTests(b, test_filter, target));

View file

@ -71,12 +71,11 @@ release/bin/zig build test-standalone -Denable-macos-sdk
release/bin/zig build test-stack-traces -Denable-macos-sdk
release/bin/zig build test-cli -Denable-macos-sdk
release/bin/zig build test-asm-link -Denable-macos-sdk
release/bin/zig build test-runtime-safety -Denable-macos-sdk
release/bin/zig build test-translate-c -Denable-macos-sdk
release/bin/zig build test-run-translated-c -Denable-macos-sdk
release/bin/zig build docs -Denable-macos-sdk
release/bin/zig build test-fmt -Denable-macos-sdk
release/bin/zig build test-stage2 -Denable-macos-sdk
release/bin/zig build test-cases -Denable-macos-sdk
if [ "${BUILD_REASON}" != "PullRequest" ]; then
mv ../LICENSE release/

View file

@ -34,12 +34,11 @@ case "$1" in
./build/zig build $BUILD_FLAGS test-stack-traces
./build/zig build $BUILD_FLAGS test-cli
./build/zig build $BUILD_FLAGS test-asm-link
./build/zig build $BUILD_FLAGS test-runtime-safety
./build/zig build $BUILD_FLAGS test-translate-c
;;
7)
./build/zig build $BUILD_FLAGS # test building self-hosted without LLVM
./build/zig build $BUILD_FLAGS test-stage2
./build/zig build $BUILD_FLAGS test-cases
;;
'')
echo "error: expecting test group argument"

View file

@ -69,12 +69,11 @@ $ZIG build test-standalone -fqemu -fwasmtime
$ZIG build test-stack-traces -fqemu -fwasmtime
$ZIG build test-cli -fqemu -fwasmtime
$ZIG build test-asm-link -fqemu -fwasmtime
$ZIG build test-runtime-safety -fqemu -fwasmtime
$ZIG build test-translate-c -fqemu -fwasmtime
$ZIG build test-run-translated-c -fqemu -fwasmtime
$ZIG build docs -fqemu -fwasmtime
$ZIG build test-fmt -fqemu -fwasmtime
$ZIG build test-stage2 -fqemu -fwasmtime
$ZIG build test-cases -fqemu -fwasmtime
# Produce the experimental std lib documentation.
mkdir -p "$RELEASE_STAGING/docs/std"

View file

@ -1394,7 +1394,22 @@ pub const TestContext = struct {
}
},
.CompareObjectFile => @panic("TODO implement in the test harness"),
.Execution => @panic("TODO implement in the test harness"),
.Execution => |expected_stdout| {
switch (result.term) {
.Exited => |code| {
if (code != 0) {
dumpArgs(zig_args.items);
return error.CompilationFailed;
}
},
else => {
dumpArgs(zig_args.items);
return error.CompilationCrashed;
},
}
try std.testing.expectEqualStrings("", result.stderr);
try std.testing.expectEqualStrings(expected_stdout, result.stdout);
},
.Header => @panic("TODO implement in the test harness"),
}
return;

61
test/cases/README.md Normal file
View file

@ -0,0 +1,61 @@
# Test Case Quick Reference
Use comments at the **end of the file** to indicate metadata about the test
case. Here are examples of different kinds of tests:
## Compile Error Test
If you want it to be run with `zig test` and match expected error messages:
```zig
// error
// is_test=1
//
// :4:13: error: 'try' outside function scope
```
## Execution
This will do `zig run` on the code and expect exit code 0.
```zig
// run
```
## Incremental Compilation
Make multiple files that have ".", and then an integer, before the ".zig"
extension, like this:
```
hello.0.zig
hello.1.zig
hello.2.zig
```
Each file can be a different kind of test, such as expecting compile errors,
or expecting to be run and exit(0). The test harness will use these to simulate
incremental compilation.
At the time of writing there is no way to specify multiple files being changed
as part of an update.
## Subdirectories
Subdirectories do not have any semantic meaning but they can be used for
organization since the test harness will recurse into them. The full directory
path will be prepended as a prefix on the test case name.
## Limiting which Backends and Targets are Tested
```zig
// run
// backend=stage2,llvm
// target=x86_64-linux,x86_64-macos
```
Possible backends are:
* `stage1`: equivalent to `-fstage1`.
* `stage2`: equivalent to passing `-fno-stage1 -fno-LLVM`.
* `llvm`: equivalent to `-fLLVM -fno-stage1`.

View file

@ -0,0 +1,21 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var array align(4) = [_]u32{0x11111111, 0x11111111};
const bytes = std.mem.sliceAsBytes(array[0..]);
if (foo(bytes) != 0x11111111) return error.Wrong;
return error.TestFailed;
}
fn foo(bytes: []u8) u32 {
const slice4 = bytes[1..5];
const int_slice = std.mem.bytesAsSlice(u32, @alignCast(4, slice4));
return int_slice[0];
}
// run
// backend=stage1

View file

@ -0,0 +1,19 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var bytes: [1]u8 align(16) = undefined;
var ptr = other;
var frame = @asyncCall(&bytes, {}, ptr, .{});
_ = frame;
return error.TestFailed;
}
fn other() callconv(.Async) void {
suspend {}
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
const Set1 = error{A, B};
const Set2 = error{A, C};
pub fn main() !void {
foo(Set1.B) catch {};
return error.TestFailed;
}
fn foo(set1: Set1) Set2 {
return @errSetCast(Set2, set1);
}
// run
// backend=stage1

View file

@ -0,0 +1,17 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
baz(bar(-129.1));
return error.TestFailed;
}
fn bar(a: f32) i8 {
return @floatToInt(i8, a);
}
fn baz(_: i8) void { }
// run
// backend=stage1

View file

@ -0,0 +1,17 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
baz(bar(-1.1));
return error.TestFailed;
}
fn bar(a: f32) u8 {
return @floatToInt(u8, a);
}
fn baz(_: u8) void { }
// run
// backend=stage1

View file

@ -0,0 +1,17 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
baz(bar(256.2));
return error.TestFailed;
}
fn bar(a: f32) u8 {
return @floatToInt(u8, a);
}
fn baz(_: u8) void { }
// run
// backend=stage1

View file

@ -0,0 +1,19 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
bar(1, 1);
return error.TestFailed;
}
fn bar(one: u1, not_zero: i32) void {
var x = one << @intCast(u0, not_zero);
_ = x;
}
// run
// backend=stage1

View file

@ -0,0 +1,22 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
const Foo = enum {
A,
B,
C,
};
pub fn main() !void {
baz(bar(3));
return error.TestFailed;
}
fn bar(a: u2) Foo {
return @intToEnum(Foo, a);
}
fn baz(_: Foo) void {}
// run
// backend=stage1

View file

@ -0,0 +1,15 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var zero: usize = 0;
var b = @intToPtr(*u8, zero);
_ = b;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,15 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var zero: usize = 0;
var b = @intToPtr(*i32, zero);
_ = b;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,24 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "invalid enum value")) {
std.process.exit(0);
}
std.process.exit(1);
}
const E = enum(u32) {
X = 1,
};
pub fn main() !void {
var e: E = undefined;
@memset(@ptrCast([*]u8, &e), 0x55, @sizeOf(E));
var n = @tagName(e);
_ = n;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,25 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "invalid enum value")) {
std.process.exit(0);
}
std.process.exit(1);
}
const U = union(enum(u32)) {
X: u8,
};
pub fn main() !void {
var u: U = undefined;
@memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U));
var t: @typeInfo(U).Union.tag_type.? = u;
var n = @tagName(t);
_ = n;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "sentinel mismatch")) {
std.process.exit(0);
}
std.process.exit(1);
}
pub fn main() !void {
var buf: [4]u8 = undefined;
const slice = buf[0..3 :0];
_ = slice;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,28 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
var frame: anyframe = undefined;
pub fn main() !void {
_ = async amain();
resume frame;
return error.TestFailed;
}
fn amain() void {
var f = async func();
await f;
await f;
}
fn func() void {
suspend {
frame = @frame();
}
}
// run
// backend=stage1

View file

@ -0,0 +1,24 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
const Foo = union {
float: f32,
int: u32,
};
pub fn main() !void {
var f = Foo { .int = 42 };
bar(&f);
return error.TestFailed;
}
fn bar(f: *Foo) void {
f.float = 12.34;
}
// run
// backend=stage1

View file

@ -0,0 +1,15 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "oh no")) {
std.process.exit(0);
}
std.process.exit(1);
}
pub fn main() !void {
if (true) @panic("oh no");
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
const x = widenSlice(&[_]u8{1, 2, 3, 4, 5});
if (x.len == 0) return error.Whatever;
return error.TestFailed;
}
fn widenSlice(slice: []align(1) const u8) []align(1) const i32 {
return std.mem.bytesAsSlice(i32, slice);
}
// run
// backend=stage1

View file

@ -0,0 +1,16 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
bar(9999) catch {};
return error.TestFailed;
}
fn bar(x: u16) anyerror {
return @intToError(x);
}
// run
// backend=stage1

View file

@ -0,0 +1,20 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "index out of bounds")) {
std.process.exit(0);
}
std.process.exit(1);
}
pub fn main() !void {
var buf_zero = [0]u8{};
const input: []u8 = &buf_zero;
const slice = input[0..0 :0];
_ = slice;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,38 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
var failing_frame: @Frame(failing) = undefined;
pub fn main() !void {
const p = nonFailing();
resume p;
const p2 = async printTrace(p);
_ = p2;
return error.TestFailed;
}
fn nonFailing() anyframe->anyerror!void {
failing_frame = async failing();
return &failing_frame;
}
fn failing() anyerror!void {
suspend {}
return second();
}
fn second() callconv(.Async) anyerror!void {
return error.Fail;
}
fn printTrace(p: anyframe->anyerror!void) void {
(await p) catch unreachable;
}
// run
// backend=stage1

View file

@ -0,0 +1,20 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var a: @Vector(4, i32) = [4]i32{111, 222, 333, 444};
var b: @Vector(4, i32) = [4]i32{111, 222, 333, 441};
const x = divExact(a, b);
_ = x;
return error.TestFailed;
}
fn divExact(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
return @divExact(a, b);
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
const x = divExact(10, 3);
if (x == 0) return error.Whatever;
return error.TestFailed;
}
fn divExact(a: i32, b: i32) i32 {
return @divExact(a, b);
}
// run
// backend=stage1

View file

@ -0,0 +1,17 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "incorrect alignment")) {
std.process.exit(0);
}
std.process.exit(1);
}
pub fn main() !void {
var x: usize = 5;
var y = @intToPtr([*]align(4) u8, x);
_ = y;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,22 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "integer overflow")) {
std.process.exit(0);
}
std.process.exit(1);
}
pub fn main() !void {
const x = add(65530, 10);
if (x == 0) return error.Whatever;
return error.TestFailed;
}
fn add(a: u16, b: u16) u16 {
return a + b;
}
// run
// backend=stage1

View file

@ -0,0 +1,19 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var a: @Vector(4, i32) = [4]i32{111, 222, 333, 444};
var b: @Vector(4, i32) = [4]i32{111, 0, 333, 444};
const x = div0(a, b);
_ = x;
return error.TestFailed;
}
fn div0(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
return @divTrunc(a, b);
}
// run
// backend=stage1

View file

@ -0,0 +1,17 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
const x = div0(999, 0);
_ = x;
return error.TestFailed;
}
fn div0(a: i32, b: i32) i32 {
return @divTrunc(a, b);
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
const x = mul(300, 6000);
if (x == 0) return error.Whatever;
return error.TestFailed;
}
fn mul(a: u16, b: u16) u16 {
return a * b;
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
const x = neg(-32768);
if (x == 32767) return error.Whatever;
return error.TestFailed;
}
fn neg(a: i16) i16 {
return -a;
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
const x = sub(10, 20);
if (x == 0) return error.Whatever;
return error.TestFailed;
}
fn sub(a: u16, b: u16) u16 {
return a - b;
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var p = async suspendOnce();
resume p; //ok
resume p; //bad
return error.TestFailed;
}
fn suspendOnce() void {
suspend {}
}
// run
// backend=stage1

View file

@ -0,0 +1,19 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
_ = nosuspend add(101, 100);
return error.TestFailed;
}
fn add(a: i32, b: i32) i32 {
if (a > 100) {
suspend {}
}
return a + b;
}
// run
// backend=stage1

View file

@ -0,0 +1,15 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var ptr: [*c]i32 = null;
var b = ptr.?;
_ = b;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,15 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var ptr: ?*i32 = null;
var b = ptr.?;
_ = b;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
const a = [_]i32{1, 2, 3, 4};
baz(bar(&a));
return error.TestFailed;
}
fn bar(a: []const i32) i32 {
return a[4];
}
fn baz(_: i32) void { }
// run
// backend=stage1

View file

@ -0,0 +1,15 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var c_ptr: [*c]u8 = 0;
var zig_ptr: *u8 = c_ptr;
_ = zig_ptr;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,20 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "sentinel mismatch")) {
std.process.exit(0);
}
std.process.exit(1);
}
pub fn main() !void {
var buf: [4]u8 = undefined;
const ptr: [*]u8 = &buf;
const slice = ptr[0..3 :0];
_ = slice;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,20 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var frame = async first();
resume frame;
return error.TestFailed;
}
fn first() void {
other();
}
fn other() void {
suspend {}
}
// run
// backend=stage1

View file

@ -0,0 +1,21 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var frame = async first();
resume frame;
return error.TestFailed;
}
fn first() void {
var frame = async other();
await frame;
}
fn other() void {
suspend {}
}
// run
// backend=stage1

View file

@ -0,0 +1,31 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
fn foo() void {
suspend {
global_frame = @frame();
}
var f = async bar(@frame());
_ = f;
std.os.exit(1);
}
fn bar(frame: anyframe) void {
suspend {
resume frame;
}
std.os.exit(1);
}
var global_frame: anyframe = undefined;
pub fn main() !void {
_ = async foo();
resume global_frame;
std.os.exit(1);
}
// run
// backend=stage1

View file

@ -0,0 +1,26 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
fn foo() void {
var f = async bar(@frame());
_ = f;
std.os.exit(1);
}
fn bar(frame: anyframe) void {
suspend {
resume frame;
}
std.os.exit(1);
}
pub fn main() !void {
_ = async foo();
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,20 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {
std.process.exit(0);
}
std.process.exit(1);
}
pub fn main() !void {
var x: u24 = 42;
var y: u5 = 24;
var z = x >> y;
_ = z;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,20 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {
std.process.exit(0);
}
std.process.exit(1);
}
pub fn main() !void {
var x: u24 = 42;
var y: u5 = 24;
var z = x << y;
_ = z;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,20 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var a: @Vector(4, i16) = [_]i16{ 1, 2, -32768, 4 };
var b: @Vector(4, i16) = [_]i16{ 1, 2, -1, 4 };
const x = div(a, b);
if (x[2] == 32767) return error.Whatever;
return error.TestFailed;
}
fn div(a: @Vector(4, i16), b: @Vector(4, i16)) @Vector(4, i16) {
return @divTrunc(a, b);
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
const x = div(-32768, -1);
if (x == 32767) return error.Whatever;
return error.TestFailed;
}
fn div(a: i16, b: i16) i16 {
return @divTrunc(a, b);
}
// run
// backend=stage1

View file

@ -0,0 +1,15 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var value: c_short = -1;
var casted = @intCast(u32, value);
_ = casted;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
const x = unsigned_cast(-10);
if (x == 0) return error.Whatever;
return error.TestFailed;
}
fn unsigned_cast(x: i32) u32 {
return @intCast(u32, x);
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
const x = shl(-16385, 1);
if (x == 0) return error.Whatever;
return error.TestFailed;
}
fn shl(a: i16, b: u4) i16 {
return @shlExact(a, b);
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
const x = shr(-16385, 1);
if (x == 0) return error.Whatever;
return error.TestFailed;
}
fn shr(a: i16, b: u4) i16 {
return @shrExact(a, b);
}
// run
// backend=stage1

View file

@ -0,0 +1,19 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "attempt to cast negative value to unsigned integer")) {
std.process.exit(0);
}
std.process.exit(1);
}
pub fn main() !void {
var x = @splat(4, @as(i32, -2147483647));
var y = @intCast(@Vector(4, u32), x);
_ = y;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,19 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "sentinel mismatch")) {
std.process.exit(0);
}
std.process.exit(1);
}
pub fn main() !void {
var buf: [4]f32 = undefined;
const slice = buf[0..3 :1.2];
_ = slice;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,19 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "sentinel mismatch")) {
std.process.exit(0);
}
std.process.exit(1);
}
pub fn main() !void {
var buf: [4]?*i32 = undefined;
const slice = buf[0..3 :null];
_ = slice;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "sentinel mismatch")) {
std.process.exit(0);
}
std.process.exit(1);
}
pub fn main() !void {
var buf: [4]u8 = undefined;
const slice = buf[0..];
const slice2 = slice[0..3 :0];
_ = slice2;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,20 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "index out of bounds")) {
std.process.exit(0);
}
std.process.exit(1);
}
pub fn main() !void {
var buf = [4]u8{ 'a', 'b', 'c', 0 };
const input: []u8 = &buf;
const slice = input[0..4 :0];
_ = slice;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,16 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var ptr: [*c]const u32 = null;
var slice = ptr[0..3];
_ = slice;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,25 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "reached unreachable code")) {
std.process.exit(0);
}
std.process.exit(1);
}
const E = enum(u32) {
X = 1,
};
pub fn main() !void {
var e: E = undefined;
@memset(@ptrCast([*]u8, &e), 0x55, @sizeOf(E));
switch (e) {
.X => @breakpoint(),
}
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,25 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "reached unreachable code")) {
std.process.exit(0);
}
std.process.exit(1);
}
const U = union(enum(u32)) {
X: u8,
};
pub fn main() !void {
var u: U = undefined;
@memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U));
switch (u) {
.X => @breakpoint(),
}
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,19 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "integer cast truncated bits")) {
std.process.exit(0);
}
std.process.exit(1);
}
pub fn main() !void {
var x = @splat(4, @as(u32, 0xdeadbeef));
var y = @intCast(@Vector(4, u16), x);
_ = y;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,15 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var value: u8 = 245;
var casted = @intCast(i8, value);
_ = casted;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
const x = shl(0b0010111111111111, 3);
if (x == 0) return error.Whatever;
return error.TestFailed;
}
fn shl(a: u16, b: u4) u16 {
return @shlExact(a, b);
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
const x = shr(0b0010111111111111, 3);
if (x == 0) return error.Whatever;
return error.TestFailed;
}
fn shr(a: u16, b: u4) u16 {
return @shrExact(a, b);
}
// run
// backend=stage1

View file

@ -0,0 +1,19 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "integer cast truncated bits")) {
std.process.exit(0);
}
std.process.exit(1);
}
pub fn main() !void {
var x = @splat(4, @as(u32, 0x80000000));
var y = @intCast(@Vector(4, i32), x);
_ = y;
return error.TestFailed;
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = stack_trace;
if (std.mem.eql(u8, message, "attempt to unwrap error: Whatever")) {
std.process.exit(0);
}
std.process.exit(1);
}
pub fn main() !void {
bar() catch unreachable;
return error.TestFailed;
}
fn bar() !void {
return error.Whatever;
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
const x = shorten_cast(1);
if (x == 0) return error.Whatever;
return error.TestFailed;
}
fn shorten_cast(x: u8) u0 {
return @intCast(u0, x);
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
const x = shorten_cast(200);
if (x == 0) return error.Whatever;
return error.TestFailed;
}
fn shorten_cast(x: i32) i8 {
return @intCast(i8, x);
}
// run
// backend=stage1

View file

@ -0,0 +1,19 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var a: @Vector(4, i32) = [_]i32{ 1, 2, 2147483643, 4 };
var b: @Vector(4, i32) = [_]i32{ 5, 6, 7, 8 };
const x = add(a, b);
_ = x;
return error.TestFailed;
}
fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
return a + b;
}
// run
// backend=stage1

View file

@ -0,0 +1,19 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var a: @Vector(4, u8) = [_]u8{ 1, 2, 200, 4 };
var b: @Vector(4, u8) = [_]u8{ 5, 6, 2, 8 };
const x = mul(b, a);
_ = x;
return error.TestFailed;
}
fn mul(a: @Vector(4, u8), b: @Vector(4, u8)) @Vector(4, u8) {
return a * b;
}
// run
// backend=stage1

View file

@ -0,0 +1,18 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var a: @Vector(4, i16) = [_]i16{ 1, -32768, 200, 4 };
const x = neg(a);
_ = x;
return error.TestFailed;
}
fn neg(a: @Vector(4, i16)) @Vector(4, i16) {
return -a;
}
// run
// backend=stage1

View file

@ -0,0 +1,19 @@
const std = @import("std");
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
_ = message;
_ = stack_trace;
std.process.exit(0);
}
pub fn main() !void {
var a: @Vector(4, u32) = [_]u32{ 1, 2, 8, 4 };
var b: @Vector(4, u32) = [_]u32{ 5, 6, 7, 8 };
const x = sub(b, a);
_ = x;
return error.TestFailed;
}
fn sub(a: @Vector(4, u32), b: @Vector(4, u32)) @Vector(4, u32) {
return a - b;
}
// run
// backend=stage1

File diff suppressed because it is too large Load diff

View file

@ -18,7 +18,6 @@ const compare_output = @import("compare_output.zig");
const standalone = @import("standalone.zig");
const stack_traces = @import("stack_traces.zig");
const assemble_and_link = @import("assemble_and_link.zig");
const runtime_safety = @import("runtime_safety.zig");
const translate_c = @import("translate_c.zig");
const run_translated_c = @import("run_translated_c.zig");
const gen_h = @import("gen_h.zig");
@ -455,21 +454,6 @@ pub fn addStackTraceTests(b: *build.Builder, test_filter: ?[]const u8, modes: []
return cases.step;
}
pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
const cases = b.allocator.create(CompareOutputContext) catch unreachable;
cases.* = CompareOutputContext{
.b = b,
.step = b.step("test-runtime-safety", "Run the runtime safety tests"),
.test_index = 0,
.test_filter = test_filter,
.modes = modes,
};
runtime_safety.addCases(cases);
return cases.step;
}
pub fn addStandaloneTests(
b: *build.Builder,
test_filter: ?[]const u8,