#!/bin/sh TEST_PWD=$(pwd) TEST_DIR="${TEST_PWD}/nvm_get_os_tmp" : nvm.sh \. ../../../nvm.sh cleanup() { rm -rf "${TEST_DIR}" } die() { echo "$@" cleanup exit 1 } [ ! -e "${TEST_DIR}" ] && mkdir "${TEST_DIR}" OS_RELEASE="${TEST_DIR}/os-release" MISSING_OS_RELEASE="${TEST_DIR}/nonexistent-os-release" # a `uname` that reports that it ran (and fails), so that any test can prove # whether `nvm_get_os` forked it MOCK_BIN="${TEST_DIR}/bin" mkdir -p "${MOCK_BIN}" { echo '#!/bin/sh' echo 'echo "uname was called" >&2' echo 'exit 1' } > "${MOCK_BIN}/uname" chmod +x "${MOCK_BIN}/uname" # asserts that `nvm_get_os` maps the os-release file to $EXPECTED, without # forking `uname`; the kernel is mocked as Linux, so Linux distro `ID`s pass on any host KERNEL_LINUX="${TEST_DIR}/ostype-linux" echo 'Linux' > "${KERNEL_LINUX}" assert_os_release() { local DESCRIPTION DESCRIPTION="${1}" local EXPECTED EXPECTED="${2}" local OUTPUT NVM_OS_RELEASE="${OS_RELEASE}" NVM_OS_KERNEL_OSTYPE="${KERNEL_LINUX}" export NVM_OS_RELEASE NVM_OS_KERNEL_OSTYPE OUTPUT="$(PATH="${MOCK_BIN}:${PATH}" nvm_get_os 2>&1)" unset NVM_OS_RELEASE NVM_OS_KERNEL_OSTYPE case "${OUTPUT}" in *'uname was called'*) die "for ${DESCRIPTION}, \`nvm_get_os\` forked \`uname\` despite \`${OS_RELEASE}\` being readable" ;; esac [ "${OUTPUT}" = "${EXPECTED}" ] || die "for ${DESCRIPTION}, expected '${EXPECTED}', got '${OUTPUT}'" } printf 'NAME=Ubuntu\nID=ubuntu\n' > "${OS_RELEASE}" assert_os_release 'a distro-style os-release' 'linux' printf 'NAME="Arch Linux"\nID=arch\n' > "${OS_RELEASE}" assert_os_release 'an os-release with a quoted NAME' 'linux' printf 'NAME=FreeBSD\nVERSION=14.0-RELEASE\nID=freebsd\n' > "${OS_RELEASE}" assert_os_release 'the FreeBSD 13.2+ os-release' 'freebsd' printf 'ID=freebsd' > "${OS_RELEASE}" assert_os_release 'an os-release whose ID has no trailing newline' 'freebsd' printf 'NAME=MSYS2\nID=msys2\nPRETTY_NAME="MSYS2"\nID_LIKE="cygwin arch"\n' > "${OS_RELEASE}" assert_os_release 'the MSYS2 os-release' 'win' printf 'NAME="Oracle Solaris"\nPRETTY_NAME="Oracle Solaris 11.4"\nCPE_NAME="cpe:/o:oracle:solaris:11:4"\nID=solaris\nVERSION=11.4\nVERSION_ID=11.4\nBUILD_ID=11.4.0.0.1.15.0\nHOME_URL="https://www.oracle.com/solaris/"\nSUPPORT_URL="https://support.oracle.com/"\n' > "${OS_RELEASE}" assert_os_release 'the Oracle Solaris 11.4 os-release' 'sunos' printf 'NAME="OmniOS"\nPRETTY_NAME="OmniOS Community Edition v11 r151048"\nCPE_NAME="cpe:/o:omniosce:omnios:11:151048:0"\nID=omnios\nVERSION=r151048\nVERSION_ID=r151048\nBUILD_ID=151048.0.2023.11.04\nHOME_URL="https://omnios.org/"\nSUPPORT_URL="https://omnios.org/"\nBUG_REPORT_URL="https://github.com/omniosorg/omnios-build/issues/new"\n' > "${OS_RELEASE}" assert_os_release 'the OmniOS r151048 os-release' 'sunos' printf 'ID=openindiana\nID_LIKE="illumos solaris"\n' > "${OS_RELEASE}" assert_os_release 'an OpenIndiana os-release' 'sunos' printf 'ID=smartos\n' > "${OS_RELEASE}" assert_os_release 'a SmartOS os-release' 'sunos' printf 'ID=illumos\n' > "${OS_RELEASE}" assert_os_release 'an illumos os-release' 'sunos' printf 'ID=ghostbsd\nID_LIKE=freebsd\n' > "${OS_RELEASE}" assert_os_release 'a GhostBSD os-release' 'freebsd' printf 'ID=freebsd # a comment\n' > "${OS_RELEASE}" assert_os_release 'an ID followed by whitespace and a comment' 'freebsd' # the file is read, not sourced: nothing in it runs printf 'exit 3\nID=ubuntu\n' > "${OS_RELEASE}" assert_os_release 'an os-release containing shell code' 'linux' # a file without an `ID`, or no file at all, falls back to parsing `uname -a` { echo '#!/bin/sh' echo 'echo "${NVM_MOCK_UNAME}"' } > "${MOCK_BIN}/uname" chmod +x "${MOCK_BIN}/uname" assert_uname_os() { local UNAME_OUTPUT UNAME_OUTPUT="${1}" local OS_RELEASE_FILE OS_RELEASE_FILE="${2}" local EXPECTED EXPECTED="${3}" local OUTPUT NVM_OS_RELEASE="${OS_RELEASE_FILE}" NVM_OS_KERNEL_OSTYPE="${MISSING_OS_RELEASE}" export NVM_OS_RELEASE NVM_OS_KERNEL_OSTYPE NVM_MOCK_UNAME="${UNAME_OUTPUT}" export NVM_MOCK_UNAME OUTPUT="$(PATH="${MOCK_BIN}:${PATH}" nvm_get_os)" unset NVM_OS_RELEASE NVM_OS_KERNEL_OSTYPE NVM_MOCK_UNAME [ "${OUTPUT}" = "${EXPECTED}" ] || die "for uname -a '${UNAME_OUTPUT}', expected '${EXPECTED}', got '${OUTPUT}'" } printf 'NAME=OnlyAName\n' > "${OS_RELEASE}" assert_uname_os 'Linux host 6.1.0 #1 SMP x86_64 GNU/Linux' "${OS_RELEASE}" 'linux' assert_uname_os 'Darwin host 23.1.0 arm64' "${OS_RELEASE}" 'darwin' assert_uname_os 'SunOS host 5.11' "${OS_RELEASE}" 'sunos' assert_uname_os 'FreeBSD host 14.0-RELEASE' "${OS_RELEASE}" 'freebsd' assert_uname_os 'OpenBSD host 7.4' "${OS_RELEASE}" 'openbsd' assert_uname_os 'AIX host 3 7' "${OS_RELEASE}" 'aix' assert_uname_os 'CYGWIN_NT-10.0 host' "${OS_RELEASE}" 'win' assert_uname_os 'MINGW64_NT-10.0 host' "${OS_RELEASE}" 'win' assert_uname_os 'MSYS_NT-10.0 host' "${OS_RELEASE}" 'win' assert_uname_os 'Darwin host 23.1.0 arm64' "${MISSING_OS_RELEASE}" 'darwin' # a pre-set `ID` in the environment must not be mistaken for the file's `ID` ID=1000 export ID assert_uname_os 'Darwin host 23.1.0 arm64' "${OS_RELEASE}" 'darwin' unset ID # DragonFly BSD has no `nvm` OS of its own: fall back to `uname -a` as before printf 'NAME="DragonFly"\nID=dragonfly\n' > "${OS_RELEASE}" assert_uname_os 'DragonFly host 6.4-RELEASE' "${OS_RELEASE}" '' # an unlisted `ID` on a non-Linux kernel is not assumed to be Linux printf 'NAME=HardenedBSD\nID=hardenedbsd\n' > "${OS_RELEASE}" assert_uname_os 'FreeBSD host 14.0-STABLE' "${OS_RELEASE}" 'freebsd' printf 'NAME=Helios\nID=helios\n' > "${OS_RELEASE}" assert_uname_os 'SunOS host 5.11' "${OS_RELEASE}" 'sunos' cleanup