summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorMichael Vogt <mvo@ubuntu.com>2015-03-13 15:01:18 +0100
committerMichael Vogt <mvo@ubuntu.com>2015-03-13 15:01:18 +0100
commit1c01d6cc57b19e599d926d245cee30ea25826220 (patch)
treee5edd13e551023f106bed0bb2db5a12ff2084250 /test
parentca495d048f6a6fd596b061208d28f319fa6dbcd8 (diff)
parent1a0619ac765cc0b2f4906c96c1a4d7f510569a3f (diff)
Merge branch 'debian/sid' into ubuntu/master
Conflicts: configure.ac debian/changelog
Diffstat (limited to 'test')
-rw-r--r--test/integration/framework113
-rwxr-xr-xtest/integration/test-allow-scores-for-all-dependency-types28
-rwxr-xr-xtest/integration/test-apt-download-progress43
-rwxr-xr-xtest/integration/test-apt-ftparchive-src-cachedb4
-rwxr-xr-xtest/integration/test-apt-get-source4
-rwxr-xr-xtest/integration/test-apt-helper24
-rwxr-xr-xtest/integration/test-apt-key6
-rwxr-xr-xtest/integration/test-apt-progress-fd67
-rwxr-xr-xtest/integration/test-apt-progress-fd-deb82218
-rwxr-xr-xtest/integration/test-apt-progress-fd-error2
-rwxr-xr-xtest/integration/test-bug-769609-triggers-still-pending-after-run75
-rwxr-xr-xtest/integration/test-failing-maintainer-scripts46
-rwxr-xr-xtest/integration/test-no-fds-leaked-to-maintainer-scripts119
-rwxr-xr-xtest/integration/test-partial-file-support62
-rwxr-xr-xtest/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum260
-rw-r--r--test/interactive-helper/aptwebserver.cc181
-rw-r--r--test/libapt/commandline_test.cc68
-rw-r--r--test/libapt/hashsums_test.cc64
-rw-r--r--test/libapt/makefile4
19 files changed, 972 insertions, 216 deletions
diff --git a/test/integration/framework b/test/integration/framework
index 7923e23d9..70ad381e9 100644
--- a/test/integration/framework
+++ b/test/integration/framework
@@ -102,7 +102,7 @@ runapt() {
local CMD="$1"
shift
case $CMD in
- sh|aptitude|*/*) ;;
+ sh|aptitude|*/*|command) ;;
*) CMD="${BUILDDIRECTORY}/$CMD";;
esac
MALLOC_PERTURB_=21 MALLOC_CHECK_=2 APT_CONFIG="$(getaptconfig)" LD_LIBRARY_PATH=${BUILDDIRECTORY} $CMD "$@"
@@ -325,6 +325,59 @@ configdpkg() {
fi
}
+configdpkgnoopchroot() {
+ # create a library to noop chroot() and rewrite maintainer script executions
+ # via execvp() as used by dpkg as we don't want our rootdir to be a fullblown
+ # chroot directory dpkg could chroot into to execute the maintainer scripts
+ msgtest 'Building library to preload to make maintainerscript work in' 'dpkg'
+ cat << EOF > noopchroot.c
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+
+static char * chrootdir = NULL;
+
+int chroot(const char *path) {
+ printf("WARNING: CHROOTing to %s was ignored!\n", path);
+ free(chrootdir);
+ chrootdir = strdup(path);
+ return 0;
+}
+int execvp(const char *file, char *const argv[]) {
+ static int (*func_execvp) (const char *, char * const []) = NULL;
+ if (func_execvp == NULL)
+ func_execvp = (int (*) (const char *, char * const [])) dlsym(RTLD_NEXT, "execvp");
+ if (chrootdir == NULL || strncmp(file, "/var/lib/dpkg/", strlen("/var/lib/dpkg/")) != 0)
+ return func_execvp(file, argv);
+ printf("REWRITE execvp call %s into %s\n", file, chrootdir);
+ char newfile[strlen(chrootdir) + strlen(file)];
+ strcpy(newfile, chrootdir);
+ strcat(newfile, file);
+ return func_execvp(newfile, argv);
+}
+EOF
+ testsuccess --nomsg gcc -fPIC -shared -o noopchroot.so noopchroot.c -ldl
+
+ mkdir -p "${TMPWORKINGDIRECTORY}/rootdir/usr/bin/"
+ DPKG="${TMPWORKINGDIRECTORY}/rootdir/usr/bin/dpkg"
+ echo "#!/bin/sh
+if [ -n \"\$LD_PRELOAD\" ]; then
+ export LD_PRELOAD=\"${TMPWORKINGDIRECTORY}/noopchroot.so \${LD_PRELOAD}\"
+else
+ export LD_PRELOAD=\"${TMPWORKINGDIRECTORY}/noopchroot.so\"
+fi
+dpkg \"\$@\"" > $DPKG
+ chmod +x $DPKG
+ sed -ie "s|^DPKG::options:: \"dpkg\";\$|DPKG::options:: \"$DPKG\";|" aptconfig.conf
+}
+
+configallowinsecurerepositories() {
+ echo "Acquire::AllowInsecureRepositories \"$1\";" > rootdir/etc/apt/apt.conf.d/allow-insecure-repositories.conf
+
+}
+
configcompression() {
while [ -n "$1" ]; do
case "$1" in
@@ -442,7 +495,7 @@ buildsimplenativepackage() {
fi
local BUILDDIR=${TMPWORKINGDIRECTORY}/incoming/${NAME}-${VERSION}
- msgninfo "Build package ${NAME} in ${VERSION} for ${RELEASE} in ${DISTSECTION}… "
+ msgtest "Build source package in version ${VERSION} for ${RELEASE} in ${DISTSECTION}" "$NAME"
mkdir -p $BUILDDIR/debian/source
echo "* most suckless software product ever" > ${BUILDDIR}/FEATURES
echo "#!/bin/sh
@@ -474,7 +527,10 @@ Package: $NAME" >> ${BUILDDIR}/debian/control
echo "Description: $DESCRIPTION" >> ${BUILDDIR}/debian/control
echo '3.0 (native)' > ${BUILDDIR}/debian/source/format
- (cd ${BUILDDIR}/..; dpkg-source -b ${NAME}-${VERSION} 2>&1) | sed -n 's#^dpkg-source: info: building [^ ]\+ in ##p' \
+ cd ${BUILDDIR}/..
+ testsuccess --nomsg dpkg-source -b ${NAME}-${VERSION}
+ cd - >/dev/null
+ sed -n 's#^dpkg-source: info: building [^ ]\+ in ##p' ${TMPWORKINGDIRECTORY}/rootdir/tmp/testsuccess.output \
| while read SRC; do
echo "pool/${SRC}" >> ${BUILDDIR}/../${RELEASE}.${DISTSECTION}.srclist
# if expr match "${SRC}" '.*\.dsc' >/dev/null 2>&1; then
@@ -486,6 +542,7 @@ Package: $NAME" >> ${BUILDDIR}/debian/control
done
for arch in $(getarchitecturesfromcommalist "$ARCH"); do
+ msgtest "Build binary package for ${RELEASE} in ${SECTION}" "$NAME"
rm -rf ${BUILDDIR}/debian/tmp
mkdir -p ${BUILDDIR}/debian/tmp/DEBIAN ${BUILDDIR}/debian/tmp/usr/share/doc/${NAME} ${BUILDDIR}/debian/tmp/usr/bin
cp ${BUILDDIR}/debian/copyright ${BUILDDIR}/debian/changelog ${BUILDDIR}/FEATURES ${BUILDDIR}/debian/tmp/usr/share/doc/${NAME}
@@ -499,11 +556,7 @@ Package: $NAME" >> ${BUILDDIR}/debian/control
local LOG="${BUILDDIR}/../${NAME}_${VERSION}_${arch}.dpkg-deb.log"
# ensure the right permissions as dpkg-deb ensists
chmod 755 ${BUILDDIR}/debian/tmp/DEBIAN
- if ! dpkg-deb -Z${COMPRESS_TYPE} --build ${BUILDDIR}/debian/tmp ${BUILDDIR}/.. >$LOG 2>&1; then
- cat $LOG
- false
- fi
- rm $LOG
+ testsuccess --nomsg dpkg-deb -Z${COMPRESS_TYPE} --build ${BUILDDIR}/debian/tmp ${BUILDDIR}/..
echo "pool/${NAME}_${VERSION}_${arch}.deb" >> ${BUILDDIR}/../${RELEASE}.${DISTSECTION}.pkglist
done
@@ -521,15 +574,13 @@ buildpackage() {
local ARCH=$(getarchitecture $4)
local PKGNAME="$(echo "$BUILDDIR" | grep -o '[^/]*$')"
local BUILDLOG="$(readlink -f "${BUILDDIR}/../${PKGNAME}_${RELEASE}_${SECTION}.dpkg-bp.log")"
- msgninfo "Build package ${PKGNAME} for ${RELEASE} in ${SECTION}… "
+ msgtest "Build package for ${RELEASE} in ${SECTION}" "$PKGNAME"
cd $BUILDDIR
if [ "$ARCH" = "all" ]; then
ARCH="$(dpkg-architecture -qDEB_HOST_ARCH 2> /dev/null)"
fi
- if ! dpkg-buildpackage -uc -us -a$ARCH >$BUILDLOG 2>&1 ; then
- cat $BUILDLOG
- false
- fi
+ testsuccess --nomsg dpkg-buildpackage -uc -us -a$ARCH
+ cp ${TMPWORKINGDIRECTORY}/rootdir/tmp/testsuccess.output $BUILDLOG
local PKGS="$(grep '^dpkg-deb: building package' $BUILDLOG | cut -d'/' -f 2 | sed -e "s#'\.##")"
local SRCS="$(grep '^dpkg-source: info: building' $BUILDLOG | grep -o '[a-z0-9._+~-]*$')"
cd - > /dev/null
@@ -539,7 +590,6 @@ buildpackage() {
for SRC in $SRCS; do
echo "pool/${SRC}" >> ${TMPWORKINGDIRECTORY}/incoming/${RELEASE}.${SECTION}.srclist
done
- msgdone "info"
}
buildaptarchive() {
@@ -730,7 +780,7 @@ buildaptarchivefromincoming() {
[ -e ftparchive.conf ] || createaptftparchiveconfig
[ -e dists ] || buildaptftparchivedirectorystructure
msgninfo "\tGenerate Packages, Sources and Contents files… "
- aptftparchive -qq generate ftparchive.conf
+ testsuccess aptftparchive generate ftparchive.conf
cd - > /dev/null
msgdone "info"
generatereleasefiles
@@ -1014,8 +1064,8 @@ acquire::cdrom::autodetect 0;" > rootdir/etc/apt/apt.conf.d/00cdrom
}
downloadfile() {
- local PROTO="$(echo "$1" | cut -d':' -f 1 )"
- apthelper -o Debug::Acquire::${PROTO}=1 \
+ local PROTO="${1%%:*}"
+ apthelper -o Debug::Acquire::${PROTO}=1 -o Debug::pkgAcquire::Worker=1 \
download-file "$1" "$2" 2>&1 || true
# only if the file exists the download was successful
if [ -e "$2" ]; then
@@ -1072,7 +1122,7 @@ testequal() {
if [ -n "$MSG" ]; then
msgtest "$MSG" "$*"
fi
- $* 2>&1 | checkdiff $COMPAREFILE - && msgpass || msgfail
+ "$@" 2>&1 | checkdiff $COMPAREFILE - && msgpass || msgfail
}
testequalor2() {
@@ -1128,10 +1178,13 @@ testnopackage() {
fi
}
-testdpkginstalled() {
- msgtest "Test for correctly installed package(s) with" "dpkg -l $*"
- local PKGS="$(dpkg -l "$@" 2>/dev/null | grep '^i' | wc -l)"
- if [ "$PKGS" != $# ]; then
+testdpkgstatus() {
+ local STATE="$1"
+ local NR="$2"
+ shift 2
+ msgtest "Test that $NR package(s) are in state $STATE with" "dpkg -l $*"
+ local PKGS="$(dpkg -l "$@" 2>/dev/null | grep "^${STATE}" | wc -l)"
+ if [ "$PKGS" != $NR ]; then
echo >&2 $PKGS
dpkg -l "$@" | grep '^[a-z]' >&2
msgfail
@@ -1140,16 +1193,12 @@ testdpkginstalled() {
fi
}
+testdpkginstalled() {
+ testdpkgstatus 'ii' "$#" "$@"
+}
+
testdpkgnotinstalled() {
- msgtest "Test for correctly not-installed package(s) with" "dpkg -l $*"
- local PKGS="$(dpkg -l "$@" 2> /dev/null | grep '^i' | wc -l)"
- if [ "$PKGS" != 0 ]; then
- echo
- dpkg -l "$@" | grep '^[a-z]' >&2
- msgfail
- else
- msgpass
- fi
+ testdpkgstatus 'ii' '0' "$@"
}
testmarkedauto() {
@@ -1171,7 +1220,7 @@ testsuccess() {
msgtest 'Test for successful execution of' "$*"
fi
local OUTPUT="${TMPWORKINGDIRECTORY}/rootdir/tmp/testsuccess.output"
- if $@ >${OUTPUT} 2>&1; then
+ if "$@" >${OUTPUT} 2>&1; then
msgpass
else
echo >&2
diff --git a/test/integration/test-allow-scores-for-all-dependency-types b/test/integration/test-allow-scores-for-all-dependency-types
index a5c98f3d6..d60cb8daf 100755
--- a/test/integration/test-allow-scores-for-all-dependency-types
+++ b/test/integration/test-allow-scores-for-all-dependency-types
@@ -32,6 +32,11 @@ insertpackage 'multipleyes' 'foo' 'amd64' '2.2' 'Conflicts: bar (<= 3)'
# having foo multiple times as conflict is a non-advisable hack in general
insertpackage 'multipleyes' 'bar' 'amd64' '2.2' 'Conflicts: foo (<= 3), foo (<= 3)'
+#774924 - slightly simplified
+insertpackage 'jessie' 'login' 'amd64' '2' 'Pre-Depends: libaudit1 (>= 0)'
+insertpackage 'jessie' 'libaudit1' 'amd64' '2' 'Depends: libaudit-common (>= 0)'
+insertpackage 'jessie' 'libaudit-common' 'amd64' '2' 'Breaks: libaudit0, libaudit1 (<< 2)'
+
cp rootdir/var/lib/dpkg/status rootdir/var/lib/dpkg/status-backup
setupaptarchive
@@ -142,3 +147,26 @@ Inst foo [1] (2 versioned [amd64])
Inst baz (2 versioned [amd64])
Conf foo (2 versioned [amd64])
Conf baz (2 versioned [amd64])' aptget install baz -st versioned
+
+# recreating the exact situation is hard, so we pull tricks to get the score
+cp -f rootdir/var/lib/dpkg/status-backup rootdir/var/lib/dpkg/status
+insertinstalledpackage 'gdm3' 'amd64' '1' 'Depends: libaudit0, libaudit0'
+insertinstalledpackage 'login' 'amd64' '1' 'Essential: yes'
+insertinstalledpackage 'libaudit0' 'amd64' '1'
+testequal 'Reading package lists...
+Building dependency tree...
+The following packages will be REMOVED:
+ gdm3 libaudit0
+The following NEW packages will be installed:
+ libaudit-common libaudit1
+The following packages will be upgraded:
+ login
+1 upgraded, 2 newly installed, 2 to remove and 0 not upgraded.
+Remv gdm3 [1]
+Remv libaudit0 [1]
+Inst libaudit-common (2 jessie [amd64])
+Conf libaudit-common (2 jessie [amd64])
+Inst libaudit1 (2 jessie [amd64])
+Conf libaudit1 (2 jessie [amd64])
+Inst login [1] (2 jessie [amd64])
+Conf login (2 jessie [amd64])' aptget dist-upgrade -st jessie
diff --git a/test/integration/test-apt-download-progress b/test/integration/test-apt-download-progress
new file mode 100755
index 000000000..0a9020bec
--- /dev/null
+++ b/test/integration/test-apt-download-progress
@@ -0,0 +1,43 @@
+#!/bin/sh
+#
+# ensure downloading sends progress as a regression test for commit 9127d7ae
+#
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+changetohttpswebserver
+
+assertprogress() {
+ T="$1"
+ testsuccess grep "dlstatus:1:0:Retrieving file 1 of 1" "$T"
+ if ! egrep -q "dlstatus:1:[0-9]{1,2}\.(.*):Retrieving file 1 of 1" "$T"; then
+ cat "$T"
+ msgfail "Failed to detect download progress"
+ fi
+ testsuccess grep "dlstatus:1:100:Retrieving file 1 of 1" "$T"
+ #cat $T
+}
+
+# we need to ensure the file is reasonable big so that apt has a chance to
+# actually report progress - but not too big to ensure its not delaying the
+# test too much
+TESTFILE=testfile.big
+testsuccess dd if=/dev/zero of=./aptarchive/$TESTFILE bs=800k count=1
+
+msgtest 'download progress works via' 'http'
+printf '\n'
+exec 3> apt-progress.log
+testsuccess apthelper download-file "http://localhost:8080/$TESTFILE" http-$TESTFILE -o APT::Status-Fd=3 -o Acquire::http::Dl-Limit=800
+assertprogress apt-progress.log
+
+msgtest 'download progress works via' 'https'
+printf '\n'
+exec 3> apt-progress.log
+testsuccess apthelper download-file "https://localhost:4433/$TESTFILE" https-$TESTFILE -o APT::Status-Fd=3 -o Acquire::https::Dl-Limit=800
+assertprogress apt-progress.log
+
+# cleanup
+rm -f apt-progress*.log
diff --git a/test/integration/test-apt-ftparchive-src-cachedb b/test/integration/test-apt-ftparchive-src-cachedb
index adcca6217..0ac4d558f 100755
--- a/test/integration/test-apt-ftparchive-src-cachedb
+++ b/test/integration/test-apt-ftparchive-src-cachedb
@@ -180,10 +180,6 @@ testequal "
E: Could not find a Source entry in the DSC 'aptarchive/pool/invalid/invalid_1.0.dsc'" aptftparchive sources aptarchive/pool/invalid
rm -f aptarchive/pool/invalid/invalid_1.0.dsc
-dd if=/dev/zero of="aptarchive/pool/invalid/toobig_1.0.dsc" bs=1k count=129 2>/dev/null
-testequal "
-E: DSC file 'aptarchive/pool/invalid/toobig_1.0.dsc' is too large!" aptftparchive sources aptarchive/pool/invalid
-
# ensure clean works
rm -f aptarchive/pool/main/*
aptftparchive clean apt-ftparchive.conf -o Debug::APT::FTPArchive::Clean=1 > clean-out.txt 2>&1
diff --git a/test/integration/test-apt-get-source b/test/integration/test-apt-get-source
index 33bd980d0..b27cbbe96 100755
--- a/test/integration/test-apt-get-source
+++ b/test/integration/test-apt-get-source
@@ -82,3 +82,7 @@ testequal "$HEADER
Need to get 0 B of source archives.
'file://${APTARCHIVE}/foo_0.0.1.dsc' foo_0.0.1.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e
'file://${APTARCHIVE}/foo_0.0.1.tar.gz' foo_0.0.1.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris -t unstable foo=0.0.1
+
+testequal "$HEADER
+Need to get 0 B of source archives.
+Fetch source foo" aptget source -q -s foo
diff --git a/test/integration/test-apt-helper b/test/integration/test-apt-helper
index c749224ca..31e471677 100755
--- a/test/integration/test-apt-helper
+++ b/test/integration/test-apt-helper
@@ -10,34 +10,36 @@ configarchitecture "i386"
changetohttpswebserver
test_apt_helper_download() {
- echo "foo" > aptarchive/foo
+ echo 'foo' > aptarchive/foo
+ echo 'bar' > aptarchive/foo2
msgtest 'apt-file download-file md5sum'
- apthelper -qq download-file http://localhost:8080/foo foo2 MD5Sum:d3b07384d113edec49eaa6238ad5ff00 && msgpass || msgfail
+ testsuccess --nomsg apthelper download-file http://localhost:8080/foo foo2 MD5Sum:d3b07384d113edec49eaa6238ad5ff00
testfileequal foo2 'foo'
msgtest 'apt-file download-file sha1'
- apthelper -qq download-file http://localhost:8080/foo foo1 SHA1:f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 && msgpass || msgfail
+ testsuccess --nomsg apthelper download-file http://localhost:8080/foo foo1 SHA1:f1d2d2f924e986ac86fdf7b36c94bcdf32beec15
testfileequal foo1 'foo'
msgtest 'apt-file download-file sha256'
- apthelper -qq download-file http://localhost:8080/foo foo3 SHA256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c && msgpass || msgfail
+ testsuccess --nomsg apthelper download-file http://localhost:8080/foo foo3 SHA256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c
testfileequal foo3 'foo'
msgtest 'apt-file download-file no-hash'
- apthelper -qq download-file http://localhost:8080/foo foo4 && msgpass || msgfail
+ testsuccess --nomsg apthelper download-file http://localhost:8080/foo foo4
testfileequal foo4 'foo'
msgtest 'apt-file download-file wrong hash'
- if ! apthelper -qq download-file http://localhost:8080/foo foo5 MD5Sum:aabbcc 2>&1 2> download.stderr; then
- msgpass
- else
- msgfail
- fi
- testfileequal download.stderr 'E: Failed to fetch http://localhost:8080/foo Hash Sum mismatch
+ testfailure --nomsg apthelper -qq download-file http://localhost:8080/foo foo5 MD5Sum:aabbcc
+ testfileequal rootdir/tmp/testfailure.output 'E: Failed to fetch http://localhost:8080/foo Hash Sum mismatch
E: Download Failed'
testfileequal foo5.FAILED 'foo'
+
+ msgtest 'apt-file download-file md5sum sha1'
+ testsuccess --nomsg apthelper download-file http://localhost:8080/foo foo6 MD5Sum:d3b07384d113edec49eaa6238ad5ff00 http://localhost:8080/foo2 foo7 SHA1:e242ed3bffccdf271b7fbaf34ed72d089537b42f
+ testfileequal foo6 'foo'
+ testfileequal foo7 'bar'
}
test_apt_helper_detect_proxy() {
diff --git a/test/integration/test-apt-key b/test/integration/test-apt-key
index 68b3f9710..47230cb55 100755
--- a/test/integration/test-apt-key
+++ b/test/integration/test-apt-key
@@ -105,3 +105,9 @@ testfileequal ./aptkey.list 'pub 2048R/528144E2 2011-01-16'
testsuccess test ! -e rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
testsuccess cmp keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg~
testsuccess cmp keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg~
+
+msgtest 'Test key removal with' '8 byte key ID'
+cleanplate
+cp -a keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
+testsuccess --nomsg aptkey --fakeroot del 5A90D141DBAC8DAE
+testempty aptkey list
diff --git a/test/integration/test-apt-progress-fd b/test/integration/test-apt-progress-fd
index d72e7e72d..68cc0439c 100755
--- a/test/integration/test-apt-progress-fd
+++ b/test/integration/test-apt-progress-fd
@@ -19,13 +19,14 @@ testequal "dlstatus:1:0:Retrieving file 1 of 1
dlstatus:1:0:Retrieving file 1 of 1
pmstatus:dpkg-exec:0:Running dpkg
pmstatus:testing:0:Installing testing (amd64)
-pmstatus:testing:20:Preparing testing (amd64)
-pmstatus:testing:40:Unpacking testing (amd64)
-pmstatus:testing:60:Preparing to configure testing (amd64)
-pmstatus:dpkg-exec:60:Running dpkg
-pmstatus:testing:60:Configuring testing (amd64)
-pmstatus:testing:80:Configuring testing (amd64)
-pmstatus:testing:100:Installed testing (amd64)" cat apt-progress.log
+pmstatus:testing:16.6667:Preparing testing (amd64)
+pmstatus:testing:33.3333:Unpacking testing (amd64)
+pmstatus:testing:50:Preparing to configure testing (amd64)
+pmstatus:dpkg-exec:50:Running dpkg
+pmstatus:testing:50:Configuring testing (amd64)
+pmstatus:testing:66.6667:Configuring testing (amd64)
+pmstatus:testing:83.3333:Installed testing (amd64)
+pmstatus:dpkg-exec:83.3333:Running dpkg" cat apt-progress.log
# upgrade
exec 3> apt-progress.log
@@ -34,13 +35,14 @@ testequal "dlstatus:1:0:Retrieving file 1 of 1
dlstatus:1:0:Retrieving file 1 of 1
pmstatus:dpkg-exec:0:Running dpkg
pmstatus:testing:0:Installing testing (amd64)
-pmstatus:testing:20:Preparing testing (amd64)
-pmstatus:testing:40:Unpacking testing (amd64)
-pmstatus:testing:60:Preparing to configure testing (amd64)
-pmstatus:dpkg-exec:60:Running dpkg
-pmstatus:testing:60:Configuring testing (amd64)
-pmstatus:testing:80:Configuring testing (amd64)
-pmstatus:testing:100:Installed testing (amd64)" cat apt-progress.log
+pmstatus:testing:16.6667:Preparing testing (amd64)
+pmstatus:testing:33.3333:Unpacking testing (amd64)
+pmstatus:testing:50:Preparing to configure testing (amd64)
+pmstatus:dpkg-exec:50:Running dpkg
+pmstatus:testing:50:Configuring testing (amd64)
+pmstatus:testing:66.6667:Configuring testing (amd64)
+pmstatus:testing:83.3333:Installed testing (amd64)
+pmstatus:dpkg-exec:83.3333:Running dpkg" cat apt-progress.log
# reinstall
exec 3> apt-progress.log
@@ -49,22 +51,24 @@ testequal "dlstatus:1:0:Retrieving file 1 of 1
dlstatus:1:0:Retrieving file 1 of 1
pmstatus:dpkg-exec:0:Running dpkg
pmstatus:testing:0:Installing testing (amd64)
-pmstatus:testing:20:Preparing testing (amd64)
-pmstatus:testing:40:Unpacking testing (amd64)
-pmstatus:testing:60:Preparing to configure testing (amd64)
-pmstatus:dpkg-exec:60:Running dpkg
-pmstatus:testing:60:Configuring testing (amd64)
-pmstatus:testing:80:Configuring testing (amd64)
-pmstatus:testing:100:Installed testing (amd64)" cat apt-progress.log
+pmstatus:testing:16.6667:Preparing testing (amd64)
+pmstatus:testing:33.3333:Unpacking testing (amd64)
+pmstatus:testing:50:Preparing to configure testing (amd64)
+pmstatus:dpkg-exec:50:Running dpkg
+pmstatus:testing:50:Configuring testing (amd64)
+pmstatus:testing:66.6667:Configuring testing (amd64)
+pmstatus:testing:83.3333:Installed testing (amd64)
+pmstatus:dpkg-exec:83.3333:Running dpkg" cat apt-progress.log
# and remove
exec 3> apt-progress.log
testsuccess aptget remove testing -y -o APT::Status-Fd=3
testequal "pmstatus:dpkg-exec:0:Running dpkg
pmstatus:testing:0:Removing testing (amd64)
-pmstatus:testing:33.3333:Preparing for removal of testing (amd64)
-pmstatus:testing:66.6667:Removing testing (amd64)
-pmstatus:testing:100:Removed testing (amd64)" cat apt-progress.log
+pmstatus:testing:25:Preparing for removal of testing (amd64)
+pmstatus:testing:50:Removing testing (amd64)
+pmstatus:testing:75:Removed testing (amd64)
+pmstatus:dpkg-exec:75:Running dpkg" cat apt-progress.log
# install non-native and ensure we get proper progress info
exec 3> apt-progress.log
@@ -75,12 +79,13 @@ testequal "dlstatus:1:0:Retrieving file 1 of 1
dlstatus:1:0:Retrieving file 1 of 1
pmstatus:dpkg-exec:0:Running dpkg
pmstatus:testing2:0:Installing testing2 (i386)
-pmstatus:testing2:20:Preparing testing2 (i386)
-pmstatus:testing2:40:Unpacking testing2 (i386)
-pmstatus:testing2:60:Preparing to configure testing2 (i386)
-pmstatus:dpkg-exec:60:Running dpkg
-pmstatus:testing2:60:Configuring testing2 (i386)
-pmstatus:testing2:80:Configuring testing2 (i386)
-pmstatus:testing2:100:Installed testing2 (i386)" cat apt-progress.log
+pmstatus:testing2:16.6667:Preparing testing2 (i386)
+pmstatus:testing2:33.3333:Unpacking testing2 (i386)
+pmstatus:testing2:50:Preparing to configure testing2 (i386)
+pmstatus:dpkg-exec:50:Running dpkg
+pmstatus:testing2:50:Configuring testing2 (i386)
+pmstatus:testing2:66.6667:Configuring testing2 (i386)
+pmstatus:testing2:83.3333:Installed testing2 (i386)
+pmstatus:dpkg-exec:83.3333:Running dpkg" cat apt-progress.log
rm -f apt-progress*.log
diff --git a/test/integration/test-apt-progress-fd-deb822 b/test/integration/test-apt-progress-fd-deb822
index 9d227942d..badc985e4 100755
--- a/test/integration/test-apt-progress-fd-deb822
+++ b/test/integration/test-apt-progress-fd-deb822
@@ -27,37 +27,41 @@ Message: Installing testing (amd64)
Status: progress
Package: testing:amd64
-Percent: 20
+Percent: 16.6667
Message: Preparing testing (amd64)
Status: progress
Package: testing:amd64
-Percent: 40
+Percent: 33.3333
Message: Unpacking testing (amd64)
Status: progress
Package: testing:amd64
-Percent: 60
+Percent: 50
Message: Preparing to configure testing (amd64)
Status: progress
-Percent: 60
+Percent: 50
Message: Running dpkg
Status: progress
Package: testing:amd64
-Percent: 60
+Percent: 50
Message: Configuring testing (amd64)
Status: progress
Package: testing:amd64
-Percent: 80
+Percent: 66.6667
Message: Configuring testing (amd64)
Status: progress
Package: testing:amd64
-Percent: 100
+Percent: 83.3333
Message: Installed testing (amd64)
+
+Status: progress
+Percent: 83.3333
+Message: Running dpkg
" cat apt-progress.log
diff --git a/test/integration/test-apt-progress-fd-error b/test/integration/test-apt-progress-fd-error
index a47095b9b..632300765 100755
--- a/test/integration/test-apt-progress-fd-error
+++ b/test/integration/test-apt-progress-fd-error
@@ -18,7 +18,7 @@ setupaptarchive
exec 3> apt-progress.log
testfailure aptget install foo1 foo2 -y -o APT::Status-Fd=3
msgtest "Ensure correct error message"
-if grep -q "aptarchive/pool/foo2_0.8.15_amd64.deb:40:trying to overwrite '/usr/bin/file-conflict', which is also in package foo1 0.8.15" apt-progress.log; then
+if grep -q "aptarchive/pool/foo2_0.8.15_amd64.deb:36.3636:trying to overwrite '/usr/bin/file-conflict', which is also in package foo1 0.8.15" apt-progress.log; then
msgpass
else
cat apt-progress.log
diff --git a/test/integration/test-bug-769609-triggers-still-pending-after-run b/test/integration/test-bug-769609-triggers-still-pending-after-run
new file mode 100755
index 000000000..146fa766b
--- /dev/null
+++ b/test/integration/test-bug-769609-triggers-still-pending-after-run
@@ -0,0 +1,75 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture 'amd64'
+
+msgtest 'Check if installed dpkg supports' 'noawait trigger'
+if dpkg-checkbuilddeps -d 'dpkg (>= 1.16.1)' /dev/null; then
+ msgpass
+else
+ msgskip 'dpkg version too old'
+ exit 0
+fi
+configdpkgnoopchroot
+
+buildtriggerpackages() {
+ local TYPE="$1"
+ setupsimplenativepackage "triggerable-$TYPE" 'all' '1.0' 'unstable' "Depends: trigdepends-$TYPE"
+ BUILDDIR="incoming/triggerable-${TYPE}-1.0"
+ cat >${BUILDDIR}/debian/postinst <<EOF
+#!/bin/sh
+if [ "\$1" = 'triggered' ]; then
+ ls -l /proc/self/fd/
+fi
+EOF
+ echo "$TYPE /usr/share/doc" > ${BUILDDIR}/debian/triggers
+ buildpackage "$BUILDDIR" 'unstable' 'main' 'native'
+ rm -rf "$BUILDDIR"
+ buildsimplenativepackage "trigdepends-$TYPE" 'all' '1.0' 'unstable'
+}
+
+#buildtriggerpackages 'interest'
+buildtriggerpackages 'interest-noawait'
+buildsimplenativepackage "trigstuff" 'all' '1.0' 'unstable'
+
+setupaptarchive
+
+runtests() {
+ local TYPE="$1"
+ msgmsg 'Working with trigger type' "$TYPE"
+ testsuccess aptget install triggerable-$TYPE -y
+ cp rootdir/tmp/testsuccess.output terminal.output
+ testsuccess grep '^REWRITE ' terminal.output
+ testdpkginstalled triggerable-$TYPE trigdepends-$TYPE
+
+ testsuccess aptget install trigdepends-$TYPE -y --reinstall
+ cp rootdir/tmp/testsuccess.output terminal.output
+ testsuccess grep '^REWRITE ' terminal.output
+ testsuccess grep ' root root ' terminal.output
+ testdpkginstalled triggerable-$TYPE trigdepends-$TYPE
+
+ testsuccess aptget install trigstuff -y
+ cp rootdir/tmp/testsuccess.output terminal.output
+ testsuccess grep '^REWRITE ' terminal.output
+ testsuccess grep ' root root ' terminal.output
+ testdpkginstalled triggerable-$TYPE trigdepends-$TYPE trigstuff
+
+ testsuccess aptget purge trigstuff -y
+ cp rootdir/tmp/testsuccess.output terminal.output
+ testsuccess grep '^REWRITE ' terminal.output
+ testsuccess grep ' root root ' terminal.output
+ testdpkginstalled triggerable-$TYPE trigdepends-$TYPE
+ testdpkgnotinstalled trigstuff
+
+ testsuccess aptget purge trigdepends-$TYPE -y
+ cp rootdir/tmp/testsuccess.output terminal.output
+ testfailure grep '^REWRITE ' terminal.output
+ testfailure grep ' root root ' terminal.output
+ testdpkgnotinstalled triggerable-$TYPE trigdepends-$TYPE
+}
+#runtests 'interest'
+runtests 'interest-noawait'
diff --git a/test/integration/test-failing-maintainer-scripts b/test/integration/test-failing-maintainer-scripts
index 3dd7d643e..953506aa5 100755
--- a/test/integration/test-failing-maintainer-scripts
+++ b/test/integration/test-failing-maintainer-scripts
@@ -6,6 +6,7 @@ TESTDIR=$(readlink -f $(dirname $0))
setupenvironment
configarchitecture 'native'
+configdpkgnoopchroot
# create a bunch of failures
createfailure() {
@@ -25,51 +26,6 @@ createfailure 'postrm'
setupaptarchive
-# create a library to noop chroot() and rewrite maintainer script executions
-# via execvp() as used by dpkg as we don't want our rootdir to be a fullblown
-# chroot directory dpkg could chroot into to execute the maintainer scripts
-cat << EOF > noopchroot.c
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <dlfcn.h>
-
-static char * chrootdir = NULL;
-
-int chroot(const char *path) {
- printf("WARNING: CHROOTing to %s was ignored!\n", path);
- free(chrootdir);
- chrootdir = strdup(path);
- return 0;
-}
-int execvp(const char *file, char *const argv[]) {
- static int (*func_execvp) (const char *, char * const []) = NULL;
- if (func_execvp == NULL)
- func_execvp = (int (*) (const char *, char * const [])) dlsym(RTLD_NEXT, "execvp");
- if (chrootdir == NULL || strncmp(file, "/var/lib/dpkg/", strlen("/var/lib/dpkg/")) != 0)
- return func_execvp(file, argv);
- printf("REWRITE execvp call %s into %s\n", file, chrootdir);
- char newfile[strlen(chrootdir) + strlen(file)];
- strcpy(newfile, chrootdir);
- strcat(newfile, file);
- return func_execvp(newfile, argv);
-}
-EOF
-testsuccess gcc -fPIC -shared -o noopchroot.so noopchroot.c -ldl
-
-mkdir -p "${TMPWORKINGDIRECTORY}/rootdir/usr/bin/"
-DPKG="${TMPWORKINGDIRECTORY}/rootdir/usr/bin/dpkg"
-echo "#!/bin/sh
-if [ -n \"\$LD_PRELOAD\" ]; then
- export LD_PRELOAD=\"${TMPWORKINGDIRECTORY}/noopchroot.so \${LD_PRELOAD}\"
-else
- export LD_PRELOAD=\"${TMPWORKINGDIRECTORY}/noopchroot.so\"
-fi
-dpkg \"\$@\"" > $DPKG
-chmod +x $DPKG
-sed -ie "s|^DPKG::options:: \"dpkg\";\$|DPKG::options:: \"$DPKG\";|" aptconfig.conf
-
# setup some pre- and post- invokes to check the output isn't garbled later
APTHOOK="${TMPWORKINGDIRECTORY}/rootdir/usr/bin/apthook"
echo '#!/bin/sh
diff --git a/test/integration/test-no-fds-leaked-to-maintainer-scripts b/test/integration/test-no-fds-leaked-to-maintainer-scripts
new file mode 100755
index 000000000..41c057042
--- /dev/null
+++ b/test/integration/test-no-fds-leaked-to-maintainer-scripts
@@ -0,0 +1,119 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture 'amd64' 'i386'
+configdpkgnoopchroot
+
+setupsimplenativepackage "fdleaks" 'all' '1.0' 'unstable'
+BUILDDIR="incoming/fdleaks-1.0"
+for script in 'preinst' 'postinst' 'prerm' 'postrm'; do
+ cat > ${BUILDDIR}/debian/$script << EOF
+#!/bin/sh
+if [ -e "$(pwd)/rootdir/tmp/read_stdin" ]; then
+ read line;
+ echo "STDIN: -\$line-"
+fi
+ls -l /proc/self/fd/
+EOF
+done
+buildpackage "$BUILDDIR" 'unstable' 'main' 'native'
+rm -rf "$BUILDDIR"
+
+PKGNAME='fdleaks:all'
+if ! dpkg-checkbuilddeps -d 'dpkg (>= 1.16.2)' /dev/null >/dev/null 2>&1; then
+ PKGNAME='fdleaks'
+fi
+
+setupaptarchive
+
+rm -f rootdir/var/log/dpkg.log rootdir/var/log/apt/term.log
+testsuccess aptget install -y fdleaks -qq < /dev/null
+
+checkfdleak() {
+ msgtest 'Check if fds were not' 'leaked'
+ if [ "$(grep 'root root' rootdir/tmp/testsuccess.output | wc -l)" = "$1" ]; then
+ msgpass
+ else
+ echo
+ cat rootdir/tmp/testsuccess.output
+ msgfail
+ fi
+}
+checkinstall() {
+ checkfdleak 8
+
+ cp rootdir/tmp/testsuccess.output terminal.output
+ tail -n +3 rootdir/var/log/apt/term.log | head -n -1 > terminal.log
+ testfileequal 'terminal.log' "$(cat terminal.output)"
+
+ testequal "startup archives unpack
+install $PKGNAME <none> 1.0
+status half-installed $PKGNAME 1.0
+status unpacked $PKGNAME 1.0
+status unpacked $PKGNAME 1.0
+startup packages configure
+configure $PKGNAME 1.0 <none>
+status unpacked $PKGNAME 1.0
+status half-configured $PKGNAME 1.0
+status installed $PKGNAME 1.0
+startup packages configure" cut -f 3- -d' ' rootdir/var/log/dpkg.log
+}
+checkinstall
+
+rm -f rootdir/var/log/dpkg.log rootdir/var/log/apt/term.log
+testsuccess aptget purge -y fdleaks -qq
+checkpurge() {
+ checkfdleak 12
+
+ cp rootdir/tmp/testsuccess.output terminal.output
+ tail -n +3 rootdir/var/log/apt/term.log | head -n -1 > terminal.log
+ testfileequal 'terminal.log' "$(cat terminal.output)"
+
+ testequal "startup packages purge
+status installed $PKGNAME 1.0
+remove $PKGNAME 1.0 <none>
+status half-configured $PKGNAME 1.0
+status half-installed $PKGNAME 1.0
+status config-files $PKGNAME 1.0
+purge $PKGNAME 1.0 <none>
+status config-files $PKGNAME 1.0
+status config-files $PKGNAME 1.0
+status config-files $PKGNAME 1.0
+status config-files $PKGNAME 1.0
+status config-files $PKGNAME 1.0
+status not-installed $PKGNAME <none>
+startup packages configure" cut -f 3- -d' ' rootdir/var/log/dpkg.log
+}
+checkpurge
+
+msgtest 'setsid provided is new enough to support' '-w'
+if dpkg-checkbuilddeps -d 'util-linux (>= 2.24.2-1)' /dev/null >/dev/null 2>&1; then
+ msgpass
+else
+ msgskip "$(command dpkg -l util-linux)"
+ exit
+fi
+
+rm -f rootdir/var/log/dpkg.log rootdir/var/log/apt/term.log
+testsuccess runapt command setsid -w "${BUILDDIRECTORY}/apt-get" install -y fdleaks -qq < /dev/null
+checkinstall
+
+rm -f rootdir/var/log/dpkg.log rootdir/var/log/apt/term.log
+testsuccess runapt command setsid -w "${BUILDDIRECTORY}/apt-get" purge -y fdleaks -qq
+checkpurge
+
+touch rootdir/tmp/read_stdin
+
+rm -f rootdir/var/log/dpkg.log rootdir/var/log/apt/term.log
+for i in $(seq 1 10); do echo "$i"; done | testsuccess aptget install -y fdleaks -qq
+checkinstall
+testequal '2' grep -c '^STDIN: ' rootdir/var/log/apt/term.log
+
+rm -f rootdir/var/log/dpkg.log rootdir/var/log/apt/term.log
+yes '' | testsuccess runapt command setsid -w "${BUILDDIRECTORY}/apt-get" purge -y fdleaks -qq
+checkpurge
+testequal '3' grep -c '^STDIN: ' rootdir/var/log/apt/term.log
diff --git a/test/integration/test-partial-file-support b/test/integration/test-partial-file-support
index 5ab326def..160d451b6 100755
--- a/test/integration/test-partial-file-support
+++ b/test/integration/test-partial-file-support
@@ -24,13 +24,25 @@ testdownloadfile() {
else
msgpass
fi
- cat "$DOWNLOADLOG" | while read field hash; do
+ sed -e '/^ <- / s#%20# #g' -e '/^ <- / s#%0a#\n#g' "$DOWNLOADLOG" | grep '^.*-Hash: ' > receivedhashes.log
+ testsuccess test -s receivedhashes.log
+ local HASHES_OK=0
+ local HASHES_BAD=0
+ while read field hash; do
local EXPECTED
case "$field" in
'MD5Sum-Hash:') EXPECTED="$(md5sum "$TESTFILE" | cut -d' ' -f 1)";;
'SHA1-Hash:') EXPECTED="$(sha1sum "$TESTFILE" | cut -d' ' -f 1)";;
'SHA256-Hash:') EXPECTED="$(sha256sum "$TESTFILE" | cut -d' ' -f 1)";;
'SHA512-Hash:') EXPECTED="$(sha512sum "$TESTFILE" | cut -d' ' -f 1)";;
+ 'Checksum-FileSize-Hash:')
+ #filesize is too weak to check for !=
+ if [ "$4" = '=' ]; then
+ EXPECTED="$(stat -c '%s' "$TESTFILE")"
+ else
+ continue
+ fi
+ ;;
*) continue;;
esac
if [ "$4" = '=' ]; then
@@ -40,15 +52,41 @@ testdownloadfile() {
fi
if [ "$EXPECTED" "$4" "$hash" ]; then
msgpass
+ HASHES_OK=$((HASHES_OK+1));
else
- cat >&2 "$DOWNLOADLOG"
msgfail "expected: $EXPECTED ; got: $hash"
+ HASHES_BAD=$((HASHES_BAD+1));
fi
- done
+ done < receivedhashes.log
+ msgtest 'At least one good hash and no bad ones'
+ if [ $HASHES_OK -eq 0 ] || [ $HASHES_BAD -ne 0 ]; then
+ cat >&2 "$DOWNLOADLOG"
+ msgfail
+ else
+ msgpass
+ fi
}
TESTFILE='aptarchive/testfile'
cp -a ${TESTDIR}/framework $TESTFILE
+cp -a ${TESTDIR}/framework "${TESTFILE}2"
+
+followuprequest() {
+ local DOWN='./testfile'
+
+ copysource $TESTFILE 1M $DOWN
+ testdownloadfile 'completely downloaded file' "${1}/testfile" "$DOWN" '='
+ testwebserverlaststatuscode '416' "$DOWNLOADLOG"
+
+ copysource $TESTFILE 1M $DOWN
+ copysource "${TESTFILE}2" 20 "${DOWN}2"
+ msgtest 'Testing download of files with' 'completely downloaded file + partial file'
+ testsuccess --nomsg apthelper -o Debug::Acquire::${1%%:*}=1 -o Debug::pkgAcquire::Worker=1 \
+ download-file "$1/testfile" "$DOWN" '' "$1/testfile2" "${DOWN}2"
+ testwebserverlaststatuscode '206' 'rootdir/tmp/testsuccess.output'
+ testsuccess diff -u "$TESTFILE" "${DOWN}"
+ testsuccess diff -u "${DOWN}" "${DOWN}2"
+}
testrun() {
webserverconfig 'aptwebserver::support::range' 'true'
@@ -65,9 +103,11 @@ testrun() {
testdownloadfile 'invalid partial data' "${1}/testfile" './testfile' '!='
testwebserverlaststatuscode '206' "$DOWNLOADLOG"
- copysource $TESTFILE 1M ./testfile
- testdownloadfile 'completely downloaded file' "${1}/testfile" './testfile' '='
- testwebserverlaststatuscode '416' "$DOWNLOADLOG"
+ webserverconfig 'aptwebserver::closeOnError' 'false'
+ followuprequest "$1"
+ webserverconfig 'aptwebserver::closeOnError' 'true'
+ followuprequest "$1"
+ webserverconfig 'aptwebserver::closeOnError' 'false'
copysource /dev/zero 1M ./testfile
testdownloadfile 'too-big partial file' "${1}/testfile" './testfile' '='
@@ -85,8 +125,18 @@ testrun() {
testwebserverlaststatuscode '200' "$DOWNLOADLOG"
}
+msgmsg 'http: Test with Content-Length'
+webserverconfig 'aptwebserver::chunked-transfer-encoding' 'false'
+testrun 'http://localhost:8080'
+msgmsg 'http: Test with Transfer-Encoding: chunked'
+webserverconfig 'aptwebserver::chunked-transfer-encoding' 'true'
testrun 'http://localhost:8080'
changetohttpswebserver
+msgmsg 'https: Test with Content-Length'
+webserverconfig 'aptwebserver::chunked-transfer-encoding' 'false'
+testrun 'https://localhost:4433'
+msgmsg 'https: Test with Transfer-Encoding: chunked'
+webserverconfig 'aptwebserver::chunked-transfer-encoding' 'true'
testrun 'https://localhost:4433'
diff --git a/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum b/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum
new file mode 100755
index 000000000..9bdc81264
--- /dev/null
+++ b/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum
@@ -0,0 +1,260 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture 'native'
+
+cat > aptarchive/Sources <<EOF
+Package: pkg-md5-ok
+Binary: pkg-md5-ok
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ d41d8cd98f00b204e9800998ecf8427e 0 pkg-md5-ok_1.0.dsc
+ d41d8cd98f00b204e9800998ecf8427e 0 pkg-md5-ok_1.0.tar.gz
+
+Package: pkg-sha256-ok
+Binary: pkg-sha256-ok
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ d41d8cd98f00b204e9800998ecf8427e 0 pkg-sha256-ok_1.0.dsc
+ d41d8cd98f00b204e9800998ecf8427e 0 pkg-sha256-ok_1.0.tar.gz
+Checksums-Sha1:
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-sha256-ok_1.0.dsc
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-sha256-ok_1.0.tar.gz
+Checksums-Sha256:
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 pkg-sha256-ok_1.0.dsc
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 pkg-sha256-ok_1.0.tar.gz
+
+Package: pkg-sha256-bad
+Binary: pkg-sha256-bad
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ d41d8cd98f00b204e9800998ecf8427e 0 pkg-sha256-bad_1.0.dsc
+ d41d8cd98f00b204e9800998ecf8427e 0 pkg-sha256-bad_1.0.tar.gz
+Checksums-Sha1:
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-sha256-bad_1.0.dsc
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-sha256-bad_1.0.tar.gz
+Checksums-Sha256:
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 0 pkg-sha256-bad_1.0.dsc
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 pkg-sha256-bad_1.0.tar.gz
+
+Package: pkg-no-md5
+Binary: pkg-no-md5
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Checksums-Sha1:
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-no-md5_1.0.dsc
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-no-md5_1.0.tar.gz
+Checksums-Sha256:
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 pkg-no-md5_1.0.dsc
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 pkg-no-md5_1.0.tar.gz
+
+Package: pkg-mixed-ok
+Binary: pkg-mixed-ok
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Checksums-Sha1:
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-mixed-ok_1.0.tar.gz
+Checksums-Sha256:
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 pkg-mixed-ok_1.0.dsc
+
+Package: pkg-mixed-sha1-bad
+Binary: pkg-mixed-sha1-bad
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Checksums-Sha1:
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 0 pkg-mixed-sha1-bad_1.0.dsc
+Checksums-Sha256:
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 pkg-mixed-sha1-bad_1.0.tar.gz
+
+Package: pkg-mixed-sha2-bad
+Binary: pkg-mixed-sha2-bad
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Checksums-Sha1:
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-mixed-sha2-bad_1.0.dsc
+Checksums-Sha256:
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 pkg-mixed-sha2-bad_1.0.tar.gz
+
+Package: pkg-md5-disagree
+Binary: pkg-md5-disagree
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ d41d8cd98f00b204e9800998ecf8427e 0 pkg-md5-disagree_1.0.dsc
+ d41d8cd98f00b204e9800998ecf8427e 0 pkg-md5-disagree_1.0.tar.gz
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 0 pkg-md5-disagree_1.0.dsc
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 pkg-md5-disagree_1.0.tar.gz
+
+Package: pkg-md5-agree
+Binary: pkg-md5-agree
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ d41d8cd98f00b204e9800998ecf8427e 0 pkg-md5-agree_1.0.dsc
+ d41d8cd98f00b204e9800998ecf8427e 0 pkg-md5-agree_1.0.tar.gz
+ d41d8cd98f00b204e9800998ecf8427e 0 pkg-md5-agree_1.0.tar.gz
+ d41d8cd98f00b204e9800998ecf8427e 0 pkg-md5-agree_1.0.dsc
+
+Package: pkg-sha256-disagree
+Binary: pkg-sha256-disagree
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ d41d8cd98f00b204e9800998ecf8427e 0 pkg-sha256-disagree_1.0.dsc
+ d41d8cd98f00b204e9800998ecf8427e 0 pkg-sha256-disagree_1.0.tar.gz
+Checksums-Sha1:
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-sha256-disagree_1.0.dsc
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-sha256-disagree_1.0.tar.gz
+Checksums-Sha256:
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 pkg-sha256-disagree_1.0.dsc
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 pkg-sha256-disagree_1.0.tar.gz
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 0 pkg-sha256-disagree_1.0.dsc
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 pkg-sha256-disagree_1.0.tar.gz
+EOF
+
+# create fetchable files
+for x in 'pkg-md5-ok' 'pkg-sha256-ok' 'pkg-sha256-bad' 'pkg-no-md5' \
+ 'pkg-mixed-ok' 'pkg-mixed-sha1-bad' 'pkg-mixed-sha2-bad' \
+ 'pkg-md5-agree' 'pkg-md5-disagree' 'pkg-sha256-disagree'; do
+ touch aptarchive/${x}_1.0.dsc aptarchive/${x}_1.0.tar.gz
+done
+
+setupaptarchive
+changetowebserver
+testsuccess aptget update
+
+testok() {
+ rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+ testequal "Reading package lists...
+Building dependency tree...
+Need to get 0 B of source archives.
+Get:1 http://localhost:8080/ $1 1.0 (dsc)
+Get:2 http://localhost:8080/ $1 1.0 (tar)
+Download complete and in download only mode" aptget source -d "$@"
+ msgtest 'Files were successfully downloaded for' "$1"
+ testsuccess --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz
+ rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+}
+
+testkeep() {
+ touch ${1}_1.0.dsc ${1}_1.0.tar.gz
+ testequal "Reading package lists...
+Building dependency tree...
+Skipping already downloaded file '${1}_1.0.dsc'
+Skipping already downloaded file '${1}_1.0.tar.gz'
+Need to get 0 B of source archives.
+Download complete and in download only mode" aptget source -d "$@"
+ msgtest 'Files already downloaded are kept for' "$1"
+ testsuccess --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz
+ rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+}
+
+testmismatch() {
+ rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+ testequal "Reading package lists...
+Building dependency tree...
+Need to get 0 B of source archives.
+Get:1 http://localhost:8080/ $1 1.0 (dsc)
+Get:2 http://localhost:8080/ $1 1.0 (tar)
+E: Failed to fetch http://localhost:8080/${1}_1.0.dsc Hash Sum mismatch
+
+E: Failed to fetch http://localhost:8080/${1}_1.0.tar.gz Hash Sum mismatch
+
+E: Failed to fetch some archives." aptget source -d "$@"
+ msgtest 'Files were not download as they have hashsum mismatches for' "$1"
+ testfailure --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz
+
+ rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+ testequal "Reading package lists...
+Building dependency tree...
+Skipping download of file 'pkg-sha256-bad_1.0.dsc' as requested hashsum is not available for authentication
+Skipping download of file 'pkg-sha256-bad_1.0.tar.gz' as requested hashsum is not available for authentication
+Need to get 0 B of source archives.
+Download complete and in download only mode" aptget source -d "$@" -o Acquire::ForceHash=ROT26
+ msgtest 'Files were not download as hash is unavailable for' "$1"
+ testfailure --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz
+
+ rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+ testequal "Reading package lists...
+Building dependency tree...
+Need to get 0 B of source archives.
+Get:1 http://localhost:8080/ $1 1.0 (dsc)
+Get:2 http://localhost:8080/ $1 1.0 (tar)
+Download complete and in download only mode" aptget source --allow-unauthenticated -d "$@" -o Acquire::ForceHash=ROT26
+ msgtest 'Files were downloaded unauthenticated as user allowed it' "$1"
+ testsuccess --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz
+}
+
+testok pkg-md5-ok
+testkeep pkg-md5-ok
+testok pkg-sha256-ok
+testkeep pkg-sha256-ok
+
+# pkg-sha256-bad has a bad SHA sum, but good MD5 sum. If apt is
+# checking the best available hash (as it should), this will trigger
+# a hash mismatch.
+testmismatch pkg-sha256-bad
+testmismatch pkg-sha256-bad
+testok pkg-sha256-bad -o Acquire::ForceHash=MD5Sum
+
+# not having MD5 sum doesn't mean the file doesn't exist at all …
+testok pkg-no-md5
+testok pkg-no-md5 -o Acquire::ForceHash=SHA256
+testequal "Reading package lists...
+Building dependency tree...
+Skipping download of file 'pkg-no-md5_1.0.dsc' as requested hashsum is not available for authentication
+Skipping download of file 'pkg-no-md5_1.0.tar.gz' as requested hashsum is not available for authentication
+Need to get 0 B of source archives.
+Download complete and in download only mode" aptget source -d pkg-no-md5 -o Acquire::ForceHash=MD5Sum
+msgtest 'Files were not download as MD5 is not available for this package' 'pkg-no-md5'
+testfailure --nomsg test -e pkg-no-md5_1.0.dsc -a -e pkg-no-md5_1.0.tar.gz
+
+# deal with cases in which we haven't for all files the same checksum type
+# mostly pathologic as this shouldn't happen, but just to be sure
+testok pkg-mixed-ok
+testequal 'Reading package lists...
+Building dependency tree...
+Need to get 0 B of source archives.
+Get:1 http://localhost:8080/ pkg-mixed-sha1-bad 1.0 (tar)
+Get:2 http://localhost:8080/ pkg-mixed-sha1-bad 1.0 (dsc)
+E: Failed to fetch http://localhost:8080/pkg-mixed-sha1-bad_1.0.dsc Hash Sum mismatch
+
+E: Failed to fetch some archives.' aptget source -d pkg-mixed-sha1-bad
+msgtest 'Only tar file is downloaded as the dsc has hashsum mismatch' 'pkg-mixed-sha1-bad'
+testsuccess --nomsg test ! -e pkg-mixed-sha1-bad_1.0.dsc -a -e pkg-mixed-sha1-bad_1.0.tar.gz
+testequal 'Reading package lists...
+Building dependency tree...
+Need to get 0 B of source archives.
+Get:1 http://localhost:8080/ pkg-mixed-sha2-bad 1.0 (tar)
+Get:2 http://localhost:8080/ pkg-mixed-sha2-bad 1.0 (dsc)
+E: Failed to fetch http://localhost:8080/pkg-mixed-sha2-bad_1.0.tar.gz Hash Sum mismatch
+
+E: Failed to fetch some archives.' aptget source -d pkg-mixed-sha2-bad
+msgtest 'Only dsc file is downloaded as the tar has hashsum mismatch' 'pkg-mixed-sha2-bad'
+testsuccess --nomsg test -e pkg-mixed-sha2-bad_1.0.dsc -a ! -e pkg-mixed-sha2-bad_1.0.tar.gz
+
+# it gets even more pathologic: multiple entries for one file, some even disagreeing!
+testok pkg-md5-agree
+testequal 'Reading package lists...
+Building dependency tree...
+E: Error parsing checksum in Files of source package pkg-md5-disagree' aptget source -d pkg-md5-disagree
+testequal 'Reading package lists...
+Building dependency tree...
+E: Error parsing checksum in Checksums-SHA256 of source package pkg-sha256-disagree' aptget source -d pkg-sha256-disagree
diff --git a/test/interactive-helper/aptwebserver.cc b/test/interactive-helper/aptwebserver.cc
index 34476e1af..cd52da692 100644
--- a/test/interactive-helper/aptwebserver.cc
+++ b/test/interactive-helper/aptwebserver.cc
@@ -19,6 +19,8 @@
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
+
+#include <algorithm>
#include <iostream>
#include <sstream>
#include <list>
@@ -79,12 +81,21 @@ static char const * httpcodeToStr(int const httpcode) /*{{{*/
return NULL;
}
/*}}}*/
+static bool chunkedTransferEncoding(std::list<std::string> const &headers) {
+ if (std::find(headers.begin(), headers.end(), "Transfer-Encoding: chunked") != headers.end())
+ return true;
+ if (_config->FindB("aptwebserver::chunked-transfer-encoding", false) == true)
+ return true;
+ return false;
+}
static void addFileHeaders(std::list<std::string> &headers, FileFd &data)/*{{{*/
{
- std::ostringstream contentlength;
- contentlength << "Content-Length: " << data.FileSize();
- headers.push_back(contentlength.str());
-
+ if (chunkedTransferEncoding(headers) == false)
+ {
+ std::ostringstream contentlength;
+ contentlength << "Content-Length: " << data.FileSize();
+ headers.push_back(contentlength.str());
+ }
std::string lastmodified("Last-Modified: ");
lastmodified.append(TimeRFC1123(data.ModificationTime()));
headers.push_back(lastmodified);
@@ -92,9 +103,12 @@ static void addFileHeaders(std::list<std::string> &headers, FileFd &data)/*{{{*/
/*}}}*/
static void addDataHeaders(std::list<std::string> &headers, std::string &data)/*{{{*/
{
- std::ostringstream contentlength;
- contentlength << "Content-Length: " << data.size();
- headers.push_back(contentlength.str());
+ if (chunkedTransferEncoding(headers) == false)
+ {
+ std::ostringstream contentlength;
+ contentlength << "Content-Length: " << data.size();
+ headers.push_back(contentlength.str());
+ }
}
/*}}}*/
static bool sendHead(int const client, int const httpcode, std::list<std::string> &headers)/*{{{*/
@@ -114,6 +128,9 @@ static bool sendHead(int const client, int const httpcode, std::list<std::string
date.append(TimeRFC1123(time(NULL)));
headers.push_back(date);
+ if (chunkedTransferEncoding(headers) == true)
+ headers.push_back("Transfer-Encoding: chunked");
+
std::clog << ">>> RESPONSE to " << client << " >>>" << std::endl;
bool Success = true;
for (std::list<std::string>::const_iterator h = headers.begin();
@@ -130,25 +147,55 @@ static bool sendHead(int const client, int const httpcode, std::list<std::string
return Success;
}
/*}}}*/
-static bool sendFile(int const client, FileFd &data) /*{{{*/
+static bool sendFile(int const client, std::list<std::string> const &headers, FileFd &data)/*{{{*/
{
bool Success = true;
+ bool const chunked = chunkedTransferEncoding(headers);
char buffer[500];
unsigned long long actual = 0;
while ((Success &= data.Read(buffer, sizeof(buffer), &actual)) == true)
{
if (actual == 0)
break;
- Success &= FileFd::Write(client, buffer, actual);
+
+ if (chunked == true)
+ {
+ std::string size;
+ strprintf(size, "%llX\r\n", actual);
+ Success &= FileFd::Write(client, size.c_str(), size.size());
+ Success &= FileFd::Write(client, buffer, actual);
+ Success &= FileFd::Write(client, "\r\n", strlen("\r\n"));
+ }
+ else
+ Success &= FileFd::Write(client, buffer, actual);
+ }
+ if (chunked == true)
+ {
+ char const * const finish = "0\r\n\r\n";
+ Success &= FileFd::Write(client, finish, strlen(finish));
}
if (Success == false)
- std::cerr << "SENDFILE: READ/WRITE ERROR to " << client << std::endl;
+ std::cerr << "SENDFILE:" << (chunked ? " CHUNKED" : "") << " READ/WRITE ERROR to " << client << std::endl;
return Success;
}
/*}}}*/
-static bool sendData(int const client, std::string const &data) /*{{{*/
+static bool sendData(int const client, std::list<std::string> const &headers, std::string const &data)/*{{{*/
{
- if (FileFd::Write(client, data.c_str(), data.size()) == false)
+ if (chunkedTransferEncoding(headers) == true)
+ {
+ unsigned long long const ullsize = data.length();
+ std::string size;
+ strprintf(size, "%llX\r\n", ullsize);
+ char const * const finish = "\r\n0\r\n\r\n";
+ if (FileFd::Write(client, size.c_str(), size.length()) == false ||
+ FileFd::Write(client, data.c_str(), ullsize) == false ||
+ FileFd::Write(client, finish, strlen(finish)) == false)
+ {
+ std::cerr << "SENDDATA: CHUNK WRITE ERROR to " << client << std::endl;
+ return false;
+ }
+ }
+ else if (FileFd::Write(client, data.c_str(), data.size()) == false)
{
std::cerr << "SENDDATA: WRITE ERROR to " << client << std::endl;
return false;
@@ -157,34 +204,38 @@ static bool sendData(int const client, std::string const &data) /*{{{*/
}
/*}}}*/
static void sendError(int const client, int const httpcode, std::string const &request,/*{{{*/
- bool content, std::string const &error = "")
+ bool const content, std::string const &error, std::list<std::string> &headers)
{
- std::list<std::string> headers;
std::string response("<html><head><title>");
response.append(httpcodeToStr(httpcode)).append("</title></head>");
response.append("<body><h1>").append(httpcodeToStr(httpcode)).append("</h1>");
if (httpcode != 200)
- {
- if (error.empty() == false)
- response.append("<p><em>Error</em>: ").append(error).append("</p>");
- response.append("This error is a result of the request: <pre>");
- }
+ response.append("<p><em>Error</em>: ");
+ else
+ response.append("<p><em>Success</em>: ");
+ if (error.empty() == false)
+ response.append(error);
+ else
+ response.append(httpcodeToStr(httpcode));
+ if (httpcode != 200)
+ response.append("</p>This error is a result of the request: <pre>");
else
- {
- if (error.empty() == false)
- response.append("<p><em>Success</em>: ").append(error).append("</p>");
response.append("The successfully executed operation was requested by: <pre>");
- }
response.append(request).append("</pre></body></html>");
+ if (httpcode != 200)
+ {
+ if (_config->FindB("aptwebserver::closeOnError", false) == true)
+ headers.push_back("Connection: close");
+ }
addDataHeaders(headers, response);
sendHead(client, httpcode, headers);
if (content == true)
- sendData(client, response);
+ sendData(client, headers, response);
}
static void sendSuccess(int const client, std::string const &request,
- bool content, std::string const &error = "")
+ bool const content, std::string const &error, std::list<std::string> &headers)
{
- sendError(client, 200, request, content, error);
+ sendError(client, 200, request, content, error, headers);
}
/*}}}*/
static void sendRedirect(int const client, int const httpcode, std::string const &uri,/*{{{*/
@@ -221,7 +272,7 @@ static void sendRedirect(int const client, int const httpcode, std::string const
headers.push_back(location);
sendHead(client, httpcode, headers);
if (content == true)
- sendData(client, response);
+ sendData(client, headers, response);
}
/*}}}*/
static int filter_hidden_files(const struct dirent *a) /*{{{*/
@@ -263,16 +314,15 @@ static int grouped_alpha_case_sort(const struct dirent **a, const struct dirent
}
/*}}}*/
static void sendDirectoryListing(int const client, std::string const &dir,/*{{{*/
- std::string const &request, bool content)
+ std::string const &request, bool content, std::list<std::string> &headers)
{
- std::list<std::string> headers;
std::ostringstream listing;
struct dirent **namelist;
int const counter = scandir(dir.c_str(), &namelist, filter_hidden_files, grouped_alpha_case_sort);
if (counter == -1)
{
- sendError(client, 500, request, content);
+ sendError(client, 500, request, content, "scandir failed", headers);
return;
}
@@ -311,18 +361,18 @@ static void sendDirectoryListing(int const client, std::string const &dir,/*{{{*
addDataHeaders(headers, response);
sendHead(client, 200, headers);
if (content == true)
- sendData(client, response);
+ sendData(client, headers, response);
}
/*}}}*/
static bool parseFirstLine(int const client, std::string const &request,/*{{{*/
std::string &filename, std::string &params, bool &sendContent,
- bool &closeConnection)
+ bool &closeConnection, std::list<std::string> &headers)
{
if (strncmp(request.c_str(), "HEAD ", 5) == 0)
sendContent = false;
if (strncmp(request.c_str(), "GET ", 4) != 0)
{
- sendError(client, 501, request, true);
+ sendError(client, 501, request, true, "", headers);
return false;
}
@@ -333,7 +383,7 @@ static bool parseFirstLine(int const client, std::string const &request,/*{{{*/
if (lineend == std::string::npos || filestart == std::string::npos ||
fileend == std::string::npos || filestart == fileend)
{
- sendError(client, 500, request, sendContent, "Filename can't be extracted");
+ sendError(client, 500, request, sendContent, "Filename can't be extracted", headers);
return false;
}
@@ -345,14 +395,14 @@ static bool parseFirstLine(int const client, std::string const &request,/*{{{*/
closeConnection = strcasecmp(LookupTag(request, "Connection", "Keep-Alive").c_str(), "close") == 0;
else
{
- sendError(client, 500, request, sendContent, "Not a HTTP/1.{0,1} request");
+ sendError(client, 500, request, sendContent, "Not a HTTP/1.{0,1} request", headers);
return false;
}
filename = request.substr(filestart, fileend - filestart);
if (filename.find(' ') != std::string::npos)
{
- sendError(client, 500, request, sendContent, "Filename contains an unencoded space");
+ sendError(client, 500, request, sendContent, "Filename contains an unencoded space", headers);
return false;
}
@@ -360,7 +410,7 @@ static bool parseFirstLine(int const client, std::string const &request,/*{{{*/
if (host.empty() == true)
{
// RFC 2616 §14.23 requires Host
- sendError(client, 400, request, sendContent, "Host header is required");
+ sendError(client, 400, request, sendContent, "Host header is required", headers);
return false;
}
host = "http://" + host;
@@ -371,7 +421,7 @@ static bool parseFirstLine(int const client, std::string const &request,/*{{{*/
{
if (absolute.find("uri") == std::string::npos)
{
- sendError(client, 400, request, sendContent, "Request is absoluteURI, but configured to not accept that");
+ sendError(client, 400, request, sendContent, "Request is absoluteURI, but configured to not accept that", headers);
return false;
}
// strip the host from the request to make it an absolute path
@@ -379,7 +429,7 @@ static bool parseFirstLine(int const client, std::string const &request,/*{{{*/
}
else if (absolute.find("path") == std::string::npos)
{
- sendError(client, 400, request, sendContent, "Request is absolutePath, but configured to not accept that");
+ sendError(client, 400, request, sendContent, "Request is absolutePath, but configured to not accept that", headers);
return false;
}
@@ -398,7 +448,8 @@ static bool parseFirstLine(int const client, std::string const &request,/*{{{*/
filename.find_first_of("\r\n\t\f\v") != std::string::npos ||
filename.find("/../") != std::string::npos)
{
- sendError(client, 400, request, sendContent, "Filename contains illegal character (sequence)");
+ std::list<std::string> headers;
+ sendError(client, 400, request, sendContent, "Filename contains illegal character (sequence)", headers);
return false;
}
@@ -434,46 +485,45 @@ static bool parseFirstLine(int const client, std::string const &request,/*{{{*/
return true;
}
/*}}}*/
-static bool handleOnTheFlyReconfiguration(int const client, std::string const &request, std::vector<std::string> const &parts)/*{{{*/
+static bool handleOnTheFlyReconfiguration(int const client, std::string const &request,/*{{{*/
+ std::vector<std::string> parts, std::list<std::string> &headers)
{
size_t const pcount = parts.size();
if (pcount == 4 && parts[1] == "set")
{
_config->Set(parts[2], parts[3]);
- sendSuccess(client, request, true, "Option '" + parts[2] + "' was set to '" + parts[3] + "'!");
+ sendSuccess(client, request, true, "Option '" + parts[2] + "' was set to '" + parts[3] + "'!", headers);
return true;
}
else if (pcount == 4 && parts[1] == "find")
{
- std::list<std::string> headers;
std::string response = _config->Find(parts[2], parts[3]);
addDataHeaders(headers, response);
sendHead(client, 200, headers);
- sendData(client, response);
+ sendData(client, headers, response);
return true;
}
else if (pcount == 3 && parts[1] == "find")
{
- std::list<std::string> headers;
if (_config->Exists(parts[2]) == true)
{
std::string response = _config->Find(parts[2]);
addDataHeaders(headers, response);
sendHead(client, 200, headers);
- sendData(client, response);
+ sendData(client, headers, response);
return true;
}
- sendError(client, 404, request, "Requested Configuration option doesn't exist.");
+ sendError(client, 404, request, true, "Requested Configuration option doesn't exist", headers);
return false;
}
else if (pcount == 3 && parts[1] == "clear")
{
_config->Clear(parts[2]);
- sendSuccess(client, request, true, "Option '" + parts[2] + "' was cleared.");
+ sendSuccess(client, request, true, "Option '" + parts[2] + "' was cleared.", headers);
return true;
}
- sendError(client, 400, request, true, "Unknown on-the-fly configuration request");
+ sendError(client, 400, request, true, "Unknown on-the-fly configuration request", headers);
return false;
}
/*}}}*/
@@ -482,18 +532,22 @@ static void * handleClient(void * voidclient) /*{{{*/
int client = *((int*)(voidclient));
std::clog << "ACCEPT client " << client << std::endl;
std::vector<std::string> messages;
- while (ReadMessages(client, messages))
+ bool closeConnection = false;
+ std::list<std::string> headers;
+ while (closeConnection == false && ReadMessages(client, messages))
{
- bool closeConnection = false;
+ // if we announced a closing, do the close
+ if (std::find(headers.begin(), headers.end(), std::string("Connection: close")) != headers.end())
+ break;
+ headers.clear();
for (std::vector<std::string>::const_iterator m = messages.begin();
m != messages.end() && closeConnection == false; ++m) {
std::clog << ">>> REQUEST from " << client << " >>>" << std::endl << *m
<< std::endl << "<<<<<<<<<<<<<<<<" << std::endl;
- std::list<std::string> headers;
std::string filename;
std::string params;
bool sendContent = true;
- if (parseFirstLine(client, *m, filename, params, sendContent, closeConnection) == false)
+ if (parseFirstLine(client, *m, filename, params, sendContent, closeConnection, headers) == false)
continue;
// special webserver command request
@@ -502,7 +556,7 @@ static void * handleClient(void * voidclient) /*{{{*/
std::vector<std::string> parts = VectorizeString(filename, '/');
if (parts[0] == "_config")
{
- handleOnTheFlyReconfiguration(client, *m, parts);
+ handleOnTheFlyReconfiguration(client, *m, parts, headers);
continue;
}
}
@@ -534,7 +588,7 @@ static void * handleClient(void * voidclient) /*{{{*/
{
char error[300];
regerror(res, pattern, error, sizeof(error));
- sendError(client, 500, *m, sendContent, error);
+ sendError(client, 500, *m, sendContent, error, headers);
continue;
}
if (regexec(pattern, filename.c_str(), 0, 0, 0) == 0)
@@ -553,7 +607,7 @@ static void * handleClient(void * voidclient) /*{{{*/
if (_config->FindB("aptwebserver::support::http", true) == false &&
LookupTag(*m, "Host").find(":4433") == std::string::npos)
{
- sendError(client, 400, *m, sendContent, "HTTP disabled, all requests must be HTTPS");
+ sendError(client, 400, *m, sendContent, "HTTP disabled, all requests must be HTTPS", headers);
continue;
}
else if (RealFileExists(filename) == true)
@@ -609,17 +663,16 @@ static void * handleClient(void * voidclient) /*{{{*/
headers.push_back(contentrange.str());
sendHead(client, 206, headers);
if (sendContent == true)
- sendFile(client, data);
+ sendFile(client, headers, data);
continue;
}
else
{
- headers.push_back("Content-Length: 0");
std::ostringstream contentrange;
contentrange << "Content-Range: bytes */" << filesize;
headers.push_back(contentrange.str());
- sendHead(client, 416, headers);
- continue;
+ sendError(client, 416, *m, sendContent, "", headers);
+ break;
}
}
}
@@ -628,22 +681,20 @@ static void * handleClient(void * voidclient) /*{{{*/
addFileHeaders(headers, data);
sendHead(client, 200, headers);
if (sendContent == true)
- sendFile(client, data);
+ sendFile(client, headers, data);
}
else if (DirectoryExists(filename) == true)
{
if (filename[filename.length()-1] == '/')
- sendDirectoryListing(client, filename, *m, sendContent);
+ sendDirectoryListing(client, filename, *m, sendContent, headers);
else
sendRedirect(client, 301, filename.append("/"), *m, sendContent);
}
else
- sendError(client, 404, *m, sendContent);
+ sendError(client, 404, *m, sendContent, "", headers);
}
_error->DumpErrors(std::cerr);
messages.clear();
- if (closeConnection == true)
- break;
}
close(client);
std::clog << "CLOSE client " << client << std::endl;
diff --git a/test/libapt/commandline_test.cc b/test/libapt/commandline_test.cc
index e403a28c8..627f1b486 100644
--- a/test/libapt/commandline_test.cc
+++ b/test/libapt/commandline_test.cc
@@ -2,6 +2,7 @@
#include <apt-pkg/cmndline.h>
#include <apt-pkg/configuration.h>
+#include <apt-private/private-cmndline.h>
#include <gtest/gtest.h>
@@ -85,3 +86,70 @@ TEST(CommandLineTest, BoolParsing)
}
}
+
+bool DoVoid(CommandLine &) { return false; }
+
+TEST(CommandLineTest,GetCommand)
+{
+ CommandLine::Dispatch Cmds[] = { {"install",&DoVoid}, {"remove", &DoVoid}, {0,0} };
+ {
+ char const * argv[] = { "apt-get", "-t", "unstable", "remove", "-d", "foo" };
+ char const * com = CommandLine::GetCommand(Cmds, sizeof(argv)/sizeof(argv[0]), argv);
+ EXPECT_STREQ("remove", com);
+ std::vector<CommandLine::Args> Args = getCommandArgs("apt-get", com);
+ ::Configuration c;
+ CommandLine CmdL(Args.data(), &c);
+ ASSERT_TRUE(CmdL.Parse(sizeof(argv)/sizeof(argv[0]), argv));
+ EXPECT_EQ(c.Find("APT::Default-Release"), "unstable");
+ EXPECT_TRUE(c.FindB("APT::Get::Download-Only"));
+ ASSERT_EQ(2, CmdL.FileSize());
+ EXPECT_EQ(std::string(CmdL.FileList[0]), "remove");
+ EXPECT_EQ(std::string(CmdL.FileList[1]), "foo");
+ }
+ {
+ char const * argv[] = {"apt-get", "-t", "unstable", "remove", "--", "-d", "foo" };
+ char const * com = CommandLine::GetCommand(Cmds, sizeof(argv)/sizeof(argv[0]), argv);
+ EXPECT_STREQ("remove", com);
+ std::vector<CommandLine::Args> Args = getCommandArgs("apt-get", com);
+ ::Configuration c;
+ CommandLine CmdL(Args.data(), &c);
+ ASSERT_TRUE(CmdL.Parse(sizeof(argv)/sizeof(argv[0]), argv));
+ EXPECT_EQ(c.Find("APT::Default-Release"), "unstable");
+ EXPECT_FALSE(c.FindB("APT::Get::Download-Only"));
+ ASSERT_EQ(3, CmdL.FileSize());
+ EXPECT_EQ(std::string(CmdL.FileList[0]), "remove");
+ EXPECT_EQ(std::string(CmdL.FileList[1]), "-d");
+ EXPECT_EQ(std::string(CmdL.FileList[2]), "foo");
+ }
+ {
+ char const * argv[] = {"apt-get", "-t", "unstable", "--", "remove", "-d", "foo" };
+ char const * com = CommandLine::GetCommand(Cmds, sizeof(argv)/sizeof(argv[0]), argv);
+ EXPECT_STREQ("remove", com);
+ std::vector<CommandLine::Args> Args = getCommandArgs("apt-get", com);
+ ::Configuration c;
+ CommandLine CmdL(Args.data(), &c);
+ ASSERT_TRUE(CmdL.Parse(sizeof(argv)/sizeof(argv[0]), argv));
+ EXPECT_EQ(c.Find("APT::Default-Release"), "unstable");
+ EXPECT_FALSE(c.FindB("APT::Get::Download-Only"));
+ ASSERT_EQ(CmdL.FileSize(), 3);
+ EXPECT_EQ(std::string(CmdL.FileList[0]), "remove");
+ EXPECT_EQ(std::string(CmdL.FileList[1]), "-d");
+ EXPECT_EQ(std::string(CmdL.FileList[2]), "foo");
+ }
+ {
+ char const * argv[] = {"apt-get", "install", "-t", "unstable", "--", "remove", "-d", "foo" };
+ char const * com = CommandLine::GetCommand(Cmds, sizeof(argv)/sizeof(argv[0]), argv);
+ EXPECT_STREQ("install", com);
+ std::vector<CommandLine::Args> Args = getCommandArgs("apt-get", com);
+ ::Configuration c;
+ CommandLine CmdL(Args.data(), &c);
+ ASSERT_TRUE(CmdL.Parse(sizeof(argv)/sizeof(argv[0]), argv));
+ EXPECT_EQ(c.Find("APT::Default-Release"), "unstable");
+ EXPECT_FALSE(c.FindB("APT::Get::Download-Only"));
+ ASSERT_EQ(CmdL.FileSize(), 4);
+ EXPECT_EQ(std::string(CmdL.FileList[0]), "install");
+ EXPECT_EQ(std::string(CmdL.FileList[1]), "remove");
+ EXPECT_EQ(std::string(CmdL.FileList[2]), "-d");
+ EXPECT_EQ(std::string(CmdL.FileList[3]), "foo");
+ }
+}
diff --git a/test/libapt/hashsums_test.cc b/test/libapt/hashsums_test.cc
index c06d85e03..ac7d41582 100644
--- a/test/libapt/hashsums_test.cc
+++ b/test/libapt/hashsums_test.cc
@@ -207,16 +207,56 @@ TEST(HashSumsTest, FileBased)
}
fd.Close();
- {
- HashString sha2("SHA256", sha256.Value());
- EXPECT_TRUE(sha2.VerifyFile(__FILE__));
- }
- {
- HashString sha2("SHA512", sha512.Value());
- EXPECT_TRUE(sha2.VerifyFile(__FILE__));
- }
- {
- HashString sha2("SHA256:" + sha256.Value());
- EXPECT_TRUE(sha2.VerifyFile(__FILE__));
- }
+ HashString sha2file("SHA512", sha512.Value());
+ EXPECT_TRUE(sha2file.VerifyFile(__FILE__));
+ HashString sha2wrong("SHA512", "00000000000");
+ EXPECT_FALSE(sha2wrong.VerifyFile(__FILE__));
+ EXPECT_EQ(sha2file, sha2file);
+ EXPECT_TRUE(sha2file == sha2file);
+ EXPECT_NE(sha2file, sha2wrong);
+ EXPECT_TRUE(sha2file != sha2wrong);
+
+ HashString sha2big("SHA256", sha256.Value());
+ EXPECT_TRUE(sha2big.VerifyFile(__FILE__));
+ HashString sha2small("sha256:" + sha256.Value());
+ EXPECT_TRUE(sha2small.VerifyFile(__FILE__));
+ EXPECT_EQ(sha2big, sha2small);
+ EXPECT_TRUE(sha2big == sha2small);
+ EXPECT_FALSE(sha2big != sha2small);
+
+ HashStringList hashes;
+ EXPECT_TRUE(hashes.empty());
+ EXPECT_TRUE(hashes.push_back(sha2file));
+ EXPECT_FALSE(hashes.empty());
+ EXPECT_EQ(1, hashes.size());
+
+ HashStringList wrong;
+ EXPECT_TRUE(wrong.push_back(sha2wrong));
+ EXPECT_NE(wrong, hashes);
+ EXPECT_FALSE(wrong == hashes);
+ EXPECT_TRUE(wrong != hashes);
+
+ HashStringList similar;
+ EXPECT_TRUE(similar.push_back(sha2big));
+ EXPECT_NE(similar, hashes);
+ EXPECT_FALSE(similar == hashes);
+ EXPECT_TRUE(similar != hashes);
+
+ EXPECT_TRUE(hashes.push_back(sha2big));
+ EXPECT_EQ(2, hashes.size());
+ EXPECT_TRUE(hashes.push_back(sha2small));
+ EXPECT_EQ(2, hashes.size());
+ EXPECT_FALSE(hashes.push_back(sha2wrong));
+ EXPECT_EQ(2, hashes.size());
+ EXPECT_TRUE(hashes.VerifyFile(__FILE__));
+
+ EXPECT_EQ(similar, hashes);
+ EXPECT_TRUE(similar == hashes);
+ EXPECT_FALSE(similar != hashes);
+ similar.clear();
+ EXPECT_TRUE(similar.empty());
+ EXPECT_EQ(0, similar.size());
+ EXPECT_NE(similar, hashes);
+ EXPECT_FALSE(similar == hashes);
+ EXPECT_TRUE(similar != hashes);
}
diff --git a/test/libapt/makefile b/test/libapt/makefile
index 69a13fd92..7f23ace46 100644
--- a/test/libapt/makefile
+++ b/test/libapt/makefile
@@ -14,8 +14,8 @@ test: $(BIN)/gtest$(BASENAME)
$(BIN)/gtest$(BASENAME): $(LIB)/gtest.a
PROGRAM = gtest${BASENAME}
-SLIBS = -lapt-pkg -pthread $(LIB)/gtest.a
-LIB_MAKES = apt-pkg/makefile
+SLIBS = -lapt-pkg -lapt-private -pthread $(LIB)/gtest.a
+LIB_MAKES = apt-pkg/makefile apt-private/makefile
SOURCE = gtest_runner.cc $(wildcard *-helpers.cc *_test.cc)
include $(PROGRAM_H)