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
30 changes: 26 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,18 @@ jobs:
zlib1g-dev \
ghostscript \
poppler-utils \
mupdf-tools
mupdf-tools \
file

- name: Build & test libppd (native)
if: matrix.use-qemu == false
run: |
set -ex
cd "$REPO_DIR"
./autogen.sh
./configure
# --enable-ppdc-utils: the downstream libppd-2-dev autopkgtest needs
# the staged `ppdc` to compile its test.drv into a PPD.
./configure --enable-ppdc-utils
make -j$(nproc) V=1
make check V=1 VERBOSE=1 || {
echo "==== test-suite.log ===="
Expand All @@ -123,6 +126,17 @@ jobs:
exit 1
}

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

# -----------------------------------------------------------------------
# EMULATED LEG (armhf via QEMU armv7, riscv64 via QEMU)
# -----------------------------------------------------------------------
Expand Down Expand Up @@ -166,12 +180,14 @@ jobs:
zlib1g-dev \
ghostscript \
poppler-utils \
mupdf-tools
mupdf-tools \
file
run: |
set -ex
cd /workspace
./autogen.sh
./configure
# --enable-ppdc-utils: needed by the libppd-2-dev autopkgtest.
./configure --enable-ppdc-utils
make -j$(nproc) V=1
make check V=1 VERBOSE=1 || {
echo "==== test-suite.log ===="
Expand All @@ -183,6 +199,12 @@ jobs:
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

# -----------------------------------------------------------------------
# ARTIFACT UPLOAD (all four legs, only on failure)
# -----------------------------------------------------------------------
Expand Down
100 changes: 100 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -367,4 +367,104 @@ ppdpo_CFLAGS = \
distclean-local:
rm -rf *.cache *~

clean-local:
rm -rf $(CIROOT)

SUBDIRS =

# ============================================================
# Staged-install downstream autopkgtests (DESTDIR staging)
# ============================================================
# Install the just-built tree into an ephemeral root ($(CIROOT)) with
# `make install DESTDIR=`, top up the bits that `make install` does not ship
# but the downstream Debian autopkgtests require, fix up the staged .pc, then
# run the unmodified downstream scripts against that tree.
CIROOT = $(abs_top_builddir)/_ciroot

EXTRA_DIST += \
ci/autopkgtest/run.sh \
ci/autopkgtest/debian-tests/control \
ci/autopkgtest/debian-tests/libppd-2-dev \
ci/autopkgtest/debian-tests/libppd-2-ppd-handling

# Fix A: check_PROGRAMS are build-only under Automake and are never copied by
# `make install`. The downstream PPD-handling test executes the test driver
# as an *installed* binary (/usr/bin/testppd), so build it and stage it into
# $(CIROOT)$(bindir). Uses libtool --mode=install so the binary is relinked
# cleanly against $(libdir) (LD_LIBRARY_PATH then forces the staged library).
STAGED_TEST_BINARIES = testppd

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 downstream PPD-handling test copies its PPDs from
# the installed $(datadir)/ppd/testppd directory, which upstream `make install`
# does not ship. Seed every test PPD the current testppd binary opens
# (test.ppd, test2.ppd, sbo_test.ppd) so the unmodified script finds them.
STAGED_TEST_PPDS = \
ppd/test.ppd \
ppd/test2.ppd \
ppd/sbo_test.ppd

install-test-data:
$(MKDIR_P) "$(CIROOT)$(datadir)/ppd/testppd"
@for f in $(STAGED_TEST_PPDS); do \
echo " STAGE $$f -> $(CIROOT)$(datadir)/ppd/testppd/"; \
$(INSTALL_DATA) "$(srcdir)/$$f" "$(CIROOT)$(datadir)/ppd/testppd/" || exit 1; \
done

# Build everything, DESTDIR-install it, top up the test-only programs/data,
# then rewrite the staged libppd.pc prefix so a downstream consumer resolves
# THIS build (not a system copy) while the system dependency .pc files
# (libcupsfilters, cups) keep resolving normally.
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/libppd.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. PPDC_DATADIR / CUPS_DATADIR point ppdc
# at the staged *.defs so `ppdc test.drv` resolves <font.defs> / <media.defs>
# from the staging tree. LIBPPD_TESTPPD / LIBPPD_PPDDIR point the PPD-handling
# test at the staged binary 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.
# NB: libppd configures with a split prefix (prefix=/ but exec_prefix=/usr and
# everything installs under /usr), so the staging root the wrapper points at is
# $(CIROOT)$(exec_prefix), not $(CIROOT)$(prefix).
CIROOT_ENV = \
CIROOT="$(CIROOT)" \
CIPREFIX="$(exec_prefix)" \
TOP_BUILDDIR="$(abs_top_builddir)" \
PPDC_DATADIR="$(CIROOT)$(datadir)/ppdc" \
CUPS_DATADIR="$(CIROOT)$(datadir)" \
LIBPPD_TESTPPD="$(CIROOT)$(bindir)/testppd" \
LIBPPD_PPDDIR="$(CIROOT)$(datadir)/ppd/testppd"

# Full downstream suite in a single wrapper invocation, so the run produces one
# aggregate PASS/FAIL summary across both tests. Neither test needs privilege
# or path redirection, so this is identical on every architecture.
test-autopkgtest: stage-ciroot
$(CIROOT_ENV) \
$(SHELL) $(srcdir)/ci/autopkgtest/run.sh libppd-2-dev libppd-2-ppd-handling

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

test-autopkgtest-ppd: stage-ciroot
$(CIROOT_ENV) \
$(SHELL) $(srcdir)/ci/autopkgtest/run.sh libppd-2-ppd-handling

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

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

set -eux

package=libppd
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 libppd API
#include <ppd/ppd.h>
#include <ppd/ppd-filter.h>
#include <ppd/ppdc.h>

int main(int argc, char *argv[])
{
// Actually use something from the library, so that it gets actually linked
cf_filter_universal_parameter_t universal_parameters;
memset(&universal_parameters, 0, sizeof(cf_filter_universal_parameter_t));
return (ppdFilterCUPSWrapper(argc, argv, ppdFilterUniversal,
&universal_parameters, NULL));
}
EOF

cat <<EOF > test.drv
#include <font.defs>
#include <media.defs>
Font *
Manufacturer "Test"
ModelName "TestPrinter"
Version 1.0
Filter image/urf 100 -
*MediaSize Letter
MediaSize A4
ColorDevice true
ColorModel Gray/Grayscale w chunky 0
*ColorModel RGB/Color rgb chunky 0
*Resolution - 8 0 0 0 "600dpi/600 DPI"
Resolution - 8 0 0 0 "1200dpi/1200 DPI"
PCFileName "test.ppd"
EOF

ppdc test.drv
echo "create test PPD ($package): OK"
export PPD=./ppd/test.ppd
export CONTENT_TYPE=text/plain
export FINAL_CONTENT_TYPE=application/vnd.cups-pdf
# Deliberately word-splitting pkg-config's output:
# shellcheck disable=SC2046
${CROSS_COMPILE}g++ -o "${package}-test" test.c $(${CROSS_COMPILE}pkg-config --cflags --libs "$package") $(${CROSS_COMPILE}pkg-config --cflags --libs "libcupsfilters")
echo "build ($package): OK"
[ -x "${package}-test" ]
echo -en 'Test1\nTest2\nTest3\n' | ./${package}-test 1 1 1 1 'PageSize=A4 Resolution=1200dpi' > test.pdf
echo "run ($package): OK"
file test.pdf | grep -q 'PDF document'
echo "check output file ($package): OK"
27 changes: 27 additions & 0 deletions ci/autopkgtest/debian-tests/libppd-2-ppd-handling
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/sh
# autopkgtest check: Run "make check" test program "testppd" using libppd
# installed on the system.
# (C) 2012 Canonical Ltd.
# (C) 2023 Till Kamppeter
# Authors: Martin Pitt, Till Kamppeter

set -eux

package=libppd
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 program and its PPD 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.
: "${LIBPPD_TESTPPD:=/usr/bin/testppd}"
: "${LIBPPD_PPDDIR:=/usr/share/ppd/testppd}"

# Copy test PPD files into right place
cp -r "$LIBPPD_PPDDIR" ppd
# Run the test program
"$LIBPPD_TESTPPD"
echo "run test program on system's $package: OK"
98 changes: 98 additions & 0 deletions ci/autopkgtest/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#!/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. LIBPPD_TESTPPD,
# LIBPPD_PPDDIR) 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. PPDC_DATADIR, CUPS_DATADIR,
# LIBPPD_TESTPPD, LIBPPD_PPDDIR) 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

# ---------------------------------------------------------------------------
# Aggregate summary (mirrors the Automake `make check` test-suite summary)
# ---------------------------------------------------------------------------
echo "============================================================================"
echo "Downstream autopkgtest summary"
echo "============================================================================"
printf '# TOTAL: %d\n' "$total"
printf '# PASS: %d\n' "$n_pass"
printf '# FAIL: %d\n' "$n_fail"
echo "----------------------------------------------------------------------------"
# Per-test breakdown (strip the leading blank line from the accumulator).
printf '%s\n' "$results" | sed '/^$/d'
echo "============================================================================"

exit $rc
2 changes: 1 addition & 1 deletion libppd.pc.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ Version: @VERSION@

Libs: -L${libdir} -lppd
Libs.private: @CUPS_LIBS@
Cflags: -I${includedir}/ppd
Cflags: -I${includedir} -I${includedir}/ppd
Loading