convert assemble and link tests to zig build system

This commit is contained in:
Andrew Kelley
2017-04-19 14:00:12 -04:00
parent 666435195f
commit d1e01e43d3
11 changed files with 921 additions and 541 deletions

View File

@@ -1,26 +1,6 @@
const std = @import("std");
const debug = std.debug;
const build = std.build;
const os = std.os;
const StdIo = os.ChildProcess.StdIo;
const Term = os.ChildProcess.Term;
const Buffer0 = std.cstr.Buffer0;
const io = std.io;
const mem = std.mem;
const fmt = std.fmt;
const List = std.list.List;
error TestFailed;
pub fn addCompileErrorTests(b: &build.Builder, test_filter: ?[]const u8) -> &build.Step {
const cases = %%b.allocator.create(CompileErrorContext);
*cases = CompileErrorContext {
.b = b,
.step = b.step("test-compile-errors", "Run the compile error tests"),
.test_index = 0,
.test_filter = test_filter,
};
const tests = @import("tests.zig");
pub fn addCases(cases: &tests.CompileErrorContext) {
cases.add("implicit semicolon - block statement",
\\export fn entry() {
\\ {}
@@ -1594,219 +1574,4 @@ pub fn addCompileErrorTests(b: &build.Builder, test_filter: ?[]const u8) -> &bui
,
"error: 'main' is private",
".tmp_source.zig:1:1: note: declared here");
return cases.step;
}
const CompileErrorContext = struct {
b: &build.Builder,
step: &build.Step,
test_index: usize,
test_filter: ?[]const u8,
const TestCase = struct {
name: []const u8,
sources: List(SourceFile),
expected_errors: List([]const u8),
link_libc: bool,
is_exe: bool,
const SourceFile = struct {
filename: []const u8,
source: []const u8,
};
pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) {
%%self.sources.append(SourceFile {
.filename = filename,
.source = source,
});
}
pub fn addExpectedError(self: &TestCase, text: []const u8) {
%%self.expected_errors.append(text);
}
};
const CompileCmpOutputStep = struct {
step: build.Step,
context: &CompileErrorContext,
name: []const u8,
test_index: usize,
case: &const TestCase,
release: bool,
pub fn create(context: &CompileErrorContext, name: []const u8,
case: &const TestCase, release: bool) -> &CompileCmpOutputStep
{
const allocator = context.b.allocator;
const ptr = %%allocator.create(CompileCmpOutputStep);
*ptr = CompileCmpOutputStep {
.step = build.Step.init("CompileCmpOutput", allocator, make),
.context = context,
.name = name,
.test_index = context.test_index,
.case = case,
.release = release,
};
context.test_index += 1;
return ptr;
}
fn make(step: &build.Step) -> %void {
const self = @fieldParentPtr(CompileCmpOutputStep, "step", step);
const b = self.context.b;
const root_src = %%os.path.join(b.allocator, "test_artifacts", self.case.sources.items[0].filename);
const obj_path = %%os.path.join(b.allocator, "test_artifacts", "test.o");
var zig_args = List([]const u8).init(b.allocator);
%%zig_args.append(if (self.case.is_exe) "build_exe" else "build_obj");
%%zig_args.append(b.pathFromRoot(root_src));
%%zig_args.append("--name");
%%zig_args.append("test");
%%zig_args.append("--output");
%%zig_args.append(b.pathFromRoot(obj_path));
if (self.release) {
%%zig_args.append("--release");
}
%%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
if (b.verbose) {
printInvocation(b.zig_exe, zig_args.toSliceConst());
}
var child = os.ChildProcess.spawn(b.zig_exe, zig_args.toSliceConst(), &b.env_map,
StdIo.Ignore, StdIo.Pipe, StdIo.Pipe, b.allocator) %% |err|
{
debug.panic("Unable to spawn {}: {}\n", b.zig_exe, @errorName(err));
};
const term = child.wait() %% |err| {
debug.panic("Unable to spawn {}: {}\n", b.zig_exe, @errorName(err));
};
switch (term) {
Term.Clean => |code| {
if (code == 0) {
%%io.stderr.printf("Compilation incorrectly succeeded\n");
return error.TestFailed;
}
},
else => {
%%io.stderr.printf("Process {} terminated unexpectedly\n", b.zig_exe);
return error.TestFailed;
},
};
var stdout_buf = %%Buffer0.initEmpty(b.allocator);
var stderr_buf = %%Buffer0.initEmpty(b.allocator);
%%(??child.stdout).readAll(&stdout_buf);
%%(??child.stderr).readAll(&stderr_buf);
const stdout = stdout_buf.toSliceConst();
const stderr = stderr_buf.toSliceConst();
if (stdout.len != 0) {
%%io.stderr.printf(
\\
\\Expected empty stdout, instead found:
\\================================================
\\{}
\\================================================
\\
, stdout);
return error.TestFailed;
}
for (self.case.expected_errors.toSliceConst()) |expected_error| {
if (mem.indexOf(u8, stderr, expected_error) == null) {
%%io.stderr.printf(
\\
\\========= Expected this compile error: =========
\\{}
\\================================================
\\{}
\\
, expected_error, stderr);
return error.TestFailed;
}
}
%%io.stderr.printf("OK\n");
}
};
fn printInvocation(exe_path: []const u8, args: []const []const u8) {
%%io.stderr.printf("{}", exe_path);
for (args) |arg| {
%%io.stderr.printf(" {}", arg);
}
%%io.stderr.printf("\n");
}
pub fn create(self: &CompileErrorContext, name: []const u8, source: []const u8,
expected_lines: ...) -> &TestCase
{
const tc = %%self.b.allocator.create(TestCase);
*tc = TestCase {
.name = name,
.sources = List(TestCase.SourceFile).init(self.b.allocator),
.expected_errors = List([]const u8).init(self.b.allocator),
.link_libc = false,
.is_exe = false,
};
tc.addSourceFile(".tmp_source.zig", source);
comptime var arg_i = 0;
inline while (arg_i < expected_lines.len; arg_i += 1) {
// TODO mem.dupe is because of issue #336
tc.addExpectedError(%%mem.dupe(self.b.allocator, u8, expected_lines[arg_i]));
}
return tc;
}
pub fn addC(self: &CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) {
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: ...) {
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: ...) {
const tc = self.create(name, source, expected_lines);
self.addCase(tc);
}
pub fn addCase(self: &CompileErrorContext, case: &const TestCase) {
const b = self.b;
for ([]bool{false, true}) |release| {
const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "{} ({})",
case.name, if (release) "release" else "debug");
if (const filter ?= self.test_filter) {
if (mem.indexOf(u8, annotated_case_name, filter) == null)
continue;
}
const compile_and_cmp_errors = CompileCmpOutputStep.create(self, annotated_case_name, case, release);
self.step.dependOn(&compile_and_cmp_errors.step);
for (case.sources.toSliceConst()) |src_file| {
const expanded_src_path = %%os.path.join(b.allocator, "test_artifacts", src_file.filename);
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
compile_and_cmp_errors.step.dependOn(&write_src.step);
}
}
}
};