[pacman-dev] [PATCH 0/4][WIP] makepkg test suite
The long-awaited makepkg test suite is finally here, or at least the start of it. The tests can be run via `make check` or they can also be run directly. Included so far are a few tests for package generation and a single libmakepkg test for some of the util/pkgbuild functions. I made some small changes to the lib in order to make it easier to use and to allow stricter error checking in the test suite (set -u). Andrew Gregory (4): util/pkgbuild: guard against unset variable util/pkgbuild: manually set extglob util/pkgbuild: fix broken indentation add basic makepkg test Makefile.am | 6 +- configure.ac | 2 + scripts/libmakepkg/util/pkgbuild.sh.in | 23 +++--- test/makepkg/Makefile.am | 9 +++ test/makepkg/README | 15 ++++ test/makepkg/test_functions.sh | 143 +++++++++++++++++++++++++++++++++ test/makepkg/tests/Makefile.am | 7 ++ test/makepkg/tests/TESTS | 4 + test/makepkg/tests/dbfiles.sh | 35 ++++++++ test/makepkg/tests/dotfiles.sh | 33 ++++++++ test/makepkg/tests/pkgbuild.sh | 53 ++++++++++++ test/makepkg/tests/util-pkgbuild.sh | 35 ++++++++ 12 files changed, 355 insertions(+), 10 deletions(-) create mode 100644 test/makepkg/Makefile.am create mode 100644 test/makepkg/README create mode 100644 test/makepkg/test_functions.sh create mode 100644 test/makepkg/tests/Makefile.am create mode 100644 test/makepkg/tests/TESTS create mode 100755 test/makepkg/tests/dbfiles.sh create mode 100755 test/makepkg/tests/dotfiles.sh create mode 100755 test/makepkg/tests/pkgbuild.sh create mode 100755 test/makepkg/tests/util-pkgbuild.sh -- 2.11.1
Allows use under 'set -u'. --- scripts/libmakepkg/util/pkgbuild.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/libmakepkg/util/pkgbuild.sh.in b/scripts/libmakepkg/util/pkgbuild.sh.in index 2a4bd3af..08b35f53 100644 --- a/scripts/libmakepkg/util/pkgbuild.sh.in +++ b/scripts/libmakepkg/util/pkgbuild.sh.in @@ -18,7 +18,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -[[ -n "$LIBMAKEPKG_UTIL_PKGBUILD_SH" ]] && return +[[ -n "${LIBMAKEPKG_UTIL_PKGBUILD_SH:-}" ]] && return LIBMAKEPKG_UTIL_PKGBUILD_SH=1 -- 2.11.1
extract_function_variable requires extglob; set it in case the caller hasn't. --- scripts/libmakepkg/util/pkgbuild.sh.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/libmakepkg/util/pkgbuild.sh.in b/scripts/libmakepkg/util/pkgbuild.sh.in index 08b35f53..7074c8c5 100644 --- a/scripts/libmakepkg/util/pkgbuild.sh.in +++ b/scripts/libmakepkg/util/pkgbuild.sh.in @@ -74,6 +74,9 @@ extract_function_variable() { local funcname=$1 attr=$2 isarray=$3 outputvar=$4 attr_regex= decl= r=1 + local reset_shopt="$(shopt -p extglob)" + shopt -s extglob + if (( isarray )); then printf -v attr_regex '^[[:space:]]* %s\+?=\(' "$2" else @@ -89,6 +92,8 @@ extract_function_variable() { r=0 done < <(grep_function "$funcname" "$attr_regex") + eval "$reset_shopt" + return $r } -- 2.11.1
--- scripts/libmakepkg/util/pkgbuild.sh.in | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/libmakepkg/util/pkgbuild.sh.in b/scripts/libmakepkg/util/pkgbuild.sh.in index 7074c8c5..ae8ba5e7 100644 --- a/scripts/libmakepkg/util/pkgbuild.sh.in +++ b/scripts/libmakepkg/util/pkgbuild.sh.in @@ -207,14 +207,14 @@ get_integlist() { continue fi - # check for e.g. "sha256sums_x86_64" - for a in "${arch[@]}"; do - local sumname="${integ}sums_${a}[@]" - if [[ -n ${!sumname} ]]; then - integlist+=("$integ") - break - fi - done + # check for e.g. "sha256sums_x86_64" + for a in "${arch[@]}"; do + local sumname="${integ}sums_${a}[@]" + if [[ -n ${!sumname} ]]; then + integlist+=("$integ") + break + fi + done done if (( ${#integlist[@]} > 0 )); then -- 2.11.1
--- Makefile.am | 6 +- configure.ac | 2 + test/makepkg/Makefile.am | 9 +++ test/makepkg/README | 15 ++++ test/makepkg/test_functions.sh | 143 ++++++++++++++++++++++++++++++++++++ test/makepkg/tests/Makefile.am | 7 ++ test/makepkg/tests/TESTS | 4 + test/makepkg/tests/dbfiles.sh | 35 +++++++++ test/makepkg/tests/dotfiles.sh | 33 +++++++++ test/makepkg/tests/pkgbuild.sh | 53 +++++++++++++ test/makepkg/tests/util-pkgbuild.sh | 35 +++++++++ 11 files changed, 341 insertions(+), 1 deletion(-) create mode 100644 test/makepkg/Makefile.am create mode 100644 test/makepkg/README create mode 100644 test/makepkg/test_functions.sh create mode 100644 test/makepkg/tests/Makefile.am create mode 100644 test/makepkg/tests/TESTS create mode 100755 test/makepkg/tests/dbfiles.sh create mode 100755 test/makepkg/tests/dotfiles.sh create mode 100755 test/makepkg/tests/pkgbuild.sh create mode 100755 test/makepkg/tests/util-pkgbuild.sh diff --git a/Makefile.am b/Makefile.am index 67ffc6b4..7b877a6c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = lib/libalpm src/util src/pacman scripts etc test/pacman test/util test/scripts +SUBDIRS = lib/libalpm src/util src/pacman scripts etc test/makepkg test/pacman test/util test/scripts if WANT_DOC SUBDIRS += doc endif @@ -26,11 +26,15 @@ dist_pkgdata_DATA = \ $(top_srcdir)/test/pacman/tests/TESTS: $(wildcard test/pacman/tests/*.py) @printf "TESTS += %s\n" $^ | LC_ALL=C sort -u > "$@" +$(top_srcdir)/test/makepkg/tests/TESTS: $(wildcard test/makepkg/tests/*.sh) + @printf "TESTS += %s\n" $^ | LC_ALL=C sort -u > "$@" + TESTS = test/scripts/parseopts_test.sh \ test/scripts/human_to_size_test.sh \ test/scripts/makepkg-template_test.sh \ test/scripts/pacman-db-upgrade-v9.py \ test/util/vercmptest.sh +include $(top_srcdir)/test/makepkg/tests/TESTS include $(top_srcdir)/test/pacman/tests/TESTS TEST_SUITE_LOG = test/test-suite.log diff --git a/configure.ac b/configure.ac index 10e4415c..d7e2c9ff 100644 --- a/configure.ac +++ b/configure.ac @@ -530,6 +530,8 @@ scripts/Makefile scripts/po/Makefile.in doc/Makefile etc/Makefile +test/makepkg/Makefile +test/makepkg/tests/Makefile test/pacman/Makefile test/pacman/tests/Makefile test/scripts/Makefile diff --git a/test/makepkg/Makefile.am b/test/makepkg/Makefile.am new file mode 100644 index 00000000..835030c0 --- /dev/null +++ b/test/makepkg/Makefile.am @@ -0,0 +1,9 @@ +SUBDIRS = tests + +check_SCRIPTS = test_functions.sh + +noinst_SCRIPTS = $(check_SCRIPTS) + +EXTRA_DIST = $(check_SCRIPTS) + +# vim:set noet: diff --git a/test/makepkg/README b/test/makepkg/README new file mode 100644 index 00000000..70c6872b --- /dev/null +++ b/test/makepkg/README @@ -0,0 +1,15 @@ +README +====== + +Running Tests +------------- + +Environment Variables +--------------------- + +PMTEST_SCRIPT_DIR - location of the makepkg executable; defaults to "$(dirname "$0")/../../../scripts)" +PMTEST_LIBMAKEPKG_DIR - base directory of the makepkg library; defaults to "$PMTEST_SCRIPT_DIR/libmakepkg" +VERBOSE - enable additional test output for debugging + +Adding New Tests +---------------- diff --git a/test/makepkg/test_functions.sh b/test/makepkg/test_functions.sh new file mode 100644 index 00000000..a6f07bcd --- /dev/null +++ b/test/makepkg/test_functions.sh @@ -0,0 +1,143 @@ +# basic setup to run before every test +# tap_init +tap_init() { + set +e + set -u + set -o pipefail +} + +# wrapper around tap_bail that immediately causes the test to exit non-zero +# tap_xbail $reason... +tap_xbail() { + tap_bail "$@" + exit 1; +} + +# read from stdin and reprint as diagnostic messages if VERBOSE is set and +# non-zero, otherwise, discard +# $command |& tap_filter +tap_filter() { + local v=${VERBOSE:-0} + if (( $v )); then + while IFS= read line; do + tap_diag "$line" + done + else + while IFS= read line; do + : + done + fi +} + +# locate the script that should be tested +locate_bin() { + local scriptdir="${PMTEST_SCRIPT_DIR:-"$(dirname "$0")/../../../scripts"}" + local script="$(realpath "${1:-"$scriptdir/makepkg-wrapper"}")" + if ! type -p "$script" &>/dev/null; then + tap_xbail "makepkg executable (%s) could not be located" "${script}" + exit 1 + fi + printf "%s" "$script" +} + +# locate an source libmakepkg files +source_libmakepkg_file() { + local file=$1; shift 1 + local scriptdir="${PMTEST_SCRIPT_DIR:-"$(dirname "$0")/../../../scripts"}" + local libdir="${PMTEST_LIBMAKEPKG_DIR:-"$scriptdir/libmakepkg"}" + source "$(realpath "$libdir/$file")" +} + +# eval a piece of code and test the return value +# tap_eval $code $test_name... +tap_eval() { + local t=$1; shift 1 + eval "$t" + tap_ok $? "$@" +} + +# extract ls-style information about a file: +# mode nhardlinks user group size month date time/year filename +_ar_stat() { + local ar=$1 path=$2; shift 2 + bsdtar --fast-read -tvf "$ar" "$@" "$path" 2>/dev/null +} + +# same as _ar_stat but with numeric owner ids +_ar_nstat() { + local ar=$1 path=$2; shift 2 + _ar_stat "$ar" "$path" --numeric-owner "$@" +} + +# check the owner of a given file, owner may be a numeric id or user name +# tap_ar_is_owner $path_to_archive $file $expected_owner $test_name... +tap_ar_is_owner() { + local ar=$1 path=$2 expect=$3; shift 3 + local statfun="_ar_stat" owner unused + [[ $expect =~ ^[0-9]+$ ]] && statfun="_ar_nstat" + if ! read -r unused unused owner unused < <($statfun "$ar" "$path"); then + tap_ok 1 "$@" + tap_diag " got: invalid path" + tap_diag " expected: '%s'" "$expect" + elif [[ $owner != $expect ]]; then + tap_ok 1 "$@" + tap_diag " got: '%s'" "$owner" + tap_diag " expected: '%s'" "$expect" + else + tap_ok 0 "$@" + fi +} + +# check the group of a given file, group may be a numeric id or user name +# tap_ar_is_group $path_to_archive $file $expected_group $test_name... +tap_ar_is_group() { + local ar=$1 path=$2 expect=$3; shift 3 + local statfun="_ar_stat" group unused + [[ $expect =~ ^[0-9]+$ ]] && statfun="_ar_nstat" + if ! read -r unused unused unused group unused < <($statfun "$ar" "$path"); then + tap_ok 1 "$@" + tap_diag " got: invalid path" + tap_diag " expected: '%s'" "$expect" + elif [[ $group != $expect ]]; then + tap_ok 1 "$@" + tap_diag " got: '%s'" "$group" + tap_diag " expected: '%s'" "$expect" + else + tap_ok 0 "$@" + fi +} + +# check if a path within an archive refers to a file +# tap_ar_is_file $path_to_archive $file $test_name... +tap_ar_is_file() { + local ar=$1 path=$2; shift 2 + local stat="$(_ar_stat "$ar" "$path")" + if [[ ${stat:0:1} != '-' ]]; then + tap_ok 1 "$@" + tap_diag " got: not a file" + tap_diag " expected: '%s'" "$path" + else + tap_ok 0 "$@" + fi +} + +# check if a path within an archive refers to a symbolic link +# tap_ar_is_link $path_to_archive $file $expected_destination $test_name... +tap_ar_is_link() { + local ar=$1 path=$2 dest=$3; shift 3 + local stat="$(_ar_stat "$ar" "$path")" + if [[ ${stat:0:1} != 'l' ]]; then + tap_ok 1 "$@" + tap_diag " got: not a link" + tap_diag " expected: '%s'" "$dest" + elif [[ ${stat##*$path -> } != $dest ]]; then + tap_ok 1 "$@" + tap_diag " got: '%s'" "${stat##*$path -> }" + tap_diag " expected: '%s'" "$dest" + else + tap_ok 0 "$@" + fi +} + +source "$(dirname "$0")"/../../tap.sh || exit 1 +tap_init diff --git a/test/makepkg/tests/Makefile.am b/test/makepkg/tests/Makefile.am new file mode 100644 index 00000000..fb59d11c --- /dev/null +++ b/test/makepkg/tests/Makefile.am @@ -0,0 +1,7 @@ +check_SCRIPTS = $(wildcard *.sh) + +noinst_SCRIPTS = $(check_SCRIPTS) + +EXTRA_DIST = $(check_SCRIPTS) + +# vim:set noet: diff --git a/test/makepkg/tests/TESTS b/test/makepkg/tests/TESTS new file mode 100644 index 00000000..f167e594 --- /dev/null +++ b/test/makepkg/tests/TESTS @@ -0,0 +1,4 @@ +TESTS += test/makepkg/tests/dbfiles.sh +TESTS += test/makepkg/tests/dotfiles.sh +TESTS += test/makepkg/tests/pkgbuild.sh +TESTS += test/makepkg/tests/util-pkgbuild.sh diff --git a/test/makepkg/tests/dbfiles.sh b/test/makepkg/tests/dbfiles.sh new file mode 100755 index 00000000..72e196ef --- /dev/null +++ b/test/makepkg/tests/dbfiles.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +source "$(dirname "$0")"/../test_functions.sh || exit 1 + +script="$(locate_bin "${1:-}")" + +TMPDIR="$(mktemp -d --tmpdir "${0##*/}.XXXXXX")" +trap "rm -rf '${TMPDIR}'" EXIT TERM + +tap_note "check that required metadata files are created" +tap_note "testing '%s'" "$script" +tap_note "using test dir '%s'" "$TMPDIR" + +( + set -e + cd "$TMPDIR" + cat >PKGBUILD <<-'PKGBUILD' + pkgname=foo + pkgver=1 + pkgrel=1 + arch=(any) + PKGBUILD + MAKEPKG_CONF="/dev/null" PKGEXT=".pkg.tar" $script +) |& tap_filter +[[ $? -eq 0 ]] || tap_xbail "test setup failed" + +pkgfile="$TMPDIR/foo-1-1-any.pkg.tar" + +tap_plan 10 +for f in .BUILDINFO .PKGINFO .MTREE; do + tap_ar_is_file "$pkgfile" "$f" "pkg contains %s" "$f" + tap_ar_is_owner "$pkgfile" "$f" "0" "%s owner is root" "$f" + tap_ar_is_group "$pkgfile" "$f" "0" "%s group is root" "$f" +done +tap_is_int "$(bsdtar -tf "$pkgfile" | wc -l)" 3 "pkg only contains known metainfo files" diff --git a/test/makepkg/tests/dotfiles.sh b/test/makepkg/tests/dotfiles.sh new file mode 100755 index 00000000..9fa81258 --- /dev/null +++ b/test/makepkg/tests/dotfiles.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +source "$(dirname "$0")"/../test_functions.sh || exit 1 + +script="$(locate_bin "${1:-}")" + +TMPDIR="$(mktemp -d --tmpdir "${0##*/}.XXXXXX")" +[[ ${KEEPFILES:-0} == 0 ]] || trap "rm -rf '${TMPDIR}'" EXIT TERM + +tap_note "test that dotfiles don't make it into the package root" +tap_note "testing '%s'" "$script" +tap_note "using test dir '%s'" "$TMPDIR" + +output="$( + set -e + cd "$TMPDIR" + cat >PKGBUILD <<-'PKGBUILD' + pkgname=foo + pkgver=1 + pkgrel=1 + arch=(any) + package() { + touch "$pkgdir"/.dotfile + } + PKGBUILD + MAKEPKG_CONF="/dev/null" PKGEXT=".pkg.tar" $script 2>&1 +)" +ret=$? + +tap_plan 3 +tap_eval "[[ '$ret' -ne 0 ]]" "makepkg exited non-zero" +tap_eval "[[ ! -f '$TMPDIR/foo-1-1-any.pkg.tar' ]]" "no package was built" +tap_eval "[[ '$output' = *'Dotfile found in package root'* ]]" "error message references dotfile" diff --git a/test/makepkg/tests/pkgbuild.sh b/test/makepkg/tests/pkgbuild.sh new file mode 100755 index 00000000..5dc8d46f --- /dev/null +++ b/test/makepkg/tests/pkgbuild.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +source "$(dirname "$0")"/../test_functions.sh || exit 1 + +script="$(locate_bin "${1:-}")" + +TMPDIR="$(mktemp -d --tmpdir "${0##*/}.XXXXXX")" +trap "rm -rf '${TMPDIR}'" EXIT TERM + +tap_note "basic package building test" +tap_note "testing '%s'" "$script" +tap_note "using test dir '%s'" "$TMPDIR" + +( + set -e + cd "$TMPDIR" + cat >PKGBUILD <<-'PKGBUILD' + pkgname=foo + pkgver=1 + pkgrel=1 + arch=(any) + package() { + touch "$pkgdir/!first" + touch "$pkgdir/target" + ln -s target "$pkgdir/link" + mkdir "$pkgdir/dir" + touch "$pkgdir/dir/.dotfile" + } + PKGBUILD + MAKEPKG_CONF="/dev/null" PKGEXT=".pkg.tar" $script +) |& tap_filter +[[ $? -eq 0 ]] || tap_xbail "test setup failed" + +pkgfile="$TMPDIR/foo-1-1-any.pkg.tar" + +tap_plan 10 +tap_ar_is_file "$pkgfile" "!first" "pkg contains !first" +tap_ar_is_file "$pkgfile" "target" "pkg contains target" +tap_ar_is_file "$pkgfile" "dir/.dotfile" "pkg contains dir/.dotfile" +tap_ar_is_link "$pkgfile" "link" "target" "pkg contains link to target" +tap_ar_is_owner "$pkgfile" "target" "0" "target owner is root" +tap_ar_is_group "$pkgfile" "target" "0" "target group is root" + +tap_eval "! bsdtar -tf '$pkgfile' | grep -qE '^\\.?\\.?/'" \ + "package paths are relative without leading dot dirs" +tap_eval "bsdtar -tf '$pkgfile' | grep -v '^\\.' | LANG=C sort -Cu" \ + "package files are sorted" +tap_eval "bsdtar -tf '$pkgfile' | LANG=C sort | LANG=C sort -Cu" \ + "package files are unique" +tap_eval "bsdtar -tf '$pkgfile' | head -n1 | grep -q '^\\.'" \ + "db files are placed at the beginning of the package" + +tap_finish diff --git a/test/makepkg/tests/util-pkgbuild.sh b/test/makepkg/tests/util-pkgbuild.sh new file mode 100755 index 00000000..3fd970c8 --- /dev/null +++ b/test/makepkg/tests/util-pkgbuild.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +source "$(dirname "$0")"/../test_functions.sh || exit 1 + +tap_note "testing libmakepkg/util/pkgbuild.sh" + +source_libmakepkg_file 'util/pkgbuild.sh' + +test_foo() { + myarray=(foo bar) + myarray+=(baz) + #myarray+=(this should be ignored) + myscalar=baz + myscalar=quux + #myscalar=ignored +} + +declare -a oarray +declare oscalar + +tap_plan 9 + +tap_eval 'have_function test_foo' 'detected existing function test_foo' +tap_eval '! have_function test_bar' 'detected missing function test_bar' + +tap_eval 'extract_function_variable test_foo myarray 1 oarray' 'extract array variable' +tap_is_int "${#oarray[@]}" 3 'extracted array length' +tap_is_str "${oarray[0]}" 'foo' 'extracted array contents' +tap_is_str "${oarray[1]}" 'bar' 'extracted array contents' +tap_is_str "${oarray[2]}" 'baz' 'extracted array contents' + +tap_eval 'extract_function_variable test_foo myscalar 0 oscalar' 'extract scalar variable' +tap_is_str "$oscalar" 'quux' 'extracted scalar value' + +tap_finish -- 2.11.1
Is this a whitespace only patch or am I missing something? On Sat, Feb 25, 2017, 12:21 PM Andrew Gregory, <andrew.gregory.8@gmail.com> wrote:
--- scripts/libmakepkg/util/pkgbuild.sh.in | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/scripts/libmakepkg/util/pkgbuild.sh.in b/scripts/libmakepkg/util/pkgbuild.sh.in index 7074c8c5..ae8ba5e7 100644 --- a/scripts/libmakepkg/util/pkgbuild.sh.in +++ b/scripts/libmakepkg/util/pkgbuild.sh.in @@ -207,14 +207,14 @@ get_integlist() { continue fi
- # check for e.g. "sha256sums_x86_64" - for a in "${arch[@]}"; do - local sumname="${integ}sums_${a}[@]" - if [[ -n ${!sumname} ]]; then - integlist+=("$integ") - break - fi - done + # check for e.g. "sha256sums_x86_64" + for a in "${arch[@]}"; do + local sumname="${integ}sums_${a}[@]" + if [[ -n ${!sumname} ]]; then + integlist+=("$integ") + break + fi + done done
if (( ${#integlist[@]} > 0 )); then -- 2.11.1
-- Signed, Kieran Colford
On 02/25/17 at 05:33pm, Kieran Colford wrote:
Is this a whitespace only patch or am I missing something?
Yes, as the commit message says, all this does is fix the indentation.
On 25.02.2017 18:21, Andrew Gregory wrote:
--- Makefile.am | 6 +- configure.ac | 2 + test/makepkg/Makefile.am | 9 +++ test/makepkg/README | 15 ++++ test/makepkg/test_functions.sh | 143 ++++++++++++++++++++++++++++++++++++ test/makepkg/tests/Makefile.am | 7 ++ test/makepkg/tests/TESTS | 4 + test/makepkg/tests/dbfiles.sh | 35 +++++++++ test/makepkg/tests/dotfiles.sh | 33 +++++++++ test/makepkg/tests/pkgbuild.sh | 53 +++++++++++++ test/makepkg/tests/util-pkgbuild.sh | 35 +++++++++ 11 files changed, 341 insertions(+), 1 deletion(-) create mode 100644 test/makepkg/Makefile.am create mode 100644 test/makepkg/README create mode 100644 test/makepkg/test_functions.sh create mode 100644 test/makepkg/tests/Makefile.am create mode 100644 test/makepkg/tests/TESTS create mode 100755 test/makepkg/tests/dbfiles.sh create mode 100755 test/makepkg/tests/dotfiles.sh create mode 100755 test/makepkg/tests/pkgbuild.sh create mode 100755 test/makepkg/tests/util-pkgbuild.sh
diff --git a/Makefile.am b/Makefile.am index 67ffc6b4..7b877a6c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = lib/libalpm src/util src/pacman scripts etc test/pacman test/util test/scripts +SUBDIRS = lib/libalpm src/util src/pacman scripts etc test/makepkg test/pacman test/util test/scripts if WANT_DOC SUBDIRS += doc endif @@ -26,11 +26,15 @@ dist_pkgdata_DATA = \ $(top_srcdir)/test/pacman/tests/TESTS: $(wildcard test/pacman/tests/*.py) @printf "TESTS += %s\n" $^ | LC_ALL=C sort -u > "$@"
+$(top_srcdir)/test/makepkg/tests/TESTS: $(wildcard test/makepkg/tests/*.sh) + @printf "TESTS += %s\n" $^ | LC_ALL=C sort -u > "$@" + TESTS = test/scripts/parseopts_test.sh \ test/scripts/human_to_size_test.sh \ test/scripts/makepkg-template_test.sh \ test/scripts/pacman-db-upgrade-v9.py \ test/util/vercmptest.sh +include $(top_srcdir)/test/makepkg/tests/TESTS include $(top_srcdir)/test/pacman/tests/TESTS
TEST_SUITE_LOG = test/test-suite.log diff --git a/configure.ac b/configure.ac index 10e4415c..d7e2c9ff 100644 --- a/configure.ac +++ b/configure.ac @@ -530,6 +530,8 @@ scripts/Makefile scripts/po/Makefile.in doc/Makefile etc/Makefile +test/makepkg/Makefile +test/makepkg/tests/Makefile test/pacman/Makefile test/pacman/tests/Makefile test/scripts/Makefile diff --git a/test/makepkg/Makefile.am b/test/makepkg/Makefile.am new file mode 100644 index 00000000..835030c0 --- /dev/null +++ b/test/makepkg/Makefile.am @@ -0,0 +1,9 @@ +SUBDIRS = tests + +check_SCRIPTS = test_functions.sh + +noinst_SCRIPTS = $(check_SCRIPTS) + +EXTRA_DIST = $(check_SCRIPTS) + +# vim:set noet: diff --git a/test/makepkg/README b/test/makepkg/README new file mode 100644 index 00000000..70c6872b --- /dev/null +++ b/test/makepkg/README @@ -0,0 +1,15 @@ +README +====== + +Running Tests +------------- + +Environment Variables +--------------------- + +PMTEST_SCRIPT_DIR - location of the makepkg executable; defaults to "$(dirname "$0")/../../../scripts)" +PMTEST_LIBMAKEPKG_DIR - base directory of the makepkg library; defaults to "$PMTEST_SCRIPT_DIR/libmakepkg" +VERBOSE - enable additional test output for debugging + +Adding New Tests +---------------- diff --git a/test/makepkg/test_functions.sh b/test/makepkg/test_functions.sh new file mode 100644 index 00000000..a6f07bcd --- /dev/null +++ b/test/makepkg/test_functions.sh @@ -0,0 +1,143 @@ +# basic setup to run before every test +# tap_init +tap_init() { + set +e + set -u + set -o pipefail +} + +# wrapper around tap_bail that immediately causes the test to exit non-zero +# tap_xbail $reason... +tap_xbail() { + tap_bail "$@" + exit 1; +} + +# read from stdin and reprint as diagnostic messages if VERBOSE is set and +# non-zero, otherwise, discard +# $command |& tap_filter +tap_filter() { + local v=${VERBOSE:-0} + if (( $v )); then + while IFS= read line; do + tap_diag "$line" + done + else + while IFS= read line; do + : + done + fi +} + +# locate the script that should be tested +locate_bin() { + local scriptdir="${PMTEST_SCRIPT_DIR:-"$(dirname "$0")/../../../scripts"}" + local script="$(realpath "${1:-"$scriptdir/makepkg-wrapper"}")" + if ! type -p "$script" &>/dev/null; then + tap_xbail "makepkg executable (%s) could not be located" "${script}" + exit 1
Isn't this exit unnecessary if xbail already exits?
+ fi + printf "%s" "$script" +} + +# locate an source libmakepkg files +source_libmakepkg_file() { + local file=$1; shift 1 + local scriptdir="${PMTEST_SCRIPT_DIR:-"$(dirname "$0")/../../../scripts"}" + local libdir="${PMTEST_LIBMAKEPKG_DIR:-"$scriptdir/libmakepkg"}" + source "$(realpath "$libdir/$file")" +} + +# eval a piece of code and test the return value +# tap_eval $code $test_name... +tap_eval() { + local t=$1; shift 1 + eval "$t" + tap_ok $? "$@" +} + +# extract ls-style information about a file: +# mode nhardlinks user group size month date time/year filename +_ar_stat() { + local ar=$1 path=$2; shift 2 + bsdtar --fast-read -tvf "$ar" "$@" "$path" 2>/dev/null +} + +# same as _ar_stat but with numeric owner ids +_ar_nstat() { + local ar=$1 path=$2; shift 2 + _ar_stat "$ar" "$path" --numeric-owner "$@" +} + +# check the owner of a given file, owner may be a numeric id or user name +# tap_ar_is_owner $path_to_archive $file $expected_owner $test_name... +tap_ar_is_owner() { + local ar=$1 path=$2 expect=$3; shift 3 + local statfun="_ar_stat" owner unused + [[ $expect =~ ^[0-9]+$ ]] && statfun="_ar_nstat" + if ! read -r unused unused owner unused < <($statfun "$ar" "$path"); then + tap_ok 1 "$@" + tap_diag " got: invalid path" + tap_diag " expected: '%s'" "$expect" + elif [[ $owner != $expect ]]; then + tap_ok 1 "$@" + tap_diag " got: '%s'" "$owner" + tap_diag " expected: '%s'" "$expect" + else + tap_ok 0 "$@" + fi +} + +# check the group of a given file, group may be a numeric id or user name +# tap_ar_is_group $path_to_archive $file $expected_group $test_name... +tap_ar_is_group() { + local ar=$1 path=$2 expect=$3; shift 3 + local statfun="_ar_stat" group unused + [[ $expect =~ ^[0-9]+$ ]] && statfun="_ar_nstat" + if ! read -r unused unused unused group unused < <($statfun "$ar" "$path"); then + tap_ok 1 "$@" + tap_diag " got: invalid path" + tap_diag " expected: '%s'" "$expect" + elif [[ $group != $expect ]]; then + tap_ok 1 "$@" + tap_diag " got: '%s'" "$group" + tap_diag " expected: '%s'" "$expect" + else + tap_ok 0 "$@" + fi +} + +# check if a path within an archive refers to a file +# tap_ar_is_file $path_to_archive $file $test_name... +tap_ar_is_file() { + local ar=$1 path=$2; shift 2 + local stat="$(_ar_stat "$ar" "$path")" + if [[ ${stat:0:1} != '-' ]]; then + tap_ok 1 "$@" + tap_diag " got: not a file" + tap_diag " expected: '%s'" "$path" + else + tap_ok 0 "$@" + fi +} + +# check if a path within an archive refers to a symbolic link +# tap_ar_is_link $path_to_archive $file $expected_destination $test_name... +tap_ar_is_link() { + local ar=$1 path=$2 dest=$3; shift 3 + local stat="$(_ar_stat "$ar" "$path")" + if [[ ${stat:0:1} != 'l' ]]; then + tap_ok 1 "$@" + tap_diag " got: not a link" + tap_diag " expected: '%s'" "$dest" + elif [[ ${stat##*$path -> } != $dest ]]; then + tap_ok 1 "$@" + tap_diag " got: '%s'" "${stat##*$path -> }" + tap_diag " expected: '%s'" "$dest" + else + tap_ok 0 "$@" + fi +} + +source "$(dirname "$0")"/../../tap.sh || exit 1 +tap_init diff --git a/test/makepkg/tests/Makefile.am b/test/makepkg/tests/Makefile.am new file mode 100644 index 00000000..fb59d11c --- /dev/null +++ b/test/makepkg/tests/Makefile.am @@ -0,0 +1,7 @@ +check_SCRIPTS = $(wildcard *.sh) + +noinst_SCRIPTS = $(check_SCRIPTS) + +EXTRA_DIST = $(check_SCRIPTS) + +# vim:set noet: diff --git a/test/makepkg/tests/TESTS b/test/makepkg/tests/TESTS new file mode 100644 index 00000000..f167e594 --- /dev/null +++ b/test/makepkg/tests/TESTS @@ -0,0 +1,4 @@ +TESTS += test/makepkg/tests/dbfiles.sh +TESTS += test/makepkg/tests/dotfiles.sh +TESTS += test/makepkg/tests/pkgbuild.sh +TESTS += test/makepkg/tests/util-pkgbuild.sh diff --git a/test/makepkg/tests/dbfiles.sh b/test/makepkg/tests/dbfiles.sh new file mode 100755 index 00000000..72e196ef --- /dev/null +++ b/test/makepkg/tests/dbfiles.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +source "$(dirname "$0")"/../test_functions.sh || exit 1 + +script="$(locate_bin "${1:-}")" + +TMPDIR="$(mktemp -d --tmpdir "${0##*/}.XXXXXX")" +trap "rm -rf '${TMPDIR}'" EXIT TERM + +tap_note "check that required metadata files are created" +tap_note "testing '%s'" "$script" +tap_note "using test dir '%s'" "$TMPDIR" + +( + set -e + cd "$TMPDIR" + cat >PKGBUILD <<-'PKGBUILD' + pkgname=foo + pkgver=1 + pkgrel=1 + arch=(any) + PKGBUILD + MAKEPKG_CONF="/dev/null" PKGEXT=".pkg.tar" $script +) |& tap_filter +[[ $? -eq 0 ]] || tap_xbail "test setup failed" + +pkgfile="$TMPDIR/foo-1-1-any.pkg.tar"
Shouldn't this, like the test below, check if foo-1-1-any.pkg.tar actually exists? Or does the test below run earlier than this, so it's tested already and can be assumed to be created? Is it the same for all other tests below, which don't check if $pkgfile exists?
+ +tap_plan 10 +for f in .BUILDINFO .PKGINFO .MTREE; do + tap_ar_is_file "$pkgfile" "$f" "pkg contains %s" "$f" + tap_ar_is_owner "$pkgfile" "$f" "0" "%s owner is root" "$f" + tap_ar_is_group "$pkgfile" "$f" "0" "%s group is root" "$f" +done +tap_is_int "$(bsdtar -tf "$pkgfile" | wc -l)" 3 "pkg only contains known metainfo files" diff --git a/test/makepkg/tests/dotfiles.sh b/test/makepkg/tests/dotfiles.sh new file mode 100755 index 00000000..9fa81258 --- /dev/null +++ b/test/makepkg/tests/dotfiles.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +source "$(dirname "$0")"/../test_functions.sh || exit 1 + +script="$(locate_bin "${1:-}")" + +TMPDIR="$(mktemp -d --tmpdir "${0##*/}.XXXXXX")" +[[ ${KEEPFILES:-0} == 0 ]] || trap "rm -rf '${TMPDIR}'" EXIT TERM + +tap_note "test that dotfiles don't make it into the package root" +tap_note "testing '%s'" "$script" +tap_note "using test dir '%s'" "$TMPDIR" + +output="$( + set -e + cd "$TMPDIR" + cat >PKGBUILD <<-'PKGBUILD' + pkgname=foo + pkgver=1 + pkgrel=1 + arch=(any) + package() { + touch "$pkgdir"/.dotfile + } + PKGBUILD + MAKEPKG_CONF="/dev/null" PKGEXT=".pkg.tar" $script 2>&1 +)" +ret=$? + +tap_plan 3 +tap_eval "[[ '$ret' -ne 0 ]]" "makepkg exited non-zero" +tap_eval "[[ ! -f '$TMPDIR/foo-1-1-any.pkg.tar' ]]" "no package was built" +tap_eval "[[ '$output' = *'Dotfile found in package root'* ]]" "error message references dotfile" diff --git a/test/makepkg/tests/pkgbuild.sh b/test/makepkg/tests/pkgbuild.sh new file mode 100755 index 00000000..5dc8d46f --- /dev/null +++ b/test/makepkg/tests/pkgbuild.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +source "$(dirname "$0")"/../test_functions.sh || exit 1 + +script="$(locate_bin "${1:-}")" + +TMPDIR="$(mktemp -d --tmpdir "${0##*/}.XXXXXX")" +trap "rm -rf '${TMPDIR}'" EXIT TERM + +tap_note "basic package building test" +tap_note "testing '%s'" "$script" +tap_note "using test dir '%s'" "$TMPDIR" + +( + set -e + cd "$TMPDIR" + cat >PKGBUILD <<-'PKGBUILD' + pkgname=foo + pkgver=1 + pkgrel=1 + arch=(any) + package() { + touch "$pkgdir/!first" + touch "$pkgdir/target" + ln -s target "$pkgdir/link" + mkdir "$pkgdir/dir" + touch "$pkgdir/dir/.dotfile" + } + PKGBUILD + MAKEPKG_CONF="/dev/null" PKGEXT=".pkg.tar" $script +) |& tap_filter +[[ $? -eq 0 ]] || tap_xbail "test setup failed" + +pkgfile="$TMPDIR/foo-1-1-any.pkg.tar" + +tap_plan 10 +tap_ar_is_file "$pkgfile" "!first" "pkg contains !first" +tap_ar_is_file "$pkgfile" "target" "pkg contains target" +tap_ar_is_file "$pkgfile" "dir/.dotfile" "pkg contains dir/.dotfile" +tap_ar_is_link "$pkgfile" "link" "target" "pkg contains link to target" +tap_ar_is_owner "$pkgfile" "target" "0" "target owner is root" +tap_ar_is_group "$pkgfile" "target" "0" "target group is root" + +tap_eval "! bsdtar -tf '$pkgfile' | grep -qE '^\\.?\\.?/'" \ + "package paths are relative without leading dot dirs" +tap_eval "bsdtar -tf '$pkgfile' | grep -v '^\\.' | LANG=C sort -Cu" \ + "package files are sorted" +tap_eval "bsdtar -tf '$pkgfile' | LANG=C sort | LANG=C sort -Cu" \ + "package files are unique" +tap_eval "bsdtar -tf '$pkgfile' | head -n1 | grep -q '^\\.'" \ + "db files are placed at the beginning of the package" + +tap_finish diff --git a/test/makepkg/tests/util-pkgbuild.sh b/test/makepkg/tests/util-pkgbuild.sh new file mode 100755 index 00000000..3fd970c8 --- /dev/null +++ b/test/makepkg/tests/util-pkgbuild.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +source "$(dirname "$0")"/../test_functions.sh || exit 1 + +tap_note "testing libmakepkg/util/pkgbuild.sh" + +source_libmakepkg_file 'util/pkgbuild.sh' + +test_foo() { + myarray=(foo bar) + myarray+=(baz) + #myarray+=(this should be ignored) + myscalar=baz + myscalar=quux + #myscalar=ignored +} + +declare -a oarray +declare oscalar + +tap_plan 9 + +tap_eval 'have_function test_foo' 'detected existing function test_foo' +tap_eval '! have_function test_bar' 'detected missing function test_bar' + +tap_eval 'extract_function_variable test_foo myarray 1 oarray' 'extract array variable' +tap_is_int "${#oarray[@]}" 3 'extracted array length' +tap_is_str "${oarray[0]}" 'foo' 'extracted array contents' +tap_is_str "${oarray[1]}" 'bar' 'extracted array contents' +tap_is_str "${oarray[2]}" 'baz' 'extracted array contents' + +tap_eval 'extract_function_variable test_foo myscalar 0 oscalar' 'extract scalar variable' +tap_is_str "$oscalar" 'quux' 'extracted scalar value' + +tap_finish
-- regards, brainpower
On 26/02/17 03:21, Andrew Gregory wrote:
Allows use under 'set -u'. --- scripts/libmakepkg/util/pkgbuild.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/libmakepkg/util/pkgbuild.sh.in b/scripts/libmakepkg/util/pkgbuild.sh.in index 2a4bd3af..08b35f53 100644 --- a/scripts/libmakepkg/util/pkgbuild.sh.in +++ b/scripts/libmakepkg/util/pkgbuild.sh.in @@ -18,7 +18,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. #
-[[ -n "$LIBMAKEPKG_UTIL_PKGBUILD_SH" ]] && return +[[ -n "${LIBMAKEPKG_UTIL_PKGBUILD_SH:-}" ]] && return LIBMAKEPKG_UTIL_PKGBUILD_SH=1
Is this going to need done for every file that you test? I'd prefer one big patch if so. A
On 26/02/17 03:21, Andrew Gregory wrote:
--- Makefile.am | 6 +- configure.ac | 2 + test/makepkg/Makefile.am | 9 +++ test/makepkg/README | 15 ++++ test/makepkg/test_functions.sh | 143 ++++++++++++++++++++++++++++++++++++ test/makepkg/tests/Makefile.am | 7 ++ test/makepkg/tests/TESTS | 4 + test/makepkg/tests/dbfiles.sh | 35 +++++++++ test/makepkg/tests/dotfiles.sh | 33 +++++++++ test/makepkg/tests/pkgbuild.sh | 53 +++++++++++++ test/makepkg/tests/util-pkgbuild.sh | 35 +++++++++ 11 files changed, 341 insertions(+), 1 deletion(-) create mode 100644 test/makepkg/Makefile.am create mode 100644 test/makepkg/README create mode 100644 test/makepkg/test_functions.sh create mode 100644 test/makepkg/tests/Makefile.am create mode 100644 test/makepkg/tests/TESTS create mode 100755 test/makepkg/tests/dbfiles.sh create mode 100755 test/makepkg/tests/dotfiles.sh create mode 100755 test/makepkg/tests/pkgbuild.sh create mode 100755 test/makepkg/tests/util-pkgbuild.sh
Looks good to me. Tests are a bit more complicated to make than pacman ones, but I will manage! Try not to use realpath in the script. This is not portable (there were issues with BSD/OSX from memory). Allan
On 03/02/17 at 02:37pm, Allan McRae wrote:
On 26/02/17 03:21, Andrew Gregory wrote:
Allows use under 'set -u'. --- scripts/libmakepkg/util/pkgbuild.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/libmakepkg/util/pkgbuild.sh.in b/scripts/libmakepkg/util/pkgbuild.sh.in index 2a4bd3af..08b35f53 100644 --- a/scripts/libmakepkg/util/pkgbuild.sh.in +++ b/scripts/libmakepkg/util/pkgbuild.sh.in @@ -18,7 +18,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. #
-[[ -n "$LIBMAKEPKG_UTIL_PKGBUILD_SH" ]] && return +[[ -n "${LIBMAKEPKG_UTIL_PKGBUILD_SH:-}" ]] && return LIBMAKEPKG_UTIL_PKGBUILD_SH=1
Is this going to need done for every file that you test? I'd prefer one big patch if so.
A
If we want to run the tests with 'set -u', this, or something similar will have to be done for all libmakepkg files. I actually think I like `[[ -v LIBMAKEPKG_UTIL_PKGBUILD_SH ]]` better though. apg
On 02/03/17 14:46, Andrew Gregory wrote:
On 03/02/17 at 02:37pm, Allan McRae wrote:
On 26/02/17 03:21, Andrew Gregory wrote:
Allows use under 'set -u'. --- scripts/libmakepkg/util/pkgbuild.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/libmakepkg/util/pkgbuild.sh.in b/scripts/libmakepkg/util/pkgbuild.sh.in index 2a4bd3af..08b35f53 100644 --- a/scripts/libmakepkg/util/pkgbuild.sh.in +++ b/scripts/libmakepkg/util/pkgbuild.sh.in @@ -18,7 +18,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. #
-[[ -n "$LIBMAKEPKG_UTIL_PKGBUILD_SH" ]] && return +[[ -n "${LIBMAKEPKG_UTIL_PKGBUILD_SH:-}" ]] && return LIBMAKEPKG_UTIL_PKGBUILD_SH=1
Is this going to need done for every file that you test? I'd prefer one big patch if so.
A
If we want to run the tests with 'set -u', this, or something similar will have to be done for all libmakepkg files. I actually think I like `[[ -v LIBMAKEPKG_UTIL_PKGBUILD_SH ]]` better though.
How long has bash 4.2 been around? Our minimum is currently 4.1.
On 03/02/17 at 02:59pm, Allan McRae wrote:
On 02/03/17 14:46, Andrew Gregory wrote:
On 03/02/17 at 02:37pm, Allan McRae wrote:
On 26/02/17 03:21, Andrew Gregory wrote:
Allows use under 'set -u'. --- scripts/libmakepkg/util/pkgbuild.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/libmakepkg/util/pkgbuild.sh.in b/scripts/libmakepkg/util/pkgbuild.sh.in index 2a4bd3af..08b35f53 100644 --- a/scripts/libmakepkg/util/pkgbuild.sh.in +++ b/scripts/libmakepkg/util/pkgbuild.sh.in @@ -18,7 +18,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. #
-[[ -n "$LIBMAKEPKG_UTIL_PKGBUILD_SH" ]] && return +[[ -n "${LIBMAKEPKG_UTIL_PKGBUILD_SH:-}" ]] && return LIBMAKEPKG_UTIL_PKGBUILD_SH=1
Is this going to need done for every file that you test? I'd prefer one big patch if so.
A
If we want to run the tests with 'set -u', this, or something similar will have to be done for all libmakepkg files. I actually think I like `[[ -v LIBMAKEPKG_UTIL_PKGBUILD_SH ]]` better though.
How long has bash 4.2 been around? Our minimum is currently 4.1.
4.2 appears to have been tagged at the end of 2011.
On 3/2/17 00:11 AM, Andrew Gregory wrote:
On 03/02/17 at 02:59pm, Allan McRae wrote:
On 02/03/17 14:46, Andrew Gregory wrote:
On 03/02/17 at 02:37pm, Allan McRae wrote:
On 26/02/17 03:21, Andrew Gregory wrote:
Allows use under 'set -u'. --- scripts/libmakepkg/util/pkgbuild.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/libmakepkg/util/pkgbuild.sh.in b/scripts/libmakepkg/util/pkgbuild.sh.in index 2a4bd3af..08b35f53 100644 --- a/scripts/libmakepkg/util/pkgbuild.sh.in +++ b/scripts/libmakepkg/util/pkgbuild.sh.in @@ -18,7 +18,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. #
-[[ -n "$LIBMAKEPKG_UTIL_PKGBUILD_SH" ]] && return +[[ -n "${LIBMAKEPKG_UTIL_PKGBUILD_SH:-}" ]] && return LIBMAKEPKG_UTIL_PKGBUILD_SH=1
Is this going to need done for every file that you test? I'd prefer one big patch if so.
A
If we want to run the tests with 'set -u', this, or something similar will have to be done for all libmakepkg files. I actually think I like `[[ -v LIBMAKEPKG_UTIL_PKGBUILD_SH ]]` better though.
How long has bash 4.2 been around? Our minimum is currently 4.1.
4.2 appears to have been tagged at the end of 2011.
We now require 4.4 anyway... -- Eli Schwartz Bug Wrangler and Trusted User
participants (5)
-
Allan McRae
-
Andrew Gregory
-
brainpower
-
Eli Schwartz
-
Kieran Colford