update
This commit is contained in:
Executable
+83
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env bash
|
||||
set -u -o pipefail
|
||||
|
||||
TEST_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
declare -a shell_files=()
|
||||
declare -a test_files=()
|
||||
failures=0
|
||||
required_command=''
|
||||
|
||||
if (( BASH_VERSINFO[0] < 4 ||
|
||||
(BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] < 3) )); then
|
||||
printf 'TA-ProxMenu tests require Bash 4.3 or newer; found %s.\n' \
|
||||
"$BASH_VERSION" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for required_command in git python3; do
|
||||
if ! command -v "$required_command" >/dev/null 2>&1; then
|
||||
printf 'TA-ProxMenu tests require %s.\n' "$required_command" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
while IFS= read -r -d '' file; do
|
||||
shell_files+=("$file")
|
||||
done < <(
|
||||
find "$TEST_ROOT" -type f \( -name '*.sh' -o -name '*.inc' \) \
|
||||
-not -path '*/.git/*' -print0 |
|
||||
sort -z
|
||||
)
|
||||
|
||||
printf 'Bash syntax\n'
|
||||
for file in "${shell_files[@]}"; do
|
||||
if ! bash -n "$file"; then
|
||||
(( failures += 1 ))
|
||||
fi
|
||||
done
|
||||
(( failures == 0 )) && printf ' PASS: %d files\n' "${#shell_files[@]}"
|
||||
|
||||
printf '\nGit whitespace\n'
|
||||
if git -C "$TEST_ROOT" diff --check &&
|
||||
git -C "$TEST_ROOT" diff --cached --check; then
|
||||
printf ' PASS\n'
|
||||
else
|
||||
(( failures += 1 ))
|
||||
fi
|
||||
|
||||
printf '\nShellCheck\n'
|
||||
if command -v shellcheck >/dev/null 2>&1; then
|
||||
# These rules cannot follow TAPM's runtime-sourced defaults/colors or
|
||||
# functions invoked indirectly through traps and menu dispatch.
|
||||
if shellcheck -x -e SC1091,SC2034,SC2154,SC2317 "${shell_files[@]}"; then
|
||||
printf ' PASS\n'
|
||||
else
|
||||
(( failures += 1 ))
|
||||
fi
|
||||
else
|
||||
printf ' SKIP: shellcheck is not installed\n'
|
||||
fi
|
||||
|
||||
while IFS= read -r -d '' file; do
|
||||
test_files+=("$file")
|
||||
done < <(
|
||||
find "${TEST_ROOT}/tests" -maxdepth 1 -type f -name 'test-*.sh' \
|
||||
-print0 | sort -z
|
||||
)
|
||||
|
||||
printf '\nBehavior tests\n'
|
||||
for file in "${test_files[@]}"; do
|
||||
printf ' %-30s ' "${file##*/}"
|
||||
if bash "$file"; then
|
||||
:
|
||||
else
|
||||
(( failures += 1 ))
|
||||
fi
|
||||
done
|
||||
|
||||
printf '\n'
|
||||
if (( failures > 0 )); then
|
||||
printf 'FAILED: %d check group(s) failed.\n' "$failures" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf 'All TA-ProxMenu checks passed.\n'
|
||||
Executable
+70
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env bash
|
||||
set -u -o pipefail
|
||||
|
||||
TEST_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
source "${TEST_ROOT}/tests/testlib.sh"
|
||||
source "${TEST_ROOT}/inc/evacuate-proxmox-node.sh"
|
||||
|
||||
set_routing_fixture() {
|
||||
MIGRATION_NODES=(node2 node3)
|
||||
NODE_STORAGE_CACHE=()
|
||||
NODE_STORAGE_CACHE[node2]='shared-a,shared-b'
|
||||
NODE_STORAGE_CACHE[node3]='shared-a,shared-c'
|
||||
PREFERRED_TARGET=node2
|
||||
}
|
||||
|
||||
set_routing_fixture
|
||||
assert_success "preferred destination is eligible" \
|
||||
choose_destination shared-a '' 0
|
||||
assert_equal node2 "$CHOSEN_DESTINATION" "preferred destination selected"
|
||||
|
||||
set_routing_fixture
|
||||
assert_success "affinity fallback is available" \
|
||||
choose_destination shared-a node3 1
|
||||
assert_equal node3 "$CHOSEN_DESTINATION" "affinity destination selected"
|
||||
assert_equal "routed to satisfy HA node-affinity preference" "$CHOSEN_NOTE" \
|
||||
"affinity routing explanation"
|
||||
|
||||
set_routing_fixture
|
||||
assert_success "storage fallback is available" \
|
||||
choose_destination shared-c '' 0
|
||||
assert_equal node3 "$CHOSEN_DESTINATION" "storage-compatible destination selected"
|
||||
|
||||
set_routing_fixture
|
||||
assert_failure "strict affinity blocks two noncompliant destinations" \
|
||||
choose_destination shared-a node4 1
|
||||
|
||||
set_routing_fixture
|
||||
MIGRATION_NODES=(node2)
|
||||
assert_success "sole eligible node overrides affinity" \
|
||||
choose_destination shared-a node4 1
|
||||
assert_equal node2 "$CHOSEN_DESTINATION" "sole eligible destination selected"
|
||||
assert_equal "only eligible node; HA node-affinity preference overridden" \
|
||||
"$CHOSEN_NOTE" "sole-node override explanation"
|
||||
|
||||
TEST_RULES_FILE="$(mktemp /tmp/tapm-ha-rules.XXXXXX)"
|
||||
cleanup_evacuation_tests() {
|
||||
if [[ "$TEST_RULES_FILE" == /tmp/tapm-ha-rules.* ]]; then
|
||||
rm -f -- "$TEST_RULES_FILE"
|
||||
fi
|
||||
}
|
||||
trap cleanup_evacuation_tests EXIT
|
||||
|
||||
printf '%s\n' \
|
||||
'node-affinity: preferred-nodes' \
|
||||
' resources vm:210,ct:211' \
|
||||
' nodes node3:20,node2:10' \
|
||||
' strict 1' >"$TEST_RULES_FILE"
|
||||
HA_RULES_FILE="$TEST_RULES_FILE"
|
||||
|
||||
assert_equal $'preferred-nodes\x1f1\x1fnode3,node2' \
|
||||
"$(get_guest_node_affinity qemu 210)" \
|
||||
"QEMU affinity parsing"
|
||||
assert_equal $'preferred-nodes\x1f1\x1fnode3,node2' \
|
||||
"$(get_guest_node_affinity lxc 211)" \
|
||||
"LXC affinity parsing"
|
||||
assert_equal $'none\x1f0\x1f' \
|
||||
"$(get_guest_node_affinity qemu 999)" \
|
||||
"guest without affinity"
|
||||
|
||||
finish_tests
|
||||
Executable
+79
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env bash
|
||||
set -u -o pipefail
|
||||
|
||||
TEST_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
source "${TEST_ROOT}/tests/testlib.sh"
|
||||
source "${TEST_ROOT}/inc/git-update.inc"
|
||||
|
||||
TEST_TEMP_DIR="$(mktemp -d /tmp/tapm-git-tests.XXXXXX)"
|
||||
TEST_REPOSITORY="${TEST_TEMP_DIR}/repository"
|
||||
|
||||
cleanup_git_tests() {
|
||||
if [[ "$TEST_TEMP_DIR" == /tmp/tapm-git-tests.* && -d "$TEST_TEMP_DIR" ]]; then
|
||||
rm -rf -- "$TEST_TEMP_DIR"
|
||||
fi
|
||||
}
|
||||
trap cleanup_git_tests EXIT
|
||||
|
||||
git init -q -b main "$TEST_REPOSITORY"
|
||||
git -C "$TEST_REPOSITORY" config user.name 'TA-ProxMenu Tests'
|
||||
git -C "$TEST_REPOSITORY" config user.email 'tapm-tests@example.invalid'
|
||||
|
||||
printf 'first\n' >"${TEST_REPOSITORY}/fixture.txt"
|
||||
git -C "$TEST_REPOSITORY" add fixture.txt
|
||||
git -C "$TEST_REPOSITORY" commit -q -m first
|
||||
commit_a="$(git -C "$TEST_REPOSITORY" rev-parse HEAD)"
|
||||
|
||||
printf 'second\n' >>"${TEST_REPOSITORY}/fixture.txt"
|
||||
git -C "$TEST_REPOSITORY" commit -q -am second
|
||||
commit_b="$(git -C "$TEST_REPOSITORY" rev-parse HEAD)"
|
||||
|
||||
git -C "$TEST_REPOSITORY" switch -q --detach "$commit_a"
|
||||
printf 'alternate\n' >"${TEST_REPOSITORY}/alternate.txt"
|
||||
git -C "$TEST_REPOSITORY" add alternate.txt
|
||||
git -C "$TEST_REPOSITORY" commit -q -m alternate
|
||||
commit_c="$(git -C "$TEST_REPOSITORY" rev-parse HEAD)"
|
||||
|
||||
git -C "$TEST_REPOSITORY" update-ref refs/tapm/a "$commit_a"
|
||||
git -C "$TEST_REPOSITORY" update-ref refs/tapm/b "$commit_b"
|
||||
git -C "$TEST_REPOSITORY" update-ref refs/tapm/c "$commit_c"
|
||||
|
||||
assert_equal current \
|
||||
"$(TAPM_GIT_RELATION "$TEST_REPOSITORY" refs/tapm/a refs/tapm/a)" \
|
||||
"equal commits"
|
||||
assert_equal behind \
|
||||
"$(TAPM_GIT_RELATION "$TEST_REPOSITORY" refs/tapm/a refs/tapm/b)" \
|
||||
"local commit behind remote"
|
||||
assert_equal ahead \
|
||||
"$(TAPM_GIT_RELATION "$TEST_REPOSITORY" refs/tapm/b refs/tapm/a)" \
|
||||
"local commit ahead of remote"
|
||||
assert_equal diverged \
|
||||
"$(TAPM_GIT_RELATION "$TEST_REPOSITORY" refs/tapm/b refs/tapm/c)" \
|
||||
"diverged commits"
|
||||
|
||||
git -C "$TEST_REPOSITORY" switch -q -C main "$commit_a"
|
||||
git -C "$TEST_REPOSITORY" update-ref refs/remotes/origin/main "$commit_a"
|
||||
assert_equal current \
|
||||
"$(TAPM_GIT_BRANCH_STATE "$TEST_REPOSITORY" main)" \
|
||||
"clean current branch"
|
||||
|
||||
printf 'untracked\n' >"${TEST_REPOSITORY}/untracked.txt"
|
||||
assert_equal dirty \
|
||||
"$(TAPM_GIT_BRANCH_STATE "$TEST_REPOSITORY" main)" \
|
||||
"dirty working tree"
|
||||
rm -f -- "${TEST_REPOSITORY}/untracked.txt"
|
||||
|
||||
git -C "$TEST_REPOSITORY" switch -q -c feature
|
||||
assert_equal wrong-branch \
|
||||
"$(TAPM_GIT_BRANCH_STATE "$TEST_REPOSITORY" main)" \
|
||||
"wrong checked-out branch"
|
||||
|
||||
git -C "$TEST_REPOSITORY" switch -q main
|
||||
git -C "$TEST_REPOSITORY" update-ref refs/remotes/origin/main "$commit_b"
|
||||
assert_success "fast-forward merge" \
|
||||
TAPM_GIT_FAST_FORWARD "$TEST_REPOSITORY" main
|
||||
assert_equal "$commit_b" \
|
||||
"$(git -C "$TEST_REPOSITORY" rev-parse HEAD)" \
|
||||
"fast-forward destination"
|
||||
|
||||
finish_tests
|
||||
Executable
+58
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env bash
|
||||
set -u -o pipefail
|
||||
|
||||
TEST_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
source "${TEST_ROOT}/tests/testlib.sh"
|
||||
source "${TEST_ROOT}/inc/deploy-iso-nfs-lxc.sh"
|
||||
|
||||
assert_success "valid storage ID" TAPM_ISO_NFS_VALID_ID PVE-Shared-Storage
|
||||
assert_failure "storage ID cannot start with a number" TAPM_ISO_NFS_VALID_ID 1-storage
|
||||
assert_failure "storage ID rejects spaces" TAPM_ISO_NFS_VALID_ID 'shared storage'
|
||||
|
||||
assert_success "valid CTID" TAPM_ISO_NFS_VALID_CTID 210
|
||||
assert_failure "reserved two-digit CTID" TAPM_ISO_NFS_VALID_CTID 99
|
||||
assert_failure "CTID rejects text" TAPM_ISO_NFS_VALID_CTID ct210
|
||||
|
||||
assert_success "valid hostname" TAPM_ISO_NFS_VALID_HOSTNAME PVE-Shared-Storage
|
||||
assert_success "valid FQDN hostname" TAPM_ISO_NFS_VALID_HOSTNAME iso-nfs.example.net
|
||||
assert_failure "hostname rejects spaces" TAPM_ISO_NFS_VALID_HOSTNAME 'ISO Storage'
|
||||
|
||||
assert_success "valid IPv4 CIDR" TAPM_ISO_NFS_VALID_IPV4_CIDR 10.10.2.45/16
|
||||
assert_failure "IPv4 octet out of range" TAPM_ISO_NFS_VALID_IPV4_CIDR 10.10.2.256/24
|
||||
assert_failure "IPv4 prefix out of range" TAPM_ISO_NFS_VALID_IPV4_CIDR 10.10.2.45/33
|
||||
assert_failure "IPv4 prefix required" TAPM_ISO_NFS_VALID_IPV4_CIDR 10.10.2.45
|
||||
|
||||
pvesm() {
|
||||
[[ "${1:-}" == status ]] || return 1
|
||||
printf '%s\n' \
|
||||
'Name Type Status Total Used Available %' \
|
||||
'local-lvm lvmthin active 100 10 90 10%' \
|
||||
'iSCSI-Datastore1 lvm active 200 20 180 10%' \
|
||||
'iSCSI-Datastore1-2 lvm active 200 20 180 10%' \
|
||||
'offline-store dir inactive 100 0 100 0%'
|
||||
}
|
||||
|
||||
SELECT_MENU() {
|
||||
local title="$1"
|
||||
|
||||
assert_equal "Root filesystem storage" "$title" "storage menu title"
|
||||
assert_equal \
|
||||
'iSCSI-Datastore1-2 (lvm) — default' \
|
||||
"${labels[0]}" \
|
||||
"default storage placed first"
|
||||
assert_equal 3 "${#labels[@]}" "only active storages offered"
|
||||
MENU_SELECTION="${values[0]}"
|
||||
}
|
||||
|
||||
test_default_storage_selection() {
|
||||
local selected_storage=''
|
||||
|
||||
TAPM_ISO_NFS_SELECT_STORAGE selected_storage \
|
||||
"Root filesystem storage" "iSCSI-Datastore1-2" || return 1
|
||||
assert_equal iSCSI-Datastore1-2 "$selected_storage" \
|
||||
"pressing Enter retains default storage"
|
||||
}
|
||||
|
||||
assert_success "default storage menu selection" test_default_storage_selection
|
||||
|
||||
finish_tests
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
set -u -o pipefail
|
||||
|
||||
TEST_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
source "${TEST_ROOT}/tests/testlib.sh"
|
||||
source "${TEST_ROOT}/inc/virtio-helpers.inc"
|
||||
|
||||
assert_equal virtio-win.iso \
|
||||
"$(TAPM_VIRTIO_FILENAME_FROM_URL \
|
||||
'https://fedorapeople.org/stable/virtio-win.iso?download=1')" \
|
||||
"stable source filename"
|
||||
assert_equal virtio-win-0.1.285.iso \
|
||||
"$(TAPM_VIRTIO_FILENAME_FROM_URL \
|
||||
'https://fedorapeople.org/archive/virtio-win-0.1.285.iso')" \
|
||||
"versioned source filename"
|
||||
assert_failure "unexpected source filename rejected" \
|
||||
TAPM_VIRTIO_FILENAME_FROM_URL \
|
||||
'https://example.invalid/virtio-win-latest.iso'
|
||||
|
||||
assert_equal virtio-win-latest-0.1.285.iso \
|
||||
"$(TAPM_VIRTIO_LABELED_FILENAME virtio-win-0.1.285.iso latest)" \
|
||||
"stable local filename"
|
||||
assert_equal virtio-win-server-2016-0.1.240.iso \
|
||||
"$(TAPM_VIRTIO_LABELED_FILENAME \
|
||||
virtio-win-0.1.240.iso server-2016)" \
|
||||
"Server 2016 local filename"
|
||||
assert_equal virtio-win-server-2008r2-0.1.172.iso \
|
||||
"$(TAPM_VIRTIO_LABELED_FILENAME \
|
||||
virtio-win-0.1.172.iso server-2008r2)" \
|
||||
"Server 2008 R2 local filename"
|
||||
assert_failure "unsafe local label rejected" \
|
||||
TAPM_VIRTIO_LABELED_FILENAME virtio-win-0.1.285.iso '../latest'
|
||||
|
||||
finish_tests
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
TEST_ASSERTIONS=0
|
||||
TEST_FAILURES=0
|
||||
|
||||
test_fail() {
|
||||
printf 'FAIL: %s\n' "$1" >&2
|
||||
(( TEST_FAILURES += 1 ))
|
||||
}
|
||||
|
||||
assert_equal() {
|
||||
local expected="$1"
|
||||
local actual="$2"
|
||||
local label="$3"
|
||||
|
||||
(( TEST_ASSERTIONS += 1 ))
|
||||
if [[ "$actual" != "$expected" ]]; then
|
||||
test_fail "${label}: expected '${expected}', received '${actual}'"
|
||||
fi
|
||||
}
|
||||
|
||||
assert_success() {
|
||||
local label="$1"
|
||||
shift
|
||||
|
||||
(( TEST_ASSERTIONS += 1 ))
|
||||
"$@" || test_fail "${label}: expected success"
|
||||
}
|
||||
|
||||
assert_failure() {
|
||||
local label="$1"
|
||||
shift
|
||||
|
||||
(( TEST_ASSERTIONS += 1 ))
|
||||
if "$@"; then
|
||||
test_fail "${label}: expected failure"
|
||||
fi
|
||||
}
|
||||
|
||||
finish_tests() {
|
||||
if (( TEST_FAILURES > 0 )); then
|
||||
printf '%d assertion(s), %d failure(s)\n' \
|
||||
"$TEST_ASSERTIONS" "$TEST_FAILURES" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf '%d assertion(s) passed\n' "$TEST_ASSERTIONS"
|
||||
}
|
||||
Reference in New Issue
Block a user