summaryrefslogtreecommitdiffstats
path: root/debian/tests
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--debian/tests/control143
-rwxr-xr-xdebian/tests/sourcesfilter98
-rw-r--r--debian/tests/testsuite219
3 files changed, 460 insertions, 0 deletions
diff --git a/debian/tests/control b/debian/tests/control
new file mode 100644
index 0000000..69f90a0
--- /dev/null
+++ b/debian/tests/control
@@ -0,0 +1,143 @@
+Tests: testsuite
+Depends:
+ apt-cudf,
+ arch-test,
+ aspcud,
+ black,
+ debian-archive-keyring,
+ debootstrap (>= 1.0.128),
+ diffoscope,
+ dpkg-dev,
+ fakechroot,
+ fakeroot,
+ genext2fs,
+ gpg,
+ grep-dctrl,
+ libcap2-bin,
+ libperl-critic-perl,
+ mmdebstrap,
+ mount,
+ perl-doc,
+ perltidy,
+ python3,
+ python3-apt,
+ python3-debian,
+ shellcheck,
+ squashfs-tools-ng,
+ sudo,
+ uidmap,
+Restrictions: needs-root, allow-stderr, skippable
+
+# add a manual trigger on those packages that in the past broke this test
+#
+# YEAR | SOURCE PACKAGE BUG NUMBERS FAILED TESTS
+# -----+-----------------------------------------------------------------------
+# | passwd #1004710
+# | python3 #1010368, #1010366
+# | man-db #1010957
+# 2022 | libc-bin #1017590
+# | cron #1012622, #1020603
+# | kmod #1020605
+# | ifupdown #1020604
+# | procps #1020602
+# -----+-----------------------------------------------------------------------
+# | fakeroot #1030638, #1023286
+# | debootstrap #1031222, #1031105, #1049898, #837060 check-against-debootstrap-dist, as-debootstrap-unshare-wrapper, chrootless
+# | libgdbm-compat4 #1031276 check-for-bit-by-bit-identical-format-output
+# | tzdata #1031395 essential-hook, multiple-include
+# 2023 | debian-archive-keyring #1019922 ascii-armored-keys, keyring, signed-by-without-host-keys
+# | doc-debian #1035913 include, install-doc-debian, install-doc-debian-and-test-hooks, multiple-include, unpack-doc-debian
+# | dash #989632
+# | adduser #1039709 check-against-debootstrap-dist
+# | debianutils #1050752 chrootless
+# | usrmerge #1050755, #1053671 chrootless-foreign, merged-fakechroot-inside-unmerged-chroot
+# -----+-----------------------------------------------------------------------
+# 2024 | dpkg #1059982 remove-start-stop-daemon-and-policy-rc-d-in-hook
+#
+Features: test-name=hint-testsuite-triggers
+Test-Command: false
+Depends:
+ adduser,
+ cron,
+ dash,
+ debian-archive-keyring,
+ debianutils,
+ debootstrap,
+ doc-debian,
+ dpkg,
+ fakeroot,
+ ifupdown,
+ kmod,
+ libc-bin,
+ libgdbm-compat4,
+ man-db,
+ passwd,
+ procps,
+ python3,
+ tzdata,
+ usrmerge,
+Restrictions: hint-testsuite-triggers
+
+# FIXME: in an ideal world, debci would have enough computational resources
+# to run this autopkgtest for all the packages in essential and
+# build-essential and priority:standard that trigger it. But we are
+# not there yet, so we must live with the situation that even if a
+# package upload breaks the mmdebstrap autopkgtest, we will only notice
+# either because another unrelated package triggers the autopkgtest
+# or because this failed:
+# https://jenkins.debian.net/job/mmdebstrap-jenkins-worker/
+## Using the hint-testsuite-triggers restriction we make all packages that are
+## put into the local archive by ./make_mirror.sh a trigger for the mmdebstrap
+## autopkgtest. This is essential, priority:required, priority:important,
+## priority:standard, build-essential, busybox, gpg, eatmydata, usr-is-merged
+## and usrmerge plus their dependency closure. The set is different depending
+## on the native architecture. Since we cannot depend on source packages and
+## to reduce the binary package set, only one binary package per source
+## package is listed here. If there are multiple choices, the binary packages
+## available on more architectures are preferred and then sorted by name.
+## Since library binary package names change frequently, this list has to be
+## updated regularly. Use the debian/compute_pkgset.py script to update the
+## list of dependencies.
+#Features: test-name=hint-testsuite-triggers
+#Test-Command: false
+#Depends: acl, adduser, anacron, apt, apt-listchanges, base-files, base-passwd,
+# bash, bash-completion, bc [ppc64el], bcron, bind9-dnsutils, binutils,
+# bsdextrautils, build-essential, busybox, bzip2, ca-certificates, cdebconf,
+# coreutils, cpio, cpp, cpp-12, cron, daemon, dash, dbus, dbus-broker, debconf,
+# debian-archive-keyring, debian-faq, debianutils, diffutils, distro-info-data,
+# dmidecode [amd64 arm64 armhf i386], dmsetup, doc-debian, dpkg, e2fsprogs,
+# eatmydata, file, findutils, gawk, gettext-base, gpg, gpgv1, grep, groff-base,
+# guile-3.0-libs, gzip, hostname, ifupdown, inetutils-telnet, init,
+# initscripts, insserv, install-info, iproute2, iputils-ping, isc-dhcp-client,
+# kmod, krb5-locales, less, libapparmor1, libargon2-1, libassuan0, libattr1,
+# libaudit-common, libbg2, libbpf1, libbrotli1, libbsd0, libc-bin, libcap-ng0,
+# libcap2, libcbor0.8, libcrypt-dev, libcryptsetup12, libcurl3-gnutls,
+# libdb5.3, libdebian-installer4, libedit2, libeinfo1, libelf1, libelogind0,
+# libexpat1, libffi8, libfido2-1, libfile-find-rule-perl, libfstrm0,
+# libfuse2 [s390x], libgc1, libgcrypt20, libgdbm-compat4, libgmp10,
+# libgnutls30, libgpg-error0, libhogweed6, libicu72, libidn2-0, libip4tc2,
+# libisl23, libjansson4, libjemalloc2, libjson-c5, libkeyutils1, libldap-2.5-0,
+# liblmdb0, liblocale-gettext-perl, liblockfile-bin, liblz4-1, liblzma5,
+# libmaxminddb0, libmd0, libmnl0, libmpc3, libmpfr6, libncursesw6, libnewt0.52,
+# libnftables1, libnftnl11, libnghttp2-14, libnsl-dev, libnss-systemd,
+# libnuma1 [ppc64el], libnumber-compare-perl, libp11-kit0, libpam-modules,
+# libpci3, libpcre2-8-0, libperl5.36, libpipeline1, libpopt0, libproc2-0,
+# libprotobuf-c1, libpsl5, libpython3-stdlib, libpython3.11-minimal,
+# libreadline8, librtas2 [ppc64el], librtmp1, libsasl2-2, libseccomp2,
+# libselinux1, libsemanage-common, libsepol2, libsigsegv2, libslang2,
+# libsqlite3-0, libssh2-1, libssl3, libtasn1-6, libtext-charwidth-perl,
+# libtext-glob-perl, libtext-iconv-perl, libtext-wrapi18n-perl, libtextwrap1,
+# libtirpc-common, libuchardet0, libunistring2, libuv1, libxml2, libxxhash0,
+# libzstd1, linux-libc-dev, login, logrotate, lsb-base, lsof, mailcap, make,
+# man-db, manpages, mawk, media-types, mime-support, nano, netbase,
+# netcat-traditional, openssh-client, opensysusers, original-awk, patch,
+# pci.ids, powerpc-ibm-utils [ppc64el], python-apt-common, python3-certifi,
+# python3-chardet, python3-charset-normalizer, python3-debian,
+# python3-debianbts, python3-httplib2, python3-idna, python3-pkg-resources,
+# python3-pycurl, python3-pyparsing, python3-pysimplesoap, python3-reportbug,
+# python3-requests, python3-six, python3-urllib3, rpcsvc-proto, runit-helper,
+# s390-tools [s390x], sed, sensible-utils, startpar,
+# sysconfig-hardware [s390x], systemd-cron, sysuser-helper, tar, tasksel,
+# traceroute, tzdata, ucf, ucspi-unix, usr-is-merged, vim-common, wamerican,
+# wget, zlib1g
+#Restrictions: hint-testsuite-triggers
diff --git a/debian/tests/sourcesfilter b/debian/tests/sourcesfilter
new file mode 100755
index 0000000..f2d6b7d
--- /dev/null
+++ b/debian/tests/sourcesfilter
@@ -0,0 +1,98 @@
+#!/usr/bin/env python3
+
+from aptsources.sourceslist import SourcesList, Deb822SourceEntry
+import apt_pkg
+import glob
+import os.path
+import sys
+import os
+
+
+def main(rootfs):
+ sources = SourcesList(False, deb822=True)
+
+ dbglvl = os.environ.get("MMDEBSTRAP_VERBOSITY", "-1")
+ try:
+ dbglvl = int(dbglvl)
+ except ValueError:
+ dbglvl = -1
+ if dbglvl >= 2:
+ print("before:", file=sys.stderr)
+ for s in sources.list:
+ print(s.str(), end="", file=sys.stderr)
+
+ os.makedirs(rootfs + "/etc/apt/sources.list.d", exist_ok=True)
+
+ # remove all the things we do not want and change components and uri
+ for s in list(sources):
+ # since we put everything into a single output file, only one-line
+ # format is supported for now
+ assert not isinstance(s, Deb822SourceEntry), s
+ s.file = rootfs + s.file
+ # if it's a local file:// repo, don't mangle it
+ if s.uri.startswith("file://"):
+ continue
+ # remove debug packages
+ if s.uri.endswith("/debian-debug"):
+ sources.remove(s)
+ continue
+ # only allow main
+ s.comps = [c for c in s.comps if c in ["main"]]
+ # remove sources with empty components list
+ if not s.comps:
+ sources.remove(s)
+ continue
+ # remove deb-src entries
+ if s.type == "deb-src":
+ sources.remove(s)
+ continue
+ # translate uri to our proxy on 127.0.0.1
+ s.uri = "http://127.0.0.1/debian"
+
+ # remove duplicates
+ # we cannot use set() because order must be preserved
+ seen = set()
+ for s in list(sources):
+ if s.str() in seen:
+ sources.remove(s)
+ continue
+ seen.add(s.str())
+
+ if dbglvl >= 2:
+ print("after:", file=sys.stderr)
+ for s in sources.list:
+ print(s.str(), end="", file=sys.stderr)
+
+ # we want to append to existing files, so backup the files which would
+ # otherwise be overwritten by sources.save()
+ files_to_backup = {}
+ for s in sources.list:
+ if os.path.isfile(s.file):
+ files_to_backup[s.file] = b""
+
+ for fname in files_to_backup:
+ with open(fname, "rb") as f:
+ files_to_backup[fname] = f.read()
+
+ sources.save()
+
+ # now prepend the original content
+ for fname in files_to_backup:
+ with open(fname, "rb") as f:
+ updated_content = f.read()
+ with open(fname, "wb") as f:
+ f.write(files_to_backup[fname] + b"\n" + updated_content)
+
+ # append apt preferences verbatim
+ for pref in glob.glob("/etc/apt/preferences.d/*"):
+ if not os.path.isfile(pref):
+ continue
+ os.makedirs(os.path.dirname(rootfs + pref), exist_ok=True)
+ with open(pref) as fin, open(rootfs + pref, "a") as fout:
+ fout.write("\n")
+ for line in fin:
+ fout.write(line)
+
+
+if __name__ == "__main__":
+ main(sys.argv[1])
diff --git a/debian/tests/testsuite b/debian/tests/testsuite
new file mode 100644
index 0000000..f8edddb
--- /dev/null
+++ b/debian/tests/testsuite
@@ -0,0 +1,219 @@
+#!/bin/sh
+
+set -exu
+
+# dump information about the autopkgtest runner
+# print to stderr to prevent wrong interleaving with set -x output
+cat /etc/debian_version >&2
+env >&2
+nproc >&2
+apt-config dump >&2
+apt-cache policy >&2
+for f in /etc/apt/sources.list /etc/apt/sources.list.d/* /etc/apt/preferences.d/*; do
+ [ -e "$f" ] || continue
+ echo "dumping contents of $f" >&2
+ cat "$f" >&2
+done
+
+# The mmdebstrap autopkgtest can take a very long time and it cannot be split
+# into multiple individual tests because they all rely on the existence of the
+# local package cache. We cannot re-generate this cache multiple times because
+# if a dinstall happens while this autopkgtest is running (not unlikely because
+# this test takes 2 hours easy) then the chroots might not be bit-by-bit
+# identical with each other anymore. Being independent of unfortunate Debian
+# mirror updates is one of the reasons the cache exists.
+#
+# By default (and this cannot be changed), a autopkgtest "test" is allowed to
+# last 10000 seconds or 2:46:40 hours. If this test takes too long, we return
+# exit code 77, marking it as "skipped".
+
+TIME_BEGIN=$(date +%s)
+
+# the archive with the highest priority where the base-files package comes from
+# determines whether we are on stable, testing or unstable
+DEFAULT_DIST=$(cat << END | python3 -
+import apt_pkg, sys
+apt_pkg.init()
+c = apt_pkg.Cache(None)
+d = apt_pkg.DepCache(c)
+s = apt_pkg.SourceList()
+s.read_main_list()
+
+highest_prio = -1
+highest_archive = None
+for pkgfile, _ in d.get_candidate_ver(c["base-files"]).file_list:
+ print("processing: %s"%pkgfile, file=sys.stderr)
+ index = s.find_index(pkgfile)
+ if index is None:
+ print("index is none -- skipping", file=sys.stderr)
+ continue
+ if not index.is_trusted:
+ print("index is not trusted -- skipping", file=sys.stderr)
+ continue
+ archive = pkgfile.archive
+ if archive not in ["stable", "testing", "unstable"]:
+ print("index archive %s is %s -- skipping"%(index, archive), file=sys.stderr)
+ continue
+ prio = d.policy.get_priority(pkgfile)
+ if prio > highest_prio:
+ highest_prio = prio
+ highest_archive = archive
+if highest_archive is None:
+ print("highest priority apt archive is neither stable, testing or unstable", file=sys.stderr)
+ for f in c.file_list:
+ print('========================', file=sys.stderr)
+ for a in ['architecture', 'archive', 'codename', 'component', 'filename', 'id', 'index_type', 'label', 'not_automatic', 'not_source', 'origin', 'site', 'size', 'version']:
+ print("%s: %s"%(a, getattr(f, a, None)), file=sys.stderr)
+ print("priority: ", d.policy.get_priority(f), file=sys.stderr)
+ exit(1)
+print("highest archive priority: %s"%highest_archive, file=sys.stderr)
+print(highest_archive)
+END
+)
+
+# On stable and testing we can run tests that require m-a:same packages to
+# exist in the same version across multiple architectures. Only on unstable we
+# disable this because packages in unstable are often out-of-sync.
+RUN_MA_SAME_TESTS=yes
+case $DEFAULT_DIST in
+ unstable)
+ RUN_MA_SAME_TESTS=no
+ ;;
+ stable|testing)
+ # nothing to do
+ ;;
+ *)
+ echo "unknown distribution $DEFAULT_DIST, must be one of stable, testing or unstable" >&2
+ ;;
+esac
+
+SRC="$(pwd)"
+
+# change to temporary directory to not interfere with the source
+cd "$AUTOPKGTEST_TMP"
+
+# coverage.sh expects the scripts to be in the current directory
+# we copy make_mirror.sh instead of symlinking it because we are going to patch
+# it
+cp -a "$SRC/make_mirror.sh" make_mirror.sh
+ln -s "$SRC/run_qemu.sh" run_qemu.sh
+ln -s "$SRC/run_null.sh" run_null.sh
+cp -a "$SRC/hooks" .
+ln -s "$SRC/coverage.sh" coverage.sh
+ln -s "$SRC/gpgvnoexpkeysig" gpgvnoexpkeysig
+ln -s "$SRC/coverage.py" coverage.py
+ln -s "$SRC/coverage.txt" coverage.txt
+ln -s "$SRC/caching_proxy.py" caching_proxy.py
+ln -s "$SRC/.perltidyrc" .perltidyrc
+ln -s "$SRC/mmdebstrap-autopkgtest-build-qemu" mmdebstrap-autopkgtest-build-qemu
+cp -a "$SRC/tests" .
+
+# on Debian Salsa CI, $AUTOPKGTEST_NORMAL_USER is empty
+if [ -z "$AUTOPKGTEST_NORMAL_USER" ]; then
+ AUTOPKGTEST_NORMAL_USER=debci
+ useradd --create-home --groups sudo "$AUTOPKGTEST_NORMAL_USER"
+# useradd --create-home --groups kvm "$AUTOPKGTEST_NORMAL_USER"
+# ls -lha /dev/kvm || true
+# lsmod | grep kvm || true
+else
+ adduser "$AUTOPKGTEST_NORMAL_USER" sudo
+# adduser "$AUTOPKGTEST_NORMAL_USER" kvm
+fi
+
+mkdir ./shared
+chown "$AUTOPKGTEST_NORMAL_USER" ./shared
+
+echo "$AUTOPKGTEST_NORMAL_USER ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
+
+# we cannot use mini_httpd (or most other http servers) because they perform a
+# chdir() into the directory that is to be served on startup. But later on we
+# completely remove and replace that directory when creating the Debian mirror.
+# Thus we need a really stupid server which is able to cope with having its
+# www-root being replaced under its feet.
+#mini_httpd -D -h 127.0.0.1 -p 80 -u "$AUTOPKGTEST_NORMAL_USER" -T UTF-8 -dd "$AUTOPKGTEST_TMP/shared/cache" &
+python3 -m http.server --directory="$AUTOPKGTEST_TMP/shared/cache" --bind 127.0.0.1 80 2>/dev/null &
+HTTPD_PID=$!
+trap "kill $HTTPD_PID" INT QUIT TERM EXIT
+
+# create a fake mmdebstrap file in the current directory that coverage.sh can
+# copy
+cat << END > ./mmdebstrap
+#!/usr/bin/perl
+use strict;
+use warnings;
+exit(1)
+END
+
+# must not be used during testing -- installed version must be used instead
+cat << END > ./tarfilter
+#!/usr/bin/env python3
+exit(1)
+END
+
+# add entries to /etc/subuid and /etc/subgid if they don't exist yet
+if [ ! -e /etc/subuid ] || ! grep "$AUTOPKGTEST_NORMAL_USER" /etc/subuid; then
+ echo "$AUTOPKGTEST_NORMAL_USER:100000:65536" >> /etc/subuid
+fi
+if [ ! -e /etc/subgid ] || ! grep "$AUTOPKGTEST_NORMAL_USER" /etc/subgid; then
+ echo "$AUTOPKGTEST_NORMAL_USER:100000:65536" >> /etc/subgid
+fi
+
+ret=0
+timeout 50m runuser -u "$AUTOPKGTEST_NORMAL_USER" -- env CMD=mmdebstrap DEFAULT_DIST=$DEFAULT_DIST RUN_MA_SAME_TESTS=$RUN_MA_SAME_TESTS HAVE_QEMU=no HAVE_BINFMT=no USE_HOST_APT_CONFIG=yes "$SRC/make_mirror.sh" || ret=$?
+if [ "$ret" -ne 0 ]; then
+ echo "./make_mirror.sh failed" >&2
+ exit 77
+fi
+
+# subtract 10 seconds to account for the inaccuracy in measuring time
+TIMEOUT=$((10000-$(date +%s)+$TIME_BEGIN-10))
+
+# now run the script
+# we set CMD so that Devel::Cover is not used
+# HAVE_QEMU=no because there is no kvm kernel module
+# HAVE_BINFMT=no because there is no binfmt_misc kernel module
+ret=0
+timeout $TIMEOUT runuser -u "$AUTOPKGTEST_NORMAL_USER" -- env CMD="mmdebstrap --setup-hook=$SRC/debian/tests/sourcesfilter --hook-dir=$SRC/hooks/file-mirror-automount" DEFAULT_DIST=$DEFAULT_DIST RUN_MA_SAME_TESTS=$RUN_MA_SAME_TESTS HAVE_QEMU=no HAVE_BINFMT=no USE_HOST_APT_CONFIG=yes "$SRC/coverage.sh" --exitfirst || ret=$?
+if [ "$ret" -eq 124 ]; then
+ echo "command timed out after $TIMEOUT seconds" >&2
+ exit 77
+elif [ "$ret" -ne 0 ]; then
+ exit $ret
+fi
+
+# subtract 10 seconds to account for the inaccuracy in measuring time
+TIMEOUT=$((10000-$(date +%s)+$TIME_BEGIN-10))
+
+# exit successfully if there is not enough time left
+if [ "$TIMEOUT" -lt 3000 ]; then
+ echo "skipping remaining tests due to lack of remaining time" >&2
+ exit 0
+fi
+
+du -hs ./shared
+
+# FORCE_UPDATE=yes to force rebuilding the cache
+# ONLY_HOSTARCH=yes to limit the number of downloaded content
+# RUN_MA_SAME_TESTS=no because foreign arches are missing
+ret=0
+timeout $TIMEOUT runuser -u "$AUTOPKGTEST_NORMAL_USER" -- env CMD=mmdebstrap DEFAULT_DIST=$DEFAULT_DIST ONLY_HOSTARCH=yes FORCE_UPDATE=yes RUN_MA_SAME_TESTS=no HAVE_QEMU=no HAVE_BINFMT=no "$SRC/make_mirror.sh" || ret=$?
+if [ "$ret" -ne 0 ]; then
+ echo "./make_mirror.sh failed" >&2
+ exit 77
+fi
+
+# subtract 10 seconds to account for the inaccuracy in measuring time
+TIMEOUT=$((10000-$(date +%s)+$TIME_BEGIN-10))
+
+# run only those tests that were skipped because of USE_HOST_APT_CONFIG=yes but
+# ignore if any of them fails
+# failures here are irrelevant for transition testing because they cannot
+# respect the apt pinning options given by the test environment
+SKIPPED_TESTS=$(grep-dctrl --exact-match --field Needs-APT-Config true --no-field-names --show-field=Test < coverage.txt)
+# for tar1.txt also add create-directory test
+SKIPPED_TESTS="create-directory $SKIPPED_TESTS"
+timeout $TIMEOUT runuser -u "$AUTOPKGTEST_NORMAL_USER" -- env CMD="mmdebstrap" DEFAULT_DIST=$DEFAULT_DIST RUN_MA_SAME_TESTS=no HAVE_QEMU=no HAVE_BINFMT=no "$SRC/coverage.py" --exitfirst $SKIPPED_TESTS || exit 77
+
+du -hs ./shared
+
+exit 0