Skip to content

Commit 18e509a

Browse files
authored
ci: add multi-arch CI and DESTDIR-staged autopkgtests for libppd (#75)
1 parent c2ce23d commit 18e509a

7 files changed

Lines changed: 335 additions & 5 deletions

File tree

.github/workflows/build.yml

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,18 @@ jobs:
103103
zlib1g-dev \
104104
ghostscript \
105105
poppler-utils \
106-
mupdf-tools
106+
mupdf-tools \
107+
file
107108
108109
- name: Build & test libppd (native)
109110
if: matrix.use-qemu == false
110111
run: |
111112
set -ex
112113
cd "$REPO_DIR"
113114
./autogen.sh
114-
./configure
115+
# --enable-ppdc-utils: the downstream libppd-2-dev autopkgtest needs
116+
# the staged `ppdc` to compile its test.drv into a PPD.
117+
./configure --enable-ppdc-utils
115118
make -j$(nproc) V=1
116119
make check V=1 VERBOSE=1 || {
117120
echo "==== test-suite.log ===="
@@ -123,6 +126,17 @@ jobs:
123126
exit 1
124127
}
125128
129+
- name: Autopkgtest (DESTDIR staging, native)
130+
if: matrix.use-qemu == false
131+
run: |
132+
set -ex
133+
cd "$REPO_DIR"
134+
# Full downstream suite: libppd-2-dev (compile/link/run) +
135+
# libppd-2-ppd-handling. Both point at the staged tree via
136+
# environment overrides, so no privilege or path redirection is
137+
# needed.
138+
make test-autopkgtest V=1
139+
126140
# -----------------------------------------------------------------------
127141
# EMULATED LEG (armhf via QEMU armv7, riscv64 via QEMU)
128142
# -----------------------------------------------------------------------
@@ -166,12 +180,14 @@ jobs:
166180
zlib1g-dev \
167181
ghostscript \
168182
poppler-utils \
169-
mupdf-tools
183+
mupdf-tools \
184+
file
170185
run: |
171186
set -ex
172187
cd /workspace
173188
./autogen.sh
174-
./configure
189+
# --enable-ppdc-utils: needed by the libppd-2-dev autopkgtest.
190+
./configure --enable-ppdc-utils
175191
make -j$(nproc) V=1
176192
make check V=1 VERBOSE=1 || {
177193
echo "==== test-suite.log ===="
@@ -183,6 +199,12 @@ jobs:
183199
exit 1
184200
}
185201
202+
# Full downstream autopkgtest suite. Both tests resolve the
203+
# staged build tree through environment overrides (no absolute
204+
# paths, no privilege, no bind mounts), so the same suite that
205+
# runs on the native legs runs unchanged under QEMU emulation.
206+
make test-autopkgtest V=1
207+
186208
# -----------------------------------------------------------------------
187209
# ARTIFACT UPLOAD (all four legs, only on failure)
188210
# -----------------------------------------------------------------------

Makefile.am

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,4 +367,104 @@ ppdpo_CFLAGS = \
367367
distclean-local:
368368
rm -rf *.cache *~
369369

370+
clean-local:
371+
rm -rf $(CIROOT)
372+
370373
SUBDIRS =
374+
375+
# ============================================================
376+
# Staged-install downstream autopkgtests (DESTDIR staging)
377+
# ============================================================
378+
# Install the just-built tree into an ephemeral root ($(CIROOT)) with
379+
# `make install DESTDIR=`, top up the bits that `make install` does not ship
380+
# but the downstream Debian autopkgtests require, fix up the staged .pc, then
381+
# run the unmodified downstream scripts against that tree.
382+
CIROOT = $(abs_top_builddir)/_ciroot
383+
384+
EXTRA_DIST += \
385+
ci/autopkgtest/run.sh \
386+
ci/autopkgtest/debian-tests/control \
387+
ci/autopkgtest/debian-tests/libppd-2-dev \
388+
ci/autopkgtest/debian-tests/libppd-2-ppd-handling
389+
390+
# Fix A: check_PROGRAMS are build-only under Automake and are never copied by
391+
# `make install`. The downstream PPD-handling test executes the test driver
392+
# as an *installed* binary (/usr/bin/testppd), so build it and stage it into
393+
# $(CIROOT)$(bindir). Uses libtool --mode=install so the binary is relinked
394+
# cleanly against $(libdir) (LD_LIBRARY_PATH then forces the staged library).
395+
STAGED_TEST_BINARIES = testppd
396+
397+
install-test-programs: $(STAGED_TEST_BINARIES)
398+
$(MKDIR_P) "$(CIROOT)$(bindir)"
399+
@for p in $(STAGED_TEST_BINARIES); do \
400+
echo " STAGE $$p -> $(CIROOT)$(bindir)/$$p"; \
401+
$(LIBTOOL) --mode=install $(INSTALL_PROGRAM) "$$p" "$(CIROOT)$(bindir)/$$p" || exit 1; \
402+
done
403+
404+
# Fix C (data seeding): the downstream PPD-handling test copies its PPDs from
405+
# the installed $(datadir)/ppd/testppd directory, which upstream `make install`
406+
# does not ship. Seed every test PPD the current testppd binary opens
407+
# (test.ppd, test2.ppd, sbo_test.ppd) so the unmodified script finds them.
408+
STAGED_TEST_PPDS = \
409+
ppd/test.ppd \
410+
ppd/test2.ppd \
411+
ppd/sbo_test.ppd
412+
413+
install-test-data:
414+
$(MKDIR_P) "$(CIROOT)$(datadir)/ppd/testppd"
415+
@for f in $(STAGED_TEST_PPDS); do \
416+
echo " STAGE $$f -> $(CIROOT)$(datadir)/ppd/testppd/"; \
417+
$(INSTALL_DATA) "$(srcdir)/$$f" "$(CIROOT)$(datadir)/ppd/testppd/" || exit 1; \
418+
done
419+
420+
# Build everything, DESTDIR-install it, top up the test-only programs/data,
421+
# then rewrite the staged libppd.pc prefix so a downstream consumer resolves
422+
# THIS build (not a system copy) while the system dependency .pc files
423+
# (libcupsfilters, cups) keep resolving normally.
424+
stage-ciroot: all
425+
rm -rf "$(CIROOT)"
426+
$(MAKE) $(AM_MAKEFLAGS) install DESTDIR="$(CIROOT)"
427+
$(MAKE) $(AM_MAKEFLAGS) install-test-programs install-test-data
428+
@pc="$(CIROOT)$(libdir)/pkgconfig/libppd.pc"; \
429+
if [ -f "$$pc" ]; then \
430+
sed -i.bak -E "s#^(prefix|exec_prefix|libdir|includedir)=(/.*)#\1=$(CIROOT)\2#" "$$pc"; \
431+
rm -f "$$pc.bak"; \
432+
echo "stage-ciroot: rewrote staged-tree paths in $$pc"; \
433+
fi
434+
435+
# Common environment for the wrapper. PPDC_DATADIR / CUPS_DATADIR point ppdc
436+
# at the staged *.defs so `ppdc test.drv` resolves <font.defs> / <media.defs>
437+
# from the staging tree. LIBPPD_TESTPPD / LIBPPD_PPDDIR point the PPD-handling
438+
# test at the staged binary and data instead of the system /usr paths, so it
439+
# needs no absolute-path redirection (no root, no proot) and runs identically
440+
# on native and QEMU-emulated architectures.
441+
# NB: libppd configures with a split prefix (prefix=/ but exec_prefix=/usr and
442+
# everything installs under /usr), so the staging root the wrapper points at is
443+
# $(CIROOT)$(exec_prefix), not $(CIROOT)$(prefix).
444+
CIROOT_ENV = \
445+
CIROOT="$(CIROOT)" \
446+
CIPREFIX="$(exec_prefix)" \
447+
TOP_BUILDDIR="$(abs_top_builddir)" \
448+
PPDC_DATADIR="$(CIROOT)$(datadir)/ppdc" \
449+
CUPS_DATADIR="$(CIROOT)$(datadir)" \
450+
LIBPPD_TESTPPD="$(CIROOT)$(bindir)/testppd" \
451+
LIBPPD_PPDDIR="$(CIROOT)$(datadir)/ppd/testppd"
452+
453+
# Full downstream suite in a single wrapper invocation, so the run produces one
454+
# aggregate PASS/FAIL summary across both tests. Neither test needs privilege
455+
# or path redirection, so this is identical on every architecture.
456+
test-autopkgtest: stage-ciroot
457+
$(CIROOT_ENV) \
458+
$(SHELL) $(srcdir)/ci/autopkgtest/run.sh libppd-2-dev libppd-2-ppd-handling
459+
460+
# Single-test convenience targets (handy for debugging one case in isolation).
461+
test-autopkgtest-dev: stage-ciroot
462+
$(CIROOT_ENV) \
463+
$(SHELL) $(srcdir)/ci/autopkgtest/run.sh libppd-2-dev
464+
465+
test-autopkgtest-ppd: stage-ciroot
466+
$(CIROOT_ENV) \
467+
$(SHELL) $(srcdir)/ci/autopkgtest/run.sh libppd-2-ppd-handling
468+
469+
.PHONY: stage-ciroot install-test-programs install-test-data \
470+
test-autopkgtest test-autopkgtest-dev test-autopkgtest-ppd
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Tests: libppd-2-dev
2+
Depends: build-essential,
3+
libcups2-dev,
4+
libcupsfilters-dev,
5+
libppd-dev,
6+
pkg-config,
7+
libppd-utils,
8+
Restrictions: allow-stderr
9+
10+
Tests: libppd-2-ppd-handling
11+
Depends: libppd-tests
12+
Restrictions: allow-stderr
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/bin/sh
2+
# autopkgtest check: Build and run a program against libppd, to verify
3+
# that the headers and pkg-config file are installed correctly
4+
# (C) 2012 Canonical Ltd.
5+
# (C) 2018-2019 Simon McVittie
6+
# (C) 2023 Till Kamppeter
7+
# Authors: Martin Pitt, Simon McVittie, Till Kamppeter
8+
9+
set -eux
10+
11+
package=libppd
12+
WORKDIR="$(mktemp -d)"
13+
export HOME="$WORKDIR"
14+
export XDG_RUNTIME_DIR="$WORKDIR"
15+
trap 'cd /; rm -rf "$WORKDIR"' 0 INT QUIT ABRT PIPE TERM
16+
17+
if [ -n "${DEB_HOST_GNU_TYPE:-}" ]; then
18+
CROSS_COMPILE="$DEB_HOST_GNU_TYPE-"
19+
else
20+
CROSS_COMPILE=
21+
fi
22+
23+
cd "$WORKDIR"
24+
cat <<EOF > test.c
25+
// All header files of libppd API
26+
#include <ppd/ppd.h>
27+
#include <ppd/ppd-filter.h>
28+
#include <ppd/ppdc.h>
29+
30+
int main(int argc, char *argv[])
31+
{
32+
// Actually use something from the library, so that it gets actually linked
33+
cf_filter_universal_parameter_t universal_parameters;
34+
memset(&universal_parameters, 0, sizeof(cf_filter_universal_parameter_t));
35+
return (ppdFilterCUPSWrapper(argc, argv, ppdFilterUniversal,
36+
&universal_parameters, NULL));
37+
}
38+
EOF
39+
40+
cat <<EOF > test.drv
41+
#include <font.defs>
42+
#include <media.defs>
43+
Font *
44+
Manufacturer "Test"
45+
ModelName "TestPrinter"
46+
Version 1.0
47+
Filter image/urf 100 -
48+
*MediaSize Letter
49+
MediaSize A4
50+
ColorDevice true
51+
ColorModel Gray/Grayscale w chunky 0
52+
*ColorModel RGB/Color rgb chunky 0
53+
*Resolution - 8 0 0 0 "600dpi/600 DPI"
54+
Resolution - 8 0 0 0 "1200dpi/1200 DPI"
55+
PCFileName "test.ppd"
56+
EOF
57+
58+
ppdc test.drv
59+
echo "create test PPD ($package): OK"
60+
export PPD=./ppd/test.ppd
61+
export CONTENT_TYPE=text/plain
62+
export FINAL_CONTENT_TYPE=application/vnd.cups-pdf
63+
# Deliberately word-splitting pkg-config's output:
64+
# shellcheck disable=SC2046
65+
${CROSS_COMPILE}g++ -o "${package}-test" test.c $(${CROSS_COMPILE}pkg-config --cflags --libs "$package") $(${CROSS_COMPILE}pkg-config --cflags --libs "libcupsfilters")
66+
echo "build ($package): OK"
67+
[ -x "${package}-test" ]
68+
echo -en 'Test1\nTest2\nTest3\n' | ./${package}-test 1 1 1 1 'PageSize=A4 Resolution=1200dpi' > test.pdf
69+
echo "run ($package): OK"
70+
file test.pdf | grep -q 'PDF document'
71+
echo "check output file ($package): OK"
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/bin/sh
2+
# autopkgtest check: Run "make check" test program "testppd" using libppd
3+
# installed on the system.
4+
# (C) 2012 Canonical Ltd.
5+
# (C) 2023 Till Kamppeter
6+
# Authors: Martin Pitt, Till Kamppeter
7+
8+
set -eux
9+
10+
package=libppd
11+
WORKDIR="$(mktemp -d)"
12+
export HOME="$WORKDIR"
13+
export XDG_RUNTIME_DIR="$WORKDIR"
14+
trap 'cd /; rm -rf "$WORKDIR"' 0 INT QUIT ABRT PIPE TERM
15+
16+
# Location of the installed test program and its PPD data. Default to the
17+
# system paths used when the package is installed (the normal Debian
18+
# autopkgtest case); allow a staged build tree to override them so the test
19+
# assumes no absolute paths and runs unprivileged on every architecture.
20+
: "${LIBPPD_TESTPPD:=/usr/bin/testppd}"
21+
: "${LIBPPD_PPDDIR:=/usr/share/ppd/testppd}"
22+
23+
# Copy test PPD files into right place
24+
cp -r "$LIBPPD_PPDDIR" ppd
25+
# Run the test program
26+
"$LIBPPD_TESTPPD"
27+
echo "run test program on system's $package: OK"

ci/autopkgtest/run.sh

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!/bin/sh
2+
# ci/autopkgtest/run.sh
3+
#
4+
# Universal DESTDIR-staging wrapper for the downstream Debian autopkgtests.
5+
# Points PATH / LD_LIBRARY_PATH / PKG_CONFIG_PATH at the staged install tree
6+
# ($CIROOT) produced by `make stage-ciroot`, then runs the unmodified
7+
# downstream scripts vendored under ci/autopkgtest/debian-tests/.
8+
#
9+
# The downstream scripts take environment overrides (e.g. LIBPPD_TESTPPD,
10+
# LIBPPD_PPDDIR) that default to the system /usr paths but can be redirected
11+
# into the staging tree. That keeps every test free of absolute-path
12+
# assumptions, so the wrapper needs no privilege and no bind mounts and runs
13+
# identically on native and QEMU-emulated architectures.
14+
#
15+
# Env in:
16+
# CIROOT staging root (default: $PWD/_ciroot)
17+
# CIPREFIX configured prefix (default: /usr)
18+
# TOP_BUILDDIR build tree (default: $PWD)
19+
# Any extra exported variables (e.g. PPDC_DATADIR, CUPS_DATADIR,
20+
# LIBPPD_TESTPPD, LIBPPD_PPDDIR) are passed straight through to the scripts.
21+
set -eu
22+
23+
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
24+
TESTS_DIR="$SCRIPT_DIR/debian-tests"
25+
26+
: "${CIROOT:=$PWD/_ciroot}"
27+
: "${CIPREFIX:=/usr}"
28+
: "${TOP_BUILDDIR:=$PWD}"
29+
30+
if [ ! -d "$CIROOT" ]; then
31+
echo "run.sh: staging root not found: $CIROOT (run 'make stage-ciroot' first)" >&2
32+
exit 1
33+
fi
34+
35+
ROOT="$CIROOT$CIPREFIX"
36+
MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null \
37+
|| gcc -dumpmachine 2>/dev/null || echo "")
38+
39+
PATH="$ROOT/bin:$ROOT/sbin:$TOP_BUILDDIR:$TOP_BUILDDIR/.libs:$PATH"
40+
LD_LIBRARY_PATH="$ROOT/lib${MULTIARCH:+:$ROOT/lib/$MULTIARCH}:$TOP_BUILDDIR/.libs${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
41+
PKG_CONFIG_PATH="$ROOT/lib/pkgconfig${MULTIARCH:+:$ROOT/lib/$MULTIARCH/pkgconfig}:$ROOT/share/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}"
42+
export PATH LD_LIBRARY_PATH PKG_CONFIG_PATH
43+
44+
if [ "$#" -eq 0 ]; then
45+
echo "run.sh: usage: run.sh <test-name> [test-name...]" >&2
46+
exit 2
47+
fi
48+
49+
rc=0
50+
total=0
51+
n_pass=0
52+
n_fail=0
53+
results=""
54+
for name in "$@"; do
55+
total=$((total + 1))
56+
script="$TESTS_DIR/$name"
57+
if [ ! -f "$script" ]; then
58+
echo "run.sh: no such test: $script" >&2
59+
n_fail=$((n_fail + 1))
60+
results="$results
61+
FAIL: $name (not found)"
62+
rc=1
63+
continue
64+
fi
65+
chmod +x "$script" 2>/dev/null || true
66+
workdir=$(mktemp -d)
67+
echo "=== autopkgtest: $name (CIROOT=$CIROOT, prefix=$CIPREFIX) ==="
68+
if ( cd "$workdir" && "$script" ); then
69+
echo "=== PASS: $name ==="
70+
n_pass=$((n_pass + 1))
71+
results="$results
72+
PASS: $name"
73+
else
74+
ec=$?
75+
echo "=== FAIL: $name (exit $ec) ===" >&2
76+
n_fail=$((n_fail + 1))
77+
results="$results
78+
FAIL: $name (exit $ec)"
79+
rc=1
80+
fi
81+
rm -rf "$workdir"
82+
done
83+
84+
# ---------------------------------------------------------------------------
85+
# Aggregate summary (mirrors the Automake `make check` test-suite summary)
86+
# ---------------------------------------------------------------------------
87+
echo "============================================================================"
88+
echo "Downstream autopkgtest summary"
89+
echo "============================================================================"
90+
printf '# TOTAL: %d\n' "$total"
91+
printf '# PASS: %d\n' "$n_pass"
92+
printf '# FAIL: %d\n' "$n_fail"
93+
echo "----------------------------------------------------------------------------"
94+
# Per-test breakdown (strip the leading blank line from the accumulator).
95+
printf '%s\n' "$results" | sed '/^$/d'
96+
echo "============================================================================"
97+
98+
exit $rc

libppd.pc.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ Version: @VERSION@
99
1010
Libs: -L${libdir} -lppd
1111
Libs.private: @CUPS_LIBS@
12-
Cflags: -I${includedir}/ppd
12+
Cflags: -I${includedir} -I${includedir}/ppd

0 commit comments

Comments
 (0)