Luigit
repositories / termux-janitor

termux-janitor

Interactive cleanup assistant for Termux: transparent, safe, confirmed disk reclamation.

owned by admin

spec/fixtures/cli/usage.md

Raw
Rendered preview

Rejected command lines

Fixture: fixture-cli-usage@1

Given

The built termux-janitor executable starts with standard input disconnected from a terminal and an empty isolated working directory.

Each listed invocation violates the command-line grammar: an unregistered option, a short option, an operand before or after the option terminator, a repeated option, an option that must appear alone combined with another option, a missing or empty option value, or a value attached with =.

Three invocations exercise the registered diagnostic echo bound with arguments one byte below it, exactly at it, and one byte above it. Two more carry a control byte and an invalid UTF-8 byte.

When

The executable starts once per listed invocation.

Required invariants

  • INV-USAGE-STATUS: Every listed invocation exits with the registered usage status.
  • INV-USAGE-DIAGNOSTIC: Every listed invocation writes one bounded stderr diagnostic that names the executable, states one concise reason, quotes the rejected argument, and repeats the usage summary.
  • INV-USAGE-ECHO-BOUND: The quoted argument never exceeds the registered diagnostic argument bound, and an argument beyond that bound is marked truncated.
  • INV-USAGE-ECHO-SANITIZED: The quoted argument equals the expected sanitized text, and the diagnostic contains no control byte and no invalid UTF-8 sequence.

Forbidden effects

  • NO-USAGE-STDOUT: Standard output remains empty for every listed invocation.
  • NO-USAGE-FIXTURE-MUTATION: The isolated working directory remains empty.

Instrumentation

try fixture.given_program("termux-janitor");
try fixture.given_standard_input(.ignored);
try fixture.given_working_directory(.empty);
try fixture.given_rejected_invocation(&.{"--nope"}, "--nope");
try fixture.given_rejected_invocation(&.{"--nope=1"}, "--nope");
try fixture.given_rejected_invocation(&.{"-h"}, "-h");
try fixture.given_rejected_invocation(&.{"cleanup"}, "cleanup");
try fixture.given_rejected_invocation(&.{ "--", "cleanup" }, "cleanup");
try fixture.given_rejected_invocation(&.{ "--ascii", "--ascii" }, "--ascii");
try fixture.given_rejected_invocation(&.{ "--dry-run", "--dry-run" }, "--dry-run");
try fixture.given_rejected_invocation(&.{ "--help", "--version" }, "--help");
try fixture.given_rejected_invocation(&.{ "--help", "--ascii" }, "--help");
try fixture.given_rejected_invocation(&.{"--config"}, "--config");
try fixture.given_rejected_invocation(&.{ "--config", "" }, "--config");
try fixture.given_rejected_invocation(&.{"--config=/tmp/x"}, "--config");
try fixture.given_rejected_invocation(&.{"--a\x01b"}, "--a<01>b");
try fixture.given_rejected_invocation(&.{"--a\xffb"}, "--a?b");
try fixture.given_rejected_invocation(&.{"--" ++ "a" ** 61}, "--" ++ "a" ** 61);
try fixture.given_rejected_invocation(&.{"--" ++ "a" ** 62}, "--" ++ "a" ** 62);
try fixture.given_rejected_invocation(&.{"--" ++ "a" ** 63}, "--" ++ "a" ** 62 ++ "...");
try fixture.when_run_each();
try fixture.then_inv_usage_status();
try fixture.then_inv_usage_diagnostic();
try fixture.then_inv_usage_echo_bound();
try fixture.then_inv_usage_echo_sanitized();
try fixture.forbid_no_usage_stdout();
try fixture.forbid_no_usage_fixture_mutation();

Variations

Accepted invocations belong to the help and version fixtures. Configuration-file errors, terminal requirements, and cancellation are separate scenarios owned by their own fixtures.

Limitations

This fixture observes exit status, both streams, and writes beneath its isolated working directory. It does not trace system calls and therefore cannot prove that no other path was read.

# Rejected command lines

**Fixture:** `fixture-cli-usage@1`

## Given

The built `termux-janitor` executable starts with standard input disconnected from a terminal and an
empty isolated working directory.

Each listed invocation violates the command-line grammar: an unregistered option, a short option, an
operand before or after the option terminator, a repeated option, an option that must appear alone
combined with another option, a missing or empty option value, or a value attached with `=`.

Three invocations exercise the registered diagnostic echo bound with arguments one byte below it,
exactly at it, and one byte above it. Two more carry a control byte and an invalid UTF-8 byte.

## When

The executable starts once per listed invocation.

## Required invariants

- **`INV-USAGE-STATUS`:** Every listed invocation exits with the registered usage status.
- **`INV-USAGE-DIAGNOSTIC`:**
  Every listed invocation writes one bounded stderr diagnostic that names the executable, states one
  concise reason, quotes the rejected argument, and repeats the usage summary.
- **`INV-USAGE-ECHO-BOUND`:**
  The quoted argument never exceeds the registered diagnostic argument bound, and an argument beyond
  that bound is marked truncated.
- **`INV-USAGE-ECHO-SANITIZED`:**
  The quoted argument equals the expected sanitized text, and the diagnostic contains no control
  byte and no invalid UTF-8 sequence.

## Forbidden effects

- **`NO-USAGE-STDOUT`:** Standard output remains empty for every listed invocation.
- **`NO-USAGE-FIXTURE-MUTATION`:**
  The isolated working directory remains empty.

## Instrumentation

```zig tj-test
try fixture.given_program("termux-janitor");
try fixture.given_standard_input(.ignored);
try fixture.given_working_directory(.empty);
try fixture.given_rejected_invocation(&.{"--nope"}, "--nope");
try fixture.given_rejected_invocation(&.{"--nope=1"}, "--nope");
try fixture.given_rejected_invocation(&.{"-h"}, "-h");
try fixture.given_rejected_invocation(&.{"cleanup"}, "cleanup");
try fixture.given_rejected_invocation(&.{ "--", "cleanup" }, "cleanup");
try fixture.given_rejected_invocation(&.{ "--ascii", "--ascii" }, "--ascii");
try fixture.given_rejected_invocation(&.{ "--dry-run", "--dry-run" }, "--dry-run");
try fixture.given_rejected_invocation(&.{ "--help", "--version" }, "--help");
try fixture.given_rejected_invocation(&.{ "--help", "--ascii" }, "--help");
try fixture.given_rejected_invocation(&.{"--config"}, "--config");
try fixture.given_rejected_invocation(&.{ "--config", "" }, "--config");
try fixture.given_rejected_invocation(&.{"--config=/tmp/x"}, "--config");
try fixture.given_rejected_invocation(&.{"--a\x01b"}, "--a<01>b");
try fixture.given_rejected_invocation(&.{"--a\xffb"}, "--a?b");
try fixture.given_rejected_invocation(&.{"--" ++ "a" ** 61}, "--" ++ "a" ** 61);
try fixture.given_rejected_invocation(&.{"--" ++ "a" ** 62}, "--" ++ "a" ** 62);
try fixture.given_rejected_invocation(&.{"--" ++ "a" ** 63}, "--" ++ "a" ** 62 ++ "...");
try fixture.when_run_each();
try fixture.then_inv_usage_status();
try fixture.then_inv_usage_diagnostic();
try fixture.then_inv_usage_echo_bound();
try fixture.then_inv_usage_echo_sanitized();
try fixture.forbid_no_usage_stdout();
try fixture.forbid_no_usage_fixture_mutation();
```

## Variations

Accepted invocations belong to the help and version fixtures. Configuration-file errors, terminal
requirements, and cancellation are separate scenarios owned by their own fixtures.

## Limitations

This fixture observes exit status, both streams, and writes beneath its isolated working directory.
It does not trace system calls and therefore cannot prove that no other path was read.