[pacman-dev] [PATCH 4/4] add basic makepkg test

Andrew Gregory andrew.gregory.8 at gmail.com
Sat Feb 25 17:21:18 UTC 2017


---
 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


More information about the pacman-dev mailing list