self-hosted: add first compare-output test

This commit is contained in:
Andrew Kelley 2018-07-23 00:35:53 -04:00
parent 93e78ee722
commit d767fae47e
6 changed files with 101 additions and 28 deletions

View File

@ -128,7 +128,6 @@ pub const Compilation = struct {
version_patch: u32,
linker_script: ?[]const u8,
cache_dir: []const u8,
out_h_path: ?[]const u8,
is_test: bool,
@ -326,7 +325,6 @@ pub const Compilation = struct {
build_mode: builtin.Mode,
is_static: bool,
zig_lib_dir: []const u8,
cache_dir: []const u8,
) !*Compilation {
const loop = event_loop_local.loop;
const comp = try event_loop_local.loop.allocator.create(Compilation{
@ -341,7 +339,6 @@ pub const Compilation = struct {
.build_mode = build_mode,
.zig_lib_dir = zig_lib_dir,
.zig_std_dir = undefined,
.cache_dir = cache_dir,
.tmp_dir = event.Future(BuildError![]u8).init(loop),
.name = undefined,
@ -777,7 +774,8 @@ pub const Compilation = struct {
defer decls.base.deref(self);
var decl_group = event.Group(BuildError!void).init(self.loop);
errdefer decl_group.cancelAll();
// TODO https://github.com/ziglang/zig/issues/1261
//errdefer decl_group.cancelAll();
var it = tree.root_node.decls.iterator(0);
while (it.next()) |decl_ptr| {

View File

@ -138,7 +138,6 @@ const usage_build_generic =
\\Compile Options:
\\ --libc [file] Provide a file which specifies libc paths
\\ --assembly [source] Add assembly file to build
\\ --cache-dir [path] Override the cache directory
\\ --emit [filetype] Emit a specific file format as compilation output
\\ --enable-timing-info Print timing diagnostics
\\ --name [name] Override output name
@ -204,7 +203,6 @@ const args_build_generic = []Flag{
}),
Flag.ArgMergeN("--assembly", 1),
Flag.Arg1("--cache-dir"),
Flag.Option("--emit", []const []const u8{
"asm",
"bin",
@ -373,13 +371,6 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
os.exit(1);
}
const rel_cache_dir = flags.single("cache-dir") orelse "zig-cache"[0..];
const full_cache_dir = os.path.resolve(allocator, ".", rel_cache_dir) catch {
try stderr.print("invalid cache dir: {}\n", rel_cache_dir);
os.exit(1);
};
defer allocator.free(full_cache_dir);
const zig_lib_dir = introspect.resolveZigLibDir(allocator) catch os.exit(1);
defer allocator.free(zig_lib_dir);
@ -401,7 +392,6 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
build_mode,
is_static,
zig_lib_dir,
full_cache_dir,
);
defer comp.destroy();
@ -472,7 +462,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
comp.emit_file_type = emit_type;
comp.assembly_files = assembly_files;
comp.link_out_file = flags.single("out-file");
comp.link_out_file = flags.single("output");
comp.link_objects = link_objects;
try comp.build();

View File

@ -8,13 +8,14 @@ const assertOrPanic = std.debug.assertOrPanic;
const errmsg = @import("errmsg.zig");
const EventLoopLocal = @import("compilation.zig").EventLoopLocal;
test "compile errors" {
var ctx: TestContext = undefined;
var ctx: TestContext = undefined;
test "stage2" {
try ctx.init();
defer ctx.deinit();
try @import("../test/stage2/compile_errors.zig").addCases(&ctx);
//try @import("../test/stage2/compare_output.zig").addCases(&ctx);
try @import("../test/stage2/compare_output.zig").addCases(&ctx);
try ctx.run();
}
@ -26,7 +27,6 @@ pub const TestContext = struct {
loop: std.event.Loop,
event_loop_local: EventLoopLocal,
zig_lib_dir: []u8,
zig_cache_dir: []u8,
file_index: std.atomic.Int(usize),
group: std.event.Group(error!void),
any_err: error!void,
@ -39,7 +39,6 @@ pub const TestContext = struct {
.loop = undefined,
.event_loop_local = undefined,
.zig_lib_dir = undefined,
.zig_cache_dir = undefined,
.group = undefined,
.file_index = std.atomic.Int(usize).init(0),
};
@ -56,16 +55,12 @@ pub const TestContext = struct {
self.zig_lib_dir = try introspect.resolveZigLibDir(allocator);
errdefer allocator.free(self.zig_lib_dir);
self.zig_cache_dir = try introspect.resolveZigCacheDir(allocator);
errdefer allocator.free(self.zig_cache_dir);
try std.os.makePath(allocator, tmp_dir_name);
errdefer std.os.deleteTree(allocator, tmp_dir_name) catch {};
}
fn deinit(self: *TestContext) void {
std.os.deleteTree(allocator, tmp_dir_name) catch {};
allocator.free(self.zig_cache_dir);
allocator.free(self.zig_lib_dir);
self.event_loop_local.deinit();
self.loop.deinit();
@ -110,7 +105,6 @@ pub const TestContext = struct {
builtin.Mode.Debug,
true, // is_static
self.zig_lib_dir,
self.zig_cache_dir,
);
errdefer comp.destroy();
@ -119,6 +113,83 @@ pub const TestContext = struct {
try self.group.call(getModuleEvent, comp, source, path, line, column, msg);
}
fn testCompareOutputLibC(
self: *TestContext,
source: []const u8,
expected_output: []const u8,
) !void {
var file_index_buf: [20]u8 = undefined;
const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr());
const file1_path = try std.os.path.join(allocator, tmp_dir_name, file_index, file1);
const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, Target(Target.Native).exeFileExt());
if (std.os.path.dirname(file1_path)) |dirname| {
try std.os.makePath(allocator, dirname);
}
// TODO async I/O
try std.io.writeFile(allocator, file1_path, source);
var comp = try Compilation.create(
&self.event_loop_local,
"test",
file1_path,
Target.Native,
Compilation.Kind.Exe,
builtin.Mode.Debug,
false,
self.zig_lib_dir,
);
errdefer comp.destroy();
_ = try comp.addLinkLib("c", true);
comp.link_out_file = output_file;
try comp.build();
try self.group.call(getModuleEventSuccess, comp, output_file, expected_output);
}
async fn getModuleEventSuccess(
comp: *Compilation,
exe_file: []const u8,
expected_output: []const u8,
) !void {
// TODO this should not be necessary
const exe_file_2 = try std.mem.dupe(allocator, u8, exe_file);
defer comp.destroy();
const build_event = await (async comp.events.get() catch unreachable);
switch (build_event) {
Compilation.Event.Ok => {
const argv = []const []const u8{exe_file_2};
// TODO use event loop
const child = try std.os.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024);
switch (child.term) {
std.os.ChildProcess.Term.Exited => |code| {
if (code != 0) {
return error.BadReturnCode;
}
},
else => {
return error.Crashed;
},
}
if (!mem.eql(u8, child.stdout, expected_output)) {
return error.OutputMismatch;
}
},
Compilation.Event.Error => |err| return err,
Compilation.Event.Fail => |msgs| {
var stderr = try std.io.getStdErr();
try stderr.write("build incorrectly failed:\n");
for (msgs) |msg| {
try errmsg.printToFile(&stderr, msg, errmsg.Color.Auto);
}
},
}
}
async fn getModuleEvent(
comp: *Compilation,
source: []const u8,

View File

@ -14,6 +14,8 @@
#define ZIG_EXTERN_C
#endif
#include <stddef.h>
struct ZigWindowsSDK {
const char *path10_ptr;
size_t path10_len;

View File

@ -23,14 +23,14 @@ test "makePath, put some files in it, deleteTree" {
test "access file" {
try os.makePath(a, "os_test_tmp");
if (os.File.access(a, "os_test_tmp/file.txt", os.default_file_mode)) |ok| {
unreachable;
if (os.File.access(a, "os_test_tmp/file.txt")) |ok| {
@panic("expected error");
} else |err| {
assert(err == error.NotFound);
}
try io.writeFile(a, "os_test_tmp/file.txt", "");
assert((try os.File.access(a, "os_test_tmp/file.txt", os.default_file_mode)) == true);
try os.File.access(a, "os_test_tmp/file.txt");
try os.deleteTree(a, "os_test_tmp");
}

View File

@ -0,0 +1,12 @@
const std = @import("std");
const TestContext = @import("../../src-self-hosted/test.zig").TestContext;
pub fn addCases(ctx: *TestContext) !void {
try ctx.testCompareOutputLibC(
\\extern fn puts([*]const u8) void;
\\export fn main() c_int {
\\ puts(c"Hello, world!");
\\ return 0;
\\}
, "Hello, world!" ++ std.cstr.line_sep);
}