Files
Aether/tests/install_current_release_link_test.sh
T

194 lines
6.8 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
set -euo pipefail
REPO_ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd -P)"
# shellcheck source=../install.sh
source "${REPO_ROOT}/install.sh"
TEST_ROOT="$(mktemp -d)/aether installer fixtures"
mkdir -p "${TEST_ROOT}"
cleanup_test_root() {
rm -rf -- "$(dirname -- "${TEST_ROOT}")"
}
trap cleanup_test_root EXIT
fail_test() {
echo "FAIL: $*" >&2
exit 1
}
assert_link_target() {
local link="$1"
local expected="$2"
[[ -L "${link}" ]] || fail_test "${link} is not a symbolic link"
[[ "$(readlink "${link}")" == "${expected}" ]] \
|| fail_test "${link} does not point to ${expected}"
}
assert_switch_rejected() {
local release_dir="$1"
local current_link="$2"
if (switch_current_release_link "${release_dir}" "${current_link}"); then
fail_test "unsafe current-link fixture was accepted: ${current_link}"
fi
}
test_initial_switch() {
local fixture="${TEST_ROOT}/initial"
local release_dir="${fixture}/release new"
local current_link="${fixture}/current"
mkdir -p "${release_dir}"
switch_current_release_link "${release_dir}" "${current_link}"
assert_link_target "${current_link}" "${release_dir}"
[[ ! -e "${current_link}.new" && ! -L "${current_link}.new" ]] \
|| fail_test "temporary link remained after initial switch"
}
test_existing_link_switch() {
local fixture="${TEST_ROOT}/existing link"
local old_release="${fixture}/release old"
local new_release="${fixture}/release new"
local current_link="${fixture}/current"
mkdir -p "${old_release}" "${new_release}"
ln -s -- "${old_release}" "${current_link}"
switch_current_release_link "${new_release}" "${current_link}"
assert_link_target "${current_link}" "${new_release}"
[[ ! -e "${old_release}/current.new" && ! -L "${old_release}/current.new" ]] \
|| fail_test "temporary link was moved into the previous release directory"
}
test_dangling_links_are_replaced() {
local fixture="${TEST_ROOT}/dangling links"
local release_dir="${fixture}/release new"
local current_link="${fixture}/current"
mkdir -p "${release_dir}"
ln -s -- "${fixture}/missing current target" "${current_link}"
ln -s -- "${fixture}/missing temporary target" "${current_link}.new"
switch_current_release_link "${release_dir}" "${current_link}"
assert_link_target "${current_link}" "${release_dir}"
[[ ! -e "${current_link}.new" && ! -L "${current_link}.new" ]] \
|| fail_test "temporary dangling link remained after switch"
}
test_current_file_is_rejected() {
local fixture="${TEST_ROOT}/current file"
local release_dir="${fixture}/release new"
local current_link="${fixture}/current"
mkdir -p "${release_dir}"
printf '%s\n' "keep-current-file" >"${current_link}"
assert_switch_rejected "${release_dir}" "${current_link}"
[[ "$(cat "${current_link}")" == "keep-current-file" ]] \
|| fail_test "current file was modified"
[[ ! -e "${current_link}.new" && ! -L "${current_link}.new" ]] \
|| fail_test "temporary link was created for an unsafe current file"
}
test_current_directory_is_rejected() {
local fixture="${TEST_ROOT}/current directory"
local release_dir="${fixture}/release new"
local current_link="${fixture}/current"
mkdir -p "${release_dir}" "${current_link}"
assert_switch_rejected "${release_dir}" "${current_link}"
[[ -d "${current_link}" && ! -L "${current_link}" ]] \
|| fail_test "current directory was modified"
[[ ! -e "${current_link}/current.new" && ! -L "${current_link}/current.new" ]] \
|| fail_test "temporary link was moved into an unsafe current directory"
}
test_temporary_file_is_rejected() {
local fixture="${TEST_ROOT}/temporary file"
local old_release="${fixture}/release old"
local new_release="${fixture}/release new"
local current_link="${fixture}/current"
mkdir -p "${old_release}" "${new_release}"
ln -s -- "${old_release}" "${current_link}"
printf '%s\n' "keep-temporary-file" >"${current_link}.new"
assert_switch_rejected "${new_release}" "${current_link}"
assert_link_target "${current_link}" "${old_release}"
[[ "$(cat "${current_link}.new")" == "keep-temporary-file" ]] \
|| fail_test "temporary file was modified"
}
test_temporary_directory_is_rejected() {
local fixture="${TEST_ROOT}/temporary directory"
local old_release="${fixture}/release old"
local new_release="${fixture}/release new"
local current_link="${fixture}/current"
mkdir -p "${old_release}" "${new_release}" "${current_link}.new"
ln -s -- "${old_release}" "${current_link}"
assert_switch_rejected "${new_release}" "${current_link}"
assert_link_target "${current_link}" "${old_release}"
[[ -d "${current_link}.new" && ! -L "${current_link}.new" ]] \
|| fail_test "temporary directory was modified"
}
test_managed_directory_link_is_rejected() {
local fixture="${TEST_ROOT}/managed directory link"
local target="${fixture}/target"
local link="${fixture}/managed"
mkdir -p "${target}"
ln -s -- "${target}" "${link}"
if (ensure_directory "${link}"); then
fail_test "managed directory symbolic link was accepted"
fi
}
test_existing_release_is_never_rewritten_in_place() {
local fixture="${TEST_ROOT}/immutable release"
local requested="${fixture}/releases/v1.2.3"
local selected
mkdir -p "${requested}"
printf '%s\n' "old-release" >"${requested}/marker"
selected="$(select_release_install_directory "${requested}")"
[[ "${selected}" != "${requested}" ]] \
|| fail_test "an existing release directory was selected for in-place rewriting"
[[ -d "${selected}" && ! -L "${selected}" ]] \
|| fail_test "replacement release directory was not allocated safely"
[[ "$(cat "${requested}/marker")" == "old-release" ]] \
|| fail_test "the existing release was modified while allocating its replacement"
}
test_new_release_keeps_the_requested_version_path() {
local fixture="${TEST_ROOT}/new release"
local requested="${fixture}/releases/v1.2.3"
local selected
mkdir -p "$(dirname -- "${requested}")"
selected="$(select_release_install_directory "${requested}")"
[[ "${selected}" == "${requested}" ]] \
|| fail_test "a new release unexpectedly received a suffixed directory"
[[ ! -e "${requested}" && ! -L "${requested}" ]] \
|| fail_test "release selection created the requested path before installation"
}
test_initial_switch
test_existing_link_switch
test_dangling_links_are_replaced
test_current_file_is_rejected
test_current_directory_is_rejected
test_temporary_file_is_rejected
test_temporary_directory_is_rejected
test_managed_directory_link_is_rejected
test_existing_release_is_never_rewritten_in_place
test_new_release_keeps_the_requested_version_path
echo "PASS: current release link safety fixtures"