#!/usr/bin/env bats # SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2026 Bryan Joshua Pedini # CLI parsing and exit codes. load test_helper setup() { common_setup; } @test "--help prints the usage and exits 0" { run skup --help assert_success assert_line 'usage: skeptical-updater [options] [command]' assert_line --partial 'refresh recompute dependency closures for every '"'user'"' root' assert_line --partial '--dry-run print native commands instead of running mutating ones' assert_line --partial 'exit status: 0 ok, 1 usage/backend error, 2 aborted' [[ -z $(cat "$FAKE_LOG") ]] } @test "-h is --help, even after a command" { run skup list -h assert_success assert_line 'usage: skeptical-updater [options] [command]' } @test "--version and -V print the version" { run skup --version assert_success assert_output 'skeptical-updater 0.1.0' run skup -V assert_output 'skeptical-updater 0.1.0' } @test "an unknown option is a usage error (exit 1)" { run skup --frobnicate assert_failure 1 assert_line 'skeptical-updater: error: unknown option: --frobnicate' assert_line "Try 'skeptical-updater --help'." } @test "an unknown command is a usage error (exit 1)" { run skup upgrade assert_failure 1 assert_line 'skeptical-updater: error: unknown command: upgrade' } @test "list, trusted and refresh take no arguments" { for c in list trusted refresh; do run skup "$c" extra assert_failure 1 assert_output --partial "'$c' takes no arguments" done } @test "the interactive mode takes no arguments either" { run skup '' foo assert_failure 1 } @test "trust and untrust need at least one package" { run skup trust assert_failure 1 assert_output --partial "'trust' needs at least one package name" run skup untrust assert_failure 1 assert_output --partial "'untrust' needs at least one package name" } @test "info and show need exactly one package" { run skup info assert_failure 1 assert_output --partial "'info' needs exactly one package name" run skup show a b assert_failure 1 assert_output --partial "'show' needs exactly one package name" } @test "invalid package names are rejected before anything runs" { # shellcheck disable=SC2016 # literal $(id) on purpose for bad in '-rf' 'a b' 'foo;rm' '../x' 'x/y' '$(id)'; do run skup trust -- "$bad" assert_failure 1 assert_output --partial "invalid package name: '$bad'" done [[ -z $(cat "$FAKE_LOG") ]] [[ ! -e $STATE ]] } @test "valid package names with + . : ~ @ _ are accepted" { run skup --backend=apt trust 'libstdc++6' 'libc6:i386' 'g++-12' 'a.b~c' 'x_y@z' assert_success run cut -f2 "$STATE_FILE" assert_output "$(printf '%s\n' "$HEADER" a.b~c g++-12 libc6:i386 libstdc++6 x_y@z)" } @test "--backend must name a known backend" { run skup --backend=portage list assert_failure 1 assert_output --partial "unknown backend 'portage' (expected apt, dnf, pacman or zypper)" } @test "--backend and --state-dir without a value are usage errors" { run skup list --backend assert_failure 1 assert_output --partial '--backend needs a value' run skup list --state-dir assert_failure 1 assert_output --partial '--state-dir needs a value' run skup list --state-dir= assert_failure 1 assert_output --partial 'empty state directory' } @test "options may follow the command; --backend NAME as two words" { run skup list --backend apt --no-refresh assert_success assert_line --index 0 'Backend: apt (Debian GNU/Linux 12 (bookworm))' log_lacks '^apt-get update' } @test "--state-dir overrides SKEPTICAL_UPDATER_STATE_DIR" { run skup --state-dir="$BATS_TEST_TMPDIR/other" trust su-dummy-c assert_success [[ -f $BATS_TEST_TMPDIR/other/trusted.tsv ]] [[ ! -e $STATE ]] } @test "-- ends option parsing" { run skup info -- --all assert_failure 1 assert_output --partial "invalid package name: '--all'" } @test "no ANSI colours when stdout is not a terminal" { run skup list --no-refresh assert_success refute_output --partial $'\e[' } @test "--no-color and NO_COLOR are accepted" { run skup --no-color list --no-refresh assert_success NO_COLOR=1 run skup list --no-refresh assert_success refute_output --partial $'\e[' }