This commit is contained in:
Edward Murphy 2018-11-06 08:45:49 +00:00 committed by GitHub
commit 6c5a67fa25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 1226 additions and 5 deletions

View File

@ -14,3 +14,15 @@ indent_size = false
[Makefile]
indent_style = tab
[test/fast/Unit tests/package_json_templates/*]
indent_style = unset
[test/generated_semvers.sh]
indent_style = unset
indent_size = unset
[test/fast/Unit tests/nvm_trim_and_reduce_whitespace_to_one_space]
indent_style = unset
indent_size = unset

536
nvm.sh
View File

@ -299,6 +299,516 @@ nvm_find_up() {
nvm_echo "${path_}"
}
# NOTE: this function only validates across one line
nvm_string_contains_regexp() {
local string
string="${1-}"
local regexp
regexp="${2-}"
if [ -z "$string" ] || [ -z "$regexp" ]; then
return 1
fi
# e.g. "nvm_string_contains_regexp abbc ^aa?b+.$" returns 0
command printf '%s' "$string" | command awk "/$regexp/{ exit 0 }{ exit 1 }"
}
# Validates that the given semver adheres to the following grammar:
#
# semver ::= comparator_set ( ' || ' comparator_set )*
# comparator_set ::= comparator ( ' ' comparator )*
# comparator ::= ( '<' | '<=' | '>' | '>=' | '' ) [0-9]+ '.' [0-9]+ '.' [0-9]+
nvm_is_normalized_semver() {
nvm_string_contains_regexp "${1-}" '^( ?(<|<=|>|>=)?[0-9]+\.[0-9]+\.[0-9]+)+( \|\| ( ?(<|<=|>|>=)?[0-9]+\.[0-9]+\.[0-9]+)+)*$'
}
nvm_trim_and_reduce_whitespace_to_one_space() {
command printf '%s' "${1-}" |
command tr '\n\r\t\v\b' ' ' |
command tr -s ' ' |
command sed 's/^ //; s/ $//; s/^ //'
}
# Attempts to normalize the given semver to the grammar defined with the function nvm_is_normalized_semver
nvm_normalize_semver() {
# split the semantic version's comparator_set's onto their own lines for iteration
local semver
semver=$(nvm_trim_and_reduce_whitespace_to_one_space "${1-}" | command tr '||' '\n')
if [ -z "$semver" ]; then
return 1
fi
local comparator_set
local validated_comparator_set
local validated_semver
validated_semver='';
while [ -n "$semver" ]; do
comparator_set=$(command printf '%s' "$semver" | command head -n1)
semver=$(command printf '%s' "$semver" | command tail -n +2)
[ -n "$comparator_set" ] || continue
# convert comparators into required grammar
validated_comparator_set=$(command printf ' %s ' "$comparator_set" |
command sed -E "
# exactly 1 space is needed before and after every comparator (including the first and last comparators)
s/\011/ /g;s/ +/ /g;
# normalize all wildcards to x
s/X|\*/x/g;
# space out numbers surrounding '-'
s/ ?- ?/ - /g;
# ' 1 ' => ' 1.x.x '
# ' ~x ' => ' ~x.x.x '
s/ (~|\^)?([0-9]+|x) / \1\2.x.x /g;
# ' 1.2 ' => ' 1.2.x '
# ' ~1.x ' => ' ~1.x.x '
# ' ^x.x ' => ' ^x.x.x '
s/ (~|\^)?(([0-9]+|x)\.([0-9]+|x)) / \1\2.x /g;
# ' 1.2.3 - 1.2.4 ' => ' >=1.2.3 <=1.2.4 '
s/ (([0-9]+|x)\.([0-9]+|x)\.([0-9]+|x)) ?\- ?(([0-9]+|x)\.([0-9]+|x)\.([0-9]+|x)) / >=\1 <=\5 /g;
# ' > 1.2.3 ' => ' >1.2.3 '
# ' < 1.2.5 ' => ' <1.2.5 '
# ' <= 1.2.3 ' => ' <=1.2.3 '
# ' >= 1.2.3 ' => ' >=1.2.3 '
# ' = 1.2.3 ' => ' =1.2.3 '
# ' ~ 1.2.3 ' => ' ~1.2.3 '
# ' ^ 1.2.3 ' => ' ^1.2.3 '
# ' v 1.2.3 ' => ' v1.2.3 '
s/ (v|<|>|<=|>=|=|~|\^) (([0-9]+|x)\.([0-9]+|x)\.([0-9]+|x)) / \1\2 /g;
# ' =1.2.3 ' => ' 1.2.3 '
# ' v1.2.3 ' => ' 1.2.3 '
s/ (=|v)//g;" |
command awk '{
# handle conversions of comparators with ^ or ~ or x into required grammar
# ` ^0.0.1 ` => ` >=0.0.1 <0.0.2 `
# ` ^0.1.2 ` => ` >=0.1.2 <0.2.0 `
# ` ^1.2.3 ` => ` >=1.2.3 <2.0.0 `
# ` ^1.0.0 ` => ` >=1.0.0 <2.0.0 `
# ` ~0.0.1 ` => ` >=0.0.1 <0.1.0 `
# ` ~0.1.2 ` => ` >=0.1.2 <0.2.0 `
# ` ~1.2.3 ` => ` >=1.2.3 <1.3.0 `
# ` ~1.0.0 ` => ` >=1.0.0 <2.0.0 `
# ` x.x.x ` => ` >0.0.0 `
# ` x.x.1 ` => ` >0.0.0 `
# ` x.1.x ` => ` >0.0.0 `
# ` x.1.2 ` => ` >0.0.0 `
# ` 1.2.x ` => ` >=1.2.0 <1.3.0 `
# ` 1.x.1 ` => ` >=1.0.0 <2.0.0 ` NOTE the last "1" is ignored in this grammar
# ` 1.x.x ` => ` >=1.0.0 <2.0.0 `
if ( ! match($0, /[\^~x]/) ) {
print $0
exit 0
}
split($0, comparators, / /)
output=""
for (i = 1; i <= length(comparators); i++) {
comparator=comparators[i]
if ( match(comparator, /^([\^~>]|>=)?x.[0-9x]+.[0-9x]$/ ) ) {
comparator=">0.0.0"
} else if ( match(comparator, /^([\^~<>]|>=|<=)?[0-9]+.x.[0-9x]$/) ) {
split(comparator, a, /\./);
if ( match(comparator, /^([\^~<>]|>=|<=).*$/ ) ) {
comparator=a[1] ".0.0";
} else {
comparator=">=" a[1] ".0.0 <" a[1]+1 ".0.0"
}
} else if ( match(comparator, /^([\^~<>]|<=|>=)?[0-9]+.[0-9]+.x$/) ) {
split(comparator, a, /\./);
if ( match(comparator, /^([\^~<>]|<=|>=).*$/ ) ) {
comparator=a[1] "." a[2] ".0";
} else {
comparator=">=" a[1] "." a[2] ".0 <" a[1] "." a[2]+1 ".0"
}
}
if ( match(comparator, /^\^/) ) {
if ( match(comparator, /^\^0.0.[0-9]+$/) ) {
version=substr(comparator,2);
split(version, a, /\./);
output=output ">=" version " <0.0." a[3]+1 " ";
} else if ( match(comparator, /^\^0.[0-9]+.[0-9]+$/) ) {
version=substr(comparator,2);
split(version, a, /\./);
output=output ">=" version " <0." a[2]+1 ".0 ";
} else if ( match(comparator, /^\^[0-9]+.[0-9]+.[0-9]+$/) ) {
version=substr(comparator,2);
split(version, a, /\./);
output=output ">=" version " <" a[1]+1 ".0.0 ";
}
} else if ( match(comparator, /^~/) ) {
if ( match(comparator, /^~[0-9]+.0.0$/) ) {
version=substr(comparator,2)
split(version, a, /\./)
output=output ">=" version " <" a[1]+1 ".0.0 "
} else if ( match(comparator, /^~0.0.[0-9]+$/) ) {
version=substr(comparator,2)
split(version, a, /\./)
output=output ">=" version " <0." a[2]+1 ".0 "
} else if ( match(comparator, /^~0.[0-9]+.[0-9]+$/) ) {
version=substr(comparator,2)
split(version, a, /\./)
output=output ">=" version " <0." a[2]+1 ".0 "
} else if ( match(comparator, /^~[0-9]+.[0-9]+.[0-9]+$/) ) {
version=substr(comparator,2)
split(version, a, /\./)
output=output ">=" version " <" a[1] "." a[2]+1 ".0 "
}
} else {
output=output comparator " "
}
}
print output
}' |
command sed -E 's/^ +//;s/ +$//'
)
# only comparator_sets composed of the required grammar are marked as valid
if nvm_string_contains_regexp "$validated_comparator_set" '^( ?(<|<=|>|>=)?[0-9]+\.[0-9]+\.[0-9]+)+$'; then
validated_semver="$validated_semver || $validated_comparator_set"
else
return 1
fi
done
validated_semver=$(command printf '%s' "$validated_semver" | command sed -E 's/^ \|\| //')
if nvm_is_normalized_semver "$validated_semver"; then
command printf '%s' "$validated_semver"
return 0
fi
return 1
}
# Given a semver and version list, find the highest compatible version by doing the following:
# - Find the newest compatible version of each comparator set.
# - Resolve to the newest of all the newest compatible versions of each comparator set.
nvm_interpret_complex_semver() {
local semver
semver="${1-}"
local version_list
version_list="${2-}" # expected to be sorted from oldest to newest
if [ -z "$semver" ] || [ -z "$version_list" ] || ! nvm_is_normalized_semver "$semver"; then
return 1
fi
# For each comparator_set in the semver:
# - Try to resolve the comparator_set to its newest compatible version.
# - But stop looking for a compatible version for a comparator_set if the current_version being iterated on is lower than an already found compatible version.
# - If by the end of the algorithm, a version other than 0.0.0 is collected in highest_compatible_version, output that version.
semver=$(command printf '%s' "$semver" | command tr '||' '\n')
local version_list_copy
local current_comparator_set
local current_version
local current_comparator_set_copy
local current_comparator
local stripped_version_from_comparator
local highest_compatible_version
highest_compatible_version='0.0.0'
while [ -n "$semver" ]; do
version_list_copy=$(command printf '%s' "$version_list")
current_comparator_set=$(command printf '%s' "$semver" | command head -n1 | command sed -E 's/^ +//;s/ +$//')
semver=$(command printf '%s' "$semver" | command tail -n +2)
[ -n "$current_comparator_set" ] || continue
# For each version in the version_list_copy (iterating from newest to oldest):
# - If current_version satisfies all comparators in current_comparator_set, we've found the newest highest version compatible with all comparators in current current_comparator_set.
# - Store the current_version in highest_compatible_version and stop iterating through versions for current_comparator_set.
while [ -n "$version_list_copy" ]; do
current_version=$(command printf '%s' "$version_list_copy" | command tail -n1 | command sed -E 's/^ +//;s/ +$//' | nvm_grep -o '^[0-9]\+\.[0-9]\+\.[0-9]\+$')
version_list_copy=$(command printf '%s' "$version_list_copy" | command sed '$d')
[ -n "$current_version" ] || continue
if [ "$highest_compatible_version" != '0.0.0' ] && nvm_version_greater "$highest_compatible_version" "$current_version"; then
# If we previously found a compatible version that is higher than the current_version, there is no need to continue checking versions.
version_list_copy=''
continue
fi
# For each comparator in the current_comparator_set_copy:
# - If current_version is compatible with all comparators, we know current_version is the newest compatible version
current_comparator_set_copy=$(command printf '%s' "$current_comparator_set" | command tr ' ' '\n')
while [ -n "$current_comparator_set_copy" ]; do
current_comparator=$(command printf '%s' "$current_comparator_set_copy" | command head -n1 | command sed -E 's/^ +//;s/ +$//')
current_comparator_set_copy=$(command printf '%s' "$current_comparator_set_copy" | command tail -n +2)
[ -n "$current_comparator" ] || continue
stripped_version_from_comparator=$(command printf '%s' "$current_comparator" | nvm_grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+$')
if [ -z "$stripped_version_from_comparator" ]; then
return 1
fi
if nvm_string_contains_regexp "$current_comparator" '^[0-9]+\.[0-9]+\.[0-9]+$'; then
if [ "$stripped_version_from_comparator" = "$current_version" ]; then
# current_comparator is looking for an exact match, and the current_version is the exact match, so this current_comparator is satisfied.
if [ -z "$current_comparator_set_copy" ]; then
# Also, this is the last comparator in the current_comparator_set_copy so we can assume we've found the newest compatible version of the current_comparator_set.
highest_compatible_version="$current_version"
version_list_copy=''
fi
elif nvm_version_greater "$stripped_version_from_comparator" "$current_version"; then
# current_version is less than the stripped_version_from_comparator, so continuing iterating through version_list_copy is pointless.
current_comparator_set_copy=''
version_list_copy=''
else
# current_version is greater than the stripped_version_from_comparator, so we should continuing iterating through version_list_copy.
current_comparator_set_copy=''
fi
elif nvm_string_contains_regexp "$current_comparator" '^<=[0-9]+\.[0-9]+\.[0-9]+$'; then
if nvm_version_greater_than_or_equal_to "$stripped_version_from_comparator" "$current_version"; then
# current_version is less than or equal to the current_comparator version number so this current_comparator is satisfied.
if [ -z "$current_comparator_set_copy" ]; then
# Also, this is the last comparator in the current_comparator_set_copy so we can assume we've found the newest compatible version of the current_comparator_set.
highest_compatible_version="$current_version"
version_list_copy=''
fi
else
# current_version is greater than the current_comparator version number so we should continue iterating through version_list_copy.
current_comparator_set_copy=''
fi
elif nvm_string_contains_regexp "$current_comparator" '^>=[0-9]+\.[0-9]+\.[0-9]+$'; then
if nvm_version_greater_than_or_equal_to "$current_version" "$stripped_version_from_comparator"; then
# current_version is greater than or equal to the current_comparator version number so this current_comparator is satisfied.
if [ -z "$current_comparator_set_copy" ]; then
# Also, this is the last comparator in the current_comparator_set_copy so we can assume we've found the newest compatible version of the current_comparator_set.
highest_compatible_version="$current_version"
version_list_copy=''
fi
else
# current_version is less than the current_comparator version number so continuing iterating through version_list_copy is pointless.
current_comparator_set_copy=''
version_list_copy=''
fi
elif nvm_string_contains_regexp "$current_comparator" '^<[0-9]+\.[0-9]+\.[0-9]+$'; then
if nvm_version_greater "$stripped_version_from_comparator" "$current_version"; then
# current_version is less than the current_comparator version number so this current_comparator is satisfied.
if [ -z "$current_comparator_set_copy" ]; then
# Also, this is the last comparator in the current_comparator_set_copy so we can assume we've found the newest compatible version of the current_comparator_set.
highest_compatible_version="$current_version"
version_list_copy=''
fi
else
# current_version is greater than or equal to the current_comparator version number so we should continue iterating through version_list_copy.
current_comparator_set_copy=''
fi
elif nvm_string_contains_regexp "$current_comparator" '^>[0-9]+\.[0-9]+\.[0-9]+$'; then
if nvm_version_greater "$current_version" "$stripped_version_from_comparator"; then
# current_version is greater than the current_comparator version number so this current_comparator is satisfied.
if [ -z "$current_comparator_set_copy" ];then
# Also, this is the last comparator in the current_comparator_set_copy so we can assume we've found the newest compatible version of the current_comparator_set.
highest_compatible_version="$current_version"
version_list_copy=''
fi
else
# current_version is less than or equal to the current_comparator version number so continuing iterating through version_list_copy is pointless.
current_comparator_set_copy=''
version_list_copy=''
fi
else
current_comparator_set_copy=''
fi
done # while [ -n "$current_comparator_set_copy" ]; do
done # while [ -n "$version_list_copy" ]; do
done # while [ -n "$semver" ]; do
if [ -n "$highest_compatible_version" ] && [ "$highest_compatible_version" != '0.0.0' ]; then
command printf '%s' "$highest_compatible_version"
return 0
fi
return 1
}
# Given a semver and version list, optimize discovery of highest compatible version with this function which quickly interprets some common semvers.
nvm_interpret_simple_semver() {
local semver
semver="${1-}"
local version_list
version_list="${2-}" # expected to be sorted from oldest to newest
if [ -z "$semver" ] || [ -z "$version_list" ] || ! nvm_string_contains_regexp "$semver" '^[<>=]*[0-9]+\.[0-9]+\.[0-9]+$'; then
return 1
fi
local stripped_version_from_semver
stripped_version_from_semver=$(command printf '%s' "$semver" | nvm_grep -o '^[0-9]\+\.[0-9]\+\.[0-9]\+$')
local newest_version_from_list
newest_version_from_list=$(command printf '%s' "$version_list" | tail -n 1 | nvm_grep -o '^[0-9]\+\.[0-9]\+\.[0-9]\+$')
if [ -z "$stripped_version_from_semver" ] || [ -z "$newest_version_from_list" ]; then
return 1
fi
local retrieved_version
# if the semver is looking for an exact match, and it exists in the provided list of versions, resolve to that version
if nvm_string_contains_regexp "$semver" '^[0-9]+\.[0-9]+\.[0-9]+$'; then
retrieved_version=$(command printf '%s' "$version_list" | nvm_grep "^$stripped_version_from_semver$")
if [ -n "$retrieved_version" ]; then
command printf '%s' "$retrieved_version"
return 0
else
command printf '%s' 'STOP' # we have determined no node version will be compatible with the semver
return 1
fi
# Semver is looking for the newest version that is <= to a sepcific version, and the version exists in the provided list of versions, resolve to that version
elif nvm_string_contains_regexp "$semver" '^<=[0-9]+\.[0-9]+\.[0-9]+$'; then
retrieved_version=$(command printf '%s' "$version_list" | nvm_grep "^$stripped_version_from_semver$")
if [ -n "$retrieved_version" ]; then
command printf '%s' "$retrieved_version"
return 0
else
return 1 # go on to try complex semver interpretation
fi
# Semver is looking for the newest version >= a specific version, and the newest version in the provided list of versions is >= the specified version, resolve to that version.
elif nvm_string_contains_regexp "$semver" '^>=[0-9]+\.[0-9]+\.[0-9]+$'; then
if nvm_version_greater_than_or_equal_to "$newest_version_from_list" "$stripped_version_from_semver"; then
command printf '%s' "$newest_version_from_list"
return 0
else
command printf '%s' 'STOP' # we have determined no node version will be compatible with the semver
return 1
fi
elif nvm_string_contains_regexp "$semver" '^>[0-9]+\.[0-9]+\.[0-9]+$'; then
if nvm_version_greater "$newest_version_from_list" "$stripped_version_from_semver"; then
command printf '%s' "$newest_version_from_list"
return 0
else
command printf '%s' 'STOP' # we have determined no node version will be compatible with the semver
return 1
fi
else
return 1
fi
}
# Given a semantic version, resolve it to the newest compatible remote node version.
nvm_interpret_node_semver() {
local semver
semver="${1-}"
if [ -z "$semver" ]; then
return 1
fi
# Validate incoming semver and transform it into the grammar that is expected by the following logic
local valid_transformed_semver
valid_transformed_semver=$(nvm_normalize_semver "$semver")
if [ -z "$valid_transformed_semver" ]; then
return 1
fi
# list of node versions is sorted from oldest to newest
local remote_node_versions
remote_node_versions=$(nvm_ls_remote | nvm_grep -o 'v[0-9]\+\.[0-9]\+\.[0-9]\+' | sed 's/^v//g')
if [ -z "$remote_node_versions" ]; then
return 1
fi
# If semver is a single comparator, use quick algorithm to determine newest compatible version
local resolved_version
resolved_version=$(nvm_interpret_simple_semver "$valid_transformed_semver" "$remote_node_versions")
if [ "$resolved_version" = 'STOP' ]; then
return 1 # nvm_interpret_simple_semver determined no node version will be compatible with the semver
elif [ -n "$resolved_version" ]; then
command printf '%s' "$resolved_version"
return 0
fi
# If semver is a semver with > 1 comparator, iterate through each remote node version from newest to oldest until finding the newest version compatible with all comparators.
resolved_version=$(nvm_interpret_complex_semver "$valid_transformed_semver" "$remote_node_versions")
if [ -n "$resolved_version" ]; then
command printf '%s' "$resolved_version"
return 0
fi
return 1
}
nvm_find_package_json() {
dir="$(nvm_find_up 'package.json')"
if [ -e "${dir}/package.json" ]; then
command printf '%s' "${dir}/package.json"
fi
}
# extracts engines.node value from package.json exactly except:
# - removes all line breaks and carriage returns
# - normalizes all consecutive whitespace to 1 occurrence
# - semantic expression must match regexp: "[|<> [:alnum:].^=~*-]\+"
nvm_get_node_from_pkg_json() {
local package_json_contents
package_json_contents="${1-}"
local engines_node_value
engines_node_value=''
local open_brackets
open_brackets=0 # a counter variable
local closed_brackets
closed_brackets=0 # a counter variable
local in_quotes
in_quotes=1 # a true/false variable
nvm_trim_and_reduce_whitespace_to_one_space "$package_json_contents" \
| nvm_grep -o '"engines": \?{ \?".*' \
| nvm_grep -o '{.*' \
| nvm_grep -o . \
| while read -r i; do
engines_node_value="$engines_node_value$i"
if [ "$i" = '"' ]; then
if [ $in_quotes -eq 1 ]; then
in_quotes=0
else
in_quotes=1
fi
# spaces are interpretted as '' here but they need to be retained
elif [ "$i" = '' ]; then
engines_node_value="$engines_node_value "
elif [ $in_quotes -eq 1 ]; then
if [ "$i" = '{' ]; then
open_brackets=$((open_brackets+1))
elif [ "$i" = '}' ]; then
closed_brackets=$((closed_brackets+1))
fi
fi
if [ "$open_brackets" -ne 0 ] && [ "$open_brackets" -eq "$closed_brackets" ]; then
command printf '%s' "$engines_node_value" \
| nvm_grep -o '"node": \?"[|<> [:alnum:].^=~*-]\+"' \
| command tr -d '"' \
| command awk -F: '{ print $2 }' \
| command sed 's/^ //; s/ $//; s/^ //'
return 0
fi
done
return 1
}
nvm_package_json_version() {
export RESOLVED_PKG_JSON_VERSION=''
local pkg_json_path
pkg_json_path=$(nvm_find_package_json)
if [ ! -e "${pkg_json_path}" ]; then
nvm_err "No package.json file found"
return 1
fi
local pkg_json_semver
pkg_json_semver=$(nvm_get_node_from_pkg_json "$(command cat "$pkg_json_path")" || command printf '')
if [ ! -n "${pkg_json_semver}" ]; then
nvm_err "Warning: could not retrieve engines.node semver expression in package.json file found at \"${pkg_json_path}\""
return 1
else
nvm_echo "Found '${pkg_json_path}' with semver expression <${pkg_json_semver}>"
# attempt complex semver range evaluation
RESOLVED_PKG_JSON_VERSION=$(nvm_interpret_node_semver "$pkg_json_semver")
if [ ! -n "${RESOLVED_PKG_JSON_VERSION}" ]; then
nvm_err "Warning: could not interpret engines.node semver expression obtained from package.json file."
return 1
fi
fi
}
nvm_find_nvmrc() {
local dir
@ -2603,14 +3113,19 @@ nvm() {
shift
fi
else
nvm_rc_version
if [ $version_not_provided -eq 1 ] && [ -z "$NVM_RC_VERSION" ]; then
nvm_rc_version || nvm_package_json_version
if [ -n "${NVM_RC_VERSION-}" ]; then
provided_version="$NVM_RC_VERSION"
elif [ -n "${RESOLVED_PKG_JSON_VERSION-}" ]; then
provided_version="$RESOLVED_PKG_JSON_VERSION"
elif [ $version_not_provided -eq 1 ]; then
unset NVM_RC_VERSION
unset RESOLVED_PKG_JSON_VERSION
>&2 nvm --help
return 127
fi
provided_version="$NVM_RC_VERSION"
unset NVM_RC_VERSION
unset RESOLVED_PKG_JSON_VERSION
fi
elif [ $# -gt 0 ]; then
shift
@ -2954,12 +3469,20 @@ nvm() {
if [ -n "${NVM_LTS-}" ]; then
VERSION="$(nvm_match_version "lts/${NVM_LTS:-*}")"
elif [ -z "${PROVIDED_VERSION-}" ]; then
nvm_rc_version
nvm_rc_version || nvm_package_json_version
if [ -n "${NVM_RC_VERSION-}" ]; then
PROVIDED_VERSION="$NVM_RC_VERSION"
VERSION="$(nvm_version "$PROVIDED_VERSION")"
elif [ -n "${RESOLVED_PKG_JSON_VERSION-}" ]; then
PROVIDED_VERSION="$RESOLVED_PKG_JSON_VERSION"
else
unset NVM_RC_VERSION
unset RESOLVED_PKG_JSON_VERSION
>&2 nvm --help
return 127
fi
VERSION="$(nvm_version "$PROVIDED_VERSION")"
unset NVM_RC_VERSION
unset RESOLVED_PKG_JSON_VERSION
else
VERSION="$(nvm_match_version "$PROVIDED_VERSION")"
fi
@ -3550,6 +4073,9 @@ nvm() {
nvm_sanitize_path nvm_has_colors nvm_process_parameters \
node_version_has_solaris_binary iojs_version_has_solaris_binary \
nvm_curl_libz_support nvm_command_info \
nvm_get_node_from_pkg_json nvm_find_package_json nvm_package_json_version \
nvm_interpret_node_semver nvm_interpret_simple_semver nvm_interpret_complex_semver nvm_normalize_semver \
nvm_is_normalized_semver nvm_string_contains_regexp nvm_trim_and_reduce_whitespace_to_one_space \
> /dev/null 2>&1
unset NVM_RC_VERSION NVM_NODEJS_ORG_MIRROR NVM_IOJS_ORG_MIRROR NVM_DIR \
NVM_CD_FLAGS NVM_BIN NVM_MAKE_JOBS \

View File

@ -0,0 +1,118 @@
#!/bin/sh
\. ../../../nvm.sh
\. ../../generated_semvers.sh
# This test suite validates the behavior of extracting the semver from a package.json's engine.node value given valid/invalid semvers and valid/invalid json structures.
# (TEST 1 POSITIVE TEST CASES)
# SEMVERS: valid
# PACKAGE.JSON TEMPLATES: invalid
test_cases="$VALID_SEMVERS_FOR_PKG_JSON"
if [ -z "$test_cases" ]; then
die 'TEST 1 for nvm_get_node_from_pkg_json given an empty set of test cases'
fi
prev_semver=''
for template_file_name in package_json_templates/_valid_*; do
while [ -n "$test_cases" ]; do
semver=$(echo "$test_cases" | head -n1)
test_cases=$(echo "$test_cases" | tail -n +2)
[ -n "$semver" ] || continue
expectedOutput=$(nvm_trim_and_reduce_whitespace_to_one_space "$semver")
if [ "$prev_semver" = "$semver" ]; then
die "Problem iterating through test_cases (TEST 1). Encountered the same value twice in a row. prev_semver='$prev_semver' semver='$semver'.\n"
fi
prev_semver="$semver"
pkg_json_contents=$(sed "s/NODE_SEMVER/$semver/g" "$template_file_name" | tail -n +3)
actual_output=$(nvm_get_node_from_pkg_json "$pkg_json_contents")
if [ "$actual_output" != "$expectedOutput" ] || [ -z "$actual_output" ] || [ -z "$pkg_json_contents" ]; then
die "'nvm_get_node_from_pkg_json' POSITIVE test case failed (TEST 1). Expected '$expectedOutput' but got '$actual_output' when given input '$semver' and template '$template_file_name':\n$pkg_json_contents"
fi
done
done
# (TEST 2 NEGATIVE TEST CASES)
# SEMVERS: valid
# PACKAGE.JSON TEMPLATES: invalid
test_cases="$VALID_SEMVERS_FOR_PKG_JSON"
if [ -z "$test_cases" ]; then
die 'TEST 2 for nvm_get_node_from_pkg_json given an empty set of test cases'
fi
prev_semver=''
for template_file_name in package_json_templates/_invalid_*; do
while [ -n "$test_cases" ]; do
semver=$(echo "$test_cases" | head -n1)
test_cases=$(echo "$test_cases" | tail -n +2)
[ -n "$semver" ] || continue
if [ "$prev_semver" = "$semver" ]; then
die "Problem iterating through test_cases (TEST 2). Encountered the same value twice in a row. prev_semver='$prev_semver' semver='$semver'.\n"
fi
prev_semver="$semver"
pkg_json_contents=$(sed "s/NODE_SEMVER/$semver/g" "$template_file_name" | tail -n +3)
actual_output=$(nvm_get_node_from_pkg_json "$pkg_json_contents")
if [ "$actual_output" != "" ] || [ -z "$semver" ] || [ -z "$pkg_json_contents" ]; then
die "'nvm_get_node_from_pkg_json' NEGATIVE test case failed (TEST 2). Expected to get empty string but got '$actual_output' when given input template '$template_file_name':\n$pkg_json_contents"
fi
done
done
# (TEST 3 NEGATIVE TEST CASES)
# SEMVERS: invalid
# PACKAGE.JSON TEMPLATES: valid
test_cases="$INVALID_SEMVERS_FOR_PKG_JSON"
if [ -z "$test_cases" ]; then
die 'TEST 3 for nvm_get_node_from_pkg_json given an empty set of test cases'
fi
prev_semver=''
for template_file_name in package_json_templates/_valid_*; do
while [ -n "$test_cases" ]; do
semver=$(echo "$test_cases" | head -n1)
[ -n "$semver" ] || continue
test_cases=$(echo "$test_cases" | tail -n +2)
if [ "$prev_semver" = "$semver" ]; then
die "Problem iterating through test_cases (TEST 3). Encountered the same value twice in a row. prev_semver='$prev_semver' semver='$semver'.\n"
fi
prev_semver="$semver"
pkg_json_contents=$(sed "s/NODE_SEMVER/$semver/g" "$template_file_name" | tail -n +3)
actual_output=$(nvm_get_node_from_pkg_json "$pkg_json_contents")
if [ "$actual_output" != "" ] || [ -z "$semver" ] || [ -z "$pkg_json_contents" ]; then
die "'nvm_get_node_from_pkg_json' NEGATIVE test case failed (TEST 3). Expected to get empty string but got '$actual_output' when given input template '$template_file_name':\n$pkg_json_contents"
fi
done
done
# (TEST 4 NEGATIVE TEST CASES)
# SEMVERS: invalid
# PACKAGE.JSON TEMPLATES: invalid
test_cases="$INVALID_SEMVERS_FOR_PKG_JSON"
if [ -z "$test_cases" ]; then
die 'TEST 4 for nvm_get_node_from_pkg_json given an empty set of test cases'
fi
prev_semver=''
for template_file_name in package_json_templates/_invalid_*; do
while [ -n "$test_cases" ]; do
semver=$(echo "$test_cases" | head -n1)
[ -n "$semver" ] || continue
test_cases=$(echo "$test_cases" | tail -n +2)
if [ "$prev_semver" = "$semver" ]; then
die "Problem iterating through test_cases (TEST 4). Encountered the same value twice in a row. prev_semver='$prev_semver' semver='$semver'.\n"
fi
prev_semver="$semver"
pkg_json_contents=$(sed "s/NODE_SEMVER/$semver/g" "$template_file_name" | tail -n +3)
actual_output=$(nvm_get_node_from_pkg_json "$pkg_json_contents")
if [ "$actual_output" != "" ] || [ -z "$semver" ] || [ -z "$pkg_json_contents" ]; then
die "'nvm_get_node_from_pkg_json' NEGATIVE test case failed (TEST 4). Expected to get empty string but got '$actual_output' when given input template '$template_file_name':\n$pkg_json_contents"
fi
done
done
exit 0

View File

@ -0,0 +1,44 @@
#!/bin/sh
\. ../../../nvm.sh
\. ../../generated_semvers.sh
# nvm_is_normalized_semver validates that a given semver adheres to a particular grammar. See grammar with definition of function nvm_is_normalized_semver() in nvm.sh.
# POSITIVE TEST CASES
positive_test_cases="$VALID_NORMALIZED_SEMVERS"
if [ -z "$positive_test_cases" ]; then
die 'positive test cases are empty'
fi
prev_semver=''
while [ -n "$positive_test_cases" ]; do
semver=$(echo "$positive_test_cases" | head -n1)
if [ -z "$semver" ] || ! nvm_is_normalized_semver "$semver"; then
die "nvm_is_normalized_semver POSITIVE test case failed. semver: '$semver'.\n"
fi
if [ "$prev_semver" = "$semver" ]; then
die "something is wrong. positive test cases received the same test case twice in a row. semver: '$semver'"
fi
prev_semver="$semver"
positive_test_cases=$(echo "$positive_test_cases" | tail -n +2)
done
# NEGATIVE TEST CASES
negative_test_cases=$(printf "%s\n%s" "$VALID_NON_NORMALIZED_SEMVERS" "$INVALID_SEMVERS_FOR_PKG_JSON")
if [ -z "$negative_test_cases" ]; then
die 'negative test cases are empty'
fi
prev_semver='initialized to non empty string'
while [ -n "$negative_test_cases" ]; do
semver=$(echo "$negative_test_cases" | head -n1)
if nvm_is_normalized_semver "$semver"; then
die "nvm_is_normalized_semver NEGATIVE test case failed. semver: '$semver'.\n"
fi
if [ "$prev_semver" = "$semver" ]; then
die "something is wrong. negative test cases received the same test case twice in a row. semver: '$semver'"
fi
prev_semver="$semver"
negative_test_cases=$(echo "$negative_test_cases" | tail -n +2)
done
exit 0

View File

@ -0,0 +1,102 @@
#!/bin/sh
\. ../../../nvm.sh
\. ../../generated_semvers.sh
# This test suite validates the behavior of normalizing a semver from its raw form to a specific grammar. See the grammar defined with nvm_is_normalized_semver() in nvm.sh.
# TEST 1: Validate that for already normalized semvers, nvm_normalize_semver outputs the same semver.
test_cases="$VALID_NORMALIZED_SEMVERS"
if [ -z "$test_cases" ]; then
die 'nvm_normalize_semver (TEST 1) was given an empty set of test cases'
fi
while [ -n "$test_cases" ]; do
semver=$(echo "$test_cases" | head -n1)
actual_output=$(nvm_normalize_semver "$semver")
if [ -z "$semver" ] || [ "$semver" != "$actual_output" ]; then
die "nvm_normalize_semver (TEST 1) test case failed. Expected output: '$semver'. Actual output: '$actual_output'. Input: '$semver'.\n"
fi
test_cases=$(echo "$test_cases" | tail -n +2)
done
# TEST 2: Validate that non normalized valid semvers produce a normalized result
test_cases="$VALID_NON_NORMALIZED_SEMVERS"
if [ -z "$test_cases" ]; then
die 'nvm_normalize_semver (TEST 2) was given an empty set of test cases'
fi
while [ -n "$test_cases" ]; do
semver=$(echo "$test_cases" | head -n1)
actual_output=$(nvm_normalize_semver "$semver")
if [ -z "$semver" ] || [ -z "$actual_output" ] || [ "$semver" = "$actual_output" ]; then
die "nvm_normalize_semver (TEST 2) test case failed. Expected output: '$semver'. Actual output: '$actual_output'. Input: '$semver'.\n"
fi
test_cases=$(echo "$test_cases" | tail -n +2)
done
# TEST 3: Validate specific outputs for some specific inputs to nvm_normalize_semver.
# input:expected_output
test_cases="1.2.3:1.2.3
1.2.3 - 1.2.4:>=1.2.3 <=1.2.4
1.2.3-1.2.4:>=1.2.3 <=1.2.4
11.22.33 - 11.22.44:>=11.22.33 <=11.22.44
1.2.x - 1.2.4:>=1.2.0 <=1.2.4
1.2.xx - 1.2.4:
1.2.3 || 1.2.4:1.2.3 || 1.2.4
*:>0.0.0
x:>0.0.0
X:>0.0.0
1:>=1.0.0 <2.0.0
1.2:>=1.2.0 <1.3.0
< 1.2.3:<1.2.3
> 1.2.3:>1.2.3
<= 1.2.3:<=1.2.3
>= 1.2.3:>=1.2.3
= 1.2.3:1.2.3
^0.0.1 ^0.1.2 ^1.2.3:>=0.0.1 <0.0.2 >=0.1.2 <0.2.0 >=1.2.3 <2.0.0
~0.0.1 ~0.1.2 ~1.2.3:>=0.0.1 <0.1.0 >=0.1.2 <0.2.0 >=1.2.3 <1.3.0
~ 1.2.3:>=1.2.3 <1.3.0
^ 1.2.3:>=1.2.3 <2.0.0
1.2.3 || 1.2.4 1.2.5:1.2.3 || 1.2.4 1.2.5
a:
1 || 2 a:
1 || a:
a || 1.2.3:
1.2.?:
^0.0.1:>=0.0.1 <0.0.2
<x.x.x:
>=x.1.1:>0.0.0
>x.1.1:>0.0.0
~x.1.1:>0.0.0
^x.1.1:>0.0.0
11.22.33:11.22.33"
if [ -z "$test_cases" ]; then
die 'nvm_normalize_semver (TEST 3) was given an empty set of test cases'
fi
while [ -n "$test_cases" ]; do
line=$(echo "$test_cases" | head -n1)
input=$(echo "$line" | awk -F: '{ print $1 }')
expected_output=$(echo "$line" | awk -F: '{ print $2 }')
actual_output=$(nvm_normalize_semver "$input")
if [ -z "$input" ] || [ "$actual_output" != "$expected_output" ]; then
die "nvm_normalize_semver (TEST 3) test case failed. Expected output: '$expected_output'. Actual output: '$actual_output'. Input: '$input'.\n"
fi
test_cases=$(echo "$test_cases" | tail -n +2)
done
# TEST 4: Validate that invalid semvers with invalid characters that shouldn't be retrieved from the package.json produce no result from nvm_normalize_semver
test_cases="$INVALID_SEMVERS_FOR_PKG_JSON"
if [ -z "$test_cases" ]; then
die 'nvm_normalize_semver (TEST 4) was given an empty set of test cases'
fi
while [ -n "$test_cases" ]; do
semver=$(echo "$test_cases" | head -n1)
actual_output=$(nvm_normalize_semver "$semver")
if [ -z "$semver" ] || [ -n "$actual_output" ]; then
die "nvm_normalize_semver (TEST 4) test case failed. Expected no output but got: '$actual_output'. Input: '$semver'.\n"
fi
test_cases=$(echo "$test_cases" | tail -n +2)
done
exit 0

View File

@ -0,0 +1,30 @@
#!/bin/sh
\. ../../../nvm.sh
\. ../../generated_semvers.sh
normalized_semver_regexp='^( ?(<|<=|>|>=)?[0-9]+\.[0-9]+\.[0-9]+)+( \|\| ( ?(<|<=|>|>=)?[0-9]+\.[0-9]+\.[0-9]+)+)*$'
# Validates the behavior of nvm_string_contains_regexp() which returns 0 if the given string contains the given regular expression.
# POSITIVE TEST CASES
test_cases="$VALID_NORMALIZED_SEMVERS"
while [ -n "$test_cases" ]; do
string=$(echo "$test_cases" | head -n1)
if [ -z "$normalized_semver_regexp" ] || [ -z "$string" ] || ! nvm_string_contains_regexp "$string" "$normalized_semver_regexp"; then
die "nvm_string_contains_regexp POSITIVE test case failed. regexp: '$normalized_semver_regexp'. string: '$string'.\n"
fi
test_cases=$(echo "$test_cases" | tail -n +2)
done
# NEGATIVE TEST CASES
# string:regexp
test_cases=$(printf "%s\n%s" "$VALID_NON_NORMALIZED_SEMVERS" "$INVALID_SEMVERS_FOR_PKG_JSON")
while [ -n "$test_cases" ]; do
string=$(echo "$test_cases" | head -n1)
if [ -z "$normalized_semver_regexp" ] || nvm_string_contains_regexp "$string" "$normalized_semver_regexp"; then
die "nvm_string_contains_regexp NEGATIVE test case failed. regexp: '$normalized_semver_regexp'. string: '$string'.\n"
fi
test_cases=$(echo "$test_cases" | tail -n +2)
done
exit 0

View File

@ -0,0 +1,53 @@
#!/bin/sh
\. ../../../nvm.sh
die () { printf "$@" ; exit 1; }
# Validates the behavior of nvm_trim_and_reduce_whitespace_to_one_space() which consolidates all consecutive white space to one space, and then trims any spaces from the ends.
# Test cases that have no new lines
# input:expected_output
test_cases='1:1
1 2 3:1 2 3
1.1 2.2 :1.1 2.2
1.2.3:1.2.3
1 1 :1 1
2 2 :2 2'
while [ -n "$test_cases" ]; do
line=$(echo "$test_cases" | head -n1)
input=$(echo "$line" | awk -F: '{ print $1 }')
expected_output=$(echo "$line" | awk -F: '{ print $2 }')
actual_output=$(nvm_trim_and_reduce_whitespace_to_one_space "$input")
if [ -z "$input" ] || [ -z "$expected_output" ] || [ "$expected_output" != "$actual_output" ]; then
die "nvm_reduce_whitespace_to_one_space test case failed. expected_output: '$expected_output'. actual_output: '$actual_output'.\n"
fi
test_cases=$(echo "$test_cases" | tail -n +2)
done
# Test cases that have new lines
expected_output='1 2 3'
test_case_with_new_line_1=' 1
2 3 '
actual_output=$(nvm_trim_and_reduce_whitespace_to_one_space "$test_case_with_new_line_1")
if [ "$actual_output" != "$expected_output" ]; then
die "nvm_trim_and_reduce_whitespace_to_one_space test with test_case_with_new_line_1 failed. Actual output: '$actual_output' Expected output: '$expected_output'"
fi
test_case_with_new_line_2=' 1 2
3 '
actual_output=$(nvm_trim_and_reduce_whitespace_to_one_space "$test_case_with_new_line_2")
if [ "$actual_output" != "$expected_output" ]; then
die "nvm_trim_and_reduce_whitespace_to_one_space test with test_case_with_new_line_2 failed. Actual output: '$actual_output' Expected output: '$expected_output'"
fi
test_case_with_new_line_3=' 1
2
3'
actual_output=$(nvm_trim_and_reduce_whitespace_to_one_space "$test_case_with_new_line_3")
if [ "$actual_output" != "$expected_output" ]; then
die "nvm_trim_and_reduce_whitespace_to_one_space test with test_case_with_new_line_3 failed. Actual output: '$actual_output' Expected output: '$expected_output'"
fi
exit 0

View File

@ -0,0 +1,6 @@
verifies incompatibility with package.json that is missing 'engines' key
{
"name": "fake",
"description": "fake"
}

View File

@ -0,0 +1,9 @@
verifies incompatibility with package.json that is missing 'engines.node' key
{
"name": "fake",
"engines": {
"npm": "fake"
},
"description": "fake"
}

View File

@ -0,0 +1,9 @@
verifies incompatibility with package.json that is missing quotes around the 'engines'node' value
{
"name": "fake",
"engines": {
"node": NODE_SEMVER
},
"description": "fake"
}

View File

@ -0,0 +1,9 @@
verifies compatibility with basic package.json with keys in the 'engines' object that have brackets
{
"name": "fake",
"engines": {
"potentialFutureKeyWithBracket}": "fake",
"node": "NODE_SEMVER"
}
}

View File

@ -0,0 +1,9 @@
verifies compatibility with basic package.json indented with spaces
{
"name": "fake",
"engines": {
"node": "NODE_SEMVER"
},
"description": "fake"
}

View File

@ -0,0 +1,9 @@
verifies compatibility with basic package.json indented with tabs
{
"name": "fake",
"engines": {
"node": "NODE_SEMVER"
},
"description": "fake"
}

View File

@ -0,0 +1,9 @@
verifies compatibility with basic package.json with tabs in the 'engines.node' value
{
"name": "fake",
"engines": {
"node": " NODE_SEMVER "
},
"description": "fake"
}

196
test/generated_semvers.sh Executable file
View File

@ -0,0 +1,196 @@
#!/bin/sh
NEWEST_NODE_VERSION=$(nvm_remote_version | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+')
NEWEST_NODE_VERSION_5='5.12.0'
# The only operators prefixing versions that would be acceptable inputs to the semver interpretation logic.
VALID_NORMALIZED_SEMVER_OPERATORS='<
>
<=
>='
# Valid semver operators that would be acceptable to find prefixing a semver in a package.json file, but would need to be validated/normalized before interpretting.
VALID_NON_NORMALIZED_SEMVER_OPERATORS='v
=
~
^'
# Versions (stripped of any operators) that are considered valid inputs to the semver interpretation logic.
VALID_NORMALIZED_VERSIONS='4.1.0
0.12.18
8.0.0
6.11.4
10.0.0'
# Semvers that won't be pulled from package.json files because they contain characters that are not included in valid semvers
INVALID_SEMVERS_FOR_PKG_JSON='&1
#
$
@
!
%
&
)
(
+
@1
#1
$1
%s
1)
1(
1_
1+
1]
1[
1"
1:
1?
1`
1!'
# Semvers that won't resolve to a node version
INVALID_SEMVERS="$INVALID_SEMVERS_FOR_PKG_JSON
~1
^1
-
=
^
1
a
asdf
1111
1 1
1.
1.2
11.222
1.2.a
1.*.*
1.x.x
11.22.a
=1.2.3
1.1.1 2.2.2
>1.1.1 <1.1.0
1.2 - 1.3
10.221.32 - 10.21.33
10.212 - 10.22
1.2.3 - 1.2.4
1.2.3-1.2.4
1.2 1.3
10 20
1||2
>1000
<0"
# Valid semvers that should resolve to a node version and are slightly more complex than the [operator][version] structure
VALID_NORMALIZED_COMPLEX_SEMVERS='10.3.0 || 8.1.1 || 4.1.0
7.7.2 || >=9.0.0 <=8.9.0 || <8.2.1
8.2.0 8.2.0
>4.0.0 <=5.0.0
8.0.0 || <6.12.0'
# Valid semvers that should resolve to a node version but need to be validated/normalized before interpretting.
VALID_NON_NORMALIZED_COMPLEX_SEMVERS='x
10
~10
^10
X
*
x.x
X.X
*.*
10.x
~10.x
^10.x
10.X.X
~10.X.X
^10.X.X
x.x.x
~X.X.X
^X.X.X
X.X.X
x.X.*
*.x.X
x.1.2
>1.1.1 <6.2.2
> 1.1.1 <6.2.2
10 - 11
10-11
4.2.2||8.1.1
4.2 || 1.3
4 || 2'
# Strings that should be extracted from a package.json engines.node value but don't need to resolve to a node version.
VALID_COMPLEX_SEMVERS_FOR_PKG_JSON="$VALID_NORMALIZED_COMPLEX_SEMVERS
<1.2.3>
<1.2>
<1>
>>1
<<1
==1
**
xx
^^1
~~1
10.211.32-10.211.33
10.211-10.222
1 1
2 2 "
die () { printf "$@" ; exit 1; }
generate_semvers() {
versions="${1-}"
operators="${2-}"
should_add_spacing_permutations=${3-1}
if [ -z "$versions" ] || [ -z "$operators" ]; then
die "Problem generating semvers: Given invalid parameters. versions: '$versions' operators: '$operators'"
fi
while [ -n "$versions" ]; do
version=$(echo "$versions" | head -n1)
versions=$(echo "$versions" | tail -n +2)
operators_copy="$operators"
while [ -n "$operators_copy" ]; do
operator=$(echo "$operators_copy" | head -n1)
operators_copy=$(echo "$operators_copy" | tail -n +2)
if [ -z "$semvers" ]; then
# NOTE: the third spacing permutation of the operator has a tab between the operator and version.
if [ $should_add_spacing_permutations -eq 0 ]; then
semvers=$(printf "%s\n%s\n%s" "${operator}${version}" "${operator} ${version}" "${operator} ${version}")
else
semvers="${operator}${version}"
fi
else
# NOTE: the third spacing permutation of the operator has a tab between the operator and version.
if [ $should_add_spacing_permutations -eq 0 ]; then
semvers=$(printf "%s\n%s\n%s\n%s" "$semvers" "${operator}${version}" "${operator} ${version}" "${operator} ${version}")
else
semvers=$(printf "%s\n%s" "$semvers" "${operator}${version}")
fi
fi
done
done
echo "$semvers"
}
VALID_NORMALIZED_SEMVERS=$(printf "%s\n%s\n%s" \
"$VALID_NORMALIZED_COMPLEX_SEMVERS" \
"$VALID_NORMALIZED_VERSIONS" \
"$(generate_semvers "$VALID_NORMALIZED_VERSIONS" "$VALID_NORMALIZED_SEMVER_OPERATORS")" \
)
VALID_NON_NORMALIZED_SEMVERS=$(printf "%s\n%s" \
"$VALID_NON_NORMALIZED_COMPLEX_SEMVERS" \
"$(generate_semvers "$VALID_NORMALIZED_VERSIONS" "$VALID_NON_NORMALIZED_SEMVER_OPERATORS" 0)" \
)
VALID_SEMVERS=$(printf "%s\n%s" \
"$VALID_NORMALIZED_SEMVERS" \
"$VALID_NON_NORMALIZED_SEMVERS" \
)
VALID_SEMVERS_FOR_PKG_JSON=$(printf "%s\n%s" \
"$VALID_SEMVERS" \
"$VALID_COMPLEX_SEMVERS_FOR_PKG_JSON" \
)

View File

@ -0,0 +1,80 @@
#!/bin/sh
die () { printf "$@" ; exit 1; }
\. ../../nvm.sh
\. ../generated_semvers.sh
# Verify that all generated valid normalized semvers produce some result
test_cases="$VALID_SEMVERS"
while [ -n "$test_cases" ]; do
semver=$(echo "$test_cases" | head -n1)
test_cases=$(echo "$test_cases" | tail -n +2)
output=$(nvm_interpret_node_semver "$semver")
if [ -z "$semver" ] || [ -z "$output" ] || ! nvm_string_contains_regexp "$output" '^[0-9]+\.[0-9]+\.[0-9]+$'; then
die "nvm_interpret_node_semver generated positive test case failed expecting a version to be outputted: semver: '$semver' output: '$output'"
fi
done
# Verify that all generated invalid normalized semvers do not produce a result
test_cases="$INVALID_SEMVERS"
while [ -n "$test_cases" ]; do
semver=$(echo "$test_cases" | head -n1)
test_cases=$(echo "$test_cases" | tail -n +2)
output=$(nvm_interpret_node_semver "$semver")
if [ -z "$semver" ] || [ -n "$output" ]; then
die "nvm_interpret_node_semver generated negative test case failed: semver: '$semver' output: '$output'"
fi
done
# Verify actual outputs given some inputs
# input:expected_output
test_cases="*:$NEWEST_NODE_VERSION
^5:$NEWEST_NODE_VERSION_5
^5.0:$NEWEST_NODE_VERSION_5
^5.x:$NEWEST_NODE_VERSION_5
^5.X:$NEWEST_NODE_VERSION_5
^5.*:$NEWEST_NODE_VERSION_5
~5:$NEWEST_NODE_VERSION_5
~5.0:$NEWEST_NODE_VERSION_5
~5.x:$NEWEST_NODE_VERSION_5
~5.X:$NEWEST_NODE_VERSION_5
~5.*:$NEWEST_NODE_VERSION_5
5:$NEWEST_NODE_VERSION_5
x:$NEWEST_NODE_VERSION
X:$NEWEST_NODE_VERSION
x.x.x:$NEWEST_NODE_VERSION
0.12.18:0.12.18
0.11.16:0.11.16
7.0.0||7.2.1:7.2.1
7-8:8.0.0
7.0:7.0.0
^7.0.0:7.10.1
~8.1.0:8.1.4
^7.0.0||6.8.1:7.10.1
>0.12.18:$NEWEST_NODE_VERSION
>=0.11.16:$NEWEST_NODE_VERSION
7.1.0 || 7.3.0 || 7.2.0:7.3.0
7.1.0 7.3.0 7.2.0:
5:$NEWEST_NODE_VERSION_5
5.x:$NEWEST_NODE_VERSION_5
5.x.x:$NEWEST_NODE_VERSION_5
5.X:$NEWEST_NODE_VERSION_5
5.X.X:$NEWEST_NODE_VERSION_5
7.5.0:7.5.0"
while [ -n "$test_cases" ]; do
line=$(echo "$test_cases" | head -n1)
input=$(echo "$line" | awk -F: '{ print $1 }')
expected_output=$(echo "$line" | awk -F: '{ print $2 }')
test_cases=$(echo "$test_cases" | tail -n +2)
actualOutput=$(nvm_interpret_node_semver "$input")
if [ "$actualOutput" != "$expected_output" ] || [ -z "$input" ]; then
die "nvm_interpret_node_semver input/output test case failed. Expected output: '$expected_output'. Actual output: '$actualOutput'. Input: '$input'.\n"
fi
done
exit 0