# 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.