mirror of
https://github.com/ziglang/zig.git
synced 2024-11-22 20:30:17 +00:00
add test harness for "run translated C" tests
This commit is contained in:
parent
f83411b0b1
commit
695c8f756b
@ -137,6 +137,7 @@ pub fn build(b: *Builder) !void {
|
||||
test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes));
|
||||
test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes));
|
||||
test_step.dependOn(tests.addTranslateCTests(b, test_filter));
|
||||
test_step.dependOn(tests.addRunTranslatedCTests(b, test_filter));
|
||||
test_step.dependOn(tests.addGenHTests(b, test_filter));
|
||||
test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes));
|
||||
test_step.dependOn(docs_step);
|
||||
|
@ -43,7 +43,6 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
|
||||
" libc [paths_file] Display native libc paths file or validate one\n"
|
||||
" run [source] [-- [args]] create executable and run immediately\n"
|
||||
" translate-c [source] convert c code to zig code\n"
|
||||
" translate-c-2 [source] experimental self-hosted translate-c\n"
|
||||
" targets list available compilation targets\n"
|
||||
" test [source] create and run a test build\n"
|
||||
" version print version number and exit\n"
|
||||
|
24
test/run_translated_c.zig
Normal file
24
test/run_translated_c.zig
Normal file
@ -0,0 +1,24 @@
|
||||
const tests = @import("tests.zig");
|
||||
|
||||
pub fn addCases(cases: *tests.RunTranslatedCContext) void {
|
||||
cases.add("hello world",
|
||||
\\#define _NO_CRT_STDIO_INLINE 1
|
||||
\\#include <stdio.h>
|
||||
\\int main(int argc, char **argv) {
|
||||
\\ printf("hello, world!\n");
|
||||
\\ return 0;
|
||||
\\}
|
||||
, "hello, world!\n");
|
||||
|
||||
cases.add("anon struct init",
|
||||
\\#include <stdlib.h>
|
||||
\\struct {int a; int b;} x = {1, 2};
|
||||
\\int main(int argc, char **argv) {
|
||||
\\ x.a += 2;
|
||||
\\ x.b += 1;
|
||||
\\ if (x.a != 3) abort();
|
||||
\\ if (x.b != 3) abort();
|
||||
\\ return 0;
|
||||
\\}
|
||||
, "");
|
||||
}
|
180
test/src/run_translated_c.zig
Normal file
180
test/src/run_translated_c.zig
Normal file
@ -0,0 +1,180 @@
|
||||
// This is the implementation of the test harness for running translated
|
||||
// C code. For the actual test cases, see test/run_translated_c.zig.
|
||||
const std = @import("std");
|
||||
const build = std.build;
|
||||
const ArrayList = std.ArrayList;
|
||||
const fmt = std.fmt;
|
||||
const mem = std.mem;
|
||||
const fs = std.fs;
|
||||
const warn = std.debug.warn;
|
||||
|
||||
pub const RunTranslatedCContext = struct {
|
||||
b: *build.Builder,
|
||||
step: *build.Step,
|
||||
test_index: usize,
|
||||
test_filter: ?[]const u8,
|
||||
|
||||
const TestCase = struct {
|
||||
name: []const u8,
|
||||
sources: ArrayList(SourceFile),
|
||||
expected_stdout: []const u8,
|
||||
allow_warnings: bool,
|
||||
|
||||
const SourceFile = struct {
|
||||
filename: []const u8,
|
||||
source: []const u8,
|
||||
};
|
||||
|
||||
pub fn addSourceFile(self: *TestCase, filename: []const u8, source: []const u8) void {
|
||||
self.sources.append(SourceFile{
|
||||
.filename = filename,
|
||||
.source = source,
|
||||
}) catch unreachable;
|
||||
}
|
||||
};
|
||||
|
||||
const DoEverythingStep = struct {
|
||||
step: build.Step,
|
||||
context: *RunTranslatedCContext,
|
||||
name: []const u8,
|
||||
case: *const TestCase,
|
||||
test_index: usize,
|
||||
|
||||
pub fn create(
|
||||
context: *RunTranslatedCContext,
|
||||
name: []const u8,
|
||||
case: *const TestCase,
|
||||
) *DoEverythingStep {
|
||||
const allocator = context.b.allocator;
|
||||
const ptr = allocator.create(DoEverythingStep) catch unreachable;
|
||||
ptr.* = DoEverythingStep{
|
||||
.context = context,
|
||||
.name = name,
|
||||
.case = case,
|
||||
.test_index = context.test_index,
|
||||
.step = build.Step.init("RunTranslatedC", allocator, make),
|
||||
};
|
||||
context.test_index += 1;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
fn make(step: *build.Step) !void {
|
||||
const self = @fieldParentPtr(DoEverythingStep, "step", step);
|
||||
const b = self.context.b;
|
||||
|
||||
warn("Test {}/{} {}...", .{ self.test_index + 1, self.context.test_index, self.name });
|
||||
// translate from c to zig
|
||||
const translated_c_code = blk: {
|
||||
var zig_args = ArrayList([]const u8).init(b.allocator);
|
||||
defer zig_args.deinit();
|
||||
|
||||
const rel_c_filename = try fs.path.join(b.allocator, &[_][]const u8{
|
||||
b.cache_root,
|
||||
self.case.sources.toSliceConst()[0].filename,
|
||||
});
|
||||
|
||||
try zig_args.append(b.zig_exe);
|
||||
try zig_args.append("translate-c");
|
||||
try zig_args.append("-lc");
|
||||
try zig_args.append(b.pathFromRoot(rel_c_filename));
|
||||
|
||||
break :blk try b.exec(zig_args.toSliceConst());
|
||||
};
|
||||
|
||||
// write stdout to a file
|
||||
|
||||
const translated_c_path = try fs.path.join(b.allocator,
|
||||
&[_][]const u8{ b.cache_root, "translated_c.zig" });
|
||||
try fs.cwd().writeFile(translated_c_path, translated_c_code);
|
||||
|
||||
// zig run the result
|
||||
const run_stdout = blk: {
|
||||
var zig_args = ArrayList([]const u8).init(b.allocator);
|
||||
defer zig_args.deinit();
|
||||
|
||||
try zig_args.append(b.zig_exe);
|
||||
try zig_args.append("-lc");
|
||||
try zig_args.append("run");
|
||||
try zig_args.append(translated_c_path);
|
||||
|
||||
break :blk try b.exec(zig_args.toSliceConst());
|
||||
};
|
||||
// compare stdout
|
||||
if (!mem.eql(u8, self.case.expected_stdout, run_stdout)) {
|
||||
warn(
|
||||
\\
|
||||
\\========= Expected this output: =========
|
||||
\\{}
|
||||
\\========= But found: ====================
|
||||
\\{}
|
||||
\\
|
||||
, .{ self.case.expected_stdout, run_stdout });
|
||||
return error.TestFailed;
|
||||
}
|
||||
|
||||
warn("OK\n", .{});
|
||||
}
|
||||
};
|
||||
|
||||
pub fn create(
|
||||
self: *RunTranslatedCContext,
|
||||
allow_warnings: bool,
|
||||
filename: []const u8,
|
||||
name: []const u8,
|
||||
source: []const u8,
|
||||
expected_stdout: []const u8,
|
||||
) *TestCase {
|
||||
const tc = self.b.allocator.create(TestCase) catch unreachable;
|
||||
tc.* = TestCase{
|
||||
.name = name,
|
||||
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
|
||||
.expected_stdout = expected_stdout,
|
||||
.allow_warnings = allow_warnings,
|
||||
};
|
||||
|
||||
tc.addSourceFile(filename, source);
|
||||
return tc;
|
||||
}
|
||||
|
||||
pub fn add(
|
||||
self: *RunTranslatedCContext,
|
||||
name: []const u8,
|
||||
source: []const u8,
|
||||
expected_stdout: []const u8,
|
||||
) void {
|
||||
const tc = self.create(false, "source.c", name, source, expected_stdout);
|
||||
self.addCase(tc);
|
||||
}
|
||||
|
||||
pub fn addAllowWarnings(
|
||||
self: *RunTranslatedCContext,
|
||||
name: []const u8,
|
||||
source: []const u8,
|
||||
expected_stdout: []const u8,
|
||||
) void {
|
||||
const tc = self.create(true, "source.c", name, source, expected_stdout);
|
||||
self.addCase(tc);
|
||||
}
|
||||
|
||||
pub fn addCase(self: *RunTranslatedCContext, case: *const TestCase) void {
|
||||
const b = self.b;
|
||||
|
||||
const annotated_case_name = fmt.allocPrint(self.b.allocator, "run-translated-c {}", .{ case.name }) catch unreachable;
|
||||
if (self.test_filter) |filter| {
|
||||
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
|
||||
}
|
||||
|
||||
const do_everything_step = DoEverythingStep.create(self, annotated_case_name, case);
|
||||
self.step.dependOn(&do_everything_step.step);
|
||||
|
||||
for (case.sources.toSliceConst()) |src_file| {
|
||||
const expanded_src_path = fs.path.join(
|
||||
b.allocator,
|
||||
&[_][]const u8{ b.cache_root, src_file.filename },
|
||||
) catch unreachable;
|
||||
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
|
||||
do_everything_step.step.dependOn(&write_src.step);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -14,6 +14,7 @@ const builtin = @import("builtin");
|
||||
const Mode = builtin.Mode;
|
||||
const LibExeObjStep = build.LibExeObjStep;
|
||||
|
||||
// Cases
|
||||
const compare_output = @import("compare_output.zig");
|
||||
const standalone = @import("standalone.zig");
|
||||
const stack_traces = @import("stack_traces.zig");
|
||||
@ -21,8 +22,12 @@ const compile_errors = @import("compile_errors.zig");
|
||||
const assemble_and_link = @import("assemble_and_link.zig");
|
||||
const runtime_safety = @import("runtime_safety.zig");
|
||||
const translate_c = @import("translate_c.zig");
|
||||
const run_translated_c = @import("run_translated_c.zig");
|
||||
const gen_h = @import("gen_h.zig");
|
||||
|
||||
// Implementations
|
||||
pub const RunTranslatedCContext = @import("src/run_translated_c.zig").RunTranslatedCContext;
|
||||
|
||||
const TestTarget = struct {
|
||||
target: Target = .Native,
|
||||
mode: builtin.Mode = .Debug,
|
||||
@ -383,6 +388,20 @@ pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.St
|
||||
return cases.step;
|
||||
}
|
||||
|
||||
pub fn addRunTranslatedCTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step {
|
||||
const cases = b.allocator.create(RunTranslatedCContext) catch unreachable;
|
||||
cases.* = .{
|
||||
.b = b,
|
||||
.step = b.step("test-run-translated-c", "Run the Run-Translated-C tests"),
|
||||
.test_index = 0,
|
||||
.test_filter = test_filter,
|
||||
};
|
||||
|
||||
run_translated_c.addCases(cases);
|
||||
|
||||
return cases.step;
|
||||
}
|
||||
|
||||
pub fn addGenHTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step {
|
||||
const cases = b.allocator.create(GenHContext) catch unreachable;
|
||||
cases.* = GenHContext{
|
||||
|
Loading…
Reference in New Issue
Block a user