mirror of
https://codeberg.org/andyscott/ziglings.git
synced 2024-11-09 11:40:46 -05:00
test: refactorize the code
Currently, if there is an error when creating the patches/healed directory, the error message will be printed on stderr, but the build runner will report the test as being successful. Add the fail function and the FailStep, so that the error will be correctly handled by the build runner. Remove the PatchStep, and instead add the heal function so that all the exercises are healed before starting the tests. The heal function executes at the configuration phase, but the possible error is handled by the build runner.
This commit is contained in:
parent
2775d21ed0
commit
108c145bdd
1 changed files with 49 additions and 31 deletions
|
@ -2,8 +2,10 @@ const std = @import("std");
|
||||||
const root = @import("../build.zig");
|
const root = @import("../build.zig");
|
||||||
|
|
||||||
const debug = std.debug;
|
const debug = std.debug;
|
||||||
|
const fmt = std.fmt;
|
||||||
const fs = std.fs;
|
const fs = std.fs;
|
||||||
|
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
const Build = std.build;
|
const Build = std.build;
|
||||||
const Step = Build.Step;
|
const Step = Build.Step;
|
||||||
const RunStep = std.Build.RunStep;
|
const RunStep = std.Build.RunStep;
|
||||||
|
@ -18,9 +20,10 @@ pub fn addCliTests(b: *std.Build, exercises: []const Exercise) *Step {
|
||||||
const outdir = "patches/healed";
|
const outdir = "patches/healed";
|
||||||
|
|
||||||
fs.cwd().makePath(outdir) catch |err| {
|
fs.cwd().makePath(outdir) catch |err| {
|
||||||
debug.print("unable to make '{s}': {s}\n", .{ outdir, @errorName(err) });
|
return fail(step, "unable to make '{s}': {s}\n", .{ outdir, @errorName(err) });
|
||||||
|
};
|
||||||
return step;
|
heal(b.allocator, exercises, outdir) catch |err| {
|
||||||
|
return fail(step, "unable to heal exercises: {s}\n", .{@errorName(err)});
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -32,14 +35,11 @@ pub fn addCliTests(b: *std.Build, exercises: []const Exercise) *Step {
|
||||||
i += 1;
|
i += 1;
|
||||||
if (ex.skip) continue;
|
if (ex.skip) continue;
|
||||||
|
|
||||||
const patch = PatchStep.create(b, ex, outdir);
|
|
||||||
|
|
||||||
const cmd = b.addSystemCommand(
|
const cmd = b.addSystemCommand(
|
||||||
&.{ b.zig_exe, "build", b.fmt("-Dn={}", .{i}), "-Dhealed", "test" },
|
&.{ b.zig_exe, "build", b.fmt("-Dn={}", .{i}), "-Dhealed", "test" },
|
||||||
);
|
);
|
||||||
cmd.setName(b.fmt("zig build -D={} -Dhealed test", .{i}));
|
cmd.setName(b.fmt("zig build -D={} -Dhealed test", .{i}));
|
||||||
cmd.expectExitCode(0);
|
cmd.expectExitCode(0);
|
||||||
cmd.step.dependOn(&patch.step);
|
|
||||||
|
|
||||||
// Some exercise output has an extra space character.
|
// Some exercise output has an extra space character.
|
||||||
if (ex.check_stdout)
|
if (ex.check_stdout)
|
||||||
|
@ -93,28 +93,21 @@ fn createCase(b: *Build, name: []const u8) *Step {
|
||||||
return case_step;
|
return case_step;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply a patch to the specified exercise.
|
// A step that will fail.
|
||||||
const PatchStep = struct {
|
const FailStep = struct {
|
||||||
const join = fs.path.join;
|
|
||||||
|
|
||||||
const exercises_path = "exercises";
|
|
||||||
const patches_path = "patches/patches";
|
|
||||||
|
|
||||||
step: Step,
|
step: Step,
|
||||||
exercise: Exercise,
|
error_msg: []const u8,
|
||||||
outdir: []const u8,
|
|
||||||
|
|
||||||
pub fn create(owner: *Build, exercise: Exercise, outdir: []const u8) *PatchStep {
|
pub fn create(owner: *Build, error_msg: []const u8) *FailStep {
|
||||||
const self = owner.allocator.create(PatchStep) catch @panic("OOM");
|
const self = owner.allocator.create(FailStep) catch @panic("OOM");
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.step = Step.init(.{
|
.step = Step.init(.{
|
||||||
.id = .custom,
|
.id = .custom,
|
||||||
.name = owner.fmt("patch {s}", .{exercise.main_file}),
|
.name = "fail",
|
||||||
.owner = owner,
|
.owner = owner,
|
||||||
.makeFn = make,
|
.makeFn = make,
|
||||||
}),
|
}),
|
||||||
.exercise = exercise,
|
.error_msg = error_msg,
|
||||||
.outdir = outdir,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -122,25 +115,50 @@ const PatchStep = struct {
|
||||||
|
|
||||||
fn make(step: *Step, _: *std.Progress.Node) !void {
|
fn make(step: *Step, _: *std.Progress.Node) !void {
|
||||||
const b = step.owner;
|
const b = step.owner;
|
||||||
const self = @fieldParentPtr(PatchStep, "step", step);
|
const self = @fieldParentPtr(FailStep, "step", step);
|
||||||
const exercise = self.exercise;
|
|
||||||
const name = exercise.baseName();
|
try step.result_error_msgs.append(b.allocator, self.error_msg);
|
||||||
|
return error.MakeFailed;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// A variant of `std.Build.Step.fail` that does not return an error so that it
|
||||||
|
// can be used in the configuration phase. It returns a FailStep, so that the
|
||||||
|
// error will be cleanly handled by the build runner.
|
||||||
|
fn fail(step: *Step, comptime format: []const u8, args: anytype) *Step {
|
||||||
|
const b = step.owner;
|
||||||
|
|
||||||
|
const fail_step = FailStep.create(b, b.fmt(format, args));
|
||||||
|
step.dependOn(&fail_step.step);
|
||||||
|
|
||||||
|
return step;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Heals all the exercises.
|
||||||
|
fn heal(allocator: Allocator, exercises: []const Exercise, outdir: []const u8) !void {
|
||||||
|
const join = fs.path.join;
|
||||||
|
|
||||||
|
const exercises_path = "exercises";
|
||||||
|
const patches_path = "patches/patches";
|
||||||
|
|
||||||
|
for (exercises) |ex| {
|
||||||
|
const name = ex.baseName();
|
||||||
|
|
||||||
// Use the POSIX patch variant.
|
// Use the POSIX patch variant.
|
||||||
const file = join(b.allocator, &.{ exercises_path, exercise.main_file }) catch
|
const file = try join(allocator, &.{ exercises_path, ex.main_file });
|
||||||
@panic("OOM");
|
const patch = b: {
|
||||||
const patch = join(b.allocator, &.{ patches_path, b.fmt("{s}.patch", .{name}) }) catch
|
const patch_name = try fmt.allocPrint(allocator, "{s}.patch", .{name});
|
||||||
@panic("OOM");
|
break :b try join(allocator, &.{ patches_path, patch_name });
|
||||||
const output = join(b.allocator, &.{ self.outdir, exercise.main_file }) catch
|
};
|
||||||
@panic("OOM");
|
const output = try join(allocator, &.{ outdir, ex.main_file });
|
||||||
|
|
||||||
const argv = &.{ "patch", "-i", patch, "-o", output, file };
|
const argv = &.{ "patch", "-i", patch, "-o", output, file };
|
||||||
|
|
||||||
var child = std.process.Child.init(argv, b.allocator);
|
var child = std.process.Child.init(argv, allocator);
|
||||||
child.stdout_behavior = .Ignore; // the POSIX standard says that stdout is not used
|
child.stdout_behavior = .Ignore; // the POSIX standard says that stdout is not used
|
||||||
_ = try child.spawnAndWait();
|
_ = try child.spawnAndWait();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Missing functions from std.Build.RunStep
|
// Missing functions from std.Build.RunStep
|
||||||
|
|
Loading…
Reference in a new issue