Test integration draft of the self-hosted compiler

This commit is contained in:
David Gonzalez Martin 2024-04-10 20:54:31 -06:00
parent 83b8429089
commit 23b6752e0e
3 changed files with 100 additions and 49 deletions

View File

@ -510,6 +510,7 @@ pub fn build(b: *std.Build) !void {
const test_command = b.addRunArtifact(test_runner); const test_command = b.addRunArtifact(test_runner);
test_command.step.dependOn(&compiler.step); test_command.step.dependOn(&compiler.step);
b.installArtifact(test_runner);
test_command.step.dependOn(b.getInstallStep()); test_command.step.dependOn(b.getInstallStep());
if (b.args) |args| { if (b.args) |args| {

View File

@ -29,9 +29,12 @@ fn collectDirectoryDirEntries(allocator: Allocator, path: []const u8) ![]const [
return dir_entries.items; return dir_entries.items;
} }
const bootstrap_relative_path = "zig-out/bin/nat";
fn runStandalone(allocator: Allocator, args: struct { fn runStandalone(allocator: Allocator, args: struct {
directory_path: []const u8, directory_path: []const u8,
group_name: []const u8, group_name: []const u8,
self_hosted: bool,
is_test: bool, is_test: bool,
}) !void { }) !void {
const test_names = try collectDirectoryDirEntries(allocator, args.directory_path); const test_names = try collectDirectoryDirEntries(allocator, args.directory_path);
@ -52,7 +55,7 @@ fn runStandalone(allocator: Allocator, args: struct {
const compile_run = try std.ChildProcess.run(.{ const compile_run = try std.ChildProcess.run(.{
.allocator = allocator, .allocator = allocator,
// TODO: delete -main_source_file? // TODO: delete -main_source_file?
.argv = &.{ "zig-out/bin/nat", if (args.is_test) "test" else "exe", "-main_source_file", source_file_path }, .argv = &.{ if (args.self_hosted) self_hosted_relative_path else bootstrap_relative_path, if (args.is_test) "test" else "exe", "-main_source_file", source_file_path },
.max_output_bytes = std.math.maxInt(u64), .max_output_bytes = std.math.maxInt(u64),
}); });
ran_compilation_count += 1; ran_compilation_count += 1;
@ -77,7 +80,7 @@ fn runStandalone(allocator: Allocator, args: struct {
std.debug.print("STDERR:\n\n{s}\n\n", .{compile_run.stderr}); std.debug.print("STDERR:\n\n{s}\n\n", .{compile_run.stderr});
} }
if (compilation_success) { if (compilation_success and !args.self_hosted) {
const test_path = try std.mem.concat(allocator, u8, &.{ "nat/", test_name }); const test_path = try std.mem.concat(allocator, u8, &.{ "nat/", test_name });
const test_run = try std.ChildProcess.run(.{ const test_run = try std.ChildProcess.run(.{
.allocator = allocator, .allocator = allocator,
@ -117,7 +120,9 @@ fn runStandalone(allocator: Allocator, args: struct {
} }
} }
fn runStandaloneTests(allocator: Allocator) !void { fn runStandaloneTests(allocator: Allocator, args: struct {
self_hosted: bool,
}) !void {
const standalone_test_dir_path = "test/standalone"; const standalone_test_dir_path = "test/standalone";
const standalone_test_names = try collectDirectoryDirEntries(allocator, standalone_test_dir_path); const standalone_test_names = try collectDirectoryDirEntries(allocator, standalone_test_dir_path);
@ -135,7 +140,7 @@ fn runStandaloneTests(allocator: Allocator) !void {
const compile_run = try std.ChildProcess.run(.{ const compile_run = try std.ChildProcess.run(.{
.allocator = allocator, .allocator = allocator,
// TODO: delete -main_source_file? // TODO: delete -main_source_file?
.argv = &.{ "zig-out/bin/nat", "exe", "-main_source_file", source_file_path }, .argv = &.{ if (args.self_hosted) self_hosted_relative_path else bootstrap_relative_path, "exe", "-main_source_file", source_file_path },
.max_output_bytes = std.math.maxInt(u64), .max_output_bytes = std.math.maxInt(u64),
}); });
ran_compilation_count += 1; ran_compilation_count += 1;
@ -160,7 +165,7 @@ fn runStandaloneTests(allocator: Allocator) !void {
std.debug.print("STDERR:\n\n{s}\n\n", .{compile_run.stderr}); std.debug.print("STDERR:\n\n{s}\n\n", .{compile_run.stderr});
} }
if (compilation_success) { if (compilation_success and !args.self_hosted) {
const test_path = try std.mem.concat(allocator, u8, &.{ "nat/", standalone_test_name }); const test_path = try std.mem.concat(allocator, u8, &.{ "nat/", standalone_test_name });
const test_run = try std.ChildProcess.run(.{ const test_run = try std.ChildProcess.run(.{
.allocator = allocator, .allocator = allocator,
@ -200,13 +205,15 @@ fn runStandaloneTests(allocator: Allocator) !void {
} }
} }
fn runBuildTests(allocator: Allocator) !void { fn runBuildTests(allocator: Allocator, args: struct {
self_hosted: bool,
}) !void {
std.debug.print("\n[BUILD TESTS]\n\n", .{}); std.debug.print("\n[BUILD TESTS]\n\n", .{});
const previous_cwd = try std.fs.cwd().realpathAlloc(allocator, "."); const previous_cwd = try std.fs.cwd().realpathAlloc(allocator, ".");
const test_dir_path = "test/build"; const test_dir_path = "test/build";
const test_names = try collectDirectoryDirEntries(allocator, test_dir_path); const test_names = try collectDirectoryDirEntries(allocator, test_dir_path);
const test_dir_realpath = try std.fs.cwd().realpathAlloc(allocator, test_dir_path); const test_dir_realpath = try std.fs.cwd().realpathAlloc(allocator, test_dir_path);
const compiler_realpath = try std.fs.cwd().realpathAlloc(allocator, "zig-out/bin/nat"); const compiler_realpath = try std.fs.cwd().realpathAlloc(allocator, if (args.self_hosted) self_hosted_relative_path else bootstrap_relative_path);
try std.posix.chdir(test_dir_realpath); try std.posix.chdir(test_dir_realpath);
const total_compilation_count = test_names.len; const total_compilation_count = test_names.len;
@ -250,7 +257,7 @@ fn runBuildTests(allocator: Allocator) !void {
std.debug.print("STDERR:\n\n{s}\n\n", .{compile_run.stderr}); std.debug.print("STDERR:\n\n{s}\n\n", .{compile_run.stderr});
} }
if (compilation_success) { if (compilation_success and !args.self_hosted) {
const test_path = try std.mem.concat(allocator, u8, &.{ "nat/", test_name }); const test_path = try std.mem.concat(allocator, u8, &.{ "nat/", test_name });
const test_run = try std.ChildProcess.run(.{ const test_run = try std.ChildProcess.run(.{
.allocator = allocator, .allocator = allocator,
@ -294,13 +301,15 @@ fn runBuildTests(allocator: Allocator) !void {
} }
} }
fn runStdTests(allocator: Allocator) !void { fn runStdTests(allocator: Allocator, args: struct {
self_hosted: bool,
}) !void {
var errors = false; var errors = false;
std.debug.print("std... ", .{}); std.debug.print("std... ", .{});
const result = try std.ChildProcess.run(.{ const result = try std.ChildProcess.run(.{
.allocator = allocator, .allocator = allocator,
.argv = &.{ "zig-out/bin/nat", "test", "-main_source_file", "lib/std/std.nat", "-name", "std" }, .argv = &.{ if (args.self_hosted) self_hosted_relative_path else bootstrap_relative_path, "test", "-main_source_file", "lib/std/std.nat", "-name", "std" },
.max_output_bytes = std.math.maxInt(u64), .max_output_bytes = std.math.maxInt(u64),
}); });
const compilation_result: TestError!bool = switch (result.term) { const compilation_result: TestError!bool = switch (result.term) {
@ -323,7 +332,7 @@ fn runStdTests(allocator: Allocator) !void {
std.debug.print("STDERR:\n\n{s}\n\n", .{result.stderr}); std.debug.print("STDERR:\n\n{s}\n\n", .{result.stderr});
} }
if (compilation_success) { if (compilation_success and !args.self_hosted) {
const test_run = try std.ChildProcess.run(.{ const test_run = try std.ChildProcess.run(.{
.allocator = allocator, .allocator = allocator,
// TODO: delete -main_source_file? // TODO: delete -main_source_file?
@ -486,32 +495,64 @@ fn runCmakeTests(allocator: Allocator, dir_path: []const u8) !void {
} }
} }
pub fn main() !void { const self_hosted_exe_name = "compiler";
const self_hosted_relative_path = "nat/" ++ self_hosted_exe_name;
fn compile_self_hosted(allocator: Allocator, args: struct {
is_test: bool,
}) !void {
const compile_run = try std.ChildProcess.run(.{
.allocator = allocator,
// TODO: delete -main_source_file?
.argv = &.{ bootstrap_relative_path, if (args.is_test) "test" else "exe", "-main_source_file", "src/main.nat", "-name", self_hosted_exe_name },
.max_output_bytes = std.math.maxInt(u64),
});
const compilation_result: TestError!bool = switch (compile_run.term) {
.Exited => |exit_code| if (exit_code == 0) true else error.abnormal_exit_code,
.Signal => error.signaled,
.Stopped => error.stopped,
.Unknown => error.unknown,
};
_ = try compilation_result;
}
fn run_test_suite(allocator: Allocator, args: struct {
self_hosted: bool,
}) bool {
const self_hosted = args.self_hosted;
std.debug.print("TESTING {s} COMPILER...\n=================\n", .{if (self_hosted) "SELF-HOSTED" else "BOOTSTRAP"});
var errors = false; var errors = false;
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
const allocator = arena.allocator();
runStandalone(allocator, .{ runStandalone(allocator, .{
.directory_path = "test/standalone", .directory_path = "test/standalone",
.group_name = "STANDALONE", .group_name = "STANDALONE",
.is_test = false, .is_test = false,
.self_hosted = self_hosted,
}) catch { }) catch {
errors = true; errors = true;
}; };
runBuildTests(allocator) catch { runBuildTests(allocator, .{
.self_hosted = self_hosted,
}) catch {
errors = true; errors = true;
}; };
runStandalone(allocator, .{ runStandalone(allocator, .{
.directory_path = "test/tests", .directory_path = "test/tests",
.group_name = "TEST EXECUTABLE", .group_name = "TEST EXECUTABLE",
.is_test = true, .is_test = true,
.self_hosted = self_hosted,
}) catch { }) catch {
errors = true; errors = true;
}; };
// //
runStdTests(allocator) catch { runStdTests(allocator, .{
.self_hosted = self_hosted,
}) catch {
errors = true; errors = true;
}; };
if (!self_hosted) {
runCmakeTests(allocator, "test/cc") catch { runCmakeTests(allocator, "test/cc") catch {
errors = true; errors = true;
}; };
@ -531,6 +572,31 @@ pub fn main() !void {
}, },
else => @compileError("OS not supported"), else => @compileError("OS not supported"),
} }
}
return errors;
}
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
const allocator = arena.allocator();
var errors = run_test_suite(allocator, .{
.self_hosted = false,
});
if (!errors) {
if (compile_self_hosted(allocator, .{
.is_test = false,
})) |_| {
errors = errors or run_test_suite(allocator, .{
.self_hosted = true,
});
} else |err| {
err catch {};
errors = true;
}
}
if (errors) { if (errors) {
return error.fail; return error.fail;

View File

@ -1,20 +1,4 @@
const std = #import("std"); const std = #import("std");
const main = fn() s32 { const main = fn() *!void {
const size = 0x1000;
if (std.page_allocator.allocate(size, alignment = 12)) |result| {
result[0] = 0;
std.print(bytes = "Allocation succeeded. Freeing...\n");
if (std.page_allocator.free(bytes_ptr = result.ptr, bytes_len = result.len)) {
std.print(bytes = "Memory freed successfully\n");
return 0;
} else {
std.print(bytes = "Memory freed with errors\n");
return 1;
}
} else {
std.print(bytes = "Allocation failed!\n");
return 1;
}
} }