mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-25 17:24:07 +00:00
e19a10396e
run_zypper_local_repo extracted six lines of the zypper branch of otherpkgs and evaluated each one in turn. The branch it measures is an if/else: the repository is deleted only when the refresh fails. Evaluating the lines separately ran the delete every time, so the test showed that zypper sd is reachable and never that a repository which refreshes is kept. The helper now evaluates the whole branch, from the #use zypper comment to the apt branch that follows, with pmatch lifted from the same file. The success case asserts rc=0 and no zypper sd; the failure case keeps its delete assertion. Flipping the refresh test in otherpkgs to "if [ $? -ne 0 ]" turns both cases red. The same mutation left the previous helper green, because it never evaluated that line. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
453 lines
15 KiB
Bash
453 lines
15 KiB
Bash
#!/usr/bin/env bats
|
|
|
|
load 'helpers/shell_source'
|
|
|
|
setup()
|
|
{
|
|
OTHERPKGS="$(repo_path 'xCAT/postscripts/otherpkgs')"
|
|
[ -r "$OTHERPKGS" ] || skip "$OTHERPKGS is required"
|
|
LOGGER_LOG="${BATS_TEST_TMPDIR}/logger.log"
|
|
CMD_LOG="${BATS_TEST_TMPDIR}/cmd.log"
|
|
: >"$LOGGER_LOG"
|
|
: >"$CMD_LOG"
|
|
export OTHERPKGS LOGGER_LOG CMD_LOG
|
|
}
|
|
|
|
# logger writes one line per message it sends. A message that carries newlines stays on one
|
|
# line, with the newlines shown as "\n", so the line count is the message count.
|
|
shadow_logger()
|
|
{
|
|
logger()
|
|
{
|
|
local msg=""
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
-p | -t) shift 2 ;;
|
|
*)
|
|
msg="$*"
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
if [ -n "$msg" ]; then
|
|
printf '%s\n' "${msg//$'\n'/\\n}" >>"$LOGGER_LOG"
|
|
else
|
|
local line
|
|
while IFS= read -r line; do
|
|
printf '%s\n' "$line" >>"$LOGGER_LOG"
|
|
done
|
|
fi
|
|
}
|
|
}
|
|
|
|
logger_call()
|
|
{
|
|
sed -n "${1}p" "$LOGGER_LOG"
|
|
}
|
|
|
|
logger_calls()
|
|
{
|
|
wc -l <"$LOGGER_LOG" | tr -d ' '
|
|
}
|
|
|
|
cmd_call()
|
|
{
|
|
sed -n "${1}p" "$CMD_LOG"
|
|
}
|
|
|
|
# A package manager that answers with PKG_STATUS and prints a three line transaction.
|
|
shadow_pkg_manager()
|
|
{
|
|
fake_pkg()
|
|
{
|
|
printf '%s\n' "$*" >>"$CMD_LOG"
|
|
printf -- '--> Running transaction check\n'
|
|
printf 'Installed: foo-1.0\n'
|
|
printf 'Error: nothing provides bar\n'
|
|
return "${PKG_STATUS:-0}"
|
|
}
|
|
zypper() { fake_pkg "$@"; }
|
|
apt-get() { fake_pkg "$@"; }
|
|
xcat_apt_get() { fake_pkg "$@"; }
|
|
apt_get_update_if_repos_changed() { :; }
|
|
}
|
|
|
|
# otherpkgs_block ANCHOR START [NTH TOTAL]
|
|
# Answers with the shell if-block that starts at the first line after the anchor. NTH and TOTAL
|
|
# go to extract_shell_if_block, which counts START in the text from the anchor to the end of the
|
|
# file. Name a START that occurs once where one exists; pass NTH and TOTAL where the candidate
|
|
# lines are the same text.
|
|
otherpkgs_block()
|
|
{
|
|
local tail="${BATS_TEST_TMPDIR}/tail-$$"
|
|
awk -v anchor="$1" 'index($0, anchor) { copy = 1 } copy { print }' "$OTHERPKGS" >"$tail"
|
|
extract_shell_if_block "$tail" "$2" "$3" "$4"
|
|
}
|
|
|
|
run_upgrade_block()
|
|
{
|
|
local block
|
|
# The upgrade block opens with the same line as the yum branch of the preremove, the install
|
|
# and the postremove blocks. The upgrade block is the first of the four.
|
|
block="$(otherpkgs_block '#now update the existing rpms' 'if [ $hasyum -eq 1 ]; then' 1 4)" || return 99
|
|
local hasyum=0 haszypper=0 hasapt=0
|
|
eval "$1=1"
|
|
local envlist="" yumcmd=fake_pkg VERBOSE= log_label=otherpkgs RETURNVAL=0 REPOFILE=/dev/null result=""
|
|
shadow_logger
|
|
shadow_pkg_manager
|
|
eval "$block"
|
|
printf 'RETURNVAL=%s\n' "$RETURNVAL"
|
|
}
|
|
|
|
run_repo_preremove_block()
|
|
{
|
|
local block
|
|
block="$(otherpkgs_block '#Now we have parsed the input' 'if [ "$repo_pkgs_preremove" != "" ]; then')" || return 99
|
|
local hasyum=0 haszypper=0 hasapt=0
|
|
eval "$1=1"
|
|
local envlist="" yumcmd=fake_pkg VERBOSE= log_label=otherpkgs RETURNVAL=0 REPOFILE=/dev/null result=""
|
|
local repo_pkgs_preremove="oldfoo"
|
|
shadow_logger
|
|
shadow_pkg_manager
|
|
eval "$block"
|
|
printf 'RETURNVAL=%s\n' "$RETURNVAL"
|
|
}
|
|
|
|
run_plain_preremove_block()
|
|
{
|
|
local block
|
|
block="$(otherpkgs_block '#Now we have parsed the input' 'if [ "$plain_pkgs_preremove" != "" ]; then')" || return 99
|
|
local envlist="" VERBOSE= log_label=otherpkgs RETURNVAL=0 result=""
|
|
local sremovecommand=fake_pkg plain_pkgs_preremove="oldfoo"
|
|
shadow_logger
|
|
shadow_pkg_manager
|
|
eval "$block"
|
|
printf 'RETURNVAL=%s\n' "$RETURNVAL"
|
|
}
|
|
|
|
@test "otherpkgs sends the package manager transaction to syslog one line per message" {
|
|
run run_upgrade_block hasyum
|
|
[ "$status" -eq 0 ]
|
|
[ "$(logger_calls)" -eq 3 ]
|
|
[ "$(logger_call 1)" = "--> Running transaction check" ]
|
|
[ "$(logger_call 2)" = "Installed: foo-1.0" ]
|
|
[ "$(logger_call 3)" = "Error: nothing provides bar" ]
|
|
}
|
|
|
|
@test "the zypper and apt upgrade paths also send one message per output line" {
|
|
run run_upgrade_block haszypper
|
|
[ "$status" -eq 0 ]
|
|
[ "$(logger_calls)" -eq 3 ]
|
|
|
|
: >"$LOGGER_LOG"
|
|
run run_upgrade_block hasapt
|
|
[ "$status" -eq 0 ]
|
|
[ "$(logger_calls)" -eq 3 ]
|
|
}
|
|
|
|
@test "the remove paths also send one message per output line" {
|
|
local manager
|
|
for manager in hasyum haszypper hasapt; do
|
|
: >"$LOGGER_LOG"
|
|
run run_repo_preremove_block "$manager"
|
|
[ "$status" -eq 0 ]
|
|
[ "$(logger_calls)" -eq 3 ]
|
|
done
|
|
|
|
: >"$LOGGER_LOG"
|
|
run run_plain_preremove_block
|
|
[ "$status" -eq 0 ]
|
|
[ "$(logger_calls)" -eq 3 ]
|
|
}
|
|
|
|
run_install_block()
|
|
{
|
|
local block
|
|
block="$(otherpkgs_block '#installation using yum/dnf or zypper' 'if [ "$repo_pkgs" != "" ]; then')" || return 99
|
|
local hasyum=0 haszypper=0 hasapt=0
|
|
eval "$1=1"
|
|
local envlist="" yumcmd=fake_pkg VERBOSE= log_label=otherpkgs RETURNVAL=0 REPOFILE=/dev/null result=""
|
|
local repo_pkgs="foo bar"
|
|
shadow_logger
|
|
shadow_pkg_manager
|
|
eval "$block"
|
|
printf 'RETURNVAL=%s\n' "$RETURNVAL"
|
|
}
|
|
|
|
run_repo_postremove_block()
|
|
{
|
|
local block
|
|
block="$(otherpkgs_block '#remove more rpms if specified with' 'if [ "$repo_pkgs_postremove" != "" ]; then')" || return 99
|
|
local hasyum=0 haszypper=0 hasapt=0
|
|
eval "$1=1"
|
|
local envlist="" yumcmd=fake_pkg VERBOSE= log_label=otherpkgs RETURNVAL=0 REPOFILE=/dev/null result=""
|
|
local repo_pkgs_postremove="oldfoo"
|
|
shadow_logger
|
|
shadow_pkg_manager
|
|
eval "$block"
|
|
printf 'RETURNVAL=%s\n' "$RETURNVAL"
|
|
}
|
|
|
|
@test "a failed package install is not logged as installed" {
|
|
local manager
|
|
for manager in hasyum haszypper hasapt; do
|
|
: >"$LOGGER_LOG"
|
|
PKG_STATUS=1 run run_install_block "$manager"
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *'RETURNVAL=1'* ]]
|
|
refute_grep -q 'foo bar installed\.' "$LOGGER_LOG"
|
|
grep -q 'failed\.' "$LOGGER_LOG"
|
|
done
|
|
}
|
|
|
|
@test "a successful package install is logged as installed" {
|
|
local manager
|
|
for manager in hasyum haszypper hasapt; do
|
|
: >"$LOGGER_LOG"
|
|
run run_install_block "$manager"
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *'RETURNVAL=0'* ]]
|
|
grep -q 'foo bar installed\.' "$LOGGER_LOG"
|
|
refute_grep -q 'failed\.' "$LOGGER_LOG"
|
|
done
|
|
}
|
|
|
|
@test "a failed package removal is not logged as removed" {
|
|
local manager
|
|
for manager in hasyum haszypper hasapt; do
|
|
: >"$LOGGER_LOG"
|
|
PKG_STATUS=1 run run_repo_postremove_block "$manager"
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *'RETURNVAL=1'* ]]
|
|
refute_grep -q 'oldfoo removed\.' "$LOGGER_LOG"
|
|
done
|
|
|
|
: >"$LOGGER_LOG"
|
|
run run_repo_postremove_block hasyum
|
|
[ "$status" -eq 0 ]
|
|
grep -q 'oldfoo removed\.' "$LOGGER_LOG"
|
|
}
|
|
|
|
@test "the url repository guard is false when OTHERPKGDIR has no http entry" {
|
|
local guard cond
|
|
guard="$(extract_first_matching_line "$OTHERPKGS" 'OTHERPKGDIR_INTERNET" *[]] *; *then')" || return 99
|
|
cond="${guard#*if }"
|
|
cond="${cond%%;then*}"
|
|
|
|
OTHERPKGDIR_INTERNET=""
|
|
run eval "$cond"
|
|
[ "$status" -ne 0 ]
|
|
|
|
OTHERPKGDIR_INTERNET="http://192.0.2.1/repo,"
|
|
run eval "$cond"
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
# Runs the OTHERPKGDIR split and then the url repository block, and leaves the repository
|
|
# files the url block wrote under BATS_TEST_TMPDIR.
|
|
run_url_repo_block()
|
|
{
|
|
local split url_block
|
|
split="$(extract_shell_if_block "$OTHERPKGS" 'if [ -n "$OTHERPKGDIR" ]; then')" || return 99
|
|
url_block="$(otherpkgs_block '#add repo for url repos in otherpkgdir' 'if [ -n "$OTHERPKGDIR_INTERNET" ];then')" || return 99
|
|
local OTHERPKGDIR="$1" OTHERPKGDIR_INTERNET="" OTHERPKGDIR_LOCAL=""
|
|
local hasyum="${2:-1}" haszypper=0 hasapt="${3:-0}"
|
|
local repo_base="$BATS_TEST_TMPDIR" urlrepoindex=0
|
|
eval "$split"
|
|
eval "$url_block"
|
|
printf 'urlrepoindex=%s\n' "$urlrepoindex"
|
|
}
|
|
|
|
@test "the generated yum baseurl carries no trailing space" {
|
|
run run_url_repo_block 'http://192.0.2.1/repo-a,/install/post/otherpkgs,http://192.0.2.1/repo-b'
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *'urlrepoindex=2'* ]]
|
|
[ "$(grep '^baseurl=' "${BATS_TEST_TMPDIR}/xCAT-otherpkgs0.repo")" = "baseurl=http://192.0.2.1/repo-a" ]
|
|
[ "$(grep '^baseurl=' "${BATS_TEST_TMPDIR}/xCAT-otherpkgs1.repo")" = "baseurl=http://192.0.2.1/repo-b" ]
|
|
}
|
|
|
|
@test "the generated apt source carries no trailing space" {
|
|
run run_url_repo_block 'http://192.0.2.1/repo-a' 0 1
|
|
[ "$status" -eq 0 ]
|
|
[ "$(cat "${BATS_TEST_TMPDIR}/xCAT-otherpkgs0.list")" = "deb http://192.0.2.1/repo-a" ]
|
|
}
|
|
|
|
# Drives the zypper branch that adds the local otherpkgs repository, refreshes it and deletes
|
|
# it again when the refresh fails. The branch is evaluated whole, so the success case shows
|
|
# that a repository which refreshes is kept.
|
|
run_zypper_local_repo()
|
|
{
|
|
local urlrepoindex="$1" index="$2"
|
|
local repo_base="$BATS_TEST_TMPDIR" mounted=1 whole_path=/install/post/otherpkgs/sles15/x86_64
|
|
local OSVER=sles15 VERBOSE= localrepoindex REPOFILE rc=1 result="" path=/pkgdir
|
|
zypper()
|
|
{
|
|
printf '%s\n' "$*" >>"$CMD_LOG"
|
|
case "$1" in
|
|
ar) sed -n '1s/^\[\(.*\)\]$/added=\1/p' "$3" >>"$CMD_LOG" ;;
|
|
esac
|
|
return "${ZYPPER_STATUS:-0}"
|
|
}
|
|
array_set_element() { :; }
|
|
eval "$(extract_shell_function "$OTHERPKGS" pmatch)" || return 99
|
|
|
|
# The three lines that name the repository are straight-line assignments, so each one is
|
|
# taken on its own. The zypper branch that follows is a branch: it is taken whole, because
|
|
# what is measured is which arm runs. Keep the extraction apart from the eval, so a failing
|
|
# zypper does not read as a failed extraction.
|
|
local pattern line
|
|
for pattern in \
|
|
'localrepoindex=' \
|
|
'REPOFILE="[$]repo_base/xCAT-otherpkgs[$]localrepoindex.repo"' \
|
|
'echo "[[]xcat-otherpkgs[$]localrepoindex[]]"'; do
|
|
line="$(extract_first_matching_line "$OTHERPKGS" "$pattern")" || return 99
|
|
eval "$line"
|
|
done
|
|
|
|
# The range ends on the apt branch that follows; its two lines are dropped.
|
|
local branch
|
|
branch="$(extract_line_range "$OTHERPKGS" '#use zypper' '#use apt')" || return 99
|
|
branch="$(printf '%s\n' "$branch" | head -n -2)"
|
|
case "$branch" in
|
|
*'zypper sd xcat-otherpkgs'*) ;;
|
|
*) return 99 ;;
|
|
esac
|
|
eval "$branch"
|
|
printf 'rc=%s\n' "$rc"
|
|
return 0
|
|
}
|
|
|
|
@test "zypper keeps the otherpkgs repository it added when the refresh succeeds" {
|
|
run run_zypper_local_repo 2 0
|
|
[ "$status" -eq 0 ]
|
|
[ "$output" = "rc=0" ]
|
|
[ "$(cmd_call 2)" = "added=xcat-otherpkgs2" ]
|
|
[ "$(cmd_call 3)" = "--non-interactive refresh xcat-otherpkgs2" ]
|
|
refute_grep -q '^sd ' "$CMD_LOG"
|
|
}
|
|
|
|
@test "zypper deletes the otherpkgs repository it added when the refresh fails" {
|
|
ZYPPER_STATUS=1 run run_zypper_local_repo 2 0
|
|
[ "$status" -eq 0 ]
|
|
[ "$output" = "rc=1" ]
|
|
[ "$(cmd_call 2)" = "added=xcat-otherpkgs2" ]
|
|
[ "$(cmd_call 4)" = "sd xcat-otherpkgs2" ]
|
|
}
|
|
|
|
run_sdk_block()
|
|
{
|
|
local block
|
|
block="$(otherpkgs_block '#adds SDK repository' 'if [ "$SDKDIR" != "" ]; then')" || return 99
|
|
local SDKDIR=/install/sles15/x86_64/sdk1 OSVER=sles15 mounted=1 VERBOSE= log_label=otherpkgs result=""
|
|
local NFSSERVER=192.0.2.1 HTTPPORT=80
|
|
eval "$(extract_shell_function "$OTHERPKGS" pmatch)" || return 99
|
|
shadow_logger
|
|
zypper()
|
|
{
|
|
printf 'zypper failed\n'
|
|
return 1
|
|
}
|
|
eval "$block"
|
|
return 0
|
|
}
|
|
|
|
@test "a failed SDK repository add is logged with the repository name" {
|
|
run run_sdk_block
|
|
[ "$status" -eq 0 ]
|
|
grep -q 'xCAT-sles15-sdk1' "$LOGGER_LOG"
|
|
}
|
|
|
|
# Drives the package list split and the two diagnostic lines that follow it. The range ends on
|
|
# the "for" line that starts the package loop, and that line is dropped: the loop is not part of
|
|
# what is measured.
|
|
run_pkglist_diagnostics()
|
|
{
|
|
local range
|
|
range="$(extract_line_range "$OTHERPKGS" 'pkgsarray=' '^[[:space:]]*for x in')" || return 99
|
|
local pkglist="foo bar" hasyum=1 yumcmd=dnf hasapt=0 haszypper=0 oifs=$IFS
|
|
eval "$(printf '%s\n' "$range" | sed '$d')"
|
|
}
|
|
|
|
@test "the package list diagnostics print nothing when VERBOSE is not set" {
|
|
VERBOSE= run run_pkglist_diagnostics
|
|
[ "$status" -eq 0 ]
|
|
[ -z "$output" ]
|
|
}
|
|
|
|
@test "the package list diagnostics print the list and the package manager under VERBOSE" {
|
|
VERBOSE=1 run run_pkglist_diagnostics
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *'pkgsarray: foo bar, 2'* ]]
|
|
[[ "$output" == *'yum/dnf: 1 (dnf), apt: 0, zypper: 0'* ]]
|
|
}
|
|
|
|
run_plain_install_block()
|
|
{
|
|
local block
|
|
block="$(otherpkgs_block '#Handle the rest with rpm' 'if [ "$plain_pkgs" != "" -a -n "$OTHERPKGDIR" ]; then')" || return 99
|
|
local envlist="" VERBOSE= log_label=otherpkgs RETURNVAL=0 result=""
|
|
local supdatecommand=fake_pkg plain_pkgs="foo bar" mounted=1
|
|
local OTHERPKGDIR="$BATS_TEST_TMPDIR"
|
|
shadow_logger
|
|
shadow_pkg_manager
|
|
# The block changes directory. A subshell keeps the test in its own directory.
|
|
(
|
|
eval "$block"
|
|
printf 'RETURNVAL=%s\n' "$RETURNVAL"
|
|
)
|
|
}
|
|
|
|
run_plain_postremove_block()
|
|
{
|
|
local block
|
|
block="$(otherpkgs_block '#remove more rpms if specified with' 'if [ "$plain_pkgs_postremove" != "" ]; then')" || return 99
|
|
local envlist="" VERBOSE= log_label=otherpkgs RETURNVAL=0 result=""
|
|
local sremovecommand=fake_pkg plain_pkgs_postremove="oldfoo"
|
|
shadow_logger
|
|
shadow_pkg_manager
|
|
eval "$block"
|
|
printf 'RETURNVAL=%s\n' "$RETURNVAL"
|
|
}
|
|
|
|
@test "a failed rpm fallback install is logged as failed" {
|
|
PKG_STATUS=1 run run_plain_install_block
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *'RETURNVAL=1'* ]]
|
|
refute_grep -q 'foo bar installed\.' "$LOGGER_LOG"
|
|
grep -q 'foo bar failed\.' "$LOGGER_LOG"
|
|
}
|
|
|
|
@test "a successful rpm fallback install is logged as installed" {
|
|
run run_plain_install_block
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *'RETURNVAL=0'* ]]
|
|
grep -q 'foo bar installed\.' "$LOGGER_LOG"
|
|
refute_grep -q 'failed\.' "$LOGGER_LOG"
|
|
}
|
|
|
|
@test "a failed package removal is logged as failed" {
|
|
local manager
|
|
for manager in hasyum haszypper hasapt; do
|
|
: >"$LOGGER_LOG"
|
|
PKG_STATUS=1 run run_repo_postremove_block "$manager"
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *'RETURNVAL=1'* ]]
|
|
grep -q 'oldfoo failed\.' "$LOGGER_LOG"
|
|
done
|
|
|
|
: >"$LOGGER_LOG"
|
|
PKG_STATUS=1 run run_plain_postremove_block
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *'RETURNVAL=1'* ]]
|
|
refute_grep -q 'oldfoo removed\.' "$LOGGER_LOG"
|
|
grep -q 'oldfoo failed\.' "$LOGGER_LOG"
|
|
}
|
|
|
|
@test "a successful package removal is logged as removed only" {
|
|
run run_plain_postremove_block
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *'RETURNVAL=0'* ]]
|
|
grep -q 'oldfoo removed\.' "$LOGGER_LOG"
|
|
refute_grep -q 'failed\.' "$LOGGER_LOG"
|
|
}
|