1
0
Fork 0
mirror of https://codeberg.org/ziglings/exercises.git synced 2025-06-08 01:57:02 +09:00

build: use multiline string literals when necessary

Update the output and hint fields in the `exercises` slice to use a
multiline string literal when the string have multiple lines or use the
`"` character.  This will greatly improve readability.
Additionally, remove the trailing whitespace on each line and check it
in the validate_exercises function.

Update the output comparison logic in ZiglingStep, since the current
code assumes that the string has only one line.

Update test/tests.zig to use the new `CheckNamedStep` in test case 1,
since RunStep.StdIo.Check is no longer able to correctly check the
output.

Fixes #283
This commit is contained in:
Manlio Perillo 2023-05-06 18:02:18 +02:00
parent 397c6671c0
commit 1dd5852bec
2 changed files with 178 additions and 33 deletions

View file

@ -43,18 +43,17 @@ pub fn addCliTests(b: *std.Build, exercises: []const Exercise) *Step {
});
cmd.setName(b.fmt("zig build -Dhealed -Dn={} test", .{n}));
cmd.expectExitCode(0);
if (ex.check_stdout) {
expectStdOutMatch(cmd, ex.output);
cmd.expectStdErrEqual("");
} else {
expectStdErrMatch(cmd, ex.output);
cmd.expectStdOutEqual("");
}
cmd.step.dependOn(&heal_step.step);
case_step.dependOn(&cmd.step);
const output = if (ex.check_stdout)
cmd.captureStdOut()
else
cmd.captureStdErr();
const verify = CheckNamedStep.create(b, ex, output);
verify.step.dependOn(&cmd.step);
case_step.dependOn(&verify.step);
}
const cleanup = b.addRemoveDirTree(tmp_path);
@ -196,6 +195,47 @@ fn createCase(b: *Build, name: []const u8) *Step {
return case_step;
}
/// Checks the output of `zig build -Dn=n test`.
const CheckNamedStep = struct {
step: Step,
exercise: Exercise,
output: FileSource,
pub fn create(owner: *Build, exercise: Exercise, output: FileSource) *CheckNamedStep {
const self = owner.allocator.create(CheckNamedStep) catch @panic("OOM");
self.* = .{
.step = Step.init(.{
.id = .custom,
.name = "check-named",
.owner = owner,
.makeFn = make,
}),
.exercise = exercise,
.output = output,
};
return self;
}
fn make(step: *Step, _: *std.Progress.Node) !void {
const b = step.owner;
const self = @fieldParentPtr(CheckNamedStep, "step", step);
// Allow up to 1 MB of output capture.
const max_bytes = 1 * 1024 * 1024;
const path = self.output.getPath(b);
const raw_output = try fs.cwd().readFileAlloc(b.allocator, path, max_bytes);
const actual = try root.trimLines(b.allocator, raw_output);
const expect = self.exercise.output;
if (!mem.eql(u8, expect, actual)) {
return step.fail("{s}: expected to see \"{s}\", found \"{s}\"", .{
self.exercise.main_file, expect, actual,
});
}
}
};
/// Checks the output of `zig build` or `zig build -Dn=1 start`.
const CheckStep = struct {
step: Step,