From e765495b114af3417aea4cffcd7c37f400aab3fe Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sat, 14 Oct 2023 22:02:32 +0300 Subject: [PATCH] tests: translate-c and run-translated-c to the test harness --- lib/std/Build/Step/TranslateC.zig | 6 + test/cases/README.md | 29 +- .../access_invalid_typeInfo_decl.zig | 2 +- .../invalid_duplicate_test_decl_name.zig | 2 +- ...n_returning_type_crashes_compiler_2655.zig | 2 +- .../return_invalid_type_from_test.zig | 2 +- ...n_invalid_value_of_non-exhaustive_enum.zig | 2 +- test/cases/f32_passed_to_variadic_fn.zig | 2 +- .../fn_typeinfo_passed_to_comptime_fn.zig | 2 +- test/cases/llvm/hello_world.zig | 2 +- .../run_translated_c/dereference address of.c | 11 + test/cases/translate_c/enums msvc.c | 16 ++ test/cases/translate_c/enums.c | 16 ++ .../try_in_comptime_in_struct_in_test.zig | 2 +- test/run_translated_c.zig | 17 +- test/src/Cases.zig | 272 +++++++++++++++--- test/translate_c.zig | 24 +- 17 files changed, 338 insertions(+), 71 deletions(-) create mode 100644 test/cases/run_translated_c/dereference address of.c create mode 100644 test/cases/translate_c/enums msvc.c create mode 100644 test/cases/translate_c/enums.c diff --git a/lib/std/Build/Step/TranslateC.zig b/lib/std/Build/Step/TranslateC.zig index 5b5682d659..26e59dad90 100644 --- a/lib/std/Build/Step/TranslateC.zig +++ b/lib/std/Build/Step/TranslateC.zig @@ -17,12 +17,14 @@ target: CrossTarget, optimize: std.builtin.OptimizeMode, output_file: std.Build.GeneratedFile, link_libc: bool, +use_clang: bool, pub const Options = struct { source_file: std.Build.LazyPath, target: CrossTarget, optimize: std.builtin.OptimizeMode, link_libc: bool = true, + use_clang: bool = true, }; pub fn create(owner: *std.Build, options: Options) *TranslateC { @@ -43,6 +45,7 @@ pub fn create(owner: *std.Build, options: Options) *TranslateC { .optimize = options.optimize, .output_file = std.Build.GeneratedFile{ .step = &self.step }, .link_libc = options.link_libc, + .use_clang = options.use_clang, }; source.addStepDependencies(&self.step); return self; @@ -130,6 +133,9 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { if (self.link_libc) { try argv_list.append("-lc"); } + if (!self.use_clang) { + try argv_list.append("-fno-clang"); + } try argv_list.append("--listen=-"); diff --git a/test/cases/README.md b/test/cases/README.md index 4c9f401ab6..97c82dae96 100644 --- a/test/cases/README.md +++ b/test/cases/README.md @@ -9,7 +9,7 @@ If you want it to be run with `zig test` and match expected error messages: ```zig // error -// is_test=1 +// is_test=true // // :4:13: error: 'try' outside function scope ``` @@ -22,6 +22,33 @@ This will do `zig run` on the code and expect exit code 0. // run ``` +## Translate-c + +If you want to test translating C code to Zig use `translate-c`: + +```c +// translate-c +// c_frontend=aro,clang +// target=x86_64-linux +// +// pub const foo = 1; +// pub const immediately_after_foo = 2; +// +// pub const somewhere_else_in_the_file = 3: +``` + +## Run Translated C + +If you want to test translating C code to Zig and then executing it use `run-translated-c`: + +```c +// run-translated-c +// c_frontend=aro,clang +// target=x86_64-linux +// +// Hello world! +``` + ## Incremental Compilation Make multiple files that have ".", and then an integer, before the ".zig" diff --git a/test/cases/compile_errors/access_invalid_typeInfo_decl.zig b/test/cases/compile_errors/access_invalid_typeInfo_decl.zig index 4233b42e7d..13fda8fa7b 100644 --- a/test/cases/compile_errors/access_invalid_typeInfo_decl.zig +++ b/test/cases/compile_errors/access_invalid_typeInfo_decl.zig @@ -6,6 +6,6 @@ test "Crash" { // error // backend=stage2 // target=native -// is_test=1 +// is_test=true // // :1:11: error: use of undeclared identifier 'B' diff --git a/test/cases/compile_errors/invalid_duplicate_test_decl_name.zig b/test/cases/compile_errors/invalid_duplicate_test_decl_name.zig index c3ecdbf4fc..48008f970d 100644 --- a/test/cases/compile_errors/invalid_duplicate_test_decl_name.zig +++ b/test/cases/compile_errors/invalid_duplicate_test_decl_name.zig @@ -4,7 +4,7 @@ test "thingy" {} // error // backend=stage2 // target=native -// is_test=1 +// is_test=true // // :1:6: error: duplicate test name: test.thingy // :2:6: note: other test here diff --git a/test/cases/compile_errors/repeated_invalid_field_access_to_generic_function_returning_type_crashes_compiler_2655.zig b/test/cases/compile_errors/repeated_invalid_field_access_to_generic_function_returning_type_crashes_compiler_2655.zig index 201c8c870b..35273065eb 100644 --- a/test/cases/compile_errors/repeated_invalid_field_access_to_generic_function_returning_type_crashes_compiler_2655.zig +++ b/test/cases/compile_errors/repeated_invalid_field_access_to_generic_function_returning_type_crashes_compiler_2655.zig @@ -9,6 +9,6 @@ test "1" { // error // backend=stage2 // target=native -// is_test=1 +// is_test=true // // :2:12: error: use of undeclared identifier 'Q' diff --git a/test/cases/compile_errors/return_invalid_type_from_test.zig b/test/cases/compile_errors/return_invalid_type_from_test.zig index acc932cb0a..dda31b6f84 100644 --- a/test/cases/compile_errors/return_invalid_type_from_test.zig +++ b/test/cases/compile_errors/return_invalid_type_from_test.zig @@ -5,6 +5,6 @@ test "example" { // error // backend=stage2 // target=native -// is_test=1 +// is_test=true // // :2:12: error: expected type 'anyerror!void', found 'comptime_int' diff --git a/test/cases/compile_errors/tagName_on_invalid_value_of_non-exhaustive_enum.zig b/test/cases/compile_errors/tagName_on_invalid_value_of_non-exhaustive_enum.zig index 2b45fb6076..06e17a1e87 100644 --- a/test/cases/compile_errors/tagName_on_invalid_value_of_non-exhaustive_enum.zig +++ b/test/cases/compile_errors/tagName_on_invalid_value_of_non-exhaustive_enum.zig @@ -6,7 +6,7 @@ test "enum" { // error // backend=stage2 // target=native -// is_test=1 +// is_test=true // // :3:9: error: no field with value '@enumFromInt(5)' in enum 'test.enum.E' // :2:15: note: declared here diff --git a/test/cases/f32_passed_to_variadic_fn.zig b/test/cases/f32_passed_to_variadic_fn.zig index 4ae1d2cf08..16f95fdfe8 100644 --- a/test/cases/f32_passed_to_variadic_fn.zig +++ b/test/cases/f32_passed_to_variadic_fn.zig @@ -9,7 +9,7 @@ pub fn main() void { // run // backend=llvm // target=x86_64-linux-gnu -// link_libc=1 +// link_libc=true // // f64: 2.000000 // f32: 10.000000 diff --git a/test/cases/fn_typeinfo_passed_to_comptime_fn.zig b/test/cases/fn_typeinfo_passed_to_comptime_fn.zig index fb64788126..4946381968 100644 --- a/test/cases/fn_typeinfo_passed_to_comptime_fn.zig +++ b/test/cases/fn_typeinfo_passed_to_comptime_fn.zig @@ -13,6 +13,6 @@ fn foo(comptime info: std.builtin.Type) !void { } // run -// is_test=1 +// is_test=true // backend=llvm // diff --git a/test/cases/llvm/hello_world.zig b/test/cases/llvm/hello_world.zig index 0f75f624ec..8bc1c60614 100644 --- a/test/cases/llvm/hello_world.zig +++ b/test/cases/llvm/hello_world.zig @@ -7,7 +7,7 @@ pub fn main() void { // run // backend=llvm // target=x86_64-linux,x86_64-macos -// link_libc=1 +// link_libc=true // // hello world! // diff --git a/test/cases/run_translated_c/dereference address of.c b/test/cases/run_translated_c/dereference address of.c new file mode 100644 index 0000000000..15b9777c7a --- /dev/null +++ b/test/cases/run_translated_c/dereference address of.c @@ -0,0 +1,11 @@ +#include +int main(void) { + int i = 0; + *&i = 42; + if (i != 42) abort(); + return 0; +} + +// run-translated-c +// c_frontend=clang +// link_libc=true diff --git a/test/cases/translate_c/enums msvc.c b/test/cases/translate_c/enums msvc.c new file mode 100644 index 0000000000..ab7242512f --- /dev/null +++ b/test/cases/translate_c/enums msvc.c @@ -0,0 +1,16 @@ +enum Foo { + FooA = 2, + FooB = 5, + Foo1, +}; + +// translate-c +// target=x86_64-windows-msvc +// c_frontend=clang +// +// pub const FooA: c_int = 2; +// pub const FooB: c_int = 5; +// pub const Foo1: c_int = 6; +// pub const enum_Foo = c_int; +// +// pub const Foo = enum_Foo; diff --git a/test/cases/translate_c/enums.c b/test/cases/translate_c/enums.c new file mode 100644 index 0000000000..528ae60190 --- /dev/null +++ b/test/cases/translate_c/enums.c @@ -0,0 +1,16 @@ +enum Foo { + FooA = 2, + FooB = 5, + Foo1, +}; + +// translate-c +// target=x86_64-linux +// c_frontend=clang,aro +// +// pub const FooA: c_int = 2; +// pub const FooB: c_int = 5; +// pub const Foo1: c_int = 6; +// pub const enum_Foo = c_uint; +// +// pub const Foo = enum_Foo; diff --git a/test/cases/try_in_comptime_in_struct_in_test.zig b/test/cases/try_in_comptime_in_struct_in_test.zig index e88aa13a7b..c6abb13ee6 100644 --- a/test/cases/try_in_comptime_in_struct_in_test.zig +++ b/test/cases/try_in_comptime_in_struct_in_test.zig @@ -8,6 +8,6 @@ test "@unionInit on union w/ tag but no fields" { } // error -// is_test=1 +// is_test=true // // :4:13: error: 'try' outside function scope diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig index 526425341a..744d08f27a 100644 --- a/test/run_translated_c.zig +++ b/test/run_translated_c.zig @@ -2,17 +2,14 @@ const std = @import("std"); const tests = @import("tests.zig"); const nl = if (@import("builtin").os.tag == .windows) "\r\n" else "\n"; -pub fn addCases(cases: *tests.RunTranslatedCContext) void { - cases.add("dereference address of", - \\#include - \\int main(void) { - \\ int i = 0; - \\ *&i = 42; - \\ if (i != 42) abort(); - \\ return 0; - \\} - , ""); +// ********************************************************* +// * * +// * DO NOT ADD NEW CASES HERE * +// * instead add a file to test/cases/run_translated_c * +// * * +// ********************************************************* +pub fn addCases(cases: *tests.RunTranslatedCContext) void { cases.add("division of floating literals", \\#define _NO_CRT_STDIO_INLINE 1 \\#include diff --git a/test/src/Cases.zig b/test/src/Cases.zig index fe1fb6fe34..4969b82033 100644 --- a/test/src/Cases.zig +++ b/test/src/Cases.zig @@ -1,6 +1,7 @@ gpa: Allocator, arena: Allocator, cases: std.ArrayList(Case), +translate: std.ArrayList(Translate), incremental_cases: std.ArrayList(IncrementalCase), pub const IncrementalCase = struct { @@ -36,7 +37,7 @@ pub const Update = struct { Execution: []const u8, /// A header update compiles the input with the equivalent of /// `-femit-h` and tests the produced header against the - /// expected result + /// expected result. Header: []const u8, }, @@ -61,6 +62,11 @@ pub const Backend = enum { llvm, }; +pub const CFrontend = enum { + clang, + aro, +}; + /// A `Case` consists of a list of `Update`. The same `Compilation` is used for each /// update, so each update's source is treated as a single file being /// updated by the test harness and incrementally compiled. @@ -143,6 +149,25 @@ pub const Case = struct { } }; +pub const Translate = struct { + /// The name of the test case. This is shown if a test fails, and + /// otherwise ignored. + name: []const u8, + + input: [:0]const u8, + target: CrossTarget, + link_libc: bool, + c_frontend: CFrontend, + kind: union(enum) { + /// Translate the input, run it and check that it + /// outputs the expected text. + run: []const u8, + /// Translate the input and check that it contains + /// the expected lines of code. + translate: []const []const u8, + }, +}; + pub fn addExe( ctx: *Cases, name: []const u8, @@ -346,9 +371,12 @@ pub fn addCompile( pub fn addFromDir(ctx: *Cases, dir: std.fs.IterableDir) void { var current_file: []const u8 = "none"; ctx.addFromDirInner(dir, ¤t_file) catch |err| { - std.debug.panic("test harness failed to process file '{s}': {s}\n", .{ - current_file, @errorName(err), - }); + std.debug.panicExtra( + @errorReturnTrace(), + @returnAddress(), + "test harness failed to process file '{s}': {s}\n", + .{ current_file, @errorName(err) }, + ); }; } @@ -395,10 +423,44 @@ fn addFromDirInner( const backends = try manifest.getConfigForKeyAlloc(ctx.arena, "backend", Backend); const targets = try manifest.getConfigForKeyAlloc(ctx.arena, "target", CrossTarget); + const c_frontends = try manifest.getConfigForKeyAlloc(ctx.arena, "c_frontend", CFrontend); const is_test = try manifest.getConfigForKeyAssertSingle("is_test", bool); const link_libc = try manifest.getConfigForKeyAssertSingle("link_libc", bool); const output_mode = try manifest.getConfigForKeyAssertSingle("output_mode", std.builtin.OutputMode); + if (manifest.type == .translate_c) { + for (c_frontends) |c_frontend| { + for (targets) |target| { + const output = try manifest.trailingLinesSplit(ctx.arena); + try ctx.translate.append(.{ + .name = std.fs.path.stem(filename), + .c_frontend = c_frontend, + .target = target, + .link_libc = link_libc, + .input = src, + .kind = .{ .translate = output }, + }); + } + } + continue; + } + if (manifest.type == .run_translated_c) { + for (c_frontends) |c_frontend| { + for (targets) |target| { + const output = try manifest.trailingSplit(ctx.arena); + try ctx.translate.append(.{ + .name = std.fs.path.stem(filename), + .c_frontend = c_frontend, + .target = target, + .link_libc = link_libc, + .input = src, + .kind = .{ .run = output }, + }); + } + } + continue; + } + var cases = std.ArrayList(usize).init(ctx.arena); // Cross-product to get all possible test combinations @@ -439,21 +501,15 @@ fn addFromDirInner( case.addCompile(src); }, .@"error" => { - const errors = try manifest.trailingAlloc(ctx.arena); + const errors = try manifest.trailingLines(ctx.arena); case.addError(src, errors); }, .run => { - var output = std.ArrayList(u8).init(ctx.arena); - var trailing_it = manifest.trailing(); - while (trailing_it.next()) |line| { - try output.appendSlice(line); - try output.append('\n'); - } - if (output.items.len > 0) { - try output.resize(output.items.len - 1); - } - case.addCompareOutput(src, try output.toOwnedSlice()); + const output = try manifest.trailingSplit(ctx.arena); + case.addCompareOutput(src, output); }, + .translate_c => @panic("c_frontend specified for compile case"), + .run_translated_c => @panic("c_frontend specified for compile case"), .cli => @panic("TODO cli tests"), } } @@ -468,6 +524,7 @@ pub fn init(gpa: Allocator, arena: Allocator) Cases { return .{ .gpa = gpa, .cases = std.ArrayList(Case).init(gpa), + .translate = std.ArrayList(Translate).init(gpa), .incremental_cases = std.ArrayList(IncrementalCase).init(gpa), .arena = arena, }; @@ -482,7 +539,7 @@ pub fn lowerToBuildSteps( incremental_exe: *std.Build.Step.Compile, ) void { const host = std.zig.system.NativeTargetInfo.detect(.{}) catch |err| - std.debug.panic("unable to detect notive host: {s}\n", .{@errorName(err)}); + std.debug.panic("unable to detect native host: {s}\n", .{@errorName(err)}); for (self.incremental_cases.items) |incr_case| { if (true) { @@ -589,7 +646,7 @@ pub fn lowerToBuildSteps( .Execution => |expected_stdout| no_exec: { const run = if (case.target.ofmt == .c) run_step: { const target_info = std.zig.system.NativeTargetInfo.detect(case.target) catch |err| - std.debug.panic("unable to detect notive host: {s}\n", .{@errorName(err)}); + std.debug.panic("unable to detect target host: {s}\n", .{@errorName(err)}); if (host.getExternalExecutor(&target_info, .{ .link_libc = true }) != .native) { // We wouldn't be able to run the compiled C code. break :no_exec; @@ -623,6 +680,68 @@ pub fn lowerToBuildSteps( .Header => @panic("TODO"), } } + + for (self.translate.items) |*case| switch (case.kind) { + .run => |output| { + const annotated_case_name = b.fmt("run-translated-c {s}", .{case.name}); + if (opt_test_filter) |filter| { + if (std.mem.indexOf(u8, annotated_case_name, filter) == null) return; + } + if (!std.process.can_spawn) { + std.debug.print("Unable to spawn child processes on {s}, skipping test.\n", .{@tagName(builtin.os.tag)}); + continue; // Pass test. + } + + const target_info = std.zig.system.NativeTargetInfo.detect(case.target) catch |err| + std.debug.panic("unable to detect target host: {s}\n", .{@errorName(err)}); + if (host.getExternalExecutor(&target_info, .{ .link_libc = true }) != .native) { + // We wouldn't be able to run the compiled C code. + continue; // Pass test. + } + + const write_src = b.addWriteFiles(); + const file_source = write_src.add("tmp.c", case.input); + + const translate_c = b.addTranslateC(.{ + .source_file = file_source, + .optimize = .Debug, + .target = case.target, + .link_libc = case.link_libc, + .use_clang = case.c_frontend == .clang, + }); + translate_c.step.name = b.fmt("{s} translate-c", .{annotated_case_name}); + + const run_exe = translate_c.addExecutable(.{}); + run_exe.step.name = b.fmt("{s} build-exe", .{annotated_case_name}); + run_exe.linkLibC(); + const run = b.addRunArtifact(run_exe); + run.step.name = b.fmt("{s} run", .{annotated_case_name}); + run.expectStdOutEqual(output); + + parent_step.dependOn(&run.step); + }, + .translate => |output| { + const annotated_case_name = b.fmt("zig translate-c {s}", .{case.name}); + if (opt_test_filter) |filter| { + if (std.mem.indexOf(u8, annotated_case_name, filter) == null) return; + } + + const write_src = b.addWriteFiles(); + const file_source = write_src.add("tmp.c", case.input); + + const translate_c = b.addTranslateC(.{ + .source_file = file_source, + .optimize = .Debug, + .target = case.target, + .link_libc = case.link_libc, + .use_clang = case.c_frontend == .clang, + }); + translate_c.step.name = annotated_case_name; + + const check_file = translate_c.addCheckFile(output); + parent_step.dependOn(&check_file.step); + }, + }; } /// Sort test filenames in-place, so that incremental test cases ("foo.0.zig", @@ -780,7 +899,7 @@ const TestManifestConfigDefaults = struct { if (std.mem.eql(u8, key, "backend")) { return "stage2"; } else if (std.mem.eql(u8, key, "target")) { - if (@"type" == .@"error") { + if (@"type" == .@"error" or @"type" == .translate_c or @"type" == .run_translated_c) { return "native"; } return comptime blk: { @@ -807,12 +926,16 @@ const TestManifestConfigDefaults = struct { .@"error" => "Obj", .run => "Exe", .compile => "Obj", + .translate_c => "Obj", + .run_translated_c => "Obj", .cli => @panic("TODO test harness for CLI tests"), }; } else if (std.mem.eql(u8, key, "is_test")) { - return "0"; + return "false"; } else if (std.mem.eql(u8, key, "link_libc")) { - return "0"; + return "false"; + } else if (std.mem.eql(u8, key, "c_frontend")) { + return "clang"; } else unreachable; } }; @@ -844,6 +967,8 @@ const TestManifest = struct { run, cli, compile, + translate_c, + run_translated_c, }; const TrailingIterator = struct { @@ -912,6 +1037,10 @@ const TestManifest = struct { break :blk .cli; } else if (std.mem.eql(u8, raw, "compile")) { break :blk .compile; + } else if (std.mem.eql(u8, raw, "translate-c")) { + break :blk .translate_c; + } else if (std.mem.eql(u8, raw, "run-translated-c")) { + break :blk .run_translated_c; } else { std.log.warn("unknown test case type requested: {s}", .{raw}); return error.UnknownTestCaseType; @@ -979,7 +1108,21 @@ const TestManifest = struct { }; } - fn trailingAlloc(self: TestManifest, allocator: Allocator) error{OutOfMemory}![]const []const u8 { + fn trailingSplit(self: TestManifest, allocator: Allocator) error{OutOfMemory}![]const u8 { + var out = std.ArrayList(u8).init(allocator); + defer out.deinit(); + var trailing_it = self.trailing(); + while (trailing_it.next()) |line| { + try out.appendSlice(line); + try out.append('\n'); + } + if (out.items.len > 0) { + try out.resize(out.items.len - 1); + } + return try out.toOwnedSlice(); + } + + fn trailingLines(self: TestManifest, allocator: Allocator) error{OutOfMemory}![]const []const u8 { var out = std.ArrayList([]const u8).init(allocator); defer out.deinit(); var it = self.trailing(); @@ -989,6 +1132,28 @@ const TestManifest = struct { return try out.toOwnedSlice(); } + fn trailingLinesSplit(self: TestManifest, allocator: Allocator) error{OutOfMemory}![]const []const u8 { + // Collect output lines split by empty lines + var out = std.ArrayList([]const u8).init(allocator); + defer out.deinit(); + var buf = std.ArrayList(u8).init(allocator); + defer buf.deinit(); + var it = self.trailing(); + while (it.next()) |line| { + if (line.len == 0) { + if (buf.items.len != 0) { + try out.append(try buf.toOwnedSlice()); + buf.items.len = 0; + } + continue; + } + try buf.appendSlice(line); + try buf.append('\n'); + } + try out.append(try buf.toOwnedSlice()); + return try out.toOwnedSlice(); + } + fn ParseFn(comptime T: type) type { return fn ([]const u8) anyerror!T; } @@ -1011,8 +1176,10 @@ const TestManifest = struct { }.parse, .Bool => return struct { fn parse(str: []const u8) anyerror!T { - const as_int = try std.fmt.parseInt(u1, str, 0); - return as_int > 0; + if (std.mem.eql(u8, str, "true")) return true; + if (std.mem.eql(u8, str, "false")) return false; + std.debug.print("{s}\n", .{str}); + return error.InvalidBool; } }.parse, .Enum => return struct { @@ -1124,9 +1291,47 @@ pub fn main() !void { if (cases.items.len == 0) { const backends = try manifest.getConfigForKeyAlloc(arena, "backend", Backend); const targets = try manifest.getConfigForKeyAlloc(arena, "target", CrossTarget); + const c_frontends = try manifest.getConfigForKeyAlloc(ctx.arena, "c_frontend", CFrontend); const is_test = try manifest.getConfigForKeyAssertSingle("is_test", bool); + const link_libc = try manifest.getConfigForKeyAssertSingle("link_libc", bool); const output_mode = try manifest.getConfigForKeyAssertSingle("output_mode", std.builtin.OutputMode); + if (manifest.type == .translate_c) { + for (c_frontends) |c_frontend| { + for (targets) |target| { + const output = try manifest.trailingLinesSplit(ctx.arena); + try ctx.translate.append(.{ + .name = std.fs.path.stem(filename), + .c_frontend = c_frontend, + .target = target, + .is_test = is_test, + .link_libc = link_libc, + .input = src, + .kind = .{ .translate = output }, + }); + } + } + continue; + } + if (manifest.type == .run_translated_c) { + for (c_frontends) |c_frontend| { + for (targets) |target| { + const output = try manifest.trailingSplit(ctx.arena); + try ctx.translate.append(.{ + .name = std.fs.path.stem(filename), + .c_frontend = c_frontend, + .target = target, + .is_test = is_test, + .link_libc = link_libc, + .output = output, + .input = src, + .kind = .{ .run = output }, + }); + } + } + continue; + } + // Cross-product to get all possible test combinations for (backends) |backend| { for (targets) |target| { @@ -1158,7 +1363,7 @@ pub fn main() !void { case.addCompile(src); }, .@"error" => { - const errors = try manifest.trailingAlloc(arena); + const errors = try manifest.trailingLines(arena); switch (strategy) { .independent => { case.addError(src, errors); @@ -1169,17 +1374,11 @@ pub fn main() !void { } }, .run => { - var output = std.ArrayList(u8).init(arena); - var trailing_it = manifest.trailing(); - while (trailing_it.next()) |line| { - try output.appendSlice(line); - try output.append('\n'); - } - if (output.items.len > 0) { - try output.resize(output.items.len - 1); - } - case.addCompareOutput(src, try output.toOwnedSlice()); + const output = try manifest.trailingSplit(ctx.arena); + case.addCompareOutput(src, output); }, + .translate_c => @panic("c_frontend specified for compile case"), + .run_translated_c => @panic("c_frontend specified for compile case"), .cli => @panic("TODO cli tests"), } } @@ -1255,6 +1454,11 @@ fn runCases(self: *Cases, zig_exe_path: []const u8) !void { host, ); } + + for (self.translate.items) |*case| { + _ = case; + @panic("TODO is this even used?"); + } } } diff --git a/test/translate_c.zig b/test/translate_c.zig index 942b69d7b0..37bf7a4878 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -3,6 +3,13 @@ const builtin = @import("builtin"); const tests = @import("tests.zig"); const CrossTarget = std.zig.CrossTarget; +// ******************************************************** +// * * +// * DO NOT ADD NEW CASES HERE * +// * instead add a file to test/cases/translate_c * +// * * +// ******************************************************** + pub fn addCases(cases: *tests.TranslateCContext) void { const default_enum_type = if (builtin.abi == .msvc) "c_int" else "c_uint"; @@ -3315,23 +3322,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub const FOO_CHAR = '\x3f'; }); - cases.add("enums", - \\enum Foo { - \\ FooA = 2, - \\ FooB = 5, - \\ Foo1, - \\}; - , &[_][]const u8{ - \\pub const FooA: c_int = 2; - \\pub const FooB: c_int = 5; - \\pub const Foo1: c_int = 6; - \\pub const enum_Foo = - ++ " " ++ default_enum_type ++ - \\; - , - \\pub const Foo = enum_Foo; - }); - cases.add("macro cast", \\#include \\int baz(void *arg) { return 0; }