repositories / termux-janitor
termux-janitor
Interactive cleanup assistant for Termux: transparent, safe, confirmed disk reclamation.
owned by admin
tests/fixtures/cli_version.zig
Rawconst std = @import("std");
const spec_data = @import("spec_data");
pub const StandardInput = enum { ignored };
pub const WorkingDirectory = enum { empty };
/// The version line the executable is required to write.
const expected_stdout = spec_data.cli_executable ++ " " ++ spec_data.artifact_version ++ "\n";
pub const Fixture = struct {
temporary: std.testing.TmpDir,
executable: ?[:0]u8 = null,
result: ?std.process.RunResult = null,
argv_ready: bool = false,
stdin_ignored: bool = false,
pub fn init() !Fixture {
return .{ .temporary = std.testing.tmpDir(.{ .iterate = true }) };
}
pub fn deinit(fixture: *Fixture) void {
if (fixture.result) |result| {
std.testing.allocator.free(result.stdout);
std.testing.allocator.free(result.stderr);
}
if (fixture.executable) |executable| std.testing.allocator.free(executable);
fixture.temporary.cleanup();
fixture.* = undefined;
}
pub fn given_program(fixture: *Fixture, executable_name: []const u8) !void {
std.debug.assert(fixture.executable == null);
try std.testing.expectEqualStrings(spec_data.cli_executable, executable_name);
fixture.executable = try std.Io.Dir.cwd().realPathFileAlloc(
std.testing.io,
"zig-out/bin/termux-janitor",
std.testing.allocator,
);
}
pub fn given_standard_input(fixture: *Fixture, mode: StandardInput) !void {
std.debug.assert(!fixture.stdin_ignored);
try std.testing.expectEqual(StandardInput.ignored, mode);
fixture.stdin_ignored = true;
}
pub fn given_working_directory(fixture: *Fixture, state: WorkingDirectory) !void {
try std.testing.expectEqual(WorkingDirectory.empty, state);
var entries = fixture.temporary.dir.iterate();
try std.testing.expect(try entries.next(std.testing.io) == null);
}
pub fn given_arguments(fixture: *Fixture, arguments: []const []const u8) !void {
std.debug.assert(!fixture.argv_ready);
try std.testing.expectEqual(@as(usize, 1), arguments.len);
try std.testing.expectEqualStrings(spec_data.cliOption(.version).spelling, arguments[0]);
fixture.argv_ready = true;
}
pub fn when_run(fixture: *Fixture) !void {
const executable = fixture.executable orelse return error.ExecutableNotConfigured;
if (!fixture.argv_ready) return error.ArgumentsNotConfigured;
if (!fixture.stdin_ignored) return error.StandardInputNotConfigured;
const arguments = [_][]const u8{ executable, spec_data.cliOption(.version).spelling };
fixture.result = try std.process.run(std.testing.allocator, std.testing.io, .{
.argv = &arguments,
.stderr_limit = .limited(@intCast(spec_data.limit_value.captured_stderr_bytes)),
.stdout_limit = .limited(@intCast(spec_data.limit_value.captured_stdout_bytes)),
.reserve_amount = expected_stdout.len,
.cwd = .{ .dir = fixture.temporary.dir },
.environ_map = null,
.expand_arg0 = .no_expand,
.progress_node = .none,
.create_no_window = true,
.disable_aslr = false,
.timeout = .{ .duration = .{
.raw = .fromSeconds(@intCast(spec_data.limit_value.test_process_timeout)),
.clock = .awake,
} },
});
}
pub fn then_inv_version_success(fixture: *Fixture) !void {
switch (fixture.resultRef().term) {
.exited => |status| try std.testing.expectEqual(
spec_data.cliExitCode(.success),
status,
),
else => return error.UnexpectedTermination,
}
}
pub fn then_inv_version_stdout(fixture: *Fixture) !void {
try std.testing.expectEqualStrings(expected_stdout, fixture.resultRef().stdout);
}
pub fn then_inv_version_charset(fixture: *Fixture) !void {
const stdout = fixture.resultRef().stdout;
const prefix = spec_data.cli_executable ++ " ";
try std.testing.expect(std.mem.startsWith(u8, stdout, prefix));
try std.testing.expect(std.mem.endsWith(u8, stdout, "\n"));
const version = stdout[prefix.len .. stdout.len - 1];
try std.testing.expect(version.len > 0);
for (version) |byte| {
const permitted = std.ascii.isAlphanumeric(byte) or
byte == '.' or byte == '-' or byte == '_' or byte == '+';
try std.testing.expect(permitted);
}
}
pub fn forbid_no_version_stderr(fixture: *Fixture) !void {
try std.testing.expectEqualStrings("", fixture.resultRef().stderr);
}
pub fn forbid_no_version_fixture_mutation(fixture: *Fixture) !void {
var entries = fixture.temporary.dir.iterate();
try std.testing.expect(try entries.next(std.testing.io) == null);
}
fn resultRef(fixture: *Fixture) *const std.process.RunResult {
if (fixture.result) |*result| return result;
@panic("process has not run");
}
};