summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorDave Reisner <dreisner@archlinux.org>2012-04-08 18:32:17 +0200
committerDan McGee <dan@archlinux.org>2012-04-24 15:38:36 +0200
commit8679cd68d825bfe28ba0c833494c415bcfa6d8f6 (patch)
tree2da70a05c56a457262a4ff68446c788d3829131b /test
parent1eb6a9cbfef4f0ad5151b4850d81141b7a535be6 (diff)
downloadpacman-8679cd68d825bfe28ba0c833494c415bcfa6d8f6.tar.gz
pacman-8679cd68d825bfe28ba0c833494c415bcfa6d8f6.tar.xz
scripts/library: introduce parseopts
This will replace our current options parser used in pacman-key, makepkg, and ideally elsewhere. It follows heuristics closer to that of GNU getopt long (and thus pacman itself), with the exception that it does not allow for options with optional arguments. Due to the way this parser will be used, this sort of functionality will not be needed. Instead of relying on eval+set, options are normalized into an array, OPTRET, which callers should expect to be populated after returning from parseopts. This avoids problems with quotes and spaces in arguments, assuming that the user quotes properly when passing into the application. A new test harness for parseopts is added in test/scripts. Signed-off-by: Dave Reisner <dreisner@archlinux.org>
Diffstat (limited to 'test')
-rw-r--r--test/scripts/Makefile.am9
-rwxr-xr-xtest/scripts/parseopts_test.sh138
2 files changed, 147 insertions, 0 deletions
diff --git a/test/scripts/Makefile.am b/test/scripts/Makefile.am
new file mode 100644
index 00000000..b949e880
--- /dev/null
+++ b/test/scripts/Makefile.am
@@ -0,0 +1,9 @@
+check_SCRIPTS = \
+ parseopts_test.sh
+
+noinst_SCRIPTS = $(check_SCRIPTS)
+
+EXTRA_DIST = \
+ $(check_SCRIPTS)
+
+# vim:set ts=2 sw=2 noet:
diff --git a/test/scripts/parseopts_test.sh b/test/scripts/parseopts_test.sh
new file mode 100755
index 00000000..b5c07b5d
--- /dev/null
+++ b/test/scripts/parseopts_test.sh
@@ -0,0 +1,138 @@
+#!/bin/bash
+
+declare -i testcount=0 pass=0 fail=0
+
+# source the library function
+if [[ -z $1 || ! -f $1 ]]; then
+ printf "error: path to parseopts library not provided or does not exist\n"
+ exit 1
+fi
+. "$1"
+
+if ! type -t parseopts >/dev/null; then
+ printf 'parseopts function not found\n'
+ exit 1
+fi
+
+# borrow opts from makepkg
+OPT_SHORT="AcdefFghiLmop:rRsV"
+OPT_LONG=('allsource' 'asroot' 'ignorearch' 'check' 'clean:' 'cleanall' 'nodeps'
+ 'noextract' 'force' 'forcever:' 'geninteg' 'help' 'holdver'
+ 'install' 'key:' 'log' 'nocolor' 'nobuild' 'nocheck' 'nosign' 'pkg:' 'rmdeps'
+ 'repackage' 'skipinteg' 'sign' 'source' 'syncdeps' 'version' 'config:'
+ 'noconfirm' 'noprogressbar')
+
+parse() {
+ local result=$1 tokencount=$2; shift 2
+
+ (( ++testcount ))
+ parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@" 2>/dev/null
+ test_result "$result" "$tokencount" "$*" "${OPTRET[@]}"
+ unset OPTRET
+}
+
+test_result() {
+ local result=$1 tokencount=$2 input=$3; shift 3
+
+ if [[ $result = "$*" ]] && (( tokencount == $# )); then
+ (( ++pass ))
+ else
+ printf '[TEST %3s]: FAIL\n' "$testcount"
+ printf ' input: %s\n' "$input"
+ printf ' output: %s (%s tokens)\n' "$*" "$#"
+ printf ' expected: %s (%s tokens)\n' "$result" "$tokencount"
+ echo
+ (( ++fail ))
+ fi
+}
+
+summarize() {
+ if (( !fail )); then
+ printf 'All %s tests successful\n' "$testcount"
+ exit 0
+ else
+ printf '%s of %s tests failed\n' "$fail" "$testcount"
+ exit 1
+ fi
+}
+trap 'summarize' EXIT
+
+printf 'Beginning parseopts tests\n'
+
+# usage: parse <expected result> <token count> test-params...
+# a failed parse will match only the end of options marker '--'
+
+# no options
+parse '--' 1
+
+# short options
+parse '-s -r --' 3 -s -r
+
+# short options, no spaces
+parse '-s -r --' 3 -sr
+
+# short opt missing an opt arg
+parse '--' 1 -s -p
+
+# short opt with an opt arg
+parse '-p PKGBUILD -L --' 4 -p PKGBUILD -L
+
+# short opt with an opt arg, no space
+parse '-p PKGBUILD --' 3 -pPKGBUILD
+
+# valid shortopts as a long opt
+parse '--' 1 --sir
+
+# long opt wiht no optarg
+parse '--log --' 2 --log
+
+# long opt with missing optarg
+parse '--' 1 -sr --pkg
+
+# long opt with optarg
+parse '--pkg foo --' 3 --pkg foo
+
+# long opt with optarg with whitespace
+parse '--pkg foo bar -- baz' 4 --pkg "foo bar" baz
+
+# long opt with optarg with =
+parse '--pkg foo=bar -- baz' 4 --pkg foo=bar baz
+
+# long opt with explicit optarg
+parse '--pkg bar -- foo baz' 5 foo --pkg=bar baz
+
+# long opt with explicit optarg, with whitespace
+parse '--pkg foo bar -- baz' 4 baz --pkg="foo bar"
+
+# long opt with explicit optarg that doesn't take optarg
+parse '--' 1 --force=always -s
+
+# long opt with explicit optarg with =
+parse '--pkg foo=bar --' 3 --pkg=foo=bar
+
+# explicit end of options with options after
+parse '-s -r -- foo bar baz' 6 -s -r -- foo bar baz
+
+# non-option parameters mixed in with options
+parse '-s -r -- foo baz' 5 -s foo baz -r
+
+# optarg with whitespace
+parse '-p foo bar -s --' 4 -p'foo bar' -s
+
+# non-option parameter with whitespace
+parse '-i -- foo bar' 3 -i 'foo bar'
+
+# successful stem match (opt has no arg)
+parse '--nocolor --' 2 --nocol
+
+# successful stem match (opt has arg)
+parse '--config foo --' 3 --conf foo
+
+# ambiguous long opt
+parse '--' 1 '--for'
+
+# exact match on a possible stem (--force & --forcever)
+parse '--force --' 2 --force
+
+# exact match on possible stem (opt has optarg)
+parse '--clean foo --' 3 --clean=foo