Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ jobs:
libfontconfig1-dev libfreetype6-dev build-essential qtbase5-dev qtchooser libcairo2-dev \
libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-test-dev \
libopenjp2-7-dev libjpeg-dev libjxl-dev libpoppler-cpp-dev libpython3-dev libdbus-1-dev \
mupdf-tools poppler-utils ghostscript wget tar make gettext
mupdf-tools poppler-utils ghostscript wget tar make gettext \
dbus file

- name: Build PDFio and libcupsfilters (Native)
if: matrix.use-qemu == false
Expand All @@ -85,6 +86,16 @@ jobs:
# V=1 shows compiler commands; VERBOSE=1 restores full internal test details
make check V=1 VERBOSE=1 || (test -f test-suite.log && cat test-suite.log; exit 1)

- name: Autopkgtest (DESTDIR staging, native)
if: matrix.use-qemu == false
run: |
set -ex
cd "$GITHUB_WORKSPACE"
# Full downstream suite: libcupsfilters-2-dev (compile/link/run) +
# libcupsfilters-2-functionality. Both point at the staged tree via
# environment overrides, so no privilege or path redirection is needed.
make test-autopkgtest V=1

- name: Upload test artifacts (Native)
if: matrix.use-qemu == false && always()
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -115,7 +126,8 @@ jobs:
libfontconfig1-dev libfreetype6-dev build-essential qtbase5-dev qtchooser libcairo2-dev \
libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-test-dev \
libopenjp2-7-dev libjpeg-dev libjxl-dev libpoppler-cpp-dev libpython3-dev libdbus-1-dev \
mupdf-tools poppler-utils ghostscript wget tar make gettext gcc g++
mupdf-tools poppler-utils ghostscript wget tar make gettext gcc g++ \
dbus file
run: |
set -ex
REPO_DIR=$(pwd)
Expand All @@ -139,6 +151,12 @@ jobs:
# Mark test-pclm-overflow.sh as XFAIL; VERBOSE=1 for full internal logs
make check V=1 VERBOSE=1 XFAIL_TESTS="cupsfilters/test-pclm-overflow.sh" || (test -f test-suite.log && cat test-suite.log; exit 1)

# Full downstream autopkgtest suite. Both tests resolve the staged
# build tree through environment overrides (no absolute paths, no
# privilege, no bind mounts), so the same suite that runs on the
# native legs runs unchanged under QEMU emulation.
make test-autopkgtest V=1

- name: Upload test artifacts (Emulated)
if: matrix.use-qemu == true && always()
uses: actions/upload-artifact@v4
Expand Down
90 changes: 90 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -380,3 +380,93 @@ uninstall-hook:
$(RM) $(DESTDIR)$(pkgcharsetdir)/pdf.utf-8

SUBDIRS =

# =============================================================================
# Downstream Debian autopkgtest harness (DESTDIR staging)
#
# Builds, DESTDIR-installs into an ephemeral $(CIROOT) tree, tops up the
# test-only programs/data that `make install` does not ship, rewrites the
# staged libcupsfilters.pc so a consumer resolves THIS build, then runs the
# vendored downstream scripts against it. No privilege, no bind mounts, no
# proot -> identical on native and QEMU-emulated architectures.
# =============================================================================
CIROOT = $(abs_top_builddir)/_ciroot

EXTRA_DIST += \
ci/autopkgtest/run.sh \
ci/autopkgtest/debian-tests/control \
ci/autopkgtest/debian-tests/libcupsfilters-2-dev \
ci/autopkgtest/debian-tests/libcupsfilters-2-functionality

# Fix A: these are check_PROGRAMS (build-only; never copied by `make install`).
# The functionality test executes them as installed binaries (/usr/bin/...),
# so build them and stage them into $(CIROOT)$(bindir). libtool --mode=install
# relinks each cleanly against $(libdir) (LD_LIBRARY_PATH then forces the
# staged library at run time).
STAGED_TEST_BINARIES = \
testdither \
testpdf1 \
testpdf2 \
test-analyze \
test-pdf \
test-ps \
testcmyk \
testrgb

install-test-programs: $(STAGED_TEST_BINARIES)
$(MKDIR_P) "$(CIROOT)$(bindir)"
@for p in $(STAGED_TEST_BINARIES); do \
echo " STAGE $$p -> $(CIROOT)$(bindir)/$$p"; \
$(LIBTOOL) --mode=install $(INSTALL_PROGRAM) "$$p" "$(CIROOT)$(bindir)/$$p" || exit 1; \
done

# Fix C (data seeding): the functionality test copies its input images from
# $(datadir)/libcupsfilters-tests, which upstream `make install` does not ship.
# Seed image.pgm and image.ppm (both are cupsfilters/image.pgm, matching the
# downstream packaging) so the unmodified script finds them.
install-test-data:
$(MKDIR_P) "$(CIROOT)$(datadir)/libcupsfilters-tests"
@echo " STAGE cupsfilters/image.pgm -> $(CIROOT)$(datadir)/libcupsfilters-tests/image.pgm"
$(INSTALL_DATA) "$(srcdir)/cupsfilters/image.pgm" "$(CIROOT)$(datadir)/libcupsfilters-tests/image.pgm"
@echo " STAGE cupsfilters/image.pgm -> $(CIROOT)$(datadir)/libcupsfilters-tests/image.ppm"
$(INSTALL_DATA) "$(srcdir)/cupsfilters/image.pgm" "$(CIROOT)$(datadir)/libcupsfilters-tests/image.ppm"

stage-ciroot: all
rm -rf "$(CIROOT)"
$(MAKE) $(AM_MAKEFLAGS) install DESTDIR="$(CIROOT)"
$(MAKE) $(AM_MAKEFLAGS) install-test-programs install-test-data
@pc="$(CIROOT)$(libdir)/pkgconfig/libcupsfilters.pc"; \
if [ -f "$$pc" ]; then \
sed -i.bak -E "s#^(prefix|exec_prefix|libdir|includedir)=(/.*)#\1=$(CIROOT)\2#" "$$pc"; \
rm -f "$$pc.bak"; \
echo "stage-ciroot: rewrote staged-tree paths in $$pc"; \
fi

# Common environment for the wrapper. LIBCUPSFILTERS_BINDIR / LIBCUPSFILTERS_TESTDIR
# point the functionality test at the staged binaries and data instead of the
# system /usr paths, so it needs no absolute-path redirection (no root, no proot)
# and runs identically on native and QEMU-emulated architectures.
CIROOT_ENV = \
CIROOT="$(CIROOT)" \
CIPREFIX="$(exec_prefix)" \
TOP_BUILDDIR="$(abs_top_builddir)" \
LIBCUPSFILTERS_BINDIR="$(CIROOT)$(bindir)" \
LIBCUPSFILTERS_TESTDIR="$(CIROOT)$(datadir)/libcupsfilters-tests"

# Full downstream suite in a single wrapper invocation -> one aggregate
# PASS/FAIL summary across both tests. Identical on every architecture.
test-autopkgtest: stage-ciroot
$(CIROOT_ENV) \
$(SHELL) $(srcdir)/ci/autopkgtest/run.sh libcupsfilters-2-dev libcupsfilters-2-functionality

# Single-test convenience targets (handy for debugging one case in isolation).
test-autopkgtest-dev: stage-ciroot
$(CIROOT_ENV) \
$(SHELL) $(srcdir)/ci/autopkgtest/run.sh libcupsfilters-2-dev

test-autopkgtest-func: stage-ciroot
$(CIROOT_ENV) \
$(SHELL) $(srcdir)/ci/autopkgtest/run.sh libcupsfilters-2-functionality

.PHONY: stage-ciroot install-test-programs install-test-data \
test-autopkgtest test-autopkgtest-dev test-autopkgtest-func
11 changes: 11 additions & 0 deletions ci/autopkgtest/debian-tests/control
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Tests: libcupsfilters-2-dev
Depends: build-essential,
dbus,
libcups2-dev,
libcupsfilters-dev,
pkg-config,
Restrictions: allow-stderr

Tests: libcupsfilters-2-functionality
Depends: libcupsfilters-tests
Restrictions: allow-stderr
52 changes: 52 additions & 0 deletions ci/autopkgtest/debian-tests/libcupsfilters-2-dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/bin/sh
# autopkgtest check: Build and run a program against libcupsfilters, to verify
# that the headers and pkg-config file are installed correctly
# (C) 2012 Canonical Ltd.
# (C) 2018-2019 Simon McVittie
# Authors: Martin Pitt, Simon McVittie

set -eux

package=libcupsfilters
WORKDIR="$(mktemp -d)"
export HOME="$WORKDIR"
export XDG_RUNTIME_DIR="$WORKDIR"
trap 'cd /; rm -rf "$WORKDIR"' 0 INT QUIT ABRT PIPE TERM

if [ -n "${DEB_HOST_GNU_TYPE:-}" ]; then
CROSS_COMPILE="$DEB_HOST_GNU_TYPE-"
else
CROSS_COMPILE=
fi

cd "$WORKDIR"
cat <<EOF > test.c
// All header files of libcupsfilters API
#include <cupsfilters/bitmap.h>
#include <cupsfilters/catalog.h>
#include <cupsfilters/colord.h>
#include <cupsfilters/colormanager.h>
#include <cupsfilters/driver.h>
#include <cupsfilters/filter.h>
#include <cupsfilters/ieee1284.h>
#include <cupsfilters/image.h>
#include <cupsfilters/ipp.h>
#include <cupsfilters/log.h>
#include <cupsfilters/pdf.h>
#include <cupsfilters/raster.h>

int main(void)
{
// Actually use something from the library, so that it gets actually linked
cfCUPSLogFunc(NULL, CF_LOGLEVEL_DEBUG, "TEST OUTPUT %d %d %d", 1, 2, 3);
return (0);
}
EOF

# Deliberately word-splitting pkg-config's output:
# shellcheck disable=SC2046
${CROSS_COMPILE}gcc -o "${package}-test" test.c $(${CROSS_COMPILE}pkg-config --cflags --libs "$package")
echo "build ($package): OK"
[ -x "${package}-test" ]
dbus-run-session -- "./${package}-test" 2>&1 | grep -q 'DEBUG: TEST OUTPUT 1 2 3'
echo "run ($package): OK"
74 changes: 74 additions & 0 deletions ci/autopkgtest/debian-tests/libcupsfilters-2-functionality
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/bin/sh
# autopkgtest check: Run "make check" test programs using libcupsfilters
# installed on the system.
# (C) 2012 Canonical Ltd.
# (C) 2023 Till Kamppeter
# Authors: Martin Pitt, Till Kamppeter

set -eux

package=libcupsfilters
WORKDIR="$(mktemp -d)"
export HOME="$WORKDIR"
export XDG_RUNTIME_DIR="$WORKDIR"
trap 'cd /; rm -rf "$WORKDIR"' 0 INT QUIT ABRT PIPE TERM

# Location of the installed test programs and their image data. Default to the
# system paths used when the package is installed (the normal Debian autopkgtest
# case); allow a staged build tree to override them so the test assumes no
# absolute paths and runs unprivileged on every architecture.
: "${LIBCUPSFILTERS_BINDIR:=/usr/bin}"
: "${LIBCUPSFILTERS_TESTDIR:=/usr/share/libcupsfilters-tests}"

# Copy test image files into right place
cp -r "$LIBCUPSFILTERS_TESTDIR" cupsfilters

# Run the test programs and check the output files
"$LIBCUPSFILTERS_BINDIR/testdither" > out
echo "run test program 'testdither' on system's $package: OK"
file out | grep -qi 'netpbm image data'
echo "check output file ($package): OK"

"$LIBCUPSFILTERS_BINDIR/testpdf1" > out
echo "run test program 'testpdf1' on system's $package: OK"
file out | grep -q 'PDF document'
echo "check output file ($package): OK"

"$LIBCUPSFILTERS_BINDIR/testpdf2" > out
echo "run test program 'testpdf2' on system's $package: OK"
file out | grep -q 'PDF document'
echo "check output file ($package): OK"

"$LIBCUPSFILTERS_BINDIR/test-analyze" > out
echo "run test program 'test-analyze' on system's $package: OK"
file out | grep -q 'ASCII text'
echo "check output file ($package): OK"

"$LIBCUPSFILTERS_BINDIR/test-pdf"
echo "run test program 'test-pdf' on system's $package: OK"
file test.pdf | grep -q 'PDF document'
echo "check output file ($package): OK"

"$LIBCUPSFILTERS_BINDIR/test-ps"
echo "run test program 'test-ps' on system's $package: OK"
file test.ps | grep -q 'PostScript document'
echo "check output file ($package): OK"

cd cupsfilters
rm -rf test
"$LIBCUPSFILTERS_BINDIR/testcmyk"
echo "run test program 'testcmyk' on system's $package: OK"
ls -1 test
ls -1 test | wc -l
ls -1 test | wc -l | grep -q '^58$'
echo "check output directory ($package): OK"

rm -rf test
"$LIBCUPSFILTERS_BINDIR/testrgb"
echo "run test program 'testrgb' on system's $package: OK"
ls -1 test
ls -1 test | wc -l
ls -1 test | wc -l | grep -q '^10$'
echo "check output directory ($package): OK"
rm -rf test
cd ..
94 changes: 94 additions & 0 deletions ci/autopkgtest/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#!/bin/sh
# ci/autopkgtest/run.sh
#
# Universal DESTDIR-staging wrapper for the downstream Debian autopkgtests.
# Points PATH / LD_LIBRARY_PATH / PKG_CONFIG_PATH at the staged install tree
# ($CIROOT) produced by `make stage-ciroot`, then runs the unmodified
# downstream scripts vendored under ci/autopkgtest/debian-tests/.
#
# The downstream scripts take environment overrides (e.g. LIBCUPSFILTERS_BINDIR,
# LIBCUPSFILTERS_TESTDIR) that default to the system /usr paths but can be
# redirected into the staging tree. That keeps every test free of absolute-path
# assumptions, so the wrapper needs no privilege and no bind mounts and runs
# identically on native and QEMU-emulated architectures.
#
# Env in:
# CIROOT staging root (default: $PWD/_ciroot)
# CIPREFIX configured prefix (default: /usr)
# TOP_BUILDDIR build tree (default: $PWD)
# Any extra exported variables (e.g. LIBCUPSFILTERS_BINDIR,
# LIBCUPSFILTERS_TESTDIR) are passed straight through to the scripts.
set -eu

SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
TESTS_DIR="$SCRIPT_DIR/debian-tests"

: "${CIROOT:=$PWD/_ciroot}"
: "${CIPREFIX:=/usr}"
: "${TOP_BUILDDIR:=$PWD}"

if [ ! -d "$CIROOT" ]; then
echo "run.sh: staging root not found: $CIROOT (run 'make stage-ciroot' first)" >&2
exit 1
fi

ROOT="$CIROOT$CIPREFIX"
MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null \
|| gcc -dumpmachine 2>/dev/null || echo "")

PATH="$ROOT/bin:$ROOT/sbin:$TOP_BUILDDIR:$TOP_BUILDDIR/.libs:$PATH"
LD_LIBRARY_PATH="$ROOT/lib${MULTIARCH:+:$ROOT/lib/$MULTIARCH}:$TOP_BUILDDIR/.libs${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
PKG_CONFIG_PATH="$ROOT/lib/pkgconfig${MULTIARCH:+:$ROOT/lib/$MULTIARCH/pkgconfig}:$ROOT/share/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}"
export PATH LD_LIBRARY_PATH PKG_CONFIG_PATH

if [ "$#" -eq 0 ]; then
echo "run.sh: usage: run.sh <test-name> [test-name...]" >&2
exit 2
fi

rc=0
total=0
n_pass=0
n_fail=0
results=""
for name in "$@"; do
total=$((total + 1))
script="$TESTS_DIR/$name"
if [ ! -f "$script" ]; then
echo "run.sh: no such test: $script" >&2
n_fail=$((n_fail + 1))
results="$results
FAIL: $name (not found)"
rc=1
continue
fi
chmod +x "$script" 2>/dev/null || true
workdir=$(mktemp -d)
echo "=== autopkgtest: $name (CIROOT=$CIROOT, prefix=$CIPREFIX) ==="
if ( cd "$workdir" && "$script" ); then
echo "=== PASS: $name ==="
n_pass=$((n_pass + 1))
results="$results
PASS: $name"
else
ec=$?
echo "=== FAIL: $name (exit $ec) ===" >&2
n_fail=$((n_fail + 1))
results="$results
FAIL: $name (exit $ec)"
rc=1
fi
rm -rf "$workdir"
done

echo "============================================================================"
echo "Downstream autopkgtest summary"
echo "============================================================================"
printf '# TOTAL: %d\n' "$total"
printf '# PASS: %d\n' "$n_pass"
printf '# FAIL: %d\n' "$n_fail"
echo "----------------------------------------------------------------------------"
printf '%s\n' "$results" | sed '/^$/d'
echo "============================================================================"

exit $rc
Loading