zig/test/tests.zig

1696 lines
58 KiB
Zig
Raw Normal View History

const std = @import("std");
const debug = std.debug;
const warn = debug.warn;
const build = std.build;
pub const Target = build.Target;
pub const CrossTarget = build.CrossTarget;
const Buffer = std.Buffer;
const io = std.io;
2019-05-26 18:17:34 +01:00
const fs = std.fs;
const mem = std.mem;
const fmt = std.fmt;
const ArrayList = std.ArrayList;
const builtin = @import("builtin");
const Mode = builtin.Mode;
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
const LibExeObjStep = build.LibExeObjStep;
const compare_output = @import("compare_output.zig");
const standalone = @import("standalone.zig");
const stack_traces = @import("stack_traces.zig");
const compile_errors = @import("compile_errors.zig");
const assemble_and_link = @import("assemble_and_link.zig");
const runtime_safety = @import("runtime_safety.zig");
2017-11-24 19:56:05 +00:00
const translate_c = @import("translate_c.zig");
const gen_h = @import("gen_h.zig");
significantly increase test coverage * add zig build option `-Dskip-libc` to skip tests that build libc (e.g. if you don't want to wait for musl to build) * add `-Denable-wine` option which uses wine to run cross compiled windows tests on non-windows hosts * add `-Denable-qemu` option which uses qemu to run cross compiled foreign architecture tests * add `-Denable-foreign-glibc=path` option which combined with `-Denable-qemu` enables running cross compiled tests that link against glibc. See https://github.com/ziglang/zig/wiki/Updating-libc#glibc for how to produce this directory. * the test matrix is done manually. release test builds are only enabled by default for the native target. this should save us some CI time, while still providing decent coverage of release builds. - add test coverage for `x86_64-linux-musl -lc` (building musl libc) - add test coverage for `x86_64-linux-gnu -lc` (building glibc) - add test coverage for `aarch64v8_5a-linux-none` - add test coverage for `aarch64v8_5a-linux-musl -lc` (building musl libc) - add test coverage for `aarch64v8_5a-linux-gnu -lc` (building glibc) - add test coverage for `arm-linux-none` - test coverage for `arm-linux-musleabihf -lc` (building musl libc) is disabled due to #3286 - test coverage for `arm-linux-gnueabihf -lc` (building glibc) is disabled due to #3287 - test coverage for `x86_64-windows-gnu -lc` (building mingw-w64) is disabled due to #3285 * enable qemu testing on the Linux CI job. There's not really a good reason to enable wine, since we have a Windows CI job as well. * remove the no longer needed `--build-file ../build.zig` from CI scripts * fix bug in glibc compilation where it wasn't properly reading the abi list txt files, resulting in "key not found" error. * std.build.Target gains: - isNetBSD - isLinux - osRequiresLibC - getArchPtrBitWidth - getExternalExecutor * zig build system gains support for enabling wine and enabling qemu. `artifact.enable_wine = true;`, `artifact.enable_qemu = true;`. This communicates that the system has these tools installed and the build system will use them to run tests. * zig build system gains support for overriding the dynamic linker of an executable artifact. * fix std.c.lseek prototype. makes behavior tests for arm-linux-musleabihf pass. * disable std lib tests that are failing on ARM. See #3288, #3289 * provide `std.os.off_t`. * disable some of the compiler_rt symbols for arm 32 bit. Fixes compiler_rt tests for arm 32 bit * add __stack_chk_guard when linking against glibc. Fixes std lib tests for aarch64-linux-gnu * workaround for "unable to inline function" using `@inlineCall`. Fixes compiler_rt tests for arm 32 bit.
2019-09-22 04:55:56 +01:00
const TestTarget = struct {
target: Target = .Native,
mode: builtin.Mode = .Debug,
link_libc: bool = false,
single_threaded: bool = false,
disable_native: bool = false,
significantly increase test coverage * add zig build option `-Dskip-libc` to skip tests that build libc (e.g. if you don't want to wait for musl to build) * add `-Denable-wine` option which uses wine to run cross compiled windows tests on non-windows hosts * add `-Denable-qemu` option which uses qemu to run cross compiled foreign architecture tests * add `-Denable-foreign-glibc=path` option which combined with `-Denable-qemu` enables running cross compiled tests that link against glibc. See https://github.com/ziglang/zig/wiki/Updating-libc#glibc for how to produce this directory. * the test matrix is done manually. release test builds are only enabled by default for the native target. this should save us some CI time, while still providing decent coverage of release builds. - add test coverage for `x86_64-linux-musl -lc` (building musl libc) - add test coverage for `x86_64-linux-gnu -lc` (building glibc) - add test coverage for `aarch64v8_5a-linux-none` - add test coverage for `aarch64v8_5a-linux-musl -lc` (building musl libc) - add test coverage for `aarch64v8_5a-linux-gnu -lc` (building glibc) - add test coverage for `arm-linux-none` - test coverage for `arm-linux-musleabihf -lc` (building musl libc) is disabled due to #3286 - test coverage for `arm-linux-gnueabihf -lc` (building glibc) is disabled due to #3287 - test coverage for `x86_64-windows-gnu -lc` (building mingw-w64) is disabled due to #3285 * enable qemu testing on the Linux CI job. There's not really a good reason to enable wine, since we have a Windows CI job as well. * remove the no longer needed `--build-file ../build.zig` from CI scripts * fix bug in glibc compilation where it wasn't properly reading the abi list txt files, resulting in "key not found" error. * std.build.Target gains: - isNetBSD - isLinux - osRequiresLibC - getArchPtrBitWidth - getExternalExecutor * zig build system gains support for enabling wine and enabling qemu. `artifact.enable_wine = true;`, `artifact.enable_qemu = true;`. This communicates that the system has these tools installed and the build system will use them to run tests. * zig build system gains support for overriding the dynamic linker of an executable artifact. * fix std.c.lseek prototype. makes behavior tests for arm-linux-musleabihf pass. * disable std lib tests that are failing on ARM. See #3288, #3289 * provide `std.os.off_t`. * disable some of the compiler_rt symbols for arm 32 bit. Fixes compiler_rt tests for arm 32 bit * add __stack_chk_guard when linking against glibc. Fixes std lib tests for aarch64-linux-gnu * workaround for "unable to inline function" using `@inlineCall`. Fixes compiler_rt tests for arm 32 bit.
2019-09-22 04:55:56 +01:00
};
const test_targets = [_]TestTarget{
TestTarget{},
TestTarget{
.link_libc = true,
},
TestTarget{
.single_threaded = true,
},
TestTarget{
.mode = .ReleaseFast,
},
TestTarget{
.link_libc = true,
.mode = .ReleaseFast,
},
TestTarget{
.mode = .ReleaseFast,
.single_threaded = true,
},
TestTarget{
.mode = .ReleaseSafe,
},
TestTarget{
.link_libc = true,
.mode = .ReleaseSafe,
},
TestTarget{
.mode = .ReleaseSafe,
.single_threaded = true,
},
TestTarget{
.mode = .ReleaseSmall,
},
TestTarget{
.link_libc = true,
.mode = .ReleaseSmall,
},
TestTarget{
.mode = .ReleaseSmall,
.single_threaded = true,
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .x86_64,
.abi = .none,
},
},
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .x86_64,
.abi = .gnu,
},
},
.link_libc = true,
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .x86_64,
.abi = .musl,
},
},
.link_libc = true,
},
significantly increase test coverage * add zig build option `-Dskip-libc` to skip tests that build libc (e.g. if you don't want to wait for musl to build) * add `-Denable-wine` option which uses wine to run cross compiled windows tests on non-windows hosts * add `-Denable-qemu` option which uses qemu to run cross compiled foreign architecture tests * add `-Denable-foreign-glibc=path` option which combined with `-Denable-qemu` enables running cross compiled tests that link against glibc. See https://github.com/ziglang/zig/wiki/Updating-libc#glibc for how to produce this directory. * the test matrix is done manually. release test builds are only enabled by default for the native target. this should save us some CI time, while still providing decent coverage of release builds. - add test coverage for `x86_64-linux-musl -lc` (building musl libc) - add test coverage for `x86_64-linux-gnu -lc` (building glibc) - add test coverage for `aarch64v8_5a-linux-none` - add test coverage for `aarch64v8_5a-linux-musl -lc` (building musl libc) - add test coverage for `aarch64v8_5a-linux-gnu -lc` (building glibc) - add test coverage for `arm-linux-none` - test coverage for `arm-linux-musleabihf -lc` (building musl libc) is disabled due to #3286 - test coverage for `arm-linux-gnueabihf -lc` (building glibc) is disabled due to #3287 - test coverage for `x86_64-windows-gnu -lc` (building mingw-w64) is disabled due to #3285 * enable qemu testing on the Linux CI job. There's not really a good reason to enable wine, since we have a Windows CI job as well. * remove the no longer needed `--build-file ../build.zig` from CI scripts * fix bug in glibc compilation where it wasn't properly reading the abi list txt files, resulting in "key not found" error. * std.build.Target gains: - isNetBSD - isLinux - osRequiresLibC - getArchPtrBitWidth - getExternalExecutor * zig build system gains support for enabling wine and enabling qemu. `artifact.enable_wine = true;`, `artifact.enable_qemu = true;`. This communicates that the system has these tools installed and the build system will use them to run tests. * zig build system gains support for overriding the dynamic linker of an executable artifact. * fix std.c.lseek prototype. makes behavior tests for arm-linux-musleabihf pass. * disable std lib tests that are failing on ARM. See #3288, #3289 * provide `std.os.off_t`. * disable some of the compiler_rt symbols for arm 32 bit. Fixes compiler_rt tests for arm 32 bit * add __stack_chk_guard when linking against glibc. Fixes std lib tests for aarch64-linux-gnu * workaround for "unable to inline function" using `@inlineCall`. Fixes compiler_rt tests for arm 32 bit.
2019-09-22 04:55:56 +01:00
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = builtin.Arch{ .aarch64 = builtin.Arch.Arm64.v8_5a },
.abi = .none,
},
},
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = builtin.Arch{ .aarch64 = builtin.Arch.Arm64.v8_5a },
.abi = .musl,
},
},
.link_libc = true,
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = builtin.Arch{ .aarch64 = builtin.Arch.Arm64.v8_5a },
.abi = .gnu,
},
},
.link_libc = true,
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v8_5a },
.abi = .none,
},
},
},
// TODO https://github.com/ziglang/zig/issues/3286
//TestTarget{
// .target = Target{
// .Cross = CrossTarget{
// .os = .linux,
// .arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v8_5a },
// .abi = .musleabihf,
// },
// },
// .link_libc = true,
//},
// TODO https://github.com/ziglang/zig/issues/3287
//TestTarget{
// .target = Target{
// .Cross = CrossTarget{
// .os = .linux,
// .arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v8_5a },
// .abi = .gnueabihf,
// },
// },
// .link_libc = true,
//},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .macosx,
.arch = .x86_64,
.abi = .gnu,
},
},
// TODO https://github.com/ziglang/zig/issues/3295
.disable_native = true,
significantly increase test coverage * add zig build option `-Dskip-libc` to skip tests that build libc (e.g. if you don't want to wait for musl to build) * add `-Denable-wine` option which uses wine to run cross compiled windows tests on non-windows hosts * add `-Denable-qemu` option which uses qemu to run cross compiled foreign architecture tests * add `-Denable-foreign-glibc=path` option which combined with `-Denable-qemu` enables running cross compiled tests that link against glibc. See https://github.com/ziglang/zig/wiki/Updating-libc#glibc for how to produce this directory. * the test matrix is done manually. release test builds are only enabled by default for the native target. this should save us some CI time, while still providing decent coverage of release builds. - add test coverage for `x86_64-linux-musl -lc` (building musl libc) - add test coverage for `x86_64-linux-gnu -lc` (building glibc) - add test coverage for `aarch64v8_5a-linux-none` - add test coverage for `aarch64v8_5a-linux-musl -lc` (building musl libc) - add test coverage for `aarch64v8_5a-linux-gnu -lc` (building glibc) - add test coverage for `arm-linux-none` - test coverage for `arm-linux-musleabihf -lc` (building musl libc) is disabled due to #3286 - test coverage for `arm-linux-gnueabihf -lc` (building glibc) is disabled due to #3287 - test coverage for `x86_64-windows-gnu -lc` (building mingw-w64) is disabled due to #3285 * enable qemu testing on the Linux CI job. There's not really a good reason to enable wine, since we have a Windows CI job as well. * remove the no longer needed `--build-file ../build.zig` from CI scripts * fix bug in glibc compilation where it wasn't properly reading the abi list txt files, resulting in "key not found" error. * std.build.Target gains: - isNetBSD - isLinux - osRequiresLibC - getArchPtrBitWidth - getExternalExecutor * zig build system gains support for enabling wine and enabling qemu. `artifact.enable_wine = true;`, `artifact.enable_qemu = true;`. This communicates that the system has these tools installed and the build system will use them to run tests. * zig build system gains support for overriding the dynamic linker of an executable artifact. * fix std.c.lseek prototype. makes behavior tests for arm-linux-musleabihf pass. * disable std lib tests that are failing on ARM. See #3288, #3289 * provide `std.os.off_t`. * disable some of the compiler_rt symbols for arm 32 bit. Fixes compiler_rt tests for arm 32 bit * add __stack_chk_guard when linking against glibc. Fixes std lib tests for aarch64-linux-gnu * workaround for "unable to inline function" using `@inlineCall`. Fixes compiler_rt tests for arm 32 bit.
2019-09-22 04:55:56 +01:00
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .windows,
.arch = .x86_64,
.abi = .msvc,
},
},
},
// TODO https://github.com/ziglang/zig/issues/3285
//TestTarget{
// .target = Target{
// .Cross = CrossTarget{
// .os = .windows,
// .arch = .x86_64,
// .abi = .gnu,
// },
// },
// .link_libc = true,
//},
};
const max_stdout_size = 1 * 1024 * 1024; // 1 MB
pub fn addCompareOutputTests(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-compare-output", "Run the compare output tests"),
.test_index = 0,
.test_filter = test_filter,
.modes = modes,
};
compare_output.addCases(cases);
return cases.step;
}
pub fn addStackTraceTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
const cases = b.allocator.create(StackTracesContext) catch unreachable;
cases.* = StackTracesContext{
.b = b,
.step = b.step("test-stack-traces", "Run the stack trace tests"),
.test_index = 0,
.test_filter = test_filter,
.modes = modes,
};
stack_traces.addCases(cases);
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 addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
const cases = b.allocator.create(CompileErrorContext) catch unreachable;
cases.* = CompileErrorContext{
.b = b,
.step = b.step("test-compile-errors", "Run the compile error tests"),
.test_index = 0,
.test_filter = test_filter,
.modes = modes,
};
compile_errors.addCases(cases);
return cases.step;
}
pub fn addStandaloneTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
const cases = b.allocator.create(StandaloneContext) catch unreachable;
cases.* = StandaloneContext{
.b = b,
.step = b.step("test-standalone", "Run the standalone tests"),
.test_index = 0,
.test_filter = test_filter,
.modes = modes,
};
standalone.addCases(cases);
return cases.step;
}
pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
const step = b.step("test-cli", "Test the command line interface");
const exe = b.addExecutable("test-cli", "test/cli.zig");
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
const run_cmd = exe.run();
run_cmd.addArgs([_][]const u8{
fs.realpathAlloc(b.allocator, b.zig_exe) catch unreachable,
b.pathFromRoot(b.cache_root),
});
step.dependOn(&run_cmd.step);
return step;
}
pub fn addAssembleAndLinkTests(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-asm-link", "Run the assemble and link tests"),
.test_index = 0,
.test_filter = test_filter,
.modes = modes,
};
assemble_and_link.addCases(cases);
return cases.step;
}
pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step {
const cases = b.allocator.create(TranslateCContext) catch unreachable;
cases.* = TranslateCContext{
.b = b,
.step = b.step("test-translate-c", "Run the C transation tests"),
.test_index = 0,
.test_filter = test_filter,
};
2017-11-24 19:56:05 +00:00
translate_c.addCases(cases);
return cases.step;
}
pub fn addGenHTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step {
const cases = b.allocator.create(GenHContext) catch unreachable;
cases.* = GenHContext{
.b = b,
.step = b.step("test-gen-h", "Run the C header file generation tests"),
.test_index = 0,
.test_filter = test_filter,
};
gen_h.addCases(cases);
return cases.step;
}
pub fn addPkgTests(
b: *build.Builder,
test_filter: ?[]const u8,
root_src: []const u8,
name: []const u8,
desc: []const u8,
modes: []const Mode,
significantly increase test coverage * add zig build option `-Dskip-libc` to skip tests that build libc (e.g. if you don't want to wait for musl to build) * add `-Denable-wine` option which uses wine to run cross compiled windows tests on non-windows hosts * add `-Denable-qemu` option which uses qemu to run cross compiled foreign architecture tests * add `-Denable-foreign-glibc=path` option which combined with `-Denable-qemu` enables running cross compiled tests that link against glibc. See https://github.com/ziglang/zig/wiki/Updating-libc#glibc for how to produce this directory. * the test matrix is done manually. release test builds are only enabled by default for the native target. this should save us some CI time, while still providing decent coverage of release builds. - add test coverage for `x86_64-linux-musl -lc` (building musl libc) - add test coverage for `x86_64-linux-gnu -lc` (building glibc) - add test coverage for `aarch64v8_5a-linux-none` - add test coverage for `aarch64v8_5a-linux-musl -lc` (building musl libc) - add test coverage for `aarch64v8_5a-linux-gnu -lc` (building glibc) - add test coverage for `arm-linux-none` - test coverage for `arm-linux-musleabihf -lc` (building musl libc) is disabled due to #3286 - test coverage for `arm-linux-gnueabihf -lc` (building glibc) is disabled due to #3287 - test coverage for `x86_64-windows-gnu -lc` (building mingw-w64) is disabled due to #3285 * enable qemu testing on the Linux CI job. There's not really a good reason to enable wine, since we have a Windows CI job as well. * remove the no longer needed `--build-file ../build.zig` from CI scripts * fix bug in glibc compilation where it wasn't properly reading the abi list txt files, resulting in "key not found" error. * std.build.Target gains: - isNetBSD - isLinux - osRequiresLibC - getArchPtrBitWidth - getExternalExecutor * zig build system gains support for enabling wine and enabling qemu. `artifact.enable_wine = true;`, `artifact.enable_qemu = true;`. This communicates that the system has these tools installed and the build system will use them to run tests. * zig build system gains support for overriding the dynamic linker of an executable artifact. * fix std.c.lseek prototype. makes behavior tests for arm-linux-musleabihf pass. * disable std lib tests that are failing on ARM. See #3288, #3289 * provide `std.os.off_t`. * disable some of the compiler_rt symbols for arm 32 bit. Fixes compiler_rt tests for arm 32 bit * add __stack_chk_guard when linking against glibc. Fixes std lib tests for aarch64-linux-gnu * workaround for "unable to inline function" using `@inlineCall`. Fixes compiler_rt tests for arm 32 bit.
2019-09-22 04:55:56 +01:00
skip_single_threaded: bool,
skip_non_native: bool,
significantly increase test coverage * add zig build option `-Dskip-libc` to skip tests that build libc (e.g. if you don't want to wait for musl to build) * add `-Denable-wine` option which uses wine to run cross compiled windows tests on non-windows hosts * add `-Denable-qemu` option which uses qemu to run cross compiled foreign architecture tests * add `-Denable-foreign-glibc=path` option which combined with `-Denable-qemu` enables running cross compiled tests that link against glibc. See https://github.com/ziglang/zig/wiki/Updating-libc#glibc for how to produce this directory. * the test matrix is done manually. release test builds are only enabled by default for the native target. this should save us some CI time, while still providing decent coverage of release builds. - add test coverage for `x86_64-linux-musl -lc` (building musl libc) - add test coverage for `x86_64-linux-gnu -lc` (building glibc) - add test coverage for `aarch64v8_5a-linux-none` - add test coverage for `aarch64v8_5a-linux-musl -lc` (building musl libc) - add test coverage for `aarch64v8_5a-linux-gnu -lc` (building glibc) - add test coverage for `arm-linux-none` - test coverage for `arm-linux-musleabihf -lc` (building musl libc) is disabled due to #3286 - test coverage for `arm-linux-gnueabihf -lc` (building glibc) is disabled due to #3287 - test coverage for `x86_64-windows-gnu -lc` (building mingw-w64) is disabled due to #3285 * enable qemu testing on the Linux CI job. There's not really a good reason to enable wine, since we have a Windows CI job as well. * remove the no longer needed `--build-file ../build.zig` from CI scripts * fix bug in glibc compilation where it wasn't properly reading the abi list txt files, resulting in "key not found" error. * std.build.Target gains: - isNetBSD - isLinux - osRequiresLibC - getArchPtrBitWidth - getExternalExecutor * zig build system gains support for enabling wine and enabling qemu. `artifact.enable_wine = true;`, `artifact.enable_qemu = true;`. This communicates that the system has these tools installed and the build system will use them to run tests. * zig build system gains support for overriding the dynamic linker of an executable artifact. * fix std.c.lseek prototype. makes behavior tests for arm-linux-musleabihf pass. * disable std lib tests that are failing on ARM. See #3288, #3289 * provide `std.os.off_t`. * disable some of the compiler_rt symbols for arm 32 bit. Fixes compiler_rt tests for arm 32 bit * add __stack_chk_guard when linking against glibc. Fixes std lib tests for aarch64-linux-gnu * workaround for "unable to inline function" using `@inlineCall`. Fixes compiler_rt tests for arm 32 bit.
2019-09-22 04:55:56 +01:00
skip_libc: bool,
is_wine_enabled: bool,
is_qemu_enabled: bool,
glibc_dir: ?[]const u8,
) *build.Step {
const step = b.step(b.fmt("test-{}", name), desc);
significantly increase test coverage * add zig build option `-Dskip-libc` to skip tests that build libc (e.g. if you don't want to wait for musl to build) * add `-Denable-wine` option which uses wine to run cross compiled windows tests on non-windows hosts * add `-Denable-qemu` option which uses qemu to run cross compiled foreign architecture tests * add `-Denable-foreign-glibc=path` option which combined with `-Denable-qemu` enables running cross compiled tests that link against glibc. See https://github.com/ziglang/zig/wiki/Updating-libc#glibc for how to produce this directory. * the test matrix is done manually. release test builds are only enabled by default for the native target. this should save us some CI time, while still providing decent coverage of release builds. - add test coverage for `x86_64-linux-musl -lc` (building musl libc) - add test coverage for `x86_64-linux-gnu -lc` (building glibc) - add test coverage for `aarch64v8_5a-linux-none` - add test coverage for `aarch64v8_5a-linux-musl -lc` (building musl libc) - add test coverage for `aarch64v8_5a-linux-gnu -lc` (building glibc) - add test coverage for `arm-linux-none` - test coverage for `arm-linux-musleabihf -lc` (building musl libc) is disabled due to #3286 - test coverage for `arm-linux-gnueabihf -lc` (building glibc) is disabled due to #3287 - test coverage for `x86_64-windows-gnu -lc` (building mingw-w64) is disabled due to #3285 * enable qemu testing on the Linux CI job. There's not really a good reason to enable wine, since we have a Windows CI job as well. * remove the no longer needed `--build-file ../build.zig` from CI scripts * fix bug in glibc compilation where it wasn't properly reading the abi list txt files, resulting in "key not found" error. * std.build.Target gains: - isNetBSD - isLinux - osRequiresLibC - getArchPtrBitWidth - getExternalExecutor * zig build system gains support for enabling wine and enabling qemu. `artifact.enable_wine = true;`, `artifact.enable_qemu = true;`. This communicates that the system has these tools installed and the build system will use them to run tests. * zig build system gains support for overriding the dynamic linker of an executable artifact. * fix std.c.lseek prototype. makes behavior tests for arm-linux-musleabihf pass. * disable std lib tests that are failing on ARM. See #3288, #3289 * provide `std.os.off_t`. * disable some of the compiler_rt symbols for arm 32 bit. Fixes compiler_rt tests for arm 32 bit * add __stack_chk_guard when linking against glibc. Fixes std lib tests for aarch64-linux-gnu * workaround for "unable to inline function" using `@inlineCall`. Fixes compiler_rt tests for arm 32 bit.
2019-09-22 04:55:56 +01:00
for (test_targets) |test_target| {
if (skip_non_native and test_target.target != .Native)
continue;
significantly increase test coverage * add zig build option `-Dskip-libc` to skip tests that build libc (e.g. if you don't want to wait for musl to build) * add `-Denable-wine` option which uses wine to run cross compiled windows tests on non-windows hosts * add `-Denable-qemu` option which uses qemu to run cross compiled foreign architecture tests * add `-Denable-foreign-glibc=path` option which combined with `-Denable-qemu` enables running cross compiled tests that link against glibc. See https://github.com/ziglang/zig/wiki/Updating-libc#glibc for how to produce this directory. * the test matrix is done manually. release test builds are only enabled by default for the native target. this should save us some CI time, while still providing decent coverage of release builds. - add test coverage for `x86_64-linux-musl -lc` (building musl libc) - add test coverage for `x86_64-linux-gnu -lc` (building glibc) - add test coverage for `aarch64v8_5a-linux-none` - add test coverage for `aarch64v8_5a-linux-musl -lc` (building musl libc) - add test coverage for `aarch64v8_5a-linux-gnu -lc` (building glibc) - add test coverage for `arm-linux-none` - test coverage for `arm-linux-musleabihf -lc` (building musl libc) is disabled due to #3286 - test coverage for `arm-linux-gnueabihf -lc` (building glibc) is disabled due to #3287 - test coverage for `x86_64-windows-gnu -lc` (building mingw-w64) is disabled due to #3285 * enable qemu testing on the Linux CI job. There's not really a good reason to enable wine, since we have a Windows CI job as well. * remove the no longer needed `--build-file ../build.zig` from CI scripts * fix bug in glibc compilation where it wasn't properly reading the abi list txt files, resulting in "key not found" error. * std.build.Target gains: - isNetBSD - isLinux - osRequiresLibC - getArchPtrBitWidth - getExternalExecutor * zig build system gains support for enabling wine and enabling qemu. `artifact.enable_wine = true;`, `artifact.enable_qemu = true;`. This communicates that the system has these tools installed and the build system will use them to run tests. * zig build system gains support for overriding the dynamic linker of an executable artifact. * fix std.c.lseek prototype. makes behavior tests for arm-linux-musleabihf pass. * disable std lib tests that are failing on ARM. See #3288, #3289 * provide `std.os.off_t`. * disable some of the compiler_rt symbols for arm 32 bit. Fixes compiler_rt tests for arm 32 bit * add __stack_chk_guard when linking against glibc. Fixes std lib tests for aarch64-linux-gnu * workaround for "unable to inline function" using `@inlineCall`. Fixes compiler_rt tests for arm 32 bit.
2019-09-22 04:55:56 +01:00
if (skip_libc and test_target.link_libc)
continue;
if (test_target.link_libc and test_target.target.osRequiresLibC()) {
// This would be a redundant test.
continue;
}
significantly increase test coverage * add zig build option `-Dskip-libc` to skip tests that build libc (e.g. if you don't want to wait for musl to build) * add `-Denable-wine` option which uses wine to run cross compiled windows tests on non-windows hosts * add `-Denable-qemu` option which uses qemu to run cross compiled foreign architecture tests * add `-Denable-foreign-glibc=path` option which combined with `-Denable-qemu` enables running cross compiled tests that link against glibc. See https://github.com/ziglang/zig/wiki/Updating-libc#glibc for how to produce this directory. * the test matrix is done manually. release test builds are only enabled by default for the native target. this should save us some CI time, while still providing decent coverage of release builds. - add test coverage for `x86_64-linux-musl -lc` (building musl libc) - add test coverage for `x86_64-linux-gnu -lc` (building glibc) - add test coverage for `aarch64v8_5a-linux-none` - add test coverage for `aarch64v8_5a-linux-musl -lc` (building musl libc) - add test coverage for `aarch64v8_5a-linux-gnu -lc` (building glibc) - add test coverage for `arm-linux-none` - test coverage for `arm-linux-musleabihf -lc` (building musl libc) is disabled due to #3286 - test coverage for `arm-linux-gnueabihf -lc` (building glibc) is disabled due to #3287 - test coverage for `x86_64-windows-gnu -lc` (building mingw-w64) is disabled due to #3285 * enable qemu testing on the Linux CI job. There's not really a good reason to enable wine, since we have a Windows CI job as well. * remove the no longer needed `--build-file ../build.zig` from CI scripts * fix bug in glibc compilation where it wasn't properly reading the abi list txt files, resulting in "key not found" error. * std.build.Target gains: - isNetBSD - isLinux - osRequiresLibC - getArchPtrBitWidth - getExternalExecutor * zig build system gains support for enabling wine and enabling qemu. `artifact.enable_wine = true;`, `artifact.enable_qemu = true;`. This communicates that the system has these tools installed and the build system will use them to run tests. * zig build system gains support for overriding the dynamic linker of an executable artifact. * fix std.c.lseek prototype. makes behavior tests for arm-linux-musleabihf pass. * disable std lib tests that are failing on ARM. See #3288, #3289 * provide `std.os.off_t`. * disable some of the compiler_rt symbols for arm 32 bit. Fixes compiler_rt tests for arm 32 bit * add __stack_chk_guard when linking against glibc. Fixes std lib tests for aarch64-linux-gnu * workaround for "unable to inline function" using `@inlineCall`. Fixes compiler_rt tests for arm 32 bit.
2019-09-22 04:55:56 +01:00
if (skip_single_threaded and test_target.single_threaded)
continue;
const ArchTag = @TagType(builtin.Arch);
if (test_target.disable_native and
test_target.target.getOs() == builtin.os and
ArchTag(test_target.target.getArch()) == ArchTag(builtin.arch))
{
continue;
}
significantly increase test coverage * add zig build option `-Dskip-libc` to skip tests that build libc (e.g. if you don't want to wait for musl to build) * add `-Denable-wine` option which uses wine to run cross compiled windows tests on non-windows hosts * add `-Denable-qemu` option which uses qemu to run cross compiled foreign architecture tests * add `-Denable-foreign-glibc=path` option which combined with `-Denable-qemu` enables running cross compiled tests that link against glibc. See https://github.com/ziglang/zig/wiki/Updating-libc#glibc for how to produce this directory. * the test matrix is done manually. release test builds are only enabled by default for the native target. this should save us some CI time, while still providing decent coverage of release builds. - add test coverage for `x86_64-linux-musl -lc` (building musl libc) - add test coverage for `x86_64-linux-gnu -lc` (building glibc) - add test coverage for `aarch64v8_5a-linux-none` - add test coverage for `aarch64v8_5a-linux-musl -lc` (building musl libc) - add test coverage for `aarch64v8_5a-linux-gnu -lc` (building glibc) - add test coverage for `arm-linux-none` - test coverage for `arm-linux-musleabihf -lc` (building musl libc) is disabled due to #3286 - test coverage for `arm-linux-gnueabihf -lc` (building glibc) is disabled due to #3287 - test coverage for `x86_64-windows-gnu -lc` (building mingw-w64) is disabled due to #3285 * enable qemu testing on the Linux CI job. There's not really a good reason to enable wine, since we have a Windows CI job as well. * remove the no longer needed `--build-file ../build.zig` from CI scripts * fix bug in glibc compilation where it wasn't properly reading the abi list txt files, resulting in "key not found" error. * std.build.Target gains: - isNetBSD - isLinux - osRequiresLibC - getArchPtrBitWidth - getExternalExecutor * zig build system gains support for enabling wine and enabling qemu. `artifact.enable_wine = true;`, `artifact.enable_qemu = true;`. This communicates that the system has these tools installed and the build system will use them to run tests. * zig build system gains support for overriding the dynamic linker of an executable artifact. * fix std.c.lseek prototype. makes behavior tests for arm-linux-musleabihf pass. * disable std lib tests that are failing on ARM. See #3288, #3289 * provide `std.os.off_t`. * disable some of the compiler_rt symbols for arm 32 bit. Fixes compiler_rt tests for arm 32 bit * add __stack_chk_guard when linking against glibc. Fixes std lib tests for aarch64-linux-gnu * workaround for "unable to inline function" using `@inlineCall`. Fixes compiler_rt tests for arm 32 bit.
2019-09-22 04:55:56 +01:00
const want_this_mode = for (modes) |m| {
if (m == test_target.mode) break true;
} else false;
if (!want_this_mode) continue;
const libc_prefix = if (test_target.target.osRequiresLibC())
""
else if (test_target.link_libc)
"c"
else
"bare";
const triple_prefix = if (test_target.target == .Native)
([]const u8)("native")
else
test_target.target.zigTripleNoSubArch(b.allocator) catch unreachable;
const these_tests = b.addTest(root_src);
these_tests.setNamePrefix(b.fmt(
"{}-{}-{}-{}-{} ",
name,
triple_prefix,
@tagName(test_target.mode),
libc_prefix,
if (test_target.single_threaded) "single" else "multi",
));
these_tests.single_threaded = test_target.single_threaded;
these_tests.setFilter(test_filter);
these_tests.setBuildMode(test_target.mode);
these_tests.setTheTarget(test_target.target);
if (test_target.link_libc) {
these_tests.linkSystemLibrary("c");
}
these_tests.overrideStdDir("std");
these_tests.enable_wine = is_wine_enabled;
these_tests.enable_qemu = is_qemu_enabled;
these_tests.glibc_multi_install_dir = glibc_dir;
step.dependOn(&these_tests.step);
}
return step;
}
pub const CompareOutputContext = struct {
b: *build.Builder,
step: *build.Step,
test_index: usize,
test_filter: ?[]const u8,
modes: []const Mode,
const Special = enum {
None,
Asm,
RuntimeSafety,
};
const TestCase = struct {
name: []const u8,
sources: ArrayList(SourceFile),
expected_output: []const u8,
link_libc: bool,
special: Special,
cli_args: []const []const u8,
const SourceFile = struct {
filename: []const u8,
source: []const u8,
};
pub fn addSourceFile(self: *TestCase, filename: []const u8, source: []const u8) void {
self.sources.append(SourceFile{
.filename = filename,
.source = source,
}) catch unreachable;
}
pub fn setCommandLineArgs(self: *TestCase, args: []const []const u8) void {
self.cli_args = args;
}
};
const RunCompareOutputStep = struct {
step: build.Step,
context: *CompareOutputContext,
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
exe: *LibExeObjStep,
name: []const u8,
expected_output: []const u8,
test_index: usize,
cli_args: []const []const u8,
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
pub fn create(
context: *CompareOutputContext,
exe: *LibExeObjStep,
name: []const u8,
expected_output: []const u8,
cli_args: []const []const u8,
) *RunCompareOutputStep {
const allocator = context.b.allocator;
const ptr = allocator.create(RunCompareOutputStep) catch unreachable;
ptr.* = RunCompareOutputStep{
.context = context,
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
.exe = exe,
.name = name,
.expected_output = expected_output,
.test_index = context.test_index,
.step = build.Step.init("RunCompareOutput", allocator, make),
.cli_args = cli_args,
};
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
ptr.step.dependOn(&exe.step);
context.test_index += 1;
return ptr;
}
fn make(step: *build.Step) !void {
const self = @fieldParentPtr(RunCompareOutputStep, "step", step);
const b = self.context.b;
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
const full_exe_path = self.exe.getOutputPath();
var args = ArrayList([]const u8).init(b.allocator);
defer args.deinit();
args.append(full_exe_path) catch unreachable;
for (self.cli_args) |arg| {
args.append(arg) catch unreachable;
}
warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
2019-05-26 18:17:34 +01:00
const child = std.ChildProcess.init(args.toSliceConst(), b.allocator) catch unreachable;
defer child.deinit();
2019-05-26 18:17:34 +01:00
child.stdin_behavior = .Ignore;
child.stdout_behavior = .Pipe;
child.stderr_behavior = .Pipe;
child.env_map = b.env_map;
child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));
var stdout = Buffer.initNull(b.allocator);
var stderr = Buffer.initNull(b.allocator);
var stdout_file_in_stream = child.stdout.?.inStream();
var stderr_file_in_stream = child.stderr.?.inStream();
stdout_file_in_stream.stream.readAllBuffer(&stdout, max_stdout_size) catch unreachable;
stderr_file_in_stream.stream.readAllBuffer(&stderr, max_stdout_size) catch unreachable;
const term = child.wait() catch |err| {
debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));
};
switch (term) {
2019-05-26 18:17:34 +01:00
.Exited => |code| {
if (code != 0) {
warn("Process {} exited with error code {}\n", full_exe_path, code);
printInvocation(args.toSliceConst());
return error.TestFailed;
}
},
else => {
warn("Process {} terminated unexpectedly\n", full_exe_path);
printInvocation(args.toSliceConst());
return error.TestFailed;
},
}
if (!mem.eql(u8, self.expected_output, stdout.toSliceConst())) {
warn(
\\
\\========= Expected this output: =========
\\{}
\\========= But found: ====================
\\{}
\\
, self.expected_output, stdout.toSliceConst());
return error.TestFailed;
}
warn("OK\n");
}
};
const RuntimeSafetyRunStep = struct {
step: build.Step,
context: *CompareOutputContext,
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
exe: *LibExeObjStep,
name: []const u8,
test_index: usize,
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
pub fn create(context: *CompareOutputContext, exe: *LibExeObjStep, name: []const u8) *RuntimeSafetyRunStep {
const allocator = context.b.allocator;
const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable;
ptr.* = RuntimeSafetyRunStep{
.context = context,
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
.exe = exe,
.name = name,
.test_index = context.test_index,
.step = build.Step.init("RuntimeSafetyRun", allocator, make),
};
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
ptr.step.dependOn(&exe.step);
context.test_index += 1;
return ptr;
}
fn make(step: *build.Step) !void {
const self = @fieldParentPtr(RuntimeSafetyRunStep, "step", step);
const b = self.context.b;
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
const full_exe_path = self.exe.getOutputPath();
warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
const child = std.ChildProcess.init([_][]const u8{full_exe_path}, b.allocator) catch unreachable;
defer child.deinit();
child.env_map = b.env_map;
2019-05-26 18:17:34 +01:00
child.stdin_behavior = .Ignore;
child.stdout_behavior = .Ignore;
child.stderr_behavior = .Ignore;
const term = child.spawnAndWait() catch |err| {
debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));
};
2019-05-27 04:35:26 +01:00
const expected_exit_code: u32 = 126;
switch (term) {
2019-05-26 18:17:34 +01:00
.Exited => |code| {
if (code != expected_exit_code) {
warn("\nProgram expected to exit with code {} " ++ "but exited with code {}\n", expected_exit_code, code);
return error.TestFailed;
}
},
2019-05-26 18:17:34 +01:00
.Signal => |sig| {
warn("\nProgram expected to exit with code {} " ++ "but instead signaled {}\n", expected_exit_code, sig);
return error.TestFailed;
},
else => {
warn("\nProgram expected to exit with code {}" ++ " but exited in an unexpected way\n", expected_exit_code);
return error.TestFailed;
},
}
warn("OK\n");
}
};
pub fn createExtra(self: *CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8, special: Special) TestCase {
var tc = TestCase{
.name = name,
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
.expected_output = expected_output,
.link_libc = false,
.special = special,
.cli_args = [_][]const u8{},
};
const root_src_name = if (special == Special.Asm) "source.s" else "source.zig";
tc.addSourceFile(root_src_name, source);
return tc;
}
pub fn create(self: *CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) TestCase {
return createExtra(self, name, source, expected_output, Special.None);
}
pub fn addC(self: *CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) void {
var tc = self.create(name, source, expected_output);
tc.link_libc = true;
self.addCase(tc);
}
pub fn add(self: *CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) void {
const tc = self.create(name, source, expected_output);
self.addCase(tc);
}
pub fn addAsm(self: *CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) void {
const tc = self.createExtra(name, source, expected_output, Special.Asm);
self.addCase(tc);
}
pub fn addRuntimeSafety(self: *CompareOutputContext, name: []const u8, source: []const u8) void {
const tc = self.createExtra(name, source, undefined, Special.RuntimeSafety);
self.addCase(tc);
}
pub fn addCase(self: *CompareOutputContext, case: TestCase) void {
const b = self.b;
2019-05-26 18:17:34 +01:00
const root_src = fs.path.join(
b.allocator,
[_][]const u8{ b.cache_root, case.sources.items[0].filename },
) catch unreachable;
switch (case.special) {
Special.Asm => {
const annotated_case_name = fmt.allocPrint(self.b.allocator, "assemble-and-link {}", case.name) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
const exe = b.addExecutable("test", null);
exe.addAssemblyFile(root_src);
for (case.sources.toSliceConst()) |src_file| {
2019-05-26 18:17:34 +01:00
const expanded_src_path = fs.path.join(
b.allocator,
[_][]const u8{ b.cache_root, src_file.filename },
) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
exe.step.dependOn(&write_src.step);
}
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
const run_and_cmp_output = RunCompareOutputStep.create(
self,
exe,
annotated_case_name,
case.expected_output,
case.cli_args,
);
self.step.dependOn(&run_and_cmp_output.step);
},
Special.None => {
for (self.modes) |mode| {
const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", "compare-output", case.name, @tagName(mode)) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) continue;
}
const exe = b.addExecutable("test", root_src);
exe.setBuildMode(mode);
if (case.link_libc) {
exe.linkSystemLibrary("c");
}
for (case.sources.toSliceConst()) |src_file| {
2019-05-26 18:17:34 +01:00
const expanded_src_path = fs.path.join(
b.allocator,
[_][]const u8{ b.cache_root, src_file.filename },
) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
exe.step.dependOn(&write_src.step);
}
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
const run_and_cmp_output = RunCompareOutputStep.create(
self,
exe,
annotated_case_name,
case.expected_output,
case.cli_args,
);
self.step.dependOn(&run_and_cmp_output.step);
}
},
Special.RuntimeSafety => {
const annotated_case_name = fmt.allocPrint(self.b.allocator, "safety {}", case.name) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
const exe = b.addExecutable("test", root_src);
if (case.link_libc) {
exe.linkSystemLibrary("c");
}
for (case.sources.toSliceConst()) |src_file| {
2019-05-26 18:17:34 +01:00
const expanded_src_path = fs.path.join(
b.allocator,
[_][]const u8{ b.cache_root, src_file.filename },
) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
exe.step.dependOn(&write_src.step);
}
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
const run_and_cmp_output = RuntimeSafetyRunStep.create(self, exe, annotated_case_name);
self.step.dependOn(&run_and_cmp_output.step);
},
}
}
};
pub const StackTracesContext = struct {
b: *build.Builder,
step: *build.Step,
test_index: usize,
test_filter: ?[]const u8,
modes: []const Mode,
const Expect = [@typeInfo(Mode).Enum.fields.len][]const u8;
pub fn addCase(
self: *StackTracesContext,
name: []const u8,
source: []const u8,
expect: Expect,
) void {
const b = self.b;
const source_pathname = fs.path.join(
b.allocator,
[_][]const u8{ b.cache_root, "source.zig" },
) catch unreachable;
for (self.modes) |mode| {
const expect_for_mode = expect[@enumToInt(mode)];
if (expect_for_mode.len == 0) continue;
const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", "stack-trace", name, @tagName(mode)) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) continue;
}
const exe = b.addExecutable("test", source_pathname);
exe.setBuildMode(mode);
const write_source = b.addWriteFile(source_pathname, source);
exe.step.dependOn(&write_source.step);
const run_and_compare = RunAndCompareStep.create(
self,
exe,
annotated_case_name,
mode,
expect_for_mode,
);
self.step.dependOn(&run_and_compare.step);
}
}
const RunAndCompareStep = struct {
step: build.Step,
context: *StackTracesContext,
exe: *LibExeObjStep,
name: []const u8,
mode: Mode,
expect_output: []const u8,
test_index: usize,
pub fn create(
context: *StackTracesContext,
exe: *LibExeObjStep,
name: []const u8,
mode: Mode,
expect_output: []const u8,
) *RunAndCompareStep {
const allocator = context.b.allocator;
const ptr = allocator.create(RunAndCompareStep) catch unreachable;
ptr.* = RunAndCompareStep{
.step = build.Step.init("StackTraceCompareOutputStep", allocator, make),
.context = context,
.exe = exe,
.name = name,
.mode = mode,
.expect_output = expect_output,
.test_index = context.test_index,
};
ptr.step.dependOn(&exe.step);
context.test_index += 1;
return ptr;
}
fn make(step: *build.Step) !void {
const self = @fieldParentPtr(RunAndCompareStep, "step", step);
const b = self.context.b;
const full_exe_path = self.exe.getOutputPath();
var args = ArrayList([]const u8).init(b.allocator);
defer args.deinit();
args.append(full_exe_path) catch unreachable;
warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
const child = std.ChildProcess.init(args.toSliceConst(), b.allocator) catch unreachable;
defer child.deinit();
child.stdin_behavior = .Ignore;
child.stdout_behavior = .Pipe;
child.stderr_behavior = .Pipe;
child.env_map = b.env_map;
child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));
var stdout = Buffer.initNull(b.allocator);
var stderr = Buffer.initNull(b.allocator);
var stdout_file_in_stream = child.stdout.?.inStream();
var stderr_file_in_stream = child.stderr.?.inStream();
stdout_file_in_stream.stream.readAllBuffer(&stdout, max_stdout_size) catch unreachable;
stderr_file_in_stream.stream.readAllBuffer(&stderr, max_stdout_size) catch unreachable;
const term = child.wait() catch |err| {
debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));
};
switch (term) {
.Exited => |code| {
const expect_code: u32 = 1;
if (code != expect_code) {
warn("Process {} exited with error code {} but expected code {}\n", full_exe_path, code, expect_code);
printInvocation(args.toSliceConst());
return error.TestFailed;
}
},
.Signal => |signum| {
warn("Process {} terminated on signal {}\n", full_exe_path, signum);
printInvocation(args.toSliceConst());
return error.TestFailed;
},
.Stopped => |signum| {
warn("Process {} stopped on signal {}\n", full_exe_path, signum);
printInvocation(args.toSliceConst());
return error.TestFailed;
},
.Unknown => |code| {
warn("Process {} terminated unexpectedly with error code {}\n", full_exe_path, code);
printInvocation(args.toSliceConst());
return error.TestFailed;
},
}
// process result
// - keep only basename of source file path
// - replace address with symbolic string
// - skip empty lines
const got: []const u8 = got_result: {
var buf = try Buffer.initSize(b.allocator, 0);
defer buf.deinit();
var bytes = stderr.toSliceConst();
if (bytes.len != 0 and bytes[bytes.len - 1] == '\n') bytes = bytes[0 .. bytes.len - 1];
var it = mem.separate(bytes, "\n");
process_lines: while (it.next()) |line| {
if (line.len == 0) continue;
const delims = [_][]const u8{ ":", ":", ":", " in " };
var marks = [_]usize{0} ** 4;
// offset search past `[drive]:` on windows
var pos: usize = if (builtin.os == .windows) 2 else 0;
for (delims) |delim, i| {
marks[i] = mem.indexOfPos(u8, line, pos, delim) orelse {
try buf.append(line);
try buf.append("\n");
continue :process_lines;
};
pos = marks[i] + delim.len;
}
pos = mem.lastIndexOfScalar(u8, line[0..marks[0]], fs.path.sep) orelse {
try buf.append(line);
try buf.append("\n");
continue :process_lines;
};
try buf.append(line[pos + 1 .. marks[2] + delims[2].len]);
try buf.append(" [address]");
try buf.append(line[marks[3]..]);
try buf.append("\n");
}
break :got_result buf.toOwnedSlice();
};
if (!mem.eql(u8, self.expect_output, got)) {
warn(
\\
\\========= Expected this output: =========
\\{}
\\================================================
\\{}
\\
, self.expect_output, got);
return error.TestFailed;
}
warn("OK\n");
}
};
};
pub const CompileErrorContext = struct {
b: *build.Builder,
step: *build.Step,
test_index: usize,
test_filter: ?[]const u8,
modes: []const Mode,
const TestCase = struct {
name: []const u8,
sources: ArrayList(SourceFile),
expected_errors: ArrayList([]const u8),
expect_exact: bool,
link_libc: bool,
is_exe: bool,
is_test: bool,
target: Target = .Native,
const SourceFile = struct {
filename: []const u8,
source: []const u8,
};
pub fn addSourceFile(self: *TestCase, filename: []const u8, source: []const u8) void {
self.sources.append(SourceFile{
.filename = filename,
.source = source,
}) catch unreachable;
}
pub fn addExpectedError(self: *TestCase, text: []const u8) void {
self.expected_errors.append(text) catch unreachable;
}
};
const CompileCmpOutputStep = struct {
step: build.Step,
context: *CompileErrorContext,
name: []const u8,
test_index: usize,
case: *const TestCase,
build_mode: Mode,
const ErrLineIter = struct {
lines: mem.SplitIterator,
const source_file = "tmp.zig";
fn init(input: []const u8) ErrLineIter {
2019-02-18 17:56:17 +00:00
return ErrLineIter{ .lines = mem.separate(input, "\n") };
}
fn next(self: *ErrLineIter) ?[]const u8 {
while (self.lines.next()) |line| {
if (mem.indexOf(u8, line, source_file) != null)
return line;
}
return null;
}
};
pub fn create(context: *CompileErrorContext, name: []const u8, case: *const TestCase, build_mode: Mode) *CompileCmpOutputStep {
const allocator = context.b.allocator;
const ptr = allocator.create(CompileCmpOutputStep) catch unreachable;
ptr.* = CompileCmpOutputStep{
.step = build.Step.init("CompileCmpOutput", allocator, make),
.context = context,
.name = name,
.test_index = context.test_index,
.case = case,
.build_mode = build_mode,
};
context.test_index += 1;
return ptr;
}
fn make(step: *build.Step) !void {
const self = @fieldParentPtr(CompileCmpOutputStep, "step", step);
const b = self.context.b;
2019-05-26 18:17:34 +01:00
const root_src = fs.path.join(
b.allocator,
[_][]const u8{ b.cache_root, self.case.sources.items[0].filename },
) catch unreachable;
var zig_args = ArrayList([]const u8).init(b.allocator);
zig_args.append(b.zig_exe) catch unreachable;
if (self.case.is_exe) {
try zig_args.append("build-exe");
} else if (self.case.is_test) {
try zig_args.append("test");
} else {
try zig_args.append("build-obj");
}
zig_args.append(b.pathFromRoot(root_src)) catch unreachable;
zig_args.append("--name") catch unreachable;
zig_args.append("test") catch unreachable;
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
zig_args.append("--output-dir") catch unreachable;
zig_args.append(b.pathFromRoot(b.cache_root)) catch unreachable;
switch (self.case.target) {
.Native => {},
.Cross => {
try zig_args.append("-target");
try zig_args.append(try self.case.target.zigTriple(b.allocator));
},
}
switch (self.build_mode) {
Mode.Debug => {},
Mode.ReleaseSafe => zig_args.append("--release-safe") catch unreachable,
Mode.ReleaseFast => zig_args.append("--release-fast") catch unreachable,
2018-04-16 02:06:00 +01:00
Mode.ReleaseSmall => zig_args.append("--release-small") catch unreachable,
}
warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
if (b.verbose) {
printInvocation(zig_args.toSliceConst());
}
2019-05-26 18:17:34 +01:00
const child = std.ChildProcess.init(zig_args.toSliceConst(), b.allocator) catch unreachable;
defer child.deinit();
child.env_map = b.env_map;
2019-05-26 18:17:34 +01:00
child.stdin_behavior = .Ignore;
child.stdout_behavior = .Pipe;
child.stderr_behavior = .Pipe;
child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", zig_args.items[0], @errorName(err));
var stdout_buf = Buffer.initNull(b.allocator);
var stderr_buf = Buffer.initNull(b.allocator);
var stdout_file_in_stream = child.stdout.?.inStream();
var stderr_file_in_stream = child.stderr.?.inStream();
stdout_file_in_stream.stream.readAllBuffer(&stdout_buf, max_stdout_size) catch unreachable;
stderr_file_in_stream.stream.readAllBuffer(&stderr_buf, max_stdout_size) catch unreachable;
const term = child.wait() catch |err| {
debug.panic("Unable to spawn {}: {}\n", zig_args.items[0], @errorName(err));
};
switch (term) {
2019-05-26 18:17:34 +01:00
.Exited => |code| {
if (code == 0) {
printInvocation(zig_args.toSliceConst());
return error.CompilationIncorrectlySucceeded;
}
},
else => {
warn("Process {} terminated unexpectedly\n", b.zig_exe);
printInvocation(zig_args.toSliceConst());
return error.TestFailed;
},
}
const stdout = stdout_buf.toSliceConst();
const stderr = stderr_buf.toSliceConst();
if (stdout.len != 0) {
warn(
\\
\\Expected empty stdout, instead found:
\\================================================
\\{}
\\================================================
\\
, stdout);
return error.TestFailed;
}
var ok = true;
if (self.case.expect_exact) {
var err_iter = ErrLineIter.init(stderr);
var i: usize = 0;
ok = while (err_iter.next()) |line| : (i += 1) {
if (i >= self.case.expected_errors.len) break false;
const expected = self.case.expected_errors.at(i);
if (mem.indexOf(u8, line, expected) == null) break false;
continue;
} else true;
ok = ok and i == self.case.expected_errors.len;
if (!ok) {
warn("\n======== Expected these compile errors: ========\n");
for (self.case.expected_errors.toSliceConst()) |expected| {
warn("{}\n", expected);
}
}
} else {
for (self.case.expected_errors.toSliceConst()) |expected| {
if (mem.indexOf(u8, stderr, expected) == null) {
warn(
\\
\\=========== Expected compile error: ============
\\{}
\\
2019-02-18 17:56:17 +00:00
, expected);
ok = false;
break;
}
}
}
if (!ok) {
warn(
\\================= Full output: =================
\\{}
\\
2019-02-18 17:56:17 +00:00
, stderr);
return error.TestFailed;
}
warn("OK\n");
}
};
pub fn create(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) *TestCase {
const tc = self.b.allocator.create(TestCase) catch unreachable;
tc.* = TestCase{
.name = name,
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
.expected_errors = ArrayList([]const u8).init(self.b.allocator),
.expect_exact = false,
.link_libc = false,
.is_exe = false,
.is_test = false,
};
tc.addSourceFile("tmp.zig", source);
comptime var arg_i = 0;
inline while (arg_i < expected_lines.len) : (arg_i += 1) {
tc.addExpectedError(expected_lines[arg_i]);
}
return tc;
}
pub fn addC(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) void {
var tc = self.create(name, source, expected_lines);
tc.link_libc = true;
self.addCase(tc);
}
pub fn addExe(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) void {
var tc = self.create(name, source, expected_lines);
tc.is_exe = true;
self.addCase(tc);
}
pub fn add(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) void {
const tc = self.create(name, source, expected_lines);
self.addCase(tc);
}
pub fn addTest(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) void {
const tc = self.create(name, source, expected_lines);
tc.is_test = true;
self.addCase(tc);
}
pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void {
const b = self.b;
const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {}", case.name) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
const compile_and_cmp_errors = CompileCmpOutputStep.create(self, annotated_case_name, case, .Debug);
self.step.dependOn(&compile_and_cmp_errors.step);
for (case.sources.toSliceConst()) |src_file| {
const expanded_src_path = fs.path.join(
b.allocator,
[_][]const u8{ b.cache_root, src_file.filename },
) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
compile_and_cmp_errors.step.dependOn(&write_src.step);
}
}
};
pub const StandaloneContext = struct {
b: *build.Builder,
step: *build.Step,
test_index: usize,
test_filter: ?[]const u8,
modes: []const Mode,
pub fn addC(self: *StandaloneContext, root_src: []const u8) void {
self.addAllArgs(root_src, true);
}
pub fn add(self: *StandaloneContext, root_src: []const u8) void {
self.addAllArgs(root_src, false);
}
pub fn addBuildFile(self: *StandaloneContext, build_file: []const u8) void {
const b = self.b;
const annotated_case_name = b.fmt("build {} (Debug)", build_file);
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
var zig_args = ArrayList([]const u8).init(b.allocator);
2019-05-26 18:17:34 +01:00
const rel_zig_exe = fs.path.relative(b.allocator, b.build_root, b.zig_exe) catch unreachable;
zig_args.append(rel_zig_exe) catch unreachable;
zig_args.append("build") catch unreachable;
zig_args.append("--build-file") catch unreachable;
zig_args.append(b.pathFromRoot(build_file)) catch unreachable;
zig_args.append("test") catch unreachable;
if (b.verbose) {
zig_args.append("--verbose") catch unreachable;
}
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
const run_cmd = b.addSystemCommand(zig_args.toSliceConst());
const log_step = b.addLog("PASS {}\n", annotated_case_name);
log_step.step.dependOn(&run_cmd.step);
self.step.dependOn(&log_step.step);
}
pub fn addAllArgs(self: *StandaloneContext, root_src: []const u8, link_libc: bool) void {
const b = self.b;
for (self.modes) |mode| {
const annotated_case_name = fmt.allocPrint(self.b.allocator, "build {} ({})", root_src, @tagName(mode)) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) continue;
}
const exe = b.addExecutable("test", root_src);
exe.setBuildMode(mode);
if (link_libc) {
exe.linkSystemLibrary("c");
}
const log_step = b.addLog("PASS {}\n", annotated_case_name);
log_step.step.dependOn(&exe.step);
self.step.dependOn(&log_step.step);
}
}
};
pub const TranslateCContext = struct {
b: *build.Builder,
step: *build.Step,
test_index: usize,
test_filter: ?[]const u8,
const TestCase = struct {
name: []const u8,
sources: ArrayList(SourceFile),
expected_lines: ArrayList([]const u8),
allow_warnings: bool,
stage2: bool,
const SourceFile = struct {
filename: []const u8,
source: []const u8,
};
pub fn addSourceFile(self: *TestCase, filename: []const u8, source: []const u8) void {
self.sources.append(SourceFile{
.filename = filename,
.source = source,
}) catch unreachable;
}
pub fn addExpectedLine(self: *TestCase, text: []const u8) void {
self.expected_lines.append(text) catch unreachable;
}
};
const TranslateCCmpOutputStep = struct {
step: build.Step,
context: *TranslateCContext,
name: []const u8,
test_index: usize,
case: *const TestCase,
pub fn create(context: *TranslateCContext, name: []const u8, case: *const TestCase) *TranslateCCmpOutputStep {
const allocator = context.b.allocator;
const ptr = allocator.create(TranslateCCmpOutputStep) catch unreachable;
ptr.* = TranslateCCmpOutputStep{
2017-09-06 03:55:03 +01:00
.step = build.Step.init("ParseCCmpOutput", allocator, make),
.context = context,
.name = name,
.test_index = context.test_index,
.case = case,
};
context.test_index += 1;
return ptr;
}
fn make(step: *build.Step) !void {
2017-11-24 19:56:05 +00:00
const self = @fieldParentPtr(TranslateCCmpOutputStep, "step", step);
const b = self.context.b;
2019-05-26 18:17:34 +01:00
const root_src = fs.path.join(
b.allocator,
[_][]const u8{ b.cache_root, self.case.sources.items[0].filename },
) catch unreachable;
var zig_args = ArrayList([]const u8).init(b.allocator);
zig_args.append(b.zig_exe) catch unreachable;
const translate_c_cmd = if (self.case.stage2) "translate-c-2" else "translate-c";
zig_args.append(translate_c_cmd) catch unreachable;
zig_args.append(b.pathFromRoot(root_src)) catch unreachable;
warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
if (b.verbose) {
printInvocation(zig_args.toSliceConst());
}
2019-05-26 18:17:34 +01:00
const child = std.ChildProcess.init(zig_args.toSliceConst(), b.allocator) catch unreachable;
defer child.deinit();
child.env_map = b.env_map;
2019-05-26 18:17:34 +01:00
child.stdin_behavior = .Ignore;
child.stdout_behavior = .Pipe;
child.stderr_behavior = .Pipe;
child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", zig_args.toSliceConst()[0], @errorName(err));
var stdout_buf = Buffer.initNull(b.allocator);
var stderr_buf = Buffer.initNull(b.allocator);
var stdout_file_in_stream = child.stdout.?.inStream();
var stderr_file_in_stream = child.stderr.?.inStream();
stdout_file_in_stream.stream.readAllBuffer(&stdout_buf, max_stdout_size) catch unreachable;
stderr_file_in_stream.stream.readAllBuffer(&stderr_buf, max_stdout_size) catch unreachable;
const term = child.wait() catch |err| {
debug.panic("Unable to spawn {}: {}\n", zig_args.toSliceConst()[0], @errorName(err));
};
switch (term) {
2019-05-26 18:17:34 +01:00
.Exited => |code| {
if (code != 0) {
warn("Compilation failed with exit code {}\n", code);
printInvocation(zig_args.toSliceConst());
return error.TestFailed;
}
},
2019-05-26 18:17:34 +01:00
.Signal => |code| {
warn("Compilation failed with signal {}\n", code);
printInvocation(zig_args.toSliceConst());
return error.TestFailed;
},
else => {
warn("Compilation terminated unexpectedly\n");
printInvocation(zig_args.toSliceConst());
return error.TestFailed;
},
}
const stdout = stdout_buf.toSliceConst();
const stderr = stderr_buf.toSliceConst();
if (stderr.len != 0 and !self.case.allow_warnings) {
warn(
2017-11-24 19:56:05 +00:00
\\====== translate-c emitted warnings: =======
\\{}
\\============================================
\\
, stderr);
2019-03-19 00:09:27 +00:00
printInvocation(zig_args.toSliceConst());
return error.TestFailed;
}
for (self.case.expected_lines.toSliceConst()) |expected_line| {
if (mem.indexOf(u8, stdout, expected_line) == null) {
warn(
\\
\\========= Expected this output: ================
\\{}
\\========= But found: ===========================
\\{}
\\
, expected_line, stdout);
2019-03-19 00:09:27 +00:00
printInvocation(zig_args.toSliceConst());
return error.TestFailed;
}
}
warn("OK\n");
}
};
fn printInvocation(args: []const []const u8) void {
for (args) |arg| {
warn("{} ", arg);
}
warn("\n");
}
pub fn create(self: *TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) *TestCase {
const tc = self.b.allocator.create(TestCase) catch unreachable;
tc.* = TestCase{
.name = name,
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
.expected_lines = ArrayList([]const u8).init(self.b.allocator),
.allow_warnings = allow_warnings,
.stage2 = false,
};
2017-10-02 02:42:33 +01:00
tc.addSourceFile(filename, source);
comptime var arg_i = 0;
inline while (arg_i < expected_lines.len) : (arg_i += 1) {
2017-09-12 03:58:06 +01:00
tc.addExpectedLine(expected_lines[arg_i]);
}
return tc;
}
pub fn add(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
2017-10-02 02:42:33 +01:00
const tc = self.create(false, "source.h", name, source, expected_lines);
self.addCase(tc);
}
pub fn addC(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
2017-10-02 02:42:33 +01:00
const tc = self.create(false, "source.c", name, source, expected_lines);
self.addCase(tc);
}
pub fn add_both(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
for ([_]bool{ false, true }) |stage2| {
const tc = self.create(false, "source.h", name, source, expected_lines);
tc.stage2 = stage2;
self.addCase(tc);
}
}
pub fn addC_both(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
for ([_]bool{ false, true }) |stage2| {
const tc = self.create(false, "source.c", name, source, expected_lines);
tc.stage2 = stage2;
self.addCase(tc);
}
}
pub fn add_2(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
const tc = self.create(false, "source.h", name, source, expected_lines);
tc.stage2 = true;
self.addCase(tc);
}
pub fn addC_2(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
const tc = self.create(false, "source.c", name, source, expected_lines);
tc.stage2 = true;
self.addCase(tc);
}
pub fn addAllowWarnings(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
2017-10-02 02:42:33 +01:00
const tc = self.create(true, "source.h", name, source, expected_lines);
self.addCase(tc);
}
pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {
const b = self.b;
const translate_c_cmd = if (case.stage2) "translate-c-2" else "translate-c";
const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {}", translate_c_cmd, case.name) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
2017-11-24 19:56:05 +00:00
const translate_c_and_cmp = TranslateCCmpOutputStep.create(self, annotated_case_name, case);
self.step.dependOn(&translate_c_and_cmp.step);
for (case.sources.toSliceConst()) |src_file| {
2019-05-26 18:17:34 +01:00
const expanded_src_path = fs.path.join(
b.allocator,
[_][]const u8{ b.cache_root, src_file.filename },
) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
2017-11-24 19:56:05 +00:00
translate_c_and_cmp.step.dependOn(&write_src.step);
}
}
};
pub const GenHContext = struct {
b: *build.Builder,
step: *build.Step,
test_index: usize,
test_filter: ?[]const u8,
const TestCase = struct {
name: []const u8,
sources: ArrayList(SourceFile),
expected_lines: ArrayList([]const u8),
const SourceFile = struct {
filename: []const u8,
source: []const u8,
};
pub fn addSourceFile(self: *TestCase, filename: []const u8, source: []const u8) void {
self.sources.append(SourceFile{
.filename = filename,
.source = source,
}) catch unreachable;
}
pub fn addExpectedLine(self: *TestCase, text: []const u8) void {
self.expected_lines.append(text) catch unreachable;
}
};
const GenHCmpOutputStep = struct {
step: build.Step,
context: *GenHContext,
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
obj: *LibExeObjStep,
name: []const u8,
test_index: usize,
case: *const TestCase,
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
pub fn create(
context: *GenHContext,
obj: *LibExeObjStep,
name: []const u8,
case: *const TestCase,
) *GenHCmpOutputStep {
const allocator = context.b.allocator;
const ptr = allocator.create(GenHCmpOutputStep) catch unreachable;
ptr.* = GenHCmpOutputStep{
.step = build.Step.init("ParseCCmpOutput", allocator, make),
.context = context,
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
.obj = obj,
.name = name,
.test_index = context.test_index,
.case = case,
};
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
ptr.step.dependOn(&obj.step);
context.test_index += 1;
return ptr;
}
fn make(step: *build.Step) !void {
const self = @fieldParentPtr(GenHCmpOutputStep, "step", step);
const b = self.context.b;
warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
const full_h_path = self.obj.getOutputHPath();
const actual_h = try io.readFileAlloc(b.allocator, full_h_path);
for (self.case.expected_lines.toSliceConst()) |expected_line| {
if (mem.indexOf(u8, actual_h, expected_line) == null) {
warn(
\\
\\========= Expected this output: ================
\\{}
\\========= But found: ===========================
\\{}
\\
, expected_line, actual_h);
return error.TestFailed;
}
}
warn("OK\n");
}
};
fn printInvocation(args: []const []const u8) void {
for (args) |arg| {
warn("{} ", arg);
}
warn("\n");
}
pub fn create(self: *GenHContext, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) *TestCase {
const tc = self.b.allocator.create(TestCase) catch unreachable;
tc.* = TestCase{
.name = name,
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
.expected_lines = ArrayList([]const u8).init(self.b.allocator),
};
tc.addSourceFile(filename, source);
comptime var arg_i = 0;
inline while (arg_i < expected_lines.len) : (arg_i += 1) {
tc.addExpectedLine(expected_lines[arg_i]);
}
return tc;
}
pub fn add(self: *GenHContext, name: []const u8, source: []const u8, expected_lines: ...) void {
const tc = self.create("test.zig", name, source, expected_lines);
self.addCase(tc);
}
pub fn addCase(self: *GenHContext, case: *const TestCase) void {
const b = self.b;
2019-05-26 18:17:34 +01:00
const root_src = fs.path.join(
b.allocator,
[_][]const u8{ b.cache_root, case.sources.items[0].filename },
) catch unreachable;
const mode = builtin.Mode.Debug;
const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", case.name, @tagName(mode)) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
const obj = b.addObject("test", root_src);
obj.setBuildMode(mode);
for (case.sources.toSliceConst()) |src_file| {
2019-05-26 18:17:34 +01:00
const expanded_src_path = fs.path.join(
b.allocator,
[_][]const u8{ b.cache_root, src_file.filename },
) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
obj.step.dependOn(&write_src.step);
}
breaking changes to zig build API and improved caching * in Zig build scripts, getOutputPath() is no longer a valid function to call, unless setOutputDir() was used, or within a custom make() function. Instead there is more convenient API to use which takes advantage of the caching system. Search this commit diff for `exe.run()` for an example. * Zig build by default enables caching. All build artifacts will go into zig-cache. If you want to access build artifacts in a convenient location, it is recommended to add an `install` step. Otherwise you can use the `run()` API mentioned above to execute programs directly from their location in the cache. Closes #330. `addSystemCommand` is available for programs not built with Zig build. * Please note that Zig does no cache evicting yet. You may have to manually delete zig-cache directories periodically to keep disk usage down. It's planned for this to be a simple Least Recently Used eviction system eventually. * `--output`, `--output-lib`, and `--output-h` are removed. Instead, use `--output-dir` which defaults to the current working directory. Or take advantage of `--cache on`, which will print the main output path to stdout, and the other artifacts will be in the same directory with predictable file names. `--disable-gen-h` is available when one wants to prevent .h file generation. * `@cImport` is always independently cached now. Closes #2015. It always writes the generated Zig code to disk which makes debug info and compile errors better. No more "TODO: remember C source location to display here" * Fix .d file parsing. (Fixes the MacOS CI failure) * Zig no longer creates "temporary files" other than inside a zig-cache directory. This breaks the CLI API that Godbolt uses. The suggested new invocation can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-09 03:53:35 +00:00
const cmp_h = GenHCmpOutputStep.create(self, obj, annotated_case_name, case);
self.step.dependOn(&cmp_h.step);
}
};
fn printInvocation(args: []const []const u8) void {
for (args) |arg| {
warn("{} ", arg);
}
warn("\n");
}