Files
small-scripts/tests/test-gen-secret.sh
Paul O'Reilly c470867039 Remove URL-unsafe characters from gen-secret charset
Remove ^, +, ~, :, @ from the allowed charset. The ^ character breaks
SQLAlchemy DATABASE_URL parsing, + becomes space in URL query strings,
: and @ are URL delimiters. The remaining charset (A-Za-z0-9._-) is
safe in URLs, database connection strings, YAML, JSON, and shell
without any encoding.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 21:29:08 +13:00

121 lines
2.7 KiB
Bash
Executable File

#!/usr/bin/env bash
set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
GEN_SECRET="$SCRIPT_DIR/scripts/gen-secret"
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
pass=0
fail=0
assert_eq() {
local desc="$1" expected="$2" actual="$3"
if [[ "$expected" == "$actual" ]]; then
echo -e "${GREEN}PASS${NC}: $desc"
((pass++))
else
echo -e "${RED}FAIL${NC}: $desc"
echo " expected: $expected"
echo " actual: $actual"
((fail++))
fi
}
assert_match() {
local desc="$1" pattern="$2" actual="$3"
if [[ "$actual" =~ $pattern ]]; then
echo -e "${GREEN}PASS${NC}: $desc"
((pass++))
else
echo -e "${RED}FAIL${NC}: $desc"
echo " pattern: $pattern"
echo " actual: $actual"
((fail++))
fi
}
assert_exit() {
local desc="$1" expected="$2" actual="$3"
if [[ "$expected" -eq "$actual" ]]; then
echo -e "${GREEN}PASS${NC}: $desc"
((pass++))
else
echo -e "${RED}FAIL${NC}: $desc"
echo " expected exit: $expected"
echo " actual exit: $actual"
((fail++))
fi
}
echo "=== gen-secret tests ==="
echo
# --- Dryrun tests ---
out=$("$GEN_SECRET" --dryrun 2>&1)
assert_eq "dryrun default length" \
'[dryrun] Would generate a 32-character secret from charset: [A-Za-z0-9._\-]' \
"$out"
out=$("$GEN_SECRET" -n 16 2>&1)
assert_eq "dryrun custom length" \
'[dryrun] Would generate a 16-character secret from charset: [A-Za-z0-9._\-]' \
"$out"
# --- Help ---
out=$("$GEN_SECRET" --help 2>&1)
rc=$?
assert_exit "help exits 0" 0 "$rc"
assert_match "help mentions LENGTH" "LENGTH" "$out"
# --- Default generation ---
out=$("$GEN_SECRET" 2>&1)
rc=$?
assert_exit "default exits 0" 0 "$rc"
assert_eq "default length is 32" 32 "${#out}"
assert_match "default uses safe charset" '^[A-Za-z0-9._-]+$' "$out"
# --- Custom length ---
out=$("$GEN_SECRET" 64 2>&1)
assert_eq "custom length 64" 64 "${#out}"
out=$("$GEN_SECRET" 1 2>&1)
assert_eq "minimum length 1" 1 "${#out}"
# --- Error cases ---
out=$("$GEN_SECRET" 0 2>&1)
rc=$?
assert_exit "length 0 exits 1" 1 "$rc"
assert_match "length 0 error message" "positive integer" "$out"
out=$("$GEN_SECRET" -5 2>&1)
rc=$?
assert_exit "negative length exits 1" 1 "$rc"
out=$("$GEN_SECRET" abc 2>&1)
rc=$?
assert_exit "non-numeric exits 1" 1 "$rc"
assert_match "non-numeric error message" "positive integer" "$out"
out=$("$GEN_SECRET" 10 20 2>&1)
rc=$?
assert_exit "too many args exits 1" 1 "$rc"
assert_match "too many args error message" "Too many arguments" "$out"
# --- Summary ---
echo
total=$((pass + fail))
echo -e "Results: ${GREEN}${pass}${NC}/${total} passed"
if [[ $fail -gt 0 ]]; then
echo -e "${RED}${fail} test(s) failed${NC}"
exit 1
fi