Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/freebsd/poudriere.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan Drewery <bryan@shatow.net>2022-11-05 18:57:06 +0300
committerBryan Drewery <bryan@shatow.net>2022-11-05 18:57:06 +0300
commit72bb09f8336c5ce957c65775040bfd0db8b7e3cc (patch)
treec6a37ec15657a11d15ee19123c0a924c776b1f0f
parente158cb8814fa6a24e9c4c5344a67d67d9d5a418e (diff)
parent1cdbb7bccda33afe142871ca75e99e7ad8849404 (diff)
Merge branch 'display_encode_args'
-rw-r--r--src/share/poudriere/include/display.sh293
-rw-r--r--src/share/poudriere/include/hash.sh120
-rw-r--r--src/share/poudriere/include/util.sh80
-rwxr-xr-xsrc/share/poudriere/jail.sh2
-rwxr-xr-xsrc/share/poudriere/ports.sh2
-rw-r--r--test/Makefile.am1
-rw-r--r--test/Makefile.in26
-rw-r--r--test/display.sh677
-rw-r--r--test/encode_args.sh72
-rw-r--r--test/hash_basic.sh17
10 files changed, 1153 insertions, 137 deletions
diff --git a/src/share/poudriere/include/display.sh b/src/share/poudriere/include/display.sh
index d4009e9c..819c465c 100644
--- a/src/share/poudriere/include/display.sh
+++ b/src/share/poudriere/include/display.sh
@@ -24,31 +24,150 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
+EX_DATAERR=65
+EX_SOFTWARE=70
+
+DISPLAY_SEP=$'\002'
+DISPLAY_USE_COLUMN=0
+DISPLAY_DYNAMIC_FORMAT_DEFAULT="%%-%ds"
+DISPLAY_TRIM_TRAILING_FIELD=1
+
display_setup() {
- [ $# -ge 1 ] || eargs display_setup format [column_sort]
- _DISPLAY_DATA=
- _DISPLAY_FORMAT="$1"
- _DISPLAY_COLUMN_SORT="${3-}"
+ [ $# -eq 1 ] || [ $# -eq 2 ] || eargs display_setup format [column_sort]
+ local IFS
+ local -; set -f
+
+ _DISPLAY_FORMAT="${1:-dynamic}"
+ _DISPLAY_HEADER=
+ _DISPLAY_COLUMN_SORT="${2-}"
+ _DISPLAY_FOOTER=
+ _DISPLAY_LINES=0
+ _DISPLAY_COLS=0
+ _DISPLAY_MAPFILE=
+ _DISPLAY_TMP=$(mktemp -t data)
+
+ mapfile _DISPLAY_MAPFILE "${_DISPLAY_TMP}" "w" ||
+ err ${EX_SOFTWARE} "mapfile"
+
+ # encode
+ set -- ${_DISPLAY_FORMAT}
+ IFS="${DISPLAY_SEP}"
+ _DISPLAY_FORMAT="$@"
+ unset IFS
+}
+
+_display_cleanup() {
+ rm -f "${_DISPLAY_TMP}" "${_DISPLAY_TMP}.filtered"
+ unset _DISPLAY_FORMAT \
+ _DISPLAY_COLUMN_SORT \
+ _DISPLAY_LINES _DISPLAY_COLS \
+ _DISPLAY_FOOTER _DISPLAY_HEADER \
+ _DISPLAY_MAPFILE _DISPLAY_TMP
}
display_add() {
- local arg
+ [ $# -gt 0 ] || eargs display_add col [col...]
+ local IFS
+
+ if [ -z "${_DISPLAY_HEADER}" ]; then
+ local arg argi line argformat format
+
+ argi=1
+ unset line
+ format=
+ for arg do
+ # Collect header custom formats if using dynamic
+ if [ "${_DISPLAY_FORMAT}" == "dynamic" ]; then
+ case "${arg}" in
+ *:*%%*)
+ argformat="${arg#*:}"
+ arg="${arg%%:*}"
+ ;;
+ *)
+ argformat="${DISPLAY_DYNAMIC_FORMAT_DEFAULT}"
+ ;;
+ esac
+ format="${format:+${format}${DISPLAY_SEP}}${argformat}"
+ fi
+ line="${line:+${line}${DISPLAY_SEP}}${arg}"
+ hash_set _display_header "${arg}" "${argi}"
+ argi=$((argi + 1))
+ done
+ _DISPLAY_COLS=$((argi - 1))
+ _DISPLAY_HEADER="${line}"
+ if [ "${_DISPLAY_FORMAT}" == "dynamic" ]; then
+ _DISPLAY_FORMAT="${format}"
+ fi
+
+ return
+ fi
# Add in newline
- [ -n "${_DISPLAY_DATA}" ] && \
- _DISPLAY_DATA="${_DISPLAY_DATA}
-"
- # Quote all arguments
- for arg do
- _DISPLAY_DATA="${_DISPLAY_DATA} '${arg}'"
+ _DISPLAY_LINES=$((_DISPLAY_LINES + 1))
+ # encode
+ IFS="${DISPLAY_SEP}"
+ line="$@"
+ unset IFS
+ mapfile_write "${_DISPLAY_MAPFILE}" "${line}" ||
+ err ${EX_SOFTWARE} "mapfile_write"
+}
+
+display_footer() {
+ local IFS
+
+ # encode
+ IFS="${DISPLAY_SEP}"
+ _DISPLAY_FOOTER="$@"
+ unset IFS
+}
+
+_display_check_lengths() {
+ local cnt arg max_length
+ local IFS
+ local -; set -f
+
+ # decode
+ IFS="${DISPLAY_SEP}"
+ set -- $@
+ unset IFS
+
+ cnt=0
+ for arg in "$@"; do
+ cnt=$((cnt + 1))
+ if [ -z "${arg}" ]; then
+ continue
+ fi
+ stripansi "${arg}" arg
+ hash_get _display_lengths "${cnt}" max_length || max_length=0
+ if [ "${#arg}" -gt "${max_length}" ]; then
+ hash_set _display_lengths "${cnt}" "${#arg}"
+ fi
done
- return 0
}
+_display_output() {
+ [ $# -eq 2 ] || eargs _display_output format data
+ local -; set -f
+ local format="$1"
+ local data="$2"
+ local IFS
+
+ # decode
+ IFS="${DISPLAY_SEP}"
+ set -- ${data}
+ unset IFS
+ printf "${format}\n" "$@"
+}
+
+# display_output [col ...]
display_output() {
- local cnt lengths length format arg flag quiet line n
- local header header_format
+ local lengths format arg flag quiet line n
+ local cols header_format
local OPTIND=1
+ local IFS
+ local -
+
+ set -f
quiet=0
@@ -65,42 +184,104 @@ display_output() {
shift $((OPTIND-1))
- format="${_DISPLAY_FORMAT}"
+ mapfile_close "${_DISPLAY_MAPFILE}" ||
+ err ${EX_SOFTWARE} "mapfile_close"
- # Determine optimal format
- n=0
- while mapfile_read_loop_redir line; do
- n=$((n + 1))
- if [ "${n}" -eq 1 ]; then
- if [ "${quiet}" -eq 1 ]; then
- continue
- fi
- header="${line}"
+ # cols to filter/reorder on
+ cols=
+ if [ "$#" -gt 0 ]; then
+ local col awktmp
+
+ if [ "$#" -gt 0 ]; then
+ _DISPLAY_COLS=0
fi
- eval "set -- ${line}"
- cnt=0
for arg in "$@"; do
- hash_get lengths ${cnt} max_length || max_length=0
- stripansi "${arg}" arg
- if [ ${#arg} -gt ${max_length} ]; then
- # Keep the hash var local to this function
- _hash_var_name "lengths" "${cnt}"
- local ${_hash_var_name}
- # Set actual value
- hash_set lengths ${cnt} ${#arg}
+ if ! hash_remove _display_header "${arg}" col; then
+ err ${EX_DATAERR:?} "No column named '${arg}'"
+ fi
+ # cols="$3,$2,$1" for awk printing
+ cols="${cols:+${cols},}\$${col}"
+ _DISPLAY_COLS=$((_DISPLAY_COLS + 1))
+ done
+
+ # Re-order and filter using awk(1) back into our internal vars.
+ awktmp=$(mktemp -t display_output)
+ {
+ echo "${_DISPLAY_FORMAT}"
+ echo "${_DISPLAY_HEADER}"
+ sort -t "${DISPLAY_SEP}" ${_DISPLAY_COLUMN_SORT} \
+ "${_DISPLAY_TMP}"
+ echo "${_DISPLAY_FOOTER}"
+ } > "${awktmp}.in"
+ awk -F"${DISPLAY_SEP}" -vOFS="${DISPLAY_SEP}" \
+ "{print ${cols}}" "${awktmp}.in" > "${awktmp}"
+ n=-1
+ while IFS= mapfile_read_loop "${awktmp}" line; do
+ case "${n}" in
+ -1)
+ _DISPLAY_FORMAT="${line}"
+ ;;
+ 0)
+ _DISPLAY_HEADER="${line}"
+ ;;
+ "$((_DISPLAY_LINES + 1))")
+ if [ -n "${_DISPLAY_FOOTER}" ]; then
+ _DISPLAY_FOOTER="${line}"
+ fi
+ ;;
+ *)
+ echo "${line}"
+ if [ "${DISPLAY_USE_COLUMN}" -eq 0 ]; then
+ _display_check_lengths "${line}"
+ fi
+ ;;
+ esac
+ n=$((n + 1))
+ done > "${_DISPLAY_TMP}.filtered"
+ rm -f "${awktmp}" "${awktmp}.in"
+ else
+ # using > rather than -o skips vfork which can't handle
+ # redirects
+ sort -t "${DISPLAY_SEP}" ${_DISPLAY_COLUMN_SORT} \
+ -o "${_DISPLAY_TMP}.filtered" "${_DISPLAY_TMP}"
+ fi
+
+ if [ "${DISPLAY_USE_COLUMN}" -eq 1 ]; then
+ {
+ if [ "${quiet}" -eq 0 ]; then
+ echo "${_DISPLAY_HEADER}"
+ fi
+ mapfile_cat "${_DISPLAY_TMP}.filtered"
+ if [ -n "${_DISPLAY_FOOTER}" ]; then
+ echo "${_DISPLAY_FOOTER}"
fi
- cnt=$((cnt + 1))
+ } | column -t -s "${DISPLAY_SEP}"
+ _display_cleanup
+ return
+ fi
+
+ # Determine optimal format from filtered data
+ _display_check_lengths "${_DISPLAY_HEADER}"
+ _display_check_lengths "${_DISPLAY_FOOTER}"
+ if [ -z "${cols}" ]; then
+ while IFS= mapfile_read_loop "${_DISPLAY_TMP}.filtered" line; do
+ _display_check_lengths "${line}"
done
- done <<-EOF
- ${_DISPLAY_DATA}
- EOF
+ fi
# Set format lengths if format is dynamic width
+ # decode
+ IFS="${DISPLAY_SEP}"
+ set -- ${_DISPLAY_FORMAT}
+ unset IFS
+ format="$@"
case "${format}" in
*%%*)
+ local length
+
set -- ${format}
lengths=
- n=0
+ n=1
for arg in "$@"; do
# Check if this is a format argument
case "${arg}" in
@@ -109,9 +290,18 @@ display_output() {
esac
case ${arg} in
*%d*)
- hash_get lengths ${n} length
+ hash_remove _display_lengths "${n}" length
+ if [ "${DISPLAY_TRIM_TRAILING_FIELD}" -eq 1 ] &&
+ [ "${n}" -eq "${_DISPLAY_COLS}" ]; then
+ case "${arg}" in
+ *-*) length=0 ;;
+ esac
+ fi
lengths="${lengths:+${lengths} }${length}"
;;
+ *)
+ hash_unset _display_lengths "${n}" || :
+ ;;
esac
n=$((n + 1))
done
@@ -119,22 +309,21 @@ display_output() {
;;
esac
- # Show header separately so it is not sorted
+ # Header
if [ "${quiet}" -eq 0 ]; then
- stripansi "${header}" header
+ stripansi "${_DISPLAY_HEADER}" _DISPLAY_HEADER
stripansi "${format}" header_format
- eval "set -- ${header}"
- printf "${header_format}\n" "$@"
+ _display_output "${header_format}" "${_DISPLAY_HEADER}"
fi
- # Sort as configured in display_setup()
- echo "${_DISPLAY_DATA}" | tail -n +2 | \
- sort ${_DISPLAY_COLUMN_SORT} | \
- while mapfile_read_loop_redir line; do
- eval "set -- ${line}"
- printf "${format}\n" "$@"
+ # Data
+ while IFS= mapfile_read_loop "${_DISPLAY_TMP}.filtered" line; do
+ _display_output "${format}" "${line}"
done
- unset _DISPLAY_DATA _DISPLAY_FORMAT \
- _DISPLAY_COLUMN_SORT
+ # Footer
+ if [ -n "${_DISPLAY_FOOTER}" ]; then
+ _display_output "${format}" "${_DISPLAY_FOOTER}"
+ fi
+ _display_cleanup
}
diff --git a/src/share/poudriere/include/hash.sh b/src/share/poudriere/include/hash.sh
index e732a512..50647694 100644
--- a/src/share/poudriere/include/hash.sh
+++ b/src/share/poudriere/include/hash.sh
@@ -35,6 +35,12 @@ if ! type eargs 2>/dev/null >&2; then
}
fi
+if ! type mapfile_read_loop_redir 2>/dev/null >&2; then
+ mapfile_read_loop_redir() {
+ read -r "$@"
+ }
+fi
+
if ! type _gsub 2>/dev/null >&2; then
# Based on Shell Scripting Recipes - Chris F.A. Johnson (c) 2005
# Replace a pattern without needing a subshell/exec
@@ -107,54 +113,77 @@ fi
_hash_var_name() {
# Replace anything not HASH_VAR_NAME_SUB_GLOB with _
- _gsub_var_name "${HASH_VAR_NAME_PREFIX}${1}_${2}" \
- _hash_var_name
+ _gsub_var_name "${HASH_VAR_NAME_PREFIX}B${1}_K${2}" _hash_var_name
}
hash_isset() {
local -; set +x
[ $# -ne 2 ] && eargs hash_isset var key
- local var="$1"
- local key="$2"
+ local _var="$1"
+ local _key="$2"
local _hash_var_name
- _hash_var_name "${var}" "${key}"
-
+ _hash_var_name "${_var}" "${_key}"
issetvar "${_hash_var_name}"
}
+hash_isset_var() {
+ local -; set +x
+ [ $# -ne 1 ] && eargs hash_isset_var var
+ local _var="$1"
+ local _line _hash_var_name ret IFS
+
+ _hash_var_name "${_var}" ""
+ ret=1
+ while IFS= mapfile_read_loop_redir _line; do
+ # XXX: mapfile_read_loop can't safely return/break
+ if [ "${ret}" -eq 0 ]; then
+ continue
+ fi
+ case "${_line}" in
+ ${_hash_var_name}*=*)
+ ret=0
+ ;;
+ *) continue ;;
+ esac
+ done <<-EOF
+ $(set)
+ EOF
+ return "${ret}"
+}
+
hash_get() {
local -; set +x
[ $# -ne 3 ] && eargs hash_get var key var_return
+ local _var="$1"
+ local _key="$2"
local _hash_var_name
- _gsub_var_name "${HASH_VAR_NAME_PREFIX}${1}_${2}" _hash_var_name
+ _hash_var_name "${_var}" "${_key}"
getvar "${_hash_var_name}" "${3}"
}
hash_set() {
local -; set +x
[ $# -eq 3 ] || eargs hash_set var key value
- local var="$1"
- local key="$2"
- local value="$3"
+ local _var="$1"
+ local _key="$2"
+ local _value="$3"
local _hash_var_name
- _hash_var_name "${var}" "${key}"
-
- # Set value in cache
- setvar "${_hash_var_name}" "${value}"
+ _hash_var_name "${_var}" "${_key}"
+ setvar "${_hash_var_name}" "${_value}"
}
hash_remove() {
local -; set +x
[ $# -ne 3 ] && eargs hash_remove var key var_return
- local var="$1"
- local key="$2"
+ local _var="$1"
+ local _key="$2"
local var_return="$3"
local _hash_var_name ret
- _hash_var_name "${var}" "${key}"
+ _hash_var_name "${_var}" "${_key}"
ret=0
getvar "${_hash_var_name}" "${var_return}" || ret=$?
if [ ${ret} -eq 0 ]; then
@@ -166,50 +195,69 @@ hash_remove() {
hash_unset() {
local -; set +x
[ $# -eq 2 ] || eargs hash_unset var key
- local var="$1"
- local key="$2"
+ local _var="$1"
+ local _key="$2"
local _hash_var_name
- _hash_var_name "${var}" "${key}"
+ _hash_var_name "${_var}" "${_key}"
unset "${_hash_var_name}"
}
+hash_unset_var() {
+ local -; set +x
+ [ $# -eq 1 ] || eargs hash_unset_var var
+ local _var="$1"
+ local _key _line _hash_var_name
+
+ _hash_var_name "${_var}" ""
+ while IFS= mapfile_read_loop_redir _line; do
+ case "${_line}" in
+ ${_hash_var_name}*=*) ;;
+ *) continue ;;
+ esac
+ _key="${_line%%=*}"
+ unset "${_key}"
+ done <<-EOF
+ $(set)
+ EOF
+}
+
list_contains() {
local -; set +x
[ $# -eq 2 ] || eargs list_contains var item
- local var="$1"
+ local _var="$1"
local item="$2"
- local value
+ local _value
- getvar "${var}" value || value=
- case " ${value} " in *" ${item} "*) ;; *) return 1 ;; esac
+ getvar "${_var}" _value || _value=
+ case " ${_value} " in *" ${item} "*) ;; *) return 1 ;; esac
return 0
}
list_add() {
local -; set +x
[ $# -eq 2 ] || eargs list_add var item
- local var="$1"
+ local _var="$1"
local item="$2"
- local value
+ local _value
- getvar "${var}" value || value=
- case " ${value} " in *" ${item} "*) return 0 ;; esac
- setvar "${var}" "${value:+${value} }${item}"
+ getvar "${_var}" _value || _value=
+ case " ${_value} " in *" ${item} "*) return 0 ;; esac
+ setvar "${_var}" "${_value:+${_value} }${item}"
}
list_remove() {
local -; set +x
[ $# -eq 2 ] || eargs list_remove var item
- local var="$1"
+ local _var="$1"
local item="$2"
- local value newvalue
+ local _value newvalue
- getvar "${var}" value || value=
- value=" ${value} "
- case "${value}" in *" ${item} "*) ;; *) return 1 ;; esac
- newvalue="${value% "${item}" *} ${value##* "${item}" }"
+ getvar "${_var}" _value || _value=
+ _value=" ${_value} "
+ case "${_value}" in *" ${item} "*) ;; *) return 1 ;; esac
+ newvalue="${_value% "${item}" *} ${_value##* "${item}" }"
newvalue="${newvalue# }"
newvalue="${newvalue% }"
- setvar "${var}" "${newvalue}"
+ setvar "${_var}" "${newvalue}"
}
diff --git a/src/share/poudriere/include/util.sh b/src/share/poudriere/include/util.sh
index 3fd31ebd..c301fafe 100644
--- a/src/share/poudriere/include/util.sh
+++ b/src/share/poudriere/include/util.sh
@@ -43,49 +43,61 @@ encode_args() {
[ $# -ge 1 ] || eargs encode_args var_return [args]
local var_return="$1"
shift
- local _args lastempty
+ local _args IFS
- _args=
- lastempty=0
- while [ "$#" -gt 0 ]; do
- _args="${_args}${_args:+${ENCODE_SEP}}${1}"
- [ "$#" -eq 1 -a -z "$1" ] && lastempty=1
- shift
- done
- # If the string ends in ENCODE_SEP then add another to
- # fix 'set' later eating it.
- [ "${lastempty}" -eq 1 ] && _args="${_args}${_args:+${ENCODE_SEP}}"
-
- setvar "${var_return}" "${_args}"
+ IFS="${ENCODE_SEP}"
+ _args="$@"
+ unset IFS
+ # Trailing empty fields need special handling.
+ case "${_args}" in
+ *"${ENCODE_SEP}")
+ setvar "${var_return}" "${_args}${ENCODE_SEP}"
+ ;;
+ *)
+ setvar "${var_return}" "${_args}"
+ ;;
+ esac
}
# Decode data from encode_args
-# Usage: eval $(decode_args data_var_name)
+# Usage: eval "$(decode_args data_var_name)"
decode_args() {
local -; set +x
[ $# -eq 1 ] || eargs decode_args encoded_args_var
local encoded_args_var="$1"
+ local _decode_args
- # oldIFS="${IFS}"; IFS="${ENCODE_SEP}"; set -- ${data}; IFS="${oldIFS}"; unset oldIFS
- echo "\
- local IFS 2>/dev/null || :; \
- case \$- in *f*) set_f=1 ;; *) set_f=0 ;; esac; \
- [ \"\${set_f}\" -eq 0 ] && set -f; \
- IFS=\"\${ENCODE_SEP}\"; \
- set -- \${${encoded_args_var}}; \
- unset IFS; \
- [ \"\${set_f}\" -eq 0 ] && set +f; \
- unset set_f; \
- "
+ _decode_args _decode_args "${encoded_args_var}"
+ echo "${_decode_args}"
}
+# Decode data from encode_args without a fork
+# Usage: _decode_args evalstr data_var_name; eval "${evalstr}"; unset evalstr
+_decode_args() {
+ local -; set +x
+ [ $# -eq 2 ] || eargs decode_args var_return_eval encoded_args_var
+ local var_return_eval="$1"
+ local encoded_args_var="$2"
+
+ # local -; set -f; IFS="${ENCODE_SEP}"; set -- ${data}; unset IFS
+ setvar "${var_return_eval}" "
+ local IFS 2>/dev/null || :;
+ case \$- in *f*) set_f=1 ;; *) set_f=0 ;; esac;
+ [ \"\${set_f}\" -eq 0 ] && set -f;
+ IFS=\"\${ENCODE_SEP}\";
+ set -- \${${encoded_args_var}};
+ unset IFS;
+ [ \"\${set_f}\" -eq 0 ] && set +f;
+ unset set_f;
+ "
+}
# Decode data from encode_args
decode_args_vars() {
local -; set +x -f
[ $# -ge 2 ] || eargs decode_args_vars data var1 [var2... varN]
local encoded_args_data="$1"
- local _value _var _vars IFS
+ local _value _var IFS
shift
local _vars="$*"
@@ -93,15 +105,21 @@ decode_args_vars() {
set -- ${encoded_args_data}
unset IFS
for _value; do
+ # Select the next var to populate.
_var="${_vars%% *}"
- _vars="${_vars#${_var} }"
- if [ "${_var}" = "${_vars}" ]; then
+ case "${_vars}" in
+ # Last one - set all remaining to here
+ ${_var})
setvar "${_var}" "$*"
break
- else
+ ;;
+ *)
setvar "${_var}" "${_value}"
- fi
- shift
+ # Pop off the var
+ _vars="${_vars#${_var} }"
+ shift
+ ;;
+ esac
done
}
diff --git a/src/share/poudriere/jail.sh b/src/share/poudriere/jail.sh
index 5c901d1a..725fa115 100755
--- a/src/share/poudriere/jail.sh
+++ b/src/share/poudriere/jail.sh
@@ -93,7 +93,7 @@ list_jail() {
local j name version arch method mnt timestamp time
if [ ${NAMEONLY} -eq 0 ]; then
- format='%%-%ds %%-%ds %%-%ds %%-%ds %%-%ds %%s'
+ format='%%-%ds %%-%ds %%-%ds %%-%ds %%-%ds %%-%ds'
display_setup "${format}" "-d -k2,2V -k3,3 -k1,1"
display_add "JAILNAME" "VERSION" "ARCH" "METHOD" \
"TIMESTAMP" "PATH"
diff --git a/src/share/poudriere/ports.sh b/src/share/poudriere/ports.sh
index 0ee72948..d08cdb87 100755
--- a/src/share/poudriere/ports.sh
+++ b/src/share/poudriere/ports.sh
@@ -193,7 +193,7 @@ fi
case $COMMAND in
list)
if [ ${NAMEONLY} -eq 0 ]; then
- format='%%-%ds %%-%ds %%-%ds %%s\n'
+ format='%%-%ds %%-%ds %%-%ds %%-%ds\n'
display_setup "${format}" "-d"
display_add "PORTSTREE" "METHOD" "TIMESTAMP" "PATH"
else
diff --git a/test/Makefile.am b/test/Makefile.am
index bee11dd9..ecb680b9 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -8,6 +8,7 @@ EXTRA_DIST= $(TESTS) \
TESTS=\
builtins.sh \
cache.sh \
+ display.sh \
do_clone.sh \
encode_args.sh \
getpid.sh \
diff --git a/test/Makefile.in b/test/Makefile.in
index 42daf32f..5e44655f 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -461,15 +461,16 @@ EXTRA_DIST = $(TESTS) \
# Depend bulk tests on jail setup
-TESTS = builtins.sh cache.sh do_clone.sh encode_args.sh getpid.sh \
- getvar.sh gsub.sh globmatch.sh hash_basic.sh list.sh locks.sh \
- locks_critical_section.sh locks_critical_section_nested.sh \
- locked_mkdir.sh locked_mkdir_waiters.sh \
- locked_mkdir_waiters_kill.sh locked_mkdir_waiters_all_lose.sh \
- mapfile.sh pkg_version.sh port_var_fetch.sh prefix_output.sh \
- read_blocking.sh read_file.sh relpath.sh relpath_common.sh \
- shash_basic.sh stripansi.sh timespec.sh timestamp.sh \
- trap_save.sh $(JAIL_TESTS) prep.sh
+TESTS = builtins.sh cache.sh display.sh do_clone.sh encode_args.sh \
+ getpid.sh getvar.sh gsub.sh globmatch.sh hash_basic.sh list.sh \
+ locks.sh locks_critical_section.sh \
+ locks_critical_section_nested.sh locked_mkdir.sh \
+ locked_mkdir_waiters.sh locked_mkdir_waiters_kill.sh \
+ locked_mkdir_waiters_all_lose.sh mapfile.sh pkg_version.sh \
+ port_var_fetch.sh prefix_output.sh read_blocking.sh \
+ read_file.sh relpath.sh relpath_common.sh shash_basic.sh \
+ stripansi.sh timespec.sh timestamp.sh trap_save.sh \
+ $(JAIL_TESTS) prep.sh
JAIL_TESTS = \
bulk-bad-DEPENDS_ARGS.sh \
bulk-build-self-immutable-base-nullfs.sh \
@@ -722,6 +723,13 @@ cache.sh.log: cache.sh
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
+display.sh.log: display.sh
+ @p='display.sh'; \
+ b='display.sh'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
do_clone.sh.log: do_clone.sh
@p='do_clone.sh'; \
b='do_clone.sh'; \
diff --git a/test/display.sh b/test/display.sh
new file mode 100644
index 00000000..feafdedd
--- /dev/null
+++ b/test/display.sh
@@ -0,0 +1,677 @@
+. common.sh
+. ${SCRIPTPREFIX}/include/util.sh
+. ${SCRIPTPREFIX}/include/hash.sh
+. ${SCRIPTPREFIX}/include/display.sh
+
+_assert_file() {
+ local lineinfo="$1"
+ local expected="$2"
+ local have="$3"
+ local reason="$4"
+ local ret=0
+
+ cmp -s "${have}" "${expected}" || ret=$?
+
+ reason="${reason:+${reason} -}
+HAVE:
+$(cat -vet "${have}")
+EXPECTED:
+$(cat -vet "${expected}")"
+ rm -f "${have}" "${expected}"
+ _assert "${lineinfo}" 0 "${ret}" "${reason}"
+}
+alias assert_file='_assert_file "$0:$LINENO"'
+
+{
+ # Basic test
+ display_setup "%%-%ds %%-%ds" "-k2,2V -k1,1d"
+ display_add "Name 1" "Release"
+ display_add "blah" "11.2-RELEASE-p1"
+ display_add "blah" "10.0-RELEASE"
+ display_add "blah 1" "10.2-RELEASE"
+ display_add "blah" "10.2-RELEASE-p10"
+ display_add "blah2" "10.2-RELEASE-p1"
+ display_add "blah" "10.2-RELEASE-p1"
+ display_add "blah" "9.3-RELEASE-p10"
+ display_add "blah" "9.3-RELEASE-p1"
+ display_add "blah" "8.2-RELEASE-p1"
+ outfile=$(mktemp -t outfile)
+ display_output > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ Name 1 Release
+ blah 8.2-RELEASE-p1
+ blah 9.3-RELEASE-p1
+ blah 9.3-RELEASE-p10
+ blah 10.0-RELEASE
+ blah 1 10.2-RELEASE
+ blah 10.2-RELEASE-p1
+ blah2 10.2-RELEASE-p1
+ blah 10.2-RELEASE-p10
+ blah 11.2-RELEASE-p1
+ EOF
+ assert_file "${expected}" "${outfile}"
+}
+
+{
+ # Basic test via filter path
+ display_setup "%%-%ds %%-%ds" "-k2,2V -k1,1d"
+ display_add "Name 1" "Release"
+ display_add "blah" "11.2-RELEASE-p1"
+ display_add "blah" "10.0-RELEASE"
+ display_add "blah 1" "10.2-RELEASE"
+ display_add "blah" "10.2-RELEASE-p10"
+ display_add "blah2" "10.2-RELEASE-p1"
+ display_add "blah" "10.2-RELEASE-p1"
+ display_add "blah" "9.3-RELEASE-p10"
+ display_add "blah" "9.3-RELEASE-p1"
+ display_add "blah" "8.2-RELEASE-p1"
+ outfile=$(mktemp -t outfile)
+ display_output "Name 1" "Release" > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ Name 1 Release
+ blah 8.2-RELEASE-p1
+ blah 9.3-RELEASE-p1
+ blah 9.3-RELEASE-p10
+ blah 10.0-RELEASE
+ blah 1 10.2-RELEASE
+ blah 10.2-RELEASE-p1
+ blah2 10.2-RELEASE-p1
+ blah 10.2-RELEASE-p10
+ blah 11.2-RELEASE-p1
+ EOF
+ assert_file "${expected}" "${outfile}"
+}
+
+{
+ # Basic test
+ old="${DISPLAY_USE_COLUMN}"
+ DISPLAY_USE_COLUMN=1
+ display_setup "%%-%ds %%-%ds" "-k2,2V -k1,1d"
+ display_add "Name" "Release"
+ display_add "blah" "11.2-RELEASE-p1"
+ display_add "blah" "10.0-RELEASE"
+ display_add "blah" "10.2-RELEASE"
+ display_add "blah" "10.2-RELEASE-p10"
+ display_add "blah2" "10.2-RELEASE-p1"
+ display_add "blah" "10.2-RELEASE-p1"
+ display_add "blah" "9.3-RELEASE-p10"
+ display_add "blah" "9.3-RELEASE-p1"
+ display_add "blah" "8.2-RELEASE-p1"
+ outfile=$(mktemp -t outfile)
+ display_output > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ Name Release
+ blah 8.2-RELEASE-p1
+ blah 9.3-RELEASE-p1
+ blah 9.3-RELEASE-p10
+ blah 10.0-RELEASE
+ blah 10.2-RELEASE
+ blah 10.2-RELEASE-p1
+ blah2 10.2-RELEASE-p1
+ blah 10.2-RELEASE-p10
+ blah 11.2-RELEASE-p1
+ EOF
+ assert_file "${expected}" "${outfile}"
+ DISPLAY_USE_COLUMN="${old}"
+}
+
+{
+ # Basic test
+ old="${DISPLAY_USE_COLUMN}"
+ DISPLAY_USE_COLUMN=1
+ display_setup "%%-%ds %%-%ds" "-k2,2V -k1,1d"
+ display_add "Name" "Release"
+ display_add "blah" "11.2-RELEASE-p1"
+ display_add "blah" "10.0-RELEASE"
+ display_add "blah" "10.2-RELEASE"
+ display_add "blah" "10.2-RELEASE-p10"
+ display_add "blah2" "10.2-RELEASE-p1"
+ display_add "blah" "10.2-RELEASE-p1"
+ display_add "blah" "9.3-RELEASE-p10"
+ display_add "blah" "9.3-RELEASE-p1"
+ display_add "blah" "8.2-RELEASE-p1"
+ outfile=$(mktemp -t outfile)
+ display_output "Name" "Release" > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ Name Release
+ blah 8.2-RELEASE-p1
+ blah 9.3-RELEASE-p1
+ blah 9.3-RELEASE-p10
+ blah 10.0-RELEASE
+ blah 10.2-RELEASE
+ blah 10.2-RELEASE-p1
+ blah2 10.2-RELEASE-p1
+ blah 10.2-RELEASE-p10
+ blah 11.2-RELEASE-p1
+ EOF
+ assert_file "${expected}" "${outfile}"
+ DISPLAY_USE_COLUMN="${old}"
+}
+
+{
+ # Basic test without trimming trailing field
+ old="${DISPLAY_TRIM_TRAILING_FIELD}"
+ DISPLAY_TRIM_TRAILING_FIELD=0
+ display_setup "%%-%ds %%-%ds" "-k2,2V -k1,1d"
+ display_add "Name" "Release"
+ display_add "blah" "11.2-RELEASE-p1"
+ display_add "blah" "10.0-RELEASE"
+ display_add "blah" "10.2-RELEASE"
+ display_add "blah" "10.2-RELEASE-p10"
+ display_add "blah2" "10.2-RELEASE-p1"
+ display_add "blah" "10.2-RELEASE-p1"
+ display_add "blah" "9.3-RELEASE-p10"
+ display_add "blah" "9.3-RELEASE-p1"
+ display_add "blah" "8.2-RELEASE-p1"
+ outfile=$(mktemp -t outfile)
+ display_output > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ Name Release
+ blah 8.2-RELEASE-p1
+ blah 9.3-RELEASE-p1
+ blah 9.3-RELEASE-p10
+ blah 10.0-RELEASE
+ blah 10.2-RELEASE
+ blah 10.2-RELEASE-p1
+ blah2 10.2-RELEASE-p1
+ blah 10.2-RELEASE-p10
+ blah 11.2-RELEASE-p1
+ EOF
+ assert_file "${expected}" "${outfile}"
+ DISPLAY_TRIM_TRAILING_FIELD="${old}"
+}
+
+{
+ # Test quiet mode
+ display_setup "%%-%ds %%-%ds" "-k2,2V -k1,1d"
+ display_add "Name" "Release"
+ display_add "blah" "11.2-RELEASE-p1"
+ display_add "blah" "10.0-RELEASE"
+ display_add "blah" "10.2-RELEASE"
+ display_add "blah" "10.2-RELEASE-p10"
+ display_add "blah2" "10.2-RELEASE-p1"
+ display_add "blah" "10.2-RELEASE-p1"
+ display_add "blah" "9.3-RELEASE-p10"
+ display_add "blah" "9.3-RELEASE-p1"
+ display_add "blah" "8.2-RELEASE-p1"
+ outfile=$(mktemp -t outfile)
+ display_output -q > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ blah 8.2-RELEASE-p1
+ blah 9.3-RELEASE-p1
+ blah 9.3-RELEASE-p10
+ blah 10.0-RELEASE
+ blah 10.2-RELEASE
+ blah 10.2-RELEASE-p1
+ blah2 10.2-RELEASE-p1
+ blah 10.2-RELEASE-p10
+ blah 11.2-RELEASE-p1
+ EOF
+ assert_file "${expected}" "${outfile}"
+}
+
+{
+ display_setup "%%-%ds %%-%ds" "-k2,2V -k1,1d"
+ display_add "Name" "Release"
+ display_add "blah" "11.2-RELEASE-p1"
+ display_add "blah" "10.0-RELEASE"
+ display_add "blah" "10.2-RELEASE"
+ display_add "blah" "10.2-RELEASE-p10"
+ display_add "blah2" "10.2-RELEASE-p1"
+ display_add "blah" "10.2-RELEASE-p1"
+ display_add "blah" "9.3-RELEASE-p10"
+ display_add "blah" "9.3-RELEASE-p1"
+ display_add "blah" "8.2-RELEASE-p1"
+ # Test for blank and null params
+ display_add "blah3"
+ display_add "blah4" ""
+ display_add "" "11-RELEASE"
+ outfile=$(mktemp -t outfile)
+ display_output > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ Name Release
+ blah3
+ blah4
+ blah 8.2-RELEASE-p1
+ blah 9.3-RELEASE-p1
+ blah 9.3-RELEASE-p10
+ blah 10.0-RELEASE
+ blah 10.2-RELEASE
+ blah 10.2-RELEASE-p1
+ blah2 10.2-RELEASE-p1
+ blah 10.2-RELEASE-p10
+ 11-RELEASE
+ blah 11.2-RELEASE-p1
+ EOF
+ assert_file "${expected}" "${outfile}"
+}
+
+{
+ display_setup "%%-%ds %%-%ds" "-k2,2V -k1,1d"
+ display_add "Name" "Release"
+ display_add "blah" "11.2-RELEASE-p1"
+ display_add "blah" "10.0-RELEASE"
+ display_add "blah" "10.2-RELEASE"
+ display_add "blah" "10.2-RELEASE-p10"
+ display_add "blah2" "10.2-RELEASE-p1"
+ display_add "blah" "10.2-RELEASE-p1"
+ display_add "blah" "9.3-RELEASE-p10"
+ display_add "blah" "9.3-RELEASE-p1"
+ display_add "blah" "8.2-RELEASE-p1"
+ outfile=$(mktemp -t outfile)
+ display_output "Name" > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ Name
+ blah
+ blah
+ blah
+ blah
+ blah
+ blah
+ blah2
+ blah
+ blah
+ EOF
+ assert_file "${expected}" "${outfile}" "Filtered column"
+}
+
+{
+ display_setup "%%-%ds %%-%ds" "-k2,2V -k1,1d"
+ display_add "Name" "Release"
+ display_add "blah" "11.2-RELEASE-p1"
+ display_add "blah" "10.0-RELEASE"
+ display_add "blah" "10.2-RELEASE"
+ display_add "blah" "10.2-RELEASE-p10"
+ display_add "blah2" "10.2-RELEASE-p1"
+ display_add "blah" "10.2-RELEASE-p1"
+ display_add "blah" "9.3-RELEASE-p10"
+ display_add "blah" "9.3-RELEASE-p1"
+ display_add "blah" "8.2-RELEASE-p1"
+ outfile=$(mktemp -t outfile)
+ display_output "Release" > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ Release
+ 8.2-RELEASE-p1
+ 9.3-RELEASE-p1
+ 9.3-RELEASE-p10
+ 10.0-RELEASE
+ 10.2-RELEASE
+ 10.2-RELEASE-p1
+ 10.2-RELEASE-p1
+ 10.2-RELEASE-p10
+ 11.2-RELEASE-p1
+ EOF
+ assert_file "${expected}" "${outfile}" "Filtered column"
+}
+
+{
+ display_setup "%%-%ds %%%ds" "-k2,2V -k1,1d"
+ display_add "Name" "Memory"
+ display_add "foo" "10"
+ display_add "blah" "5"
+ display_footer "" "15 G"
+ outfile=$(mktemp -t outfile)
+ display_output > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ Name Memory
+ blah 5
+ foo 10
+ 15 G
+ EOF
+ assert_file "${expected}" "${outfile}"
+}
+
+{
+ # Test footer with dynamic
+ display_setup "%%-%ds %%%ds" "-k2,2V -k1,1d"
+ display_add "Name" "Memory"
+ display_add "foo" "10"
+ display_add "blah" "5"
+ display_footer "" "15 G"
+ outfile=$(mktemp -t outfile)
+ display_output "Name" "Memory" > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ Name Memory
+ blah 5
+ foo 10
+ 15 G
+ EOF
+ assert_file "${expected}" "${outfile}" "dynamic with footer"
+}
+
+{
+ display_setup "%%-%ds %%-%ds" "-k2,2V -k1,1d"
+ display_add "Name" "Memory"
+ display_add "foo" "10"
+ display_add "blah" "5"
+ display_footer "" "15 G"
+ outfile=$(mktemp -t outfile)
+ display_output > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ Name Memory
+ blah 5
+ foo 10
+ 15 G
+ EOF
+ assert_file "${expected}" "${outfile}"
+}
+
+{
+ display_setup "%%-%ds %%-%ds %%-%ds" "-k2,2V -k1,1d"
+ display_add "Name 1" "Mem" "Blah"
+ display_add "foo bar" "10" "0"
+ display_add "blah" "5" "0"
+ display_footer "" "15 GiB" "0"
+ outfile=$(mktemp -t outfile)
+ display_output > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ Name 1 Mem Blah
+ blah 5 0
+ foo bar 10 0
+ 15 GiB 0
+ EOF
+ assert_file "${expected}" "${outfile}"
+}
+
+{
+ display_setup "%%-%ds %%-%ds" "-k2,2V -k1,1d"
+ display_add "Name" "Release"
+ display_add "" "11.2-RELEASE-p1"
+ outfile=$(mktemp -t outfile)
+ display_output > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ Name Release
+ 11.2-RELEASE-p1
+ EOF
+ assert_file "${expected}" "${outfile}"
+}
+
+{
+ display_setup "%s %s" "-k2,2V -k1,1d"
+ display_add "Name" "Release"
+ display_add "blah" "11.2-RELEASE-p1"
+ display_add "blah" "10.0-RELEASE"
+ display_add "blah" "10.2-RELEASE"
+ display_add "blah" "10.2-RELEASE-p10"
+ display_add "blah2" "10.2-RELEASE-p1"
+ display_add "blah" "10.2-RELEASE-p1"
+ display_add "blah" "9.3-RELEASE-p10"
+ display_add "blah" "9.3-RELEASE-p1"
+ display_add "blah" "8.2-RELEASE-p1"
+ outfile=$(mktemp -t outfile)
+ display_output > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ Name Release
+ blah 8.2-RELEASE-p1
+ blah 9.3-RELEASE-p1
+ blah 9.3-RELEASE-p10
+ blah 10.0-RELEASE
+ blah 10.2-RELEASE
+ blah 10.2-RELEASE-p1
+ blah2 10.2-RELEASE-p1
+ blah 10.2-RELEASE-p10
+ blah 11.2-RELEASE-p1
+ EOF
+ assert_file "${expected}" "${outfile}"
+}
+
+{
+ # Test no trailing spaces
+ display_setup "%%-%ds %%s" "-k2,2V -k1,1d"
+ display_add "Name" "Release"
+ display_add "blah" "11.2-RELEASE-p1"
+ display_add "blah" "10.0-RELEASE"
+ display_add "blah" "10.2-RELEASE"
+ display_add "blah" "10.2-RELEASE-p10"
+ display_add "blah2" "10.2-RELEASE-p1"
+ display_add "blah" "10.2-RELEASE-p1"
+ display_add "blah" "9.3-RELEASE-p10"
+ display_add "blah" "9.3-RELEASE-p1"
+ display_add "blah" "8.2-RELEASE-p1"
+ outfile=$(mktemp -t outfile)
+ display_output > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ Name Release
+ blah 8.2-RELEASE-p1
+ blah 9.3-RELEASE-p1
+ blah 9.3-RELEASE-p10
+ blah 10.0-RELEASE
+ blah 10.2-RELEASE
+ blah 10.2-RELEASE-p1
+ blah2 10.2-RELEASE-p1
+ blah 10.2-RELEASE-p10
+ blah 11.2-RELEASE-p1
+ EOF
+ assert_file "${expected}" "${outfile}"
+}
+
+{
+ # Test a case that was totally wrong due to quoting the first field
+ display_setup "%%%ds %%-%ds %%-%ds" "-k1,1n"
+ display_add "JID" "IP Address" "vnet_num"
+ display_add "189" "" 0
+ display_add "188" "" 0
+ display_add "187" "" 0
+ display_add "150" "10.2.1.4,127.0.1.4" 0
+ display_add "99" "10.2.1.3,127.0.1.3" 0
+ display_add "87" "192.168.2.38" 0
+ display_add "85" "192.168.2.52" 0
+ outfile=$(mktemp -t outfile)
+ display_output > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ JID IP Address vnet_num
+ 85 192.168.2.52 0
+ 87 192.168.2.38 0
+ 99 10.2.1.3,127.0.1.3 0
+ 150 10.2.1.4,127.0.1.4 0
+ 187 0
+ 188 0
+ 189 0
+ EOF
+ assert_file "${expected}" "${outfile}"
+}
+
+{
+ # Test with dynamic formats
+ display_setup "dynamic" "-k1,1n"
+ display_add "JID" "IP Address" "vnet_num"
+ display_add "189" "" 0
+ display_add "188" "" 0
+ display_add "187" "" 0
+ display_add "150" "10.2.1.4,127.0.1.4" 0
+ display_add "99" "10.2.1.3,127.0.1.3" 0
+ display_add "87" "192.168.2.38" 0
+ display_add "85" "192.168.2.52" 0
+ outfile=$(mktemp -t outfile)
+ display_output > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ JID IP Address vnet_num
+ 85 192.168.2.52 0
+ 87 192.168.2.38 0
+ 99 10.2.1.3,127.0.1.3 0
+ 150 10.2.1.4,127.0.1.4 0
+ 187 0
+ 188 0
+ 189 0
+ EOF
+ assert_file "${expected}" "${outfile}" "dynamic formats"
+}
+
+{
+ # Test with dynamic formats with specified field format
+ display_setup "dynamic" "-k1,1n"
+ display_add "JID:%%%ds" "IP Address:%%%ds" "vnet_num"
+ display_add "189" "" 0
+ display_add "188" "" 0
+ display_add "187" "" 0
+ display_add "150" "10.2.1.4,127.0.1.4" 0
+ display_add "99" "10.2.1.3,127.0.1.3" 0
+ display_add "87" "192.168.2.38" 0
+ display_add "85" "192.168.2.52" 0
+ outfile=$(mktemp -t outfile)
+ display_output > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ JID IP Address vnet_num
+ 85 192.168.2.52 0
+ 87 192.168.2.38 0
+ 99 10.2.1.3,127.0.1.3 0
+ 150 10.2.1.4,127.0.1.4 0
+ 187 0
+ 188 0
+ 189 0
+ EOF
+ assert_file "${expected}" "${outfile}" "dynamic formats with specified field format"
+}
+
+{
+ # Test filter/reorder
+ display_setup "%%%ds %%-%ds %%-%ds" "-k1,1n"
+ display_add "JID" "IP Address super long" "vnet_num"
+ display_add "189" "" 0
+ display_add "188" "" 0
+ display_add "187" "" 0
+ display_add "150" "10.2.1.4,127.0.1.4" 0
+ display_add "99" "10.2.1.3,127.0.1.3" 0
+ display_add "87" "192.168.2.38" 0
+ display_add "85" "192.168.2.52" 0
+ outfile=$(mktemp -t outfile)
+ display_output "vnet_num" "IP Address" > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ vnet_num IP Address super long
+ 0 192.168.2.52
+ 0 192.168.2.38
+ 0 10.2.1.3,127.0.1.3
+ 0 10.2.1.4,127.0.1.4
+ 0
+ 0
+ 0
+ EOF
+ assert_file "${expected}" "${outfile}" "filtered/reordered column"
+}
+
+{
+ # Test filter/reorder with quiet
+ display_setup "%%%ds %%-%ds %%-%ds" "-k1,1n"
+ display_add "JID" "IP Address" "vnet_num"
+ display_add "189" "" 0
+ display_add "188" "" 0
+ display_add "187" "" 0
+ display_add "150" "10.2.1.4,127.0.1.4" 0
+ display_add "99" "10.2.1.3,127.0.1.3" 0
+ display_add "87" "192.168.2.38" 0
+ display_add "85" "192.168.2.52" 0
+ outfile=$(mktemp -t outfile)
+ display_output -q "vnet_num" "IP Address" > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ 0 192.168.2.52
+ 0 192.168.2.38
+ 0 10.2.1.3,127.0.1.3
+ 0 10.2.1.4,127.0.1.4
+ 0
+ 0
+ 0
+ EOF
+ assert_file "${expected}" "${outfile}" "filtered/reordered column + quiet"
+}
+
+{
+ # Test filter/reorder
+ display_setup "%%%ds %%-%ds %%-%ds" "-k1,1n"
+ display_add "JID" "IP Address" "vnet_num"
+ display_add "189" "" 0
+ display_add "188" "" 0
+ display_add "187" "" 0
+ display_add "150" "10.2.1.4,127.0.1.4" 0
+ display_add "99" "10.2.1.3,127.0.1.3" 0
+ display_add "87" "192.168.2.38" 0
+ display_add "85" "192.168.2.52" 0
+ outfile=$(mktemp -t outfile)
+ display_output "vnet_num" "IP Address" > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ vnet_num IP Address
+ 0 192.168.2.52
+ 0 192.168.2.38
+ 0 10.2.1.3,127.0.1.3
+ 0 10.2.1.4,127.0.1.4
+ 0
+ 0
+ 0
+ EOF
+ assert_file "${expected}" "${outfile}" "filtered column"
+}
+
+{
+ # Test with dynamic formats with filter/reorder
+ display_setup "dynamic" "-k1,1n"
+ display_add "JID" "IP Address" "vnet_num"
+ display_add "189" "" 0
+ display_add "188" "" 0
+ display_add "187" "" 0
+ display_add "150" "10.2.1.4,127.0.1.4" 0
+ display_add "99" "10.2.1.3,127.0.1.3" 0
+ display_add "87" "192.168.2.38" 0
+ display_add "85" "192.168.2.52" 0
+ outfile=$(mktemp -t outfile)
+ display_output "JID" "vnet_num" "IP Address" > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ JID vnet_num IP Address
+ 85 0 192.168.2.52
+ 87 0 192.168.2.38
+ 99 0 10.2.1.3,127.0.1.3
+ 150 0 10.2.1.4,127.0.1.4
+ 187 0
+ 188 0
+ 189 0
+ EOF
+ assert_file "${expected}" "${outfile}" "dynamic formats with reordered cols"
+}
+
+{
+ # Test with dynamic formats and filtered/reordered
+ display_setup "dynamic" "-k1,1n"
+ display_add "JID" "IP Address" "vnet_num"
+ display_add "189" "" 0
+ display_add "188" "" 0
+ display_add "187" "" 0
+ display_add "150" "10.2.1.4,127.0.1.4" 0
+ display_add "99" "10.2.1.3,127.0.1.3" 0
+ display_add "87" "192.168.2.38" 0
+ display_add "85" "192.168.2.52" 0
+ outfile=$(mktemp -t outfile)
+ display_output "vnet_num" "IP Address" "JID" > "${outfile}"
+ expected=$(mktemp -t expected)
+ cat > "${expected}" <<-EOF
+ vnet_num IP Address JID
+ 0 192.168.2.52 85
+ 0 192.168.2.38 87
+ 0 10.2.1.3,127.0.1.3 99
+ 0 10.2.1.4,127.0.1.4 150
+ 0 187
+ 0 188
+ 0 189
+ EOF
+ assert_file "${expected}" "${outfile}" "dynamic format with reordered column"
+}
diff --git a/test/encode_args.sh b/test/encode_args.sh
index 809e2bd0..8ab1f27f 100644
--- a/test/encode_args.sh
+++ b/test/encode_args.sh
@@ -54,7 +54,7 @@ assert 2 $# "decode 2 argument argcnt"
assert "1" "$1" "decode 2 argument argument 1"
assert "2 3" "$2" "decode 2 argument argument 2"
set -- bad bad bad bad bad
-eval $(decode_args data)
+eval "$(decode_args data)"
assert 2 $# "decode 2 argument argcnt"
assert "1" "$1" "decode 2 argument argument 1"
assert "2 3" "$2" "decode 2 argument argument 2"
@@ -74,10 +74,24 @@ oldIFS="${IFS}"; IFS="${ENCODE_SEP}"; set -- ${data}; IFS="${oldIFS}"; unset old
[ -f "${TMP}" ]
assert 1 $? "decoding cmdsubst should not fire: ${TMP}"
set -- bad bad bad bad bad
-eval $(decode_args data)
+eval "$(decode_args data)"
[ -f "${TMP}" ]
assert 1 $? "decoding cmdsubst should not fire: ${TMP}"
+# Test 1 leading empty arguments
+encode_args data "" "1"
+assert "${ENCODE_SEP}1" "${data}" "encode 1 trailing args"
+set -- bad bad bad bad bad
+oldIFS="${IFS}"; IFS="${ENCODE_SEP}"; set -- ${data}; IFS="${oldIFS}"; unset oldIFS
+assert 2 $# "decode 1 trailing arguments argcnt"
+assert "" "$1" "decode 1 trailing arguments argument 1"
+assert "1" "$2" "decode 1 trailing arguments argument 2"
+set -- bad bad bad bad bad
+eval "$(decode_args data)"
+assert 2 $# "decode 1 trailing arguments argcnt"
+assert "" "$1" "decode 1 trailing arguments argument 1"
+assert "1" "$2" "decode 1 trailing arguments argument 2"
+
# Test 1 trailing empty arguments
encode_args data "1" ""
assert "1${ENCODE_SEP}${ENCODE_SEP}" "${data}" "encode 1 trailing args"
@@ -87,11 +101,39 @@ assert 2 $# "decode 1 trailing arguments argcnt"
assert "1" "$1" "decode 1 trailing arguments argument 1"
assert "" "$2" "decode 1 trailing arguments argument 2"
set -- bad bad bad bad bad
-eval $(decode_args data)
+eval "$(decode_args data)"
assert 2 $# "decode 1 trailing arguments argcnt"
assert "1" "$1" "decode 1 trailing arguments argument 1"
assert "" "$2" "decode 1 trailing arguments argument 2"
+# Test leading, middle, and end empty arguments
+encode_args data "" "" "1" ""
+assert "${ENCODE_SEP}${ENCODE_SEP}1${ENCODE_SEP}${ENCODE_SEP}" "${data}" "encode 3 trailing args"
+set -- bad bad bad bad bad
+oldIFS="${IFS}"; IFS="${ENCODE_SEP}"; set -- ${data}; IFS="${oldIFS}"; unset oldIFS
+assert 4 $# "decode 3 trailing arguments argcnt"
+assert "" "$1" "decode 3 trailing arguments argument 1"
+assert "" "$2" "decode 3 trailing arguments argument 2"
+assert "1" "$3" "decode 3 trailing arguments argument 3"
+assert "" "$4" "decode 3 trailing arguments argument 4"
+set -- bad bad bad bad bad
+eval "$(decode_args data)"
+assert 4 $# "decode 3 trailing arguments argcnt"
+assert "" "$1" "decode 3 trailing arguments argument 1"
+assert "" "$2" "decode 3 trailing arguments argument 2"
+assert "1" "$3" "decode 3 trailing arguments argument 3"
+assert "" "$4" "decode 3 trailing arguments argument 4"
+one=bad
+two=bad
+three=bad
+four=bad
+decode_args_vars "${data}" one two three four
+assert 0 "$?" "decode_args_vars"
+assert "" "$one" "decode 2 argument argument 1"
+assert "" "$two" "decode 2 argument argument 2"
+assert "1" "$three" "decode 2 argument argument 3"
+assert "" "$four" "decode 2 argument argument 4"
+
# Test trailing empty arguments
encode_args data "1" "" "" ""
assert "1${ENCODE_SEP}${ENCODE_SEP}${ENCODE_SEP}${ENCODE_SEP}" "${data}" "encode 3 trailing args"
@@ -103,12 +145,22 @@ assert "" "$2" "decode 3 trailing arguments argument 2"
assert "" "$3" "decode 3 trailing arguments argument 3"
assert "" "$4" "decode 3 trailing arguments argument 4"
set -- bad bad bad bad bad
-eval $(decode_args data)
+eval "$(decode_args data)"
assert 4 $# "decode 3 trailing arguments argcnt"
assert "1" "$1" "decode 3 trailing arguments argument 1"
assert "" "$2" "decode 3 trailing arguments argument 2"
assert "" "$3" "decode 3 trailing arguments argument 3"
assert "" "$4" "decode 3 trailing arguments argument 4"
+one=bad
+two=bad
+three=bad
+four=bad
+decode_args_vars "${data}" one two three four
+assert 0 "$?" "decode_args_vars"
+assert "1" "$one" "decode 2 argument argument 1"
+assert "" "$two" "decode 2 argument argument 2"
+assert "" "$three" "decode 2 argument argument 3"
+assert "" "$four" "decode 2 argument argument 4"
# Test trailing empty arguments with data
encode_args data "1" "" "" "x"
@@ -121,7 +173,8 @@ assert "" "$2" "decode 3 trailing arguments x argument 2"
assert "" "$3" "decode 3 trailing arguments x argument 3"
assert "x" "$4" "decode 3 trailing arguments x argument 4"
set -- bad bad bad bad bad
-eval $(decode_args data)
+_decode_args _decode_args data
+eval "${_decode_args}"
assert 4 $# "decode 3 trailing arguments x argcnt"
assert "1" "$1" "decode 3 trailing arguments x argument 1"
assert "" "$2" "decode 3 trailing arguments x argument 2"
@@ -140,7 +193,7 @@ assert "x" "$four" "decode 3 trailing arguments x argument 4"
encode_args data "1" "*" " * " " 4"
set -- bad bad bad bad bad
-eval $(decode_args data)
+eval "$(decode_args data)"
assert 4 $# "decode 3 trailing arguments x argcnt"
assert "1" "$1" "decode 3 trailing arguments x argument 1"
assert "*" "$2" "decode 3 trailing arguments x argument 2"
@@ -157,6 +210,11 @@ assert "*" "$two" "decode 3 trailing arguments x argument 2"
assert " * " "$three" "decode 3 trailing arguments x argument 3"
assert " 4" "$four" "decode 3 trailing arguments x argument 4"
+decode_args_vars "${data}" one two
+assert 0 "$?" "decode_args_vars"
+assert "1" "$one" "decode 3 trailing arguments x argument 1"
+assert "* * 4" "$two" "decode 3 trailing arguments x argument 2"
+
# Test parsing safety
# $()
@@ -169,7 +227,7 @@ oldIFS="${IFS}"; IFS="${ENCODE_SEP}"; set -- ${data}; IFS="${oldIFS}"; unset old
[ -f "${tmpfile}" ]
assert_not 0 $? "File should not exist when decoded"
set -- bad bad bad bad bad
-eval $(decode_args data)
+eval "$(decode_args data)"
[ -f "${tmpfile}" ]
assert_not 0 $? "File should not exist when decoded"
diff --git a/test/hash_basic.sh b/test/hash_basic.sh
index df821c44..01447d70 100644
--- a/test/hash_basic.sh
+++ b/test/hash_basic.sh
@@ -24,4 +24,21 @@ assert "ports-mgmt/pkg" "${value}" "Removed value should match"
value=
assert_ret 1 hash_get pkgname-origin "pkg-1.7" value
+assert_ret 1 hash_isset_var 'blah'
+hash_set blah 1 foo
+hash_set blah 2 foo
+hash_set blah 3 foo
+hash_set blah 45 foo
+hash_set blah2 1 foo
+hash_set foo 1 foo
+assert_ret 0 hash_isset_var 'blah'
+assert_ret 0 hash_unset_var 'blah'
+assert_ret 1 hash_isset blah 1
+assert_ret 1 hash_isset blah 2
+assert_ret 1 hash_isset blah 3
+assert_ret 1 hash_isset blah 45
+assert_ret 0 hash_isset blah2 1
+assert_ret 0 hash_isset foo 1
+assert_ret 1 hash_isset_var 'blah'
+
exit 0