From d767fae47e89aef53505191cf11ce7e592a784b2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 23 Jul 2018 00:35:53 -0400 Subject: [PATCH] self-hosted: add first compare-output test --- src-self-hosted/compilation.zig | 6 +-- src-self-hosted/main.zig | 12 +---- src-self-hosted/test.zig | 91 +++++++++++++++++++++++++++++---- src/windows_sdk.h | 2 + std/os/test.zig | 6 +-- test/stage2/compare_output.zig | 12 +++++ 6 files changed, 101 insertions(+), 28 deletions(-) create mode 100644 test/stage2/compare_output.zig diff --git a/src-self-hosted/compilation.zig b/src-self-hosted/compilation.zig index 3adeb55b56..356fecc6da 100644 --- a/src-self-hosted/compilation.zig +++ b/src-self-hosted/compilation.zig @@ -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| { diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index 5c27e5f57e..d7e52bc404 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -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(); diff --git a/src-self-hosted/test.zig b/src-self-hosted/test.zig index d3541c73b6..1c76bc9e11 100644 --- a/src-self-hosted/test.zig +++ b/src-self-hosted/test.zig @@ -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, diff --git a/src/windows_sdk.h b/src/windows_sdk.h index 080ed55bed..2d531ad372 100644 --- a/src/windows_sdk.h +++ b/src/windows_sdk.h @@ -14,6 +14,8 @@ #define ZIG_EXTERN_C #endif +#include + struct ZigWindowsSDK { const char *path10_ptr; size_t path10_len; diff --git a/std/os/test.zig b/std/os/test.zig index 52e6ffdc1c..9e795e8ad2 100644 --- a/std/os/test.zig +++ b/std/os/test.zig @@ -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"); } diff --git a/test/stage2/compare_output.zig b/test/stage2/compare_output.zig new file mode 100644 index 0000000000..35adcbb96b --- /dev/null +++ b/test/stage2/compare_output.zig @@ -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); +}