From patchwork Sat Feb 25 17:21:18 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Gregory X-Patchwork-Id: 29 Return-Path: Delivered-To: patchwork@archlinux.org Received: from nymeria.archlinux.org by nymeria.archlinux.org (Dovecot) with LMTP id eZzzHyC9sVjrDwAAtiB/HQ for ; Sat, 25 Feb 2017 18:21:36 +0100 Received: from nymeria.archlinux.org (localhost.localdomain [127.0.0.1]) by nymeria.archlinux.org (Postfix) with ESMTP id C904840835; Sat, 25 Feb 2017 18:21:31 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on nymeria.archlinux.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.5 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_MED,T_DKIM_INVALID shortcircuit=no autolearn=unavailable autolearn_force=no version=3.4.1 Received: from luna.archlinux.org (luna.archlinux.org [5.9.250.164]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by nymeria.archlinux.org (Postfix) with ESMTPS; Sat, 25 Feb 2017 18:21:31 +0100 (CET) Received: from luna.archlinux.org (luna.archlinux.org [127.0.0.1]) by luna.archlinux.org (Postfix) with ESMTP id 913AF2CC51; Sat, 25 Feb 2017 17:21:27 +0000 (UTC) Authentication-Results: luna.archlinux.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=tGtPtD3E Received: from luna.archlinux.org (luna.archlinux.org [127.0.0.1]) by luna.archlinux.org (Postfix) with ESMTP id 527062C82A for ; Sat, 25 Feb 2017 17:21:23 +0000 (UTC) Received: from nymeria.archlinux.org (nymeria.archlinux.org [89.238.67.251]) by luna.archlinux.org (Postfix) with ESMTPS for ; Sat, 25 Feb 2017 17:21:23 +0000 (UTC) Received: from nymeria.archlinux.org (localhost.localdomain [127.0.0.1]) by nymeria.archlinux.org (Postfix) with ESMTP id 3A5F04040D for ; Sat, 25 Feb 2017 18:21:18 +0100 (CET) Received: from mail-qk0-x22d.google.com (mail-qk0-x22d.google.com [IPv6:2607:f8b0:400d:c09::22d]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by nymeria.archlinux.org (Postfix) with ESMTPS for ; Sat, 25 Feb 2017 18:21:17 +0100 (CET) Received: by mail-qk0-x22d.google.com with SMTP id u188so46888778qkc.2 for ; Sat, 25 Feb 2017 09:21:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ivgV18ScfCQbhVta6Wn49ZC9sUAuu2hi1OjyOhFKeGY=; b=tGtPtD3EUm2EpOmOSpTavPPfFwV9JJWCPyjdNDleCxsU/6moBOiErizylVeIXZeYNe nboYV2p3dZtiRXIIbzMSKhCXev+H218060DCISIXXMIPoO7yYgYoPK7bPuA4hmIgjDbz 2asMC+VdKZbUQo0GcwZgUgzF6/qj5kcNQQMsB13VcV88sUmlcpok5EWlVBzjcYd0p9KX gy2M21kARAEFWsnTyyRg5eou5AErG+X4q0ViiPS3CpVDmcWR9DpVr3UFqU8n02Mbke+D Mxq/kdtQDyv+7+1usbECLNdBbk+BDiAZYc7ZQdGKR8muRoH0RneNT00jorusguIUx422 59Rg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ivgV18ScfCQbhVta6Wn49ZC9sUAuu2hi1OjyOhFKeGY=; b=gkc0NZdhGTsbv97jTpghd6483KXUox5qIqjW3kUxFjk9z+lQzHu/dv0qZNJ87vktWJ UTfotwmEkr4SENgb31ZEwd7dexUQcVCrv3Lh9N9aDPjSlPtUuChT9/63tSf/dzPPCgyb F/6rp318FA3fC7gu1s6XkEzEEkHnT6HfGtQdAjQxclsf1RKpT6+FUQS4ihjQhw9e2XR5 bzFxTQ0AqhPGgRy1btW0sP16+lI2dUdhqhsVw6YYRFBRDLrEXym+/GJpmiJPA9Dl3Jjz urzSZU/aUzVWaSVfxNB/YsGZOT3OTSyEZ+K7KLIbKDJ47RAyFjgDBNrnz/dypUGcObJM x1hg== X-Gm-Message-State: AMke39kRq84m7nQDXr5rrGeqal/U8G4VveQ1502G4Qdul75JzmD09DHvl+wXaW6dsb8pRA== X-Received: by 10.55.60.133 with SMTP id j127mr4817490qka.190.1488043276543; Sat, 25 Feb 2017 09:21:16 -0800 (PST) Received: from localhost.local (cpe-98-27-61-138.nc.res.rr.com. [98.27.61.138]) by smtp.gmail.com with ESMTPSA id 15sm7105057qkd.35.2017.02.25.09.21.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 25 Feb 2017 09:21:16 -0800 (PST) From: Andrew Gregory To: pacman-dev@archlinux.org Date: Sat, 25 Feb 2017 12:21:18 -0500 Message-Id: <20170225172118.5780-5-andrew.gregory.8@gmail.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20170225172118.5780-1-andrew.gregory.8@gmail.com> References: <20170225172118.5780-1-andrew.gregory.8@gmail.com> Subject: [pacman-dev] [PATCH 4/4] add basic makepkg test X-BeenThere: pacman-dev@archlinux.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Discussion list for pacman development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Discussion list for pacman development Cc: Andrew Gregory Errors-To: pacman-dev-bounces@archlinux.org Sender: "pacman-dev" X-UID: 83 Status: X-Keywords: Content-Length: 13363 --- 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