diff options
author | 2017-09-20 21:28:22 +0200 | |
---|---|---|
committer | 2017-09-26 20:46:26 +0200 | |
commit | 8a8ce07898a3aabce36291d13ea8a313ebd32d79 (patch) | |
tree | be9cf91621f34d4d44d327058fa6f81ee2ec752f /eclass | |
parent | dev-lang/mercury: fix failing foreign-decl-line-number unit test due to GCC d... (diff) | |
download | gentoo-8a8ce07898a3aabce36291d13ea8a313ebd32d79.tar.gz gentoo-8a8ce07898a3aabce36291d13ea8a313ebd32d79.tar.bz2 gentoo-8a8ce07898a3aabce36291d13ea8a313ebd32d79.zip |
eapi7-ver.eclass: Initial implementation of ver_test().
This should strictly follow Algorithms 3.1 to 3.7 specified in PMS:
https://projects.gentoo.org/pms/6/pms.html#x1-310003.3
Diffstat (limited to 'eclass')
-rw-r--r-- | eclass/eapi7-ver.eclass | 126 | ||||
-rwxr-xr-x | eclass/tests/eapi7-ver.sh | 112 | ||||
-rwxr-xr-x | eclass/tests/eapi7-ver_benchmark.sh | 34 |
3 files changed, 269 insertions, 3 deletions
diff --git a/eclass/eapi7-ver.eclass b/eclass/eapi7-ver.eclass index 6f8f0c0a1c37..1ad1cbe2edc2 100644 --- a/eclass/eapi7-ver.eclass +++ b/eclass/eapi7-ver.eclass @@ -16,8 +16,6 @@ # # https://bugs.gentoo.org/482170 # -# Note: version comparison function is not included currently. -# # @ROFF .SS # Version strings # @@ -185,5 +183,127 @@ ver_rs() { # revision parts), and the comparison is performed according to # the algorithm specified in the PMS. ver_test() { - die "${FUNCNAME}: not implemented" + local v1 v2 op i tail result + local -a v1comp v2comp + local match=( + "+([0-9])*(.+([0-9]))" # numeric components + "[a-z]" # letter component + "*(@(_alpha|_beta|_pre|_rc|_p)*([0-9]))" # suffixes + "-r+([0-9])" # revision + ) + + local LC_ALL=C shopt_save=$(shopt -p extglob) + shopt -s extglob + + if [[ $# -eq 2 ]]; then + v1=${PVR} + elif [[ $# -eq 3 ]]; then + v1=$1; shift + else + die "${FUNCNAME}: bad number of arguments" + fi + op=$1 + v2=$2 + + case ${op} in + -eq|-ne|-lt|-le|-gt|-ge) ;; + *) die "${FUNCNAME}: invalid operator: ${op}" ;; + esac + + # Test for both versions being valid, and split them into parts + for (( i=0; i<4; i++ )); do + tail=${v1##${match[i]}} + v1comp[i]=${v1%"${tail}"} + v1=${tail} + tail=${v2##${match[i]}} + v2comp[i]=${v2%"${tail}"} + v2=${tail} + done + # There must not be any remaining tail, and the numeric part + # must be non-empty. All other parts are optional. + [[ -z ${v1} && -z ${v2} && -n ${v1comp[0]} && -n ${v2comp[0]} ]] \ + || die "${FUNCNAME}: invalid version" + + # Compare numeric components (PMS algorithm 3.2) + _ver_cmp_num() { + local a=(${1//./ }) b=(${2//./ }) + local an=${#a[@]} bn=${#b[@]} + local i + # First component + [[ 10#${a[0]} -gt 10#${b[0]} ]] && return 2 + [[ 10#${a[0]} -lt 10#${b[0]} ]] && return 1 + for (( i=1; i<an && i<bn; i++ )); do + # Other components (PMS algorithm 3.3) + if [[ ${a[i]} == 0* || ${b[i]} == 0* ]]; then + local ap=${a[i]%%*(0)} bp=${b[i]%%*(0)} + [[ ${ap} > ${bp} ]] && return 2 + [[ ${ap} < ${bp} ]] && return 1 + else + [[ ${a[i]} -gt ${b[i]} ]] && return 2 + [[ ${a[i]} -lt ${b[i]} ]] && return 1 + fi + done + [[ ${an} -gt ${bn} ]] && return 2 + [[ ${an} -lt ${bn} ]] && return 1 + return 0 + } + + # Compare letter components (PMS algorithm 3.4) + _ver_cmp_let() { + local a=$1 b=$2 + [[ ${a} > ${b} ]] && return 2 + [[ ${a} < ${b} ]] && return 1 + return 0 + } + + # Compare suffixes (PMS algorithm 3.5) + _ver_cmp_suf() { + local a=(${1//_/ }) b=(${2//_/ }) + local an=${#a[@]} bn=${#b[@]} + local i + for (( i=0; i<an && i<bn; i++ )); do + # Compare each suffix (PMS algorithm 3.6) + if [[ ${a[i]%%*([0-9])} == "${b[i]%%*([0-9])}" ]]; then + [[ 10#${a[i]##*([a-z])} -gt 10#${b[i]##*([a-z])} ]] && return 2 + [[ 10#${a[i]##*([a-z])} -lt 10#${b[i]##*([a-z])} ]] && return 1 + else + # Check for p first + [[ ${a[i]} == p*([0-9]) ]] && return 2 + [[ ${b[i]} == p*([0-9]) ]] && return 1 + # Hack: Use that alpha < beta < pre < rc alphabetically + [[ ${a[i]} > ${b[i]} ]] && return 2 || return 1 + fi + done + if [[ ${an} -gt ${bn} ]]; then + [[ ${a[bn]} == p*([0-9]) ]] && return 2 || return 1 + elif [[ ${an} -lt ${bn} ]]; then + [[ ${b[an]} == p*([0-9]) ]] && return 1 || return 2 + fi + return 0 + } + + # Compare revision components (PMS algorithm 3.7) + _ver_cmp_rev() { + local a=${1#-r} b=${2#-r} + [[ 10#${a} -gt 10#${b} ]] && return 2 + [[ 10#${a} -lt 10#${b} ]] && return 1 + return 0 + } + + # Version comparison top-level logic (PMS algorithm 3.1) + _ver_cmp_num "${v1comp[0]}" "${v2comp[0]}" && + _ver_cmp_let "${v1comp[1]}" "${v2comp[1]}" && + _ver_cmp_suf "${v1comp[2]}" "${v2comp[2]}" && + _ver_cmp_rev "${v1comp[3]}" "${v2comp[3]}" + + case $? in + 0) result=0 ;; # a = b + 1) result=-1 ;; # a < b + 2) result=1 ;; # a > b + *) die "${FUNCNAME}: invalid return code: $?" ;; + esac + + ${shopt_save} + + test "${result}" "${op}" 0 } diff --git a/eclass/tests/eapi7-ver.sh b/eclass/tests/eapi7-ver.sh index 8a96e4d29b1b..fd085a415b6e 100755 --- a/eclass/tests/eapi7-ver.sh +++ b/eclass/tests/eapi7-ver.sh @@ -17,6 +17,15 @@ teq() { tend ${?} "returned: ${got}" } +teqr() { + local expected=$1; shift + tbegin "$* -> ${expected}" + "$@" + local ret=$? + [[ ${ret} -eq ${expected} ]] + tend $? "returned: ${ret}" +} + txf() { tbegin "XFAIL: ${*}" local got=$("${@}" 2>&1) @@ -63,3 +72,106 @@ teq 1.2.3 ver_rs 3-5 . 1.2.3 txf ver_cut foo 1.2.3 txf ver_rs -3 _ a1b2c3d4e5 txf ver_rs 5-3 _ a1b2c3d4e5 + +# Tests from Portage's test_vercmp.py +teqr 0 ver_test 6.0 -gt 5.0 +teqr 0 ver_test 5.0 -gt 5 +teqr 0 ver_test 1.0-r1 -gt 1.0-r0 +teqr 0 ver_test 999999999999999999 -gt 999999999999999998 # 18 digits +teqr 0 ver_test 1.0.0 -gt 1.0 +teqr 0 ver_test 1.0.0 -gt 1.0b +teqr 0 ver_test 1b -gt 1 +teqr 0 ver_test 1b_p1 -gt 1_p1 +teqr 0 ver_test 1.1b -gt 1.1 +teqr 0 ver_test 12.2.5 -gt 12.2b +teqr 0 ver_test 4.0 -lt 5.0 +teqr 0 ver_test 5 -lt 5.0 +teqr 0 ver_test 1.0_pre2 -lt 1.0_p2 +teqr 0 ver_test 1.0_alpha2 -lt 1.0_p2 +teqr 0 ver_test 1.0_alpha1 -lt 1.0_beta1 +teqr 0 ver_test 1.0_beta3 -lt 1.0_rc3 +teqr 0 ver_test 1.001000000000000001 -lt 1.001000000000000002 +teqr 0 ver_test 1.00100000000 -lt 1.001000000000000001 +teqr 0 ver_test 999999999999999998 -lt 999999999999999999 +teqr 0 ver_test 1.01 -lt 1.1 +teqr 0 ver_test 1.0-r0 -lt 1.0-r1 +teqr 0 ver_test 1.0 -lt 1.0-r1 +teqr 0 ver_test 1.0 -lt 1.0.0 +teqr 0 ver_test 1.0b -lt 1.0.0 +teqr 0 ver_test 1_p1 -lt 1b_p1 +teqr 0 ver_test 1 -lt 1b +teqr 0 ver_test 1.1 -lt 1.1b +teqr 0 ver_test 12.2b -lt 12.2.5 +teqr 0 ver_test 4.0 -eq 4.0 +teqr 0 ver_test 1.0 -eq 1.0 +teqr 0 ver_test 1.0-r0 -eq 1.0 +teqr 0 ver_test 1.0 -eq 1.0-r0 +teqr 0 ver_test 1.0-r0 -eq 1.0-r0 +teqr 0 ver_test 1.0-r1 -eq 1.0-r1 +teqr 1 ver_test 1 -eq 2 +teqr 1 ver_test 1.0_alpha -eq 1.0_pre +teqr 1 ver_test 1.0_beta -eq 1.0_alpha +teqr 1 ver_test 1 -eq 0.0 +teqr 1 ver_test 1.0-r0 -eq 1.0-r1 +teqr 1 ver_test 1.0-r1 -eq 1.0-r0 +teqr 1 ver_test 1.0 -eq 1.0-r1 +teqr 1 ver_test 1.0-r1 -eq 1.0 +teqr 1 ver_test 1.0 -eq 1.0.0 +teqr 1 ver_test 1_p1 -eq 1b_p1 +teqr 1 ver_test 1b -eq 1 +teqr 1 ver_test 1.1b -eq 1.1 +teqr 1 ver_test 12.2b -eq 12.2 + +# A subset of tests from Paludis +teqr 0 ver_test 1.0_alpha -gt 1_alpha +teqr 0 ver_test 1.0_alpha -gt 1 +teqr 0 ver_test 1.0_alpha -lt 1.0 +teqr 0 ver_test 1.2.0.0_alpha7-r4 -gt 1.2_alpha7-r4 +teqr 0 ver_test 0001 -eq 1 +teqr 0 ver_test 01 -eq 001 +teqr 0 ver_test 0001.1 -eq 1.1 +teqr 0 ver_test 01.01 -eq 1.01 +teqr 0 ver_test 1.010 -eq 1.01 +teqr 0 ver_test 1.00 -eq 1.0 +teqr 0 ver_test 1.0100 -eq 1.010 +teqr 0 ver_test 1-r00 -eq 1-r0 + +# Additional tests +teqr 0 ver_test 0_rc99 -lt 0 +teqr 0 ver_test 011 -eq 11 +teqr 0 ver_test 019 -eq 19 +teqr 0 ver_test 1.2 -eq 001.2 +teqr 0 ver_test 1.2 -gt 1.02 +teqr 0 ver_test 1.2a -lt 1.2b +teqr 0 ver_test 1.2_pre1 -gt 1.2_pre1_beta2 +teqr 0 ver_test 1.2_pre1 -lt 1.2_pre1_p2 +teqr 0 ver_test 1.00 -lt 1.0.0 +teqr 0 ver_test 1.010 -eq 1.01 +teqr 0 ver_test 1.01 -lt 1.1 +teqr 0 ver_test 1.2_pre08-r09 -eq 1.2_pre8-r9 +teqr 0 ver_test 0 -lt 576460752303423488 # 2**59 +#teqr 0 ver_test 0 -lt 9223372036854775808 # 2**63 fails, integer rollover + +# Bad number or ordering of arguments +txf ver_test 1 +txf ver_test 1 -lt 2 3 +txf ver_test -lt 1 2 + +# Bad operators +txf ver_test 1 "<" 2 +txf ver_test 1 lt 2 +txf ver_test 1 -foo 2 + +# Malformed versions +txf ver_test "" -ne 1 +txf ver_test 1. -ne 1 +txf ver_test 1ab -ne 1 +txf ver_test b -ne 1 +txf ver_test 1-r1_pre -ne 1 +txf ver_test 1-pre1 -ne 1 +txf ver_test 1_foo -ne 1 +txf ver_test 1_pre1.1 -ne 1 +txf ver_test 1-r1.0 -ne 1 +txf ver_test cvs.9999 -ne 9999 + +texit diff --git a/eclass/tests/eapi7-ver_benchmark.sh b/eclass/tests/eapi7-ver_benchmark.sh index 1de26444c9b3..c46713713368 100755 --- a/eclass/tests/eapi7-ver_benchmark.sh +++ b/eclass/tests/eapi7-ver_benchmark.sh @@ -76,6 +76,38 @@ replacing_versionator() { done >/dev/null } +comparing() { + local x + for x in {1..1000}; do + ver_test 1b_p1 -le 1_p1 + ver_test 1.1b -le 1.1 + ver_test 12.2.5 -le 12.2b + ver_test 4.0 -le 5.0 + ver_test 5 -le 5.0 + ver_test 1.0_pre2 -le 1.0_p2 + ver_test 1.0_alpha2 -le 1.0_p2 + ver_test 1.0_alpha1 -le 1.0_beta1 + ver_test 1.0_beta3 -le 1.0_rc3 + ver_test 1.001000000000000001 -le 1.001000000000000002 + done +} + +comparing_versionator() { + local x + for x in {1..100}; do + version_is_at_least 1b_p1 1_p1 + version_is_at_least 1.1b 1.1 + version_is_at_least 12.2.5 12.2b + version_is_at_least 4.0 5.0 + version_is_at_least 5 5.0 + version_is_at_least 1.0_pre2 1.0_p2 + version_is_at_least 1.0_alpha2 1.0_p2 + version_is_at_least 1.0_alpha1 1.0_beta1 + version_is_at_least 1.0_beta3 1.0_rc3 + version_is_at_least 1.001000000000000001 1.001000000000000002 + done +} + get_times() { local factor=${1}; shift echo "${*}" @@ -111,3 +143,5 @@ get_times 1 cutting get_times 10 cutting_versionator get_times 1 replacing get_times 10 replacing_versionator +get_times 1 comparing +get_times 10 comparing_versionator |