diff --git a/nvm.sh b/nvm.sh index 4e0dd33..90ab4ff 100755 --- a/nvm.sh +++ b/nvm.sh @@ -909,13 +909,30 @@ nvm_get_os() { } nvm_get_arch() { - local NVM_UNAME - NVM_UNAME="$(uname -m)" + local HOST_ARCH + local NVM_OS + local EXIT_CODE + + NVM_OS="$(nvm_get_os)" + # If the OS is SunOS, first try to use pkgsrc to guess + # the most appropriate arch. If it's not available, use + # isainfo to get the instruction set supported by the + # kernel. + if [ "_$NVM_OS" = "_sunos" ]; then + HOST_ARCH=$(pkg_info -Q MACHINE_ARCH pkg_install) + EXIT_CODE=$? + if [ $EXIT_CODE -ne 0 ]; then + HOST_ARCH=$(isainfo -n) + fi + else + HOST_ARCH="$(uname -m)" + fi + local NVM_ARCH - case "$NVM_UNAME" in - x86_64) NVM_ARCH="x64" ;; + case "$HOST_ARCH" in + x86_64 | amd64) NVM_ARCH="x64" ;; i*86) NVM_ARCH="x86" ;; - *) NVM_ARCH="$NVM_UNAME" ;; + *) NVM_ARCH="$HOST_ARCH" ;; esac echo "$NVM_ARCH" } @@ -1303,6 +1320,54 @@ nvm_die_on_prefix() { fi } +# Succeeds if $IOJS_VERSION represents an io.js version that has a +# Solaris binary, fails otherwise. +# Currently, only io.js 3.3.1 has a Solaris binary available, and it's the +# latest io.js version available. The expectation is that any potential io.js +# version later than v3.3.1 will also have Solaris binaries. +iojs_version_has_solaris_binary() { + local IOJS_VERSION=$1 + local STRIPPED_IOJS_VERSION="$(nvm_strip_iojs_prefix $IOJS_VERSION)" + if [ "_$STRIPPED_IOJS_VERSION" = "$IOJS_VERSION" ]; then + return 1 + fi + + # io.js started shipping Solaris binaries with io.js v3.3.1 + nvm_version_greater_than_or_equal_to "$STRIPPED_IOJS_VERSION" v3.3.1 +} + +# Succeeds if $NODE_VERSION represents a node version that has a +# Solaris binary, fails otherwise. +# Currently, node versions starting from v0.8.6 have a Solaris binary +# avaliable. +node_version_has_solaris_binary() { + local NODE_VERSION=$1 + # Error out if $NODE_VERSION is actually an io.js version + local STRIPPED_IOJS_VERSION="$(nvm_strip_iojs_prefix $NODE_VERSION)" + if [ "_$STRIPPED_IOJS_VERSION" != "_$NODE_VERSION" ]; then + return 1 + fi + + # node (unmerged) started shipping Solaris binaries with v0.8.6 and + # node versions v1.0.0 or greater are not considered valid "unmerged" node + # versions. + nvm_version_greater_than_or_equal_to "$NODE_VERSION" v0.8.6 && + ! nvm_version_greater_than_or_equal_to "$NODE_VERSION" v1.0.0 +} + +# Succeeds if $VERSION represents a version (node, io.js or merged) that has a +# Solaris binary, fails otherwise. +nvm_has_solaris_binary() { + local VERSION=$1 + if nvm_is_merged_node_version "$VERSION"; then + return 0 # All merged node versions have a Solaris binary + elif nvm_is_iojs_version "$VERSION"; then + iojs_version_has_solaris_binary "$VERSION" + else + node_version_has_solaris_binary "$VERSION" + fi +} + nvm() { if [ $# -lt 1 ]; then nvm help @@ -1485,9 +1550,11 @@ nvm() { if [ "_$NVM_OS" = "_freebsd" ]; then # node.js and io.js do not have a FreeBSD binary nobinary=1 - elif [ "_$NVM_OS" = "_sunos" ] && ([ "$NVM_IOJS" = true ] || [ "$NVM_NODE_MERGED" = true ]); then - # io.js does not have a SunOS binary - nobinary=1 + elif [ "_$NVM_OS" = "_sunos" ]; then + # Not all node/io.js versions have a Solaris binary + if ! nvm_has_solaris_binary "$VERSION"; then + nobinary=1 + fi fi local NVM_INSTALL_SUCCESS # skip binary install if "nobinary" option specified. diff --git a/test/common.sh b/test/common.sh new file mode 100644 index 0000000..7d09064 --- /dev/null +++ b/test/common.sh @@ -0,0 +1,13 @@ +assert_ok() { + local FUNCTION=$1 + shift + + $($FUNCTION $@) || die '"'"$FUNCTION $@"'" should have succeeded, but failed' +} + +assert_not_ok() { + local FUNCTION=$1 + shift + + ! $($FUNCTION $@) || die '"'"$FUNCTION $@"'" should have failed, but succeeded' +} diff --git a/test/fast/Unit tests/iojs_version_has_solaris_binary b/test/fast/Unit tests/iojs_version_has_solaris_binary new file mode 100755 index 0000000..7a797cb --- /dev/null +++ b/test/fast/Unit tests/iojs_version_has_solaris_binary @@ -0,0 +1,17 @@ +#!/bin/sh + +die () { echo $@ ; exit 1; } + +. ../../../nvm.sh +. ../../common.sh + +assert_not_ok iojs_version_has_solaris_binary "" +assert_not_ok iojs_version_has_solaris_binary "foo" +assert_not_ok iojs_version_has_solaris_binary "v1.1.0" + +assert_ok iojs_version_has_solaris_binary "v3.3.1" +assert_ok iojs_version_has_solaris_binary "iojs-v3.3.1" +assert_ok iojs_version_has_solaris_binary "v3.3.2" +assert_ok iojs_version_has_solaris_binary "iojs-v3.3.2" +assert_ok iojs_version_has_solaris_binary "v3.4.1" +assert_ok iojs_version_has_solaris_binary "iojs-v3.4.1" diff --git a/test/fast/Unit tests/node_version_has_solaris_binary b/test/fast/Unit tests/node_version_has_solaris_binary new file mode 100755 index 0000000..db62d59 --- /dev/null +++ b/test/fast/Unit tests/node_version_has_solaris_binary @@ -0,0 +1,33 @@ +#!/bin/sh + +die () { echo $@ ; exit 1; } + +. ../../../nvm.sh +. ../../common.sh + +# Invalid version numbers fail +assert_not_ok node_version_has_solaris_binary "" +assert_not_ok node_version_has_solaris_binary "foo" + +# "Invalid" node version numbers fail +assert_not_ok node_version_has_solaris_binary "v1.0.0" +assert_not_ok node_version_has_solaris_binary "v3.3.1" + +# Valid io.js version numbers that have a Solaris binary fail +assert_not_ok node_version_has_solaris_binary "iojs-v3.3.1" + +# Invvalid io.js version numbers fail +assert_not_ok node_version_has_solaris_binary "iojs-v0.12.7" + +# Valid node version numbers that don't have a Solaris binary fail +assert_not_ok node_version_has_solaris_binary "v0.8.5" + +# Valid node version numbers that have a Solaris binary succeed +assert_ok node_version_has_solaris_binary "v0.8.6" +assert_ok node_version_has_solaris_binary "v0.10.0" +assert_ok node_version_has_solaris_binary "v0.12.7" + +# Valid "merged" version numbers fail, because they're not +# considered node version numbers +assert_not_ok node_version_has_solaris_binary "v4.0.0" +assert_not_ok node_version_has_solaris_binary "v4.1.1" diff --git a/test/fast/Unit tests/nvm_get_arch b/test/fast/Unit tests/nvm_get_arch new file mode 100755 index 0000000..b3fd51b --- /dev/null +++ b/test/fast/Unit tests/nvm_get_arch @@ -0,0 +1,80 @@ +#!/bin/sh + +# Save the PATH as it was when the test started to restore it when it +# finishes +ORIG_PATH=$PATH + +cleanup() { + # Restore the PATH as it was when the test started + export PATH=ORIG_PATH +} + +die () { cleanup; echo $@ ; exit 1; } + +. ../../../nvm.sh + +# Directory where mocked binaries used by nvm_get_arch for each OS/arch are +# located +MOCKS_DIR=`pwd`/../../mocks +# Sets the PATH for these tests to include the symlinks to the mocked +# binaries +export PATH=.:${PATH} + +# Setups mock binaries for a given OS and arch that mimic +# the output of the real binaries used by nvm_get_arch to guess +# the architecture of a given system. +setup_mock_arch() { + local OS=$1 + local ARCH=$2 + local OPT=$3 + + if [ "_$OS" = "_solaris" ] || [ "_$OS" = "_smartos" ]; then + ln -sf "${MOCKS_DIR}/isainfo_${ARCH}" ./isainfo + if [ "_$OPT" != "_no_pkg_info" ]; then + ln -sf "${MOCKS_DIR}/pkg_info_${ARCH}" ./pkg_info + fi + fi + + ln -sf "${MOCKS_DIR}/uname_${OS}_${ARCH}" ./uname +} + +# Cleans up the setup done by setup_mock_arch. +cleanup_mock_arch() { + local OS=$1 + local ARCH=$2 + + if [ "_$OS" = "_solaris" ] || [ "_$OS" = "_smartos" ]; then + rm -f ./isainfo + rm -f ./pkg_info + fi + + rm -f ./uname +} + +# Runs nvm_get_arch for architecture $ARCH and OS $OS, and compares the +# expected output $EXPECTED_OUTPUT with the actual output. Does nothing +# and exits cleanly if they match, dies otherwise. +run_test() { + local ARCH=$1 + local OS=$2 + local EXPECTED_OUTPUT=$3 + local OPT=$4 + + setup_mock_arch $OS $ARCH $OPT + local OUTPUT="$(nvm_get_arch)" + cleanup_mock_arch $OS $ARCH + [ "_$OUTPUT" = "_$EXPECTED_OUTPUT" ] || + die "nvm_get_arch for OS \"$OS\" and arch \"$ARCH\" with OPT \"$OPT\" did + not return \"$EXPECTED_OUTPUT\"; got \"$OUTPUT\"" +} + +run_test x86 smartos x86 +run_test x86 smartos x86 no_pkg_info + +run_test amd64 smartos x64 +run_test amd64 smartos x64 no_pkg_info + +run_test x86 osx x86 +run_test amd64 osx x64 + +cleanup diff --git a/test/fast/Unit tests/nvm_has_solaris_binary b/test/fast/Unit tests/nvm_has_solaris_binary new file mode 100755 index 0000000..5a29112 --- /dev/null +++ b/test/fast/Unit tests/nvm_has_solaris_binary @@ -0,0 +1,32 @@ +#!/bin/sh + +die () { echo $@ ; exit 1; } + +. ../../../nvm.sh +. ../../common.sh + +# Invalid version numbers fail +assert_not_ok nvm_has_solaris_binary "" +assert_not_ok nvm_has_solaris_binary "foo" + +# "Invalid" node version numbers fail +assert_not_ok nvm_has_solaris_binary "v1.0.0" +assert_not_ok nvm_has_solaris_binary "v3.3.1" + +# Valid io.js version numbers that have a Solaris binary succeed +assert_ok nvm_has_solaris_binary "iojs-v3.3.1" + +# Invvalid io.js version numbers fail +assert_not_ok nvm_has_solaris_binary "iojs-v0.12.7" + +# Valid node version numbers that don't have a Solaris binary fail +assert_not_ok nvm_has_solaris_binary "v0.8.5" + +# Valid node version numbers that have a Solaris binary succeed +assert_ok nvm_has_solaris_binary "v0.8.6" +assert_ok nvm_has_solaris_binary "v0.10.0" +assert_ok nvm_has_solaris_binary "v0.12.7" + +# Valid "merged" version numbers succeed +assert_ok nvm_has_solaris_binary "v4.0.0" +assert_ok nvm_has_solaris_binary "v4.1.1" diff --git a/test/mocks/isainfo_amd64 b/test/mocks/isainfo_amd64 new file mode 100755 index 0000000..37f805b --- /dev/null +++ b/test/mocks/isainfo_amd64 @@ -0,0 +1,5 @@ +if [ "_$1" = "_-n" ]; then + echo "amd64" +else + echo "amd64 i386" +fi diff --git a/test/mocks/isainfo_x86 b/test/mocks/isainfo_x86 new file mode 100755 index 0000000..4658d2a --- /dev/null +++ b/test/mocks/isainfo_x86 @@ -0,0 +1,5 @@ +if [ "_$1" = "_-n" ]; then + echo "i386" +else + echo "i386" +fi diff --git a/test/mocks/pkg_info_amd64 b/test/mocks/pkg_info_amd64 new file mode 100755 index 0000000..8437c2b --- /dev/null +++ b/test/mocks/pkg_info_amd64 @@ -0,0 +1 @@ +echo "x86_64" diff --git a/test/mocks/pkg_info_x86 b/test/mocks/pkg_info_x86 new file mode 100755 index 0000000..a555469 --- /dev/null +++ b/test/mocks/pkg_info_x86 @@ -0,0 +1 @@ +echo "i386" diff --git a/test/mocks/uname_osx_amd64 b/test/mocks/uname_osx_amd64 new file mode 100755 index 0000000..8552d1d --- /dev/null +++ b/test/mocks/uname_osx_amd64 @@ -0,0 +1,5 @@ +if [ "_$1" = "_-m" ]; then + echo "x86_64" +else + echo "Darwin foo.local 13.4.0 Darwin Kernel Version 13.4.0: Sun Aug 17 19:50:11 PDT 2014; root:xnu-2422.115.4~1/RELEASE_X86_64 x86_64" + fi diff --git a/test/mocks/uname_osx_x86 b/test/mocks/uname_osx_x86 new file mode 100755 index 0000000..0d91a7e --- /dev/null +++ b/test/mocks/uname_osx_x86 @@ -0,0 +1,5 @@ +if [ "_$1" = "_-m" ]; then + echo "i386" +else + echo "Darwin foo.local 13.4.0 Darwin Kernel Version 13.4.0: Sun Aug 17 19:50:11 PDT 2014; root:xnu-2422.115.4~1/RELEASE_I386 i386" + fi diff --git a/test/mocks/uname_smartos_amd64 b/test/mocks/uname_smartos_amd64 new file mode 100755 index 0000000..452f3bc --- /dev/null +++ b/test/mocks/uname_smartos_amd64 @@ -0,0 +1,5 @@ +if [ "_$1" = "_-m" ]; then + echo "i86pc" +else + echo "SunOS dev 5.11 joyent_20150219T102159Z i86pc i386 i86pc Solaris" +fi diff --git a/test/mocks/uname_smartos_x86 b/test/mocks/uname_smartos_x86 new file mode 100755 index 0000000..452f3bc --- /dev/null +++ b/test/mocks/uname_smartos_x86 @@ -0,0 +1,5 @@ +if [ "_$1" = "_-m" ]; then + echo "i86pc" +else + echo "SunOS dev 5.11 joyent_20150219T102159Z i86pc i386 i86pc Solaris" +fi