first commit
This commit is contained in:
commit
1354db6c39
90 files changed
+13123
No files matched your search
@@ -0,0 +1,260 @@
|
||||
#!/usr/bin/env bats
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (C) 2026 Bryan Joshua Pedini
|
||||
|
||||
# The statefile: creation, format, sorting, dedupe, comments, atomic writes, trust/untrust/refresh.
|
||||
|
||||
load test_helper
|
||||
|
||||
setup() { common_setup; }
|
||||
|
||||
@test "trust creates the directory (0755) and the file (0644) with the header" {
|
||||
run skup trust su-dummy-c
|
||||
assert_success
|
||||
assert_output 'trusted su-dummy-c'
|
||||
[[ $(stat -c %a "$STATE") == 755 ]]
|
||||
[[ $(stat -c %a "$STATE_FILE") == 644 ]]
|
||||
run cat "$STATE_FILE"
|
||||
assert_line --index 0 "$HEADER"
|
||||
assert_line --index 1 --regexp "^apt${T}su-dummy-c${T}user${T}${DATE_RE}\$"
|
||||
[[ ${#lines[@]} -eq 2 ]]
|
||||
}
|
||||
|
||||
@test "intermediate directories are created too" {
|
||||
run skup --state-dir="$BATS_TEST_TMPDIR/a/b/c" trust su-dummy-c
|
||||
assert_success
|
||||
[[ -f $BATS_TEST_TMPDIR/a/b/c/trusted.tsv ]]
|
||||
[[ $(stat -c %a "$BATS_TEST_TMPDIR/a/b/c") == 755 ]]
|
||||
}
|
||||
|
||||
@test "trust writes the user row and dep:<root> rows for the installed closure" {
|
||||
run skup trust su-dummy-a
|
||||
assert_success
|
||||
assert_output 'trusted su-dummy-a (+1 dependency: su-dummy-b)'
|
||||
run cat "$STATE_FILE"
|
||||
assert_line --index 1 --regexp "^apt${T}su-dummy-a${T}user${T}${DATE_RE}\$"
|
||||
assert_line --index 2 --regexp "^apt${T}su-dummy-b${T}dep:su-dummy-a${T}${DATE_RE}\$"
|
||||
log_has "dpkg-query -W -f \${db:Status-Abbrev}\\t\${Package}\\t\${Pre-Depends}\\t\${Depends}\\t\${Provides}\\n"
|
||||
}
|
||||
|
||||
@test "the apt closure follows Provides (virtual packages) and alternatives" {
|
||||
run skup trust su-dummy-w
|
||||
assert_success
|
||||
assert_output 'trusted su-dummy-w (+1 dependency: su-dummy-v)'
|
||||
}
|
||||
|
||||
@test "the apt closure walks real chains through virtual packages (base-files -> awk -> mawk)" {
|
||||
run skup trust base-files
|
||||
assert_success
|
||||
assert_output 'trusted base-files (+4 dependencies: gcc-12-base libc6 libgcc-s1 mawk)'
|
||||
run cut -f2,3 "$STATE_FILE"
|
||||
assert_line "mawk${T}dep:base-files"
|
||||
assert_line "gcc-12-base${T}dep:base-files"
|
||||
}
|
||||
|
||||
@test "a not-installed (rc) package is not part of a closure" {
|
||||
run skup trust su-dummy-f
|
||||
assert_success
|
||||
assert_output 'trusted su-dummy-f'
|
||||
}
|
||||
|
||||
@test "records are sorted on (backend, package); comments are kept in order" {
|
||||
write_state '# my own note' \
|
||||
"pacman${T}zsh${T}user${T}2026-01-01T00:00:00Z" \
|
||||
"apt${T}zsh${T}user${T}2026-01-01T00:00:00Z" \
|
||||
'# second note' \
|
||||
"apt${T}foo-bar${T}user${T}2026-01-01T00:00:00Z" \
|
||||
"apt${T}foo${T}dep:zsh${T}2026-01-01T00:00:00Z" \
|
||||
"dnf${T}abc${T}user${T}2026-01-01T00:00:00Z"
|
||||
run skup trust su-dummy-c
|
||||
assert_success
|
||||
run cat "$STATE_FILE"
|
||||
assert_line --index 0 '# my own note'
|
||||
assert_line --index 1 '# second note'
|
||||
assert_line --index 2 "apt${T}foo${T}dep:zsh${T}2026-01-01T00:00:00Z"
|
||||
assert_line --index 3 "apt${T}foo-bar${T}user${T}2026-01-01T00:00:00Z"
|
||||
assert_line --index 4 --regexp "^apt${T}su-dummy-c${T}user${T}"
|
||||
assert_line --index 5 "apt${T}zsh${T}user${T}2026-01-01T00:00:00Z"
|
||||
assert_line --index 6 "dnf${T}abc${T}user${T}2026-01-01T00:00:00Z"
|
||||
assert_line --index 7 "pacman${T}zsh${T}user${T}2026-01-01T00:00:00Z"
|
||||
[[ ${#lines[@]} -eq 8 ]]
|
||||
}
|
||||
|
||||
@test "duplicates are collapsed: a user row wins over a dep row, else the first one" {
|
||||
write_state "$HEADER" \
|
||||
"apt${T}b${T}dep:x${T}2026-01-01T00:00:00Z" \
|
||||
"apt${T}b${T}user${T}2026-02-02T00:00:00Z" \
|
||||
"apt${T}c${T}dep:x${T}2026-03-03T00:00:00Z" \
|
||||
"apt${T}c${T}dep:y${T}2026-04-04T00:00:00Z"
|
||||
run skup trust su-dummy-c
|
||||
assert_success
|
||||
run cat "$STATE_FILE"
|
||||
assert_line "apt${T}b${T}user${T}2026-02-02T00:00:00Z"
|
||||
assert_line "apt${T}c${T}dep:x${T}2026-03-03T00:00:00Z"
|
||||
refute_line --partial 'dep:y'
|
||||
refute_line --partial "b${T}dep:x"
|
||||
}
|
||||
|
||||
@test "a user row is never downgraded to dep:" {
|
||||
run skup trust su-dummy-b
|
||||
run skup trust su-dummy-a
|
||||
assert_success
|
||||
assert_output 'trusted su-dummy-a (its installed dependency was already trusted)'
|
||||
run cut -f2,3 "$STATE_FILE"
|
||||
assert_line "su-dummy-b${T}user"
|
||||
refute_line --partial 'dep:'
|
||||
}
|
||||
|
||||
@test "an existing dep: row is upgraded to user, keeping one row" {
|
||||
run skup trust su-dummy-a
|
||||
run skup trust su-dummy-b
|
||||
assert_success
|
||||
assert_output 'trusted su-dummy-b'
|
||||
run cut -f2,3 "$STATE_FILE"
|
||||
assert_line "su-dummy-b${T}user"
|
||||
[[ $(grep -c su-dummy-b "$STATE_FILE") -eq 1 ]]
|
||||
}
|
||||
|
||||
@test "trusting an already trusted package reports it and changes nothing" {
|
||||
run skup trust su-dummy-c
|
||||
before=$(cat "$STATE_FILE")
|
||||
run skup trust su-dummy-c
|
||||
assert_success
|
||||
assert_output 'su-dummy-c was already trusted'
|
||||
[[ $(cat "$STATE_FILE") == "$before" ]]
|
||||
}
|
||||
|
||||
@test "malformed lines are kept verbatim, with a warning" {
|
||||
write_state "$HEADER" "apt${T}only-two" "apt${T}x${T}weird${T}2026-01-01T00:00:00Z"
|
||||
run skup trust su-dummy-c
|
||||
assert_success
|
||||
assert_output --partial "trusted.tsv:2: malformed line kept verbatim: apt${T}only-two"
|
||||
assert_output --partial "trusted.tsv:3: malformed line kept verbatim"
|
||||
run cat "$STATE_FILE"
|
||||
assert_line "apt${T}only-two"
|
||||
assert_line "apt${T}x${T}weird${T}2026-01-01T00:00:00Z"
|
||||
}
|
||||
|
||||
@test "blank lines and CRLF line ends are tolerated" {
|
||||
printf '%s\r\n\r\n%s\r\n\n' "$HEADER" "apt${T}su-dummy-a${T}user${T}2026-01-01T00:00:00Z" >"$BATS_TEST_TMPDIR/st"
|
||||
mkdir -p "$STATE"
|
||||
mv "$BATS_TEST_TMPDIR/st" "$STATE_FILE"
|
||||
run skup list --no-refresh
|
||||
assert_line '3 upgradable, 1 trusted (hidden, use --all to show), 2 to review:'
|
||||
}
|
||||
|
||||
@test "writes are atomic (new file renamed over the old one) and leave no temp file" {
|
||||
run skup trust su-dummy-c
|
||||
ino1=$(stat -c %i "$STATE_FILE")
|
||||
run skup trust su-dummy-a
|
||||
assert_success
|
||||
ino2=$(stat -c %i "$STATE_FILE")
|
||||
[[ $ino1 != "$ino2" ]]
|
||||
run ls -A "$STATE"
|
||||
assert_output "$(printf '%s\n' trusted.lock trusted.tsv)"
|
||||
}
|
||||
|
||||
@test "a failing write leaves the old file intact" {
|
||||
run skup trust su-dummy-c
|
||||
before=$(cat "$STATE_FILE")
|
||||
# make the state dir read-only (root ignores directory modes: skip then)
|
||||
chmod 0555 "$STATE"
|
||||
if [[ -w $STATE ]]; then
|
||||
chmod 0755 "$STATE"
|
||||
skip "running as root: directory modes are not enforced"
|
||||
fi
|
||||
run skup trust su-dummy-a
|
||||
chmod 0755 "$STATE"
|
||||
assert_failure 1
|
||||
[[ $(cat "$STATE_FILE") == "$before" ]]
|
||||
}
|
||||
|
||||
@test "untrust removes the row for PKG and every dep:PKG row, nothing else" {
|
||||
write_state "$HEADER" \
|
||||
"apt${T}su-dummy-a${T}user${T}2026-01-01T00:00:00Z" \
|
||||
"apt${T}su-dummy-b${T}dep:su-dummy-a${T}2026-01-01T00:00:00Z" \
|
||||
"apt${T}x${T}dep:y${T}2026-01-01T00:00:00Z" \
|
||||
"apt${T}su-dummy-c${T}user${T}2026-01-01T00:00:00Z" \
|
||||
"pacman${T}su-dummy-a${T}user${T}2026-01-01T00:00:00Z" \
|
||||
"pacman${T}su-dummy-b${T}dep:su-dummy-a${T}2026-01-01T00:00:00Z"
|
||||
run skup untrust su-dummy-a
|
||||
assert_success
|
||||
assert_output 'untrusted su-dummy-a (2 rows removed)'
|
||||
run cat "$STATE_FILE"
|
||||
assert_output "$(printf '%s\n' "$HEADER" \
|
||||
"apt${T}su-dummy-c${T}user${T}2026-01-01T00:00:00Z" \
|
||||
"apt${T}x${T}dep:y${T}2026-01-01T00:00:00Z" \
|
||||
"pacman${T}su-dummy-a${T}user${T}2026-01-01T00:00:00Z" \
|
||||
"pacman${T}su-dummy-b${T}dep:su-dummy-a${T}2026-01-01T00:00:00Z")"
|
||||
}
|
||||
|
||||
@test "untrust of a dependency-only package removes its dep row" {
|
||||
run skup trust su-dummy-a
|
||||
run skup untrust su-dummy-b
|
||||
assert_success
|
||||
assert_output 'untrusted su-dummy-b (1 row removed)'
|
||||
run cut -f2 "$STATE_FILE"
|
||||
assert_line su-dummy-a
|
||||
refute_line su-dummy-b
|
||||
}
|
||||
|
||||
@test "untrust of a package that is not trusted warns, exit 0" {
|
||||
run skup untrust nope
|
||||
assert_success
|
||||
assert_output --partial 'warning: nope is not trusted (no row for backend apt)'
|
||||
[[ ! -e $STATE_FILE ]]
|
||||
}
|
||||
|
||||
@test "refresh recomputes closures: adds missing rows, drops stale ones, keeps the rest" {
|
||||
write_state "$HEADER" \
|
||||
"apt${T}su-dummy-a${T}user${T}2026-01-01T00:00:00Z" \
|
||||
"apt${T}su-dummy-b${T}dep:su-dummy-a${T}2026-01-01T00:00:00Z" \
|
||||
"apt${T}stale${T}dep:su-dummy-a${T}2026-01-01T00:00:00Z" \
|
||||
"apt${T}orphan${T}dep:gone${T}2026-01-01T00:00:00Z" \
|
||||
"apt${T}su-dummy-w${T}user${T}2026-01-01T00:00:00Z" \
|
||||
"pacman${T}stale${T}dep:su-dummy-a${T}2026-01-01T00:00:00Z"
|
||||
run skup refresh
|
||||
assert_success
|
||||
assert_output 'refreshed the dependency closures of 2 trusted roots: 1 added, 2 removed'
|
||||
run cat "$STATE_FILE"
|
||||
assert_line "apt${T}su-dummy-b${T}dep:su-dummy-a${T}2026-01-01T00:00:00Z"
|
||||
assert_line --regexp "^apt${T}su-dummy-v${T}dep:su-dummy-w${T}${DATE_RE}\$"
|
||||
refute_line --partial "apt${T}stale"
|
||||
refute_line --partial 'orphan'
|
||||
assert_line "pacman${T}stale${T}dep:su-dummy-a${T}2026-01-01T00:00:00Z"
|
||||
assert_line "apt${T}su-dummy-a${T}user${T}2026-01-01T00:00:00Z"
|
||||
}
|
||||
|
||||
@test "refresh with no user roots for this backend does nothing" {
|
||||
write_state "$HEADER" "pacman${T}x${T}user${T}2026-01-01T00:00:00Z"
|
||||
run skup refresh
|
||||
assert_success
|
||||
assert_output 'No trusted root packages for backend apt: nothing to refresh.'
|
||||
}
|
||||
|
||||
@test "trusted prints the statefile verbatim" {
|
||||
write_state "$HEADER" '# note' "apt${T}x${T}user${T}2026-01-01T00:00:00Z"
|
||||
run skup trusted
|
||||
assert_success
|
||||
assert_output "$(printf '%s\n' "$HEADER" '# note' "apt${T}x${T}user${T}2026-01-01T00:00:00Z")"
|
||||
}
|
||||
|
||||
@test "trusted without a statefile says so, exit 0" {
|
||||
run skup trusted
|
||||
assert_success
|
||||
assert_output "No trusted packages yet ($STATE_FILE does not exist)."
|
||||
}
|
||||
|
||||
@test "only rows of the current backend hide packages" {
|
||||
write_state "$HEADER" "pacman${T}su-dummy-a${T}user${T}2026-01-01T00:00:00Z"
|
||||
run skup list --no-refresh
|
||||
assert_line '3 upgradable, 0 trusted (hidden, use --all to show), 3 to review:'
|
||||
assert_line --regexp '^ \[1\] su-dummy-a '
|
||||
}
|
||||
|
||||
@test "the reason does not matter for hiding: dep rows hide too" {
|
||||
write_state "$HEADER" "apt${T}su-dummy-b${T}dep:whatever${T}2026-01-01T00:00:00Z"
|
||||
run skup list --no-refresh
|
||||
assert_line '3 upgradable, 1 trusted (hidden, use --all to show), 2 to review:'
|
||||
refute_output --partial 'su-dummy-b'
|
||||
}
|
||||
Reference in new issue
Block a user