diff options
Diffstat (limited to '')
-rw-r--r-- | debian/tests/control | 143 | ||||
-rwxr-xr-x | debian/tests/sourcesfilter | 98 | ||||
-rw-r--r-- | debian/tests/testsuite | 219 |
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 |