diff options
Diffstat (limited to 'test')
23 files changed, 956 insertions, 112 deletions
diff --git a/test/integration/Packages-bug-723705-tagfile-truncates-fields b/test/integration/Packages-bug-723705-tagfile-truncates-fields new file mode 100644 index 000000000..c42b85072 --- /dev/null +++ b/test/integration/Packages-bug-723705-tagfile-truncates-fields @@ -0,0 +1,167 @@ +Package: cdebconf-gtk-udeb +Source: cdebconf +Version: 0.185 +Installed-Size: 92 +Maintainer: Debian Install System Team <debian-boot@lists.debian.org> +Architecture: amd64 +Description: Gtk+ frontend for Debian Configuration Management System +Description-md5: 75d036e0a245499123544e2254b92e9c +Section: debian-installer +Priority: optional +Filename: pool/main/c/cdebconf/cdebconf-gtk-udeb_0.185_amd64.udeb +Size: 27278 +MD5sum: a1bbbc1d4fb8e0615b5621abac021924 +SHA1: b1a7ab55a90f61e5337847d02ff1d12d73559def +SHA256: cd79f3205304a7932b3309c4df9898c9a53929bc651912659858e087ebe1c18a + +Package: cdebconf-newt-udeb +Source: cdebconf +Version: 0.185 +Installed-Size: 58 +Maintainer: Debian Install System Team <debian-boot@lists.debian.org> +Architecture: amd64 +Description: Newt frontend for Debian Configuration Management System +Description-md5: e080be5e38cb8c57bca2f3effe9ee030 +Section: debian-installer +Priority: optional +Filename: pool/main/c/cdebconf/cdebconf-newt-udeb_0.185_amd64.udeb +Size: 19192 +MD5sum: de27807f56dae2f2403b3322d5fe6bd2 +SHA1: 57883e223d46a9f25966f9b986e6a3bc2f67d8ef +SHA256: 5f8b9c3a5430f2ec879484a7736582b152d76cc8ba9bc19328268f3635759a1b + +Package: cdebconf-udeb +Source: cdebconf +Version: 0.185 +Installed-Size: 245 +Maintainer: Debian Install System Team <debian-boot@lists.debian.org> +Architecture: amd64 +Provides: debconf-2.0 +Description: Debian Configuration Management System (C-implementation) +Description-md5: 9f3579e9d9f86ac89e667a8707d3cbd3 +Section: debian-installer +Priority: standard +Filename: pool/main/c/cdebconf/cdebconf-udeb_0.185_amd64.udeb +Size: 77376 +MD5sum: e3883706fdbf54c2e5ea959c92b2d37f +SHA1: 0232f1bdf1531db628516ed3a46a27466b267fdc +SHA256: 96345575417a3e4df8a2cadaa55784ec8f6c042defb1e2fc002d941b6116ceab + +Package: cdebconf-gtk-terminal +Source: cdebconf-terminal +Version: 0.22 +Installed-Size: 64 +Maintainer: Debian Install System Team <debian-boot@lists.debian.org> +Architecture: amd64 +Provides: cdebconf-terminal +Depends: cdebconf-gtk-udeb, libc6-udeb (>= 2.17), libglib2.0-udeb (>= 2.36.4), libgtk2.0-0-udeb (>= 2.24.0), libvte9-udeb (>= 1:0.28.0), cdebconf-udeb, cdebconf-gtk-terminal, cdebconf-gtk-terminal, cdebconf-gtk-terminal, cdebconf-gtk-terminal, cdebconf-gtk-terminal, cdebconf-gtk-terminal, cdebconf-gtk-terminal +Description: cdebconf gtk plugin displaying a terminal +Description-md5: 18c4446758aec003eb8cd0a43419f1aa +Section: debian-installer +Priority: extra +Filename: pool/main/c/cdebconf-terminal/cdebconf-gtk-terminal_0.22_amd64.udeb +Size: 14734 +MD5sum: f9c3a7354560cb88e0396e2b7ba54363 +SHA1: 9c1c93328e758bfd9de2752466b271aaf38c8177 +SHA256: ca749853fc3b93db1d08ccdc6b46de27633de52bc5b880fa65275897ebcaaf69 + +Package: cdebconf-newt-terminal +Source: cdebconf-terminal +Version: 0.22 +Installed-Size: 43 +Maintainer: Debian Install System Team <debian-boot@lists.debian.org> +Architecture: amd64 +Provides: cdebconf-terminal +Depends: cdebconf-newt-udeb (>= 0.146), libc6-udeb (>= 2.17), libnewt0.52 +Description: cdebconf newt plugin to provide a clean terminal +Description-md5: 4109a053022081b573d864d84d6eb16d +Section: debian-installer +Priority: extra +Filename: pool/main/c/cdebconf-terminal/cdebconf-newt-terminal_0.22_amd64.udeb +Size: 4538 +MD5sum: 20db6152fce5081fcbf49c7c08f21246 +SHA1: fa2a40f777a2f48b9634866bc780fb059e60b2fe +SHA256: c4d99ef27285f0c9090005313165627e56e0972e687af7e68c2b1d1538e2ae09 + +Package: libc6-udeb +Source: eglibc (2.17-92) +Version: 2.17-92+b1 +Installed-Size: 3126 +Maintainer: GNU Libc Maintainers <debian-glibc@lists.debian.org> +Architecture: amd64 +Provides: glibc-2.17-1, libc-udeb, libc6 +Description: Embedded GNU C Library: Shared libraries - udeb +Description-md5: 9552ce73b7b3fb466e3d89fe8db9a563 +Section: debian-installer +Priority: extra +Filename: pool/main/e/eglibc/libc6-udeb_2.17-92+b1_amd64.udeb +Size: 1056000 +MD5sum: 7fd7032eeeecf7f76eff79a0543fbd72 +SHA1: 724b6a81b8fbc9d4d2bb43d656c08de73f7ada25 +SHA256: 137d4c001bbfde8161315c36e6cb8653ae2c50a8d6b6d2d27396c492d91a1723 + +Package: libglib2.0-udeb +Source: glib2.0 +Version: 2.36.4-1 +Installed-Size: 10070 +Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org> +Architecture: amd64 +Description: GLib library of C routines - minimal runtime +Description-md5: 0244040042870a89aa49f037cce3f1e9 +Section: debian-installer +Priority: optional +Filename: pool/main/g/glib2.0/libglib2.0-udeb_2.36.4-1_amd64.udeb +Size: 1714604 +MD5sum: 72da029f1bbb36057d874f1f82a5d00a +SHA1: 32bce78a052ef19a620f43ecbe12404fa570c0f1 +SHA256: 8edbc7cb872c0a82705913563f93f9eec5750881e4378c5a48770cde840cd6eb + +Package: libgtk2.0-0-udeb +Source: gtk+2.0 +Version: 2.24.20-1 +Installed-Size: 5035 +Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org> +Architecture: amd64 +Provides: gtk2.0-binver-2.10.0 +Description: GTK+ graphical user interface library - minimal runtime +Description-md5: 32e5112b80c02578837cff4f65dfec84 +Section: debian-installer +Priority: extra +Filename: pool/main/g/gtk+2.0/libgtk2.0-0-udeb_2.24.20-1_amd64.udeb +Size: 1643046 +MD5sum: 25513478eb2e02e5766c0eea0b411ca9 +SHA1: 9274f05bfa930a3406403441ce061bade04e2064 +SHA256: d5f611f48928ae02f759105cf8cff467cde1cb44df56ad31067168b46a80f8bc + +Package: libvte9-udeb +Source: vte +Version: 1:0.28.2-5 +Installed-Size: 628 +Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org> +Architecture: amd64 +Description: Terminal emulator widget for GTK+ 2.0 - minimal runtime +Description-md5: e7993385c30bae6e96c8cb87795a513c +Section: debian-installer +Priority: extra +Filename: pool/main/v/vte/libvte9-udeb_0.28.2-5_amd64.udeb +Size: 216968 +MD5sum: 7da7201effaf5ced19abd9d0b45aa2c6 +SHA1: a424cf779e7614d79740c422b6342de04fed3646 +SHA256: 4963033cbda5a8ba7eb8ebf1debae34463b8e63b821259860cfb51c1ab99562d + +Package: zlib1g-udeb +Source: zlib +Version: 1:1.2.8.dfsg-1 +Installed-Size: 115 +Maintainer: Mark Brown <broonie@debian.org> +Architecture: amd64 +Description: compression library - runtime for Debian installer +Description-md5: 9cab974e3eab657c53bc17611b894c7a +Section: debian-installer +Priority: optional +Filename: pool/main/z/zlib/zlib1g-udeb_1.2.8.dfsg-1_amd64.udeb +Size: 45270 +MD5sum: c02884420f79a3ae4569cf67782f3e74 +SHA1: 7cd1a7c8be4e086de733a0ce76f87d42b8b2173b +SHA256: 61641ee2b5e185232108333438b72bec71ef549fe0e0df1b2b3afa37174e53a7 + diff --git a/test/integration/apt.pem b/test/integration/apt.pem new file mode 100644 index 000000000..f48df054d --- /dev/null +++ b/test/integration/apt.pem @@ -0,0 +1,49 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCt4R1Q2oYF6utL +19GBhnlHW8L2BI7PRFWge/ZpqIZWsaFcb30FV86Z6aXXZmgfEJ2814ZZYD1IKeCe +JsJpns7B4vYe1v64r995ZNBQAAKIYjICkKZOBgOphV+ChBfrCctVXgfLbMP6iBdH +J02wHzSCCdZm0sdVl9tB5l/OyJU8Mb4KB3btBhfZfY2M6lU+FOjcXs1LOduUrv7K +fZ+DEalvVGkomLtHtD0qb2vkqFrTjVCkziUVWhhxFFflt08oQ01Clxpl+uv7rOQo +jtkJ1LrMuv7iPfaZ/z3qLiFxZYG1BCGEwTOKCtJo6bgFzXiN3q7Q5FFlmv851x2J +Dn8C7Qm7AgMBAAECggEAE3q6vAofJZ6Ryadd8zLLd3ESQFl2XkX7icUZb/DPS/sO +ZrqeuPCDVr7UM3NnisNjyHoktPKRKvp2DYGuGgMOiq4QgJf5ZVten8zpgWze28SU +cbEe0HLgCifE8Ww2+b/ZJbEpEmMW+YQxh2khzO9SBJdxi4dliXM/vvw+E35pKZsB +s6glrz6VQAxxa9fY4fLnB2DafHy+pUvRVw8gC6PCM9jXN9tMYAqztsJu7aaanNyT +HX2UDWa8hxVx6t5UQZuxvst9N+RcEwmVCR2qlfZt/VRBRibBm62crEKbTD00mNHQ +4AIDn3g6Y3SXpDlgtNpjLyBL3fODPIwqwGdblaSKkQKBgQDYXecu0Eda7kbR5ciW +IAn8XOxsBIkkh8YVl2gRiiajRVoeiYBHaW9TyuQiaWrftiDQxB/N4G2focTXy/7O +VJn6e/SUoO/ZGRw2GbTxLUQptgvFsejYCcW9XpC8MCwE/y2swiY7JM0WR8cV2nCk +a/Cls6f1LjL13aFO0PAorEcahQKBgQDNuth6EHZVwfDgUuqhRw4HIIpfsfiA3UOd +b5k/NsfQIev1YUqnfucgInNPDq2Jf8eTQw3TKaszo2DCjDffCsEgM09Tym143Bd6 +AsMuqAStsE3IEC7pnmh95l29/7mh4OuG5cp5JUx0Pi5PkuJ6ywA8P1rM1MB9Zf52 +NGJCo1pnPwKBgQCx/n4i+uDYo1DLd/dN2UmdvGwaaJjR3ohMVuQcGcSzaGg82u0W +0lvtWOnYjVSIeXIBjHaFjW1hd1lSFdWms96AO9z3MHZf6NJWh0tdZNnAXqzMlBFz +OIbdxJ/Y0OBFtA9FIesFmL7G54GWLr+f49Ry3Jr9jmYJ8au0BRqsux07aQKBgC4q +CT2KyCMCO/z6XjAGc71hres/UlYIUI3ZZvfqYPfxRLNxO4FOVqq9UEajMomyJKSE +3WtO5F3YAXRmZnskPKXvHZPdzqbaLGJykD298h7PewSzrPM7WpM1yD9ETPFoOTGy +CrcYiYlkEpxEh5GqT8k1JjjkXLVG18zKgGoXocedAoGAQyU2DCNfxwzIJfFHKZEG +zpni72cR68Tu3AhW/38vMR2ZPca4KzXrUA52T+j7vkQC38LHm/mzNXNP7Vya0PJ3 +WoYOcLtg2uFPh0P/35ArEzuNooLsvulgg1jsamPbF8KAvJZKZHr30hlC/JGYSBbV +bnkzJTShsKzHIUiLtQ8Ja+E= +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIJAJ39xapQo0vLMA0GCSqGSIb3DQEBBQUAMFMxCzAJBgNV +BAYTAkRFMRMwEQYDVQQIDApTb21lLVN0YXRlMRswGQYDVQQKDBJBUFQgVGVzdGNh +c2VzIEdtYkgxEjAQBgNVBAMMCWxvY2FsaG9zdDAgFw0xMzA5MTYwODQ4MzVaGA80 +NzUxMDgxMzA4NDgzNVowUzELMAkGA1UEBhMCREUxEzARBgNVBAgMClNvbWUtU3Rh +dGUxGzAZBgNVBAoMEkFQVCBUZXN0Y2FzZXMgR21iSDESMBAGA1UEAwwJbG9jYWxo +b3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAreEdUNqGBerrS9fR +gYZ5R1vC9gSOz0RVoHv2aaiGVrGhXG99BVfOmeml12ZoHxCdvNeGWWA9SCngnibC +aZ7OweL2Htb+uK/feWTQUAACiGIyApCmTgYDqYVfgoQX6wnLVV4Hy2zD+ogXRydN +sB80ggnWZtLHVZfbQeZfzsiVPDG+Cgd27QYX2X2NjOpVPhTo3F7NSznblK7+yn2f +gxGpb1RpKJi7R7Q9Km9r5Kha041QpM4lFVoYcRRX5bdPKENNQpcaZfrr+6zkKI7Z +CdS6zLr+4j32mf896i4hcWWBtQQhhMEzigrSaOm4Bc14jd6u0ORRZZr/OdcdiQ5/ +Au0JuwIDAQABo1AwTjAdBgNVHQ4EFgQUhd26E7ykEYRTDbgMzkYtFtENhSkwHwYD +VR0jBBgwFoAUhd26E7ykEYRTDbgMzkYtFtENhSkwDAYDVR0TBAUwAwEB/zANBgkq +hkiG9w0BAQUFAAOCAQEAWcyMKi0Vc4beGV7w4Qft0/2P68jjMlQRdgkz+gGXbMVr +//KhqR3PbgFmHHpUsZ718AHeerNNdfFzOUptiAiOqH2muyAGdeWCxJ8KcU0sic8x +/h3TOzMYfEozhgMSJp9YW1z655uHcb15S7jb4zZwXwGyQzxwXT35SKj2mCqSbjIb +G987DGI+MtyoGRXhIwnBEsGTI1ck3NoeXBJ/tS/Ma8gUUC2xldMSprtHjeUHvZV2 +iz/HTqGlMLGW96AVeZiFNiC1fJ6pvref2XW5MkkvQm8tOi2cSrwJc9CgnCpCxkLp +liRsbwAduwkA26XzEomMR7yyYS5pm0Eu0cO9X39FKQ== +-----END CERTIFICATE----- diff --git a/test/integration/framework b/test/integration/framework index 4003d932c..d899bb574 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -216,14 +216,13 @@ getarchitectures() { } configarchitecture() { - local CONFFILE=rootdir/etc/apt/apt.conf.d/01multiarch.conf - rm -f $CONFFILE - echo "APT::Architecture \"$(getarchitecture $1)\";" > $CONFFILE - shift - while [ -n "$1" ]; do - echo "APT::Architectures:: \"$(getarchitecture $1)\";" >> $CONFFILE - shift - done + { + echo "APT::Architecture \"$(getarchitecture $1)\";" + while [ -n "$1" ]; do + echo "APT::Architectures:: \"$(getarchitecture $1)\";" + shift + done + } >rootdir/etc/apt/apt.conf.d/01multiarch.conf configdpkg } @@ -236,16 +235,17 @@ configdpkg() { echo -n > rootdir/var/lib/dpkg/status fi fi + rm -f rootdir/etc/apt/apt.conf.d/00foreigndpkg if $(which dpkg) --assert-multi-arch >/dev/null 2>&1; then local ARCHS="$(getarchitectures)" if echo "$ARCHS" | grep -E -q '[^ ]+ [^ ]+'; then DPKGARCH="$(dpkg --print-architecture)" for ARCH in ${ARCHS}; do if [ "${ARCH}" != "${DPKGARCH}" ]; then - if ! dpkg --add-architecture ${ARCH}; then + if ! dpkg --add-architecture ${ARCH} >/dev/null 2>&1; then # old-style used e.g. in Ubuntu-P – and as it seems travis - echo "DPKG::options:: \"--foreign-architecture\";" >> aptconfig.conf - echo "DPKG::options:: \"${ARCH}\";" >> aptconfig.conf + echo "DPKG::options:: \"--foreign-architecture\";" >> rootdir/etc/apt/apt.conf.d/00foreigndpkg + echo "DPKG::options:: \"${ARCH}\";" >> rootdir/etc/apt/apt.conf.d/00foreigndpkg fi fi done @@ -278,7 +278,11 @@ setupsimplenativepackage() { local VERSION="$3" local RELEASE="${4:-unstable}" local DEPENDENCIES="$5" - local DESCRIPTION="$6" + local DESCRIPTION="${6:-"Description: an autogenerated dummy ${NAME}=${VERSION}/${RELEASE} + If you find such a package installed on your system, + something went horribly wrong! They are autogenerated + und used only by testcases and surf no other propose…"}" + local SECTION="${7:-others}" local DISTSECTION if [ "$SECTION" = "$(echo "$SECTION" | cut -d'/' -f 2)" ]; then @@ -310,14 +314,8 @@ Package: $NAME" > debian/control echo "Architecture: any" >> debian/control fi test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> debian/control - if [ -z "$DESCRIPTION" ]; then - echo "Description: an autogenerated dummy ${NAME}=${VERSION}/${RELEASE} - If you find such a package installed on your system, - YOU did something horribly wrong! They are autogenerated - und used only by testcases for APT and surf no other propose…" >> debian/control - else - echo "Description: $DESCRIPTION" >> debian/control - fi + echo "Description: $DESCRIPTION" >> debian/control + test -e debian/compat || echo "7" > debian/compat test -e debian/source/format || echo "3.0 (native)" > debian/source/format test -e debian/rules || cp /usr/share/doc/debhelper/examples/rules.tiny debian/rules @@ -330,7 +328,11 @@ buildsimplenativepackage() { local VERSION="$3" local RELEASE="${4:-unstable}" local DEPENDENCIES="$5" - local DESCRIPTION="$6" + local DESCRIPTION="${6:-"Description: an autogenerated dummy ${NAME}=${VERSION}/${RELEASE} + If you find such a package installed on your system, + something went horribly wrong! They are autogenerated + und used only by testcases and surf no other propose…"}" + local SECTION="${7:-others}" local PRIORITY="${8:-optional}" local DISTSECTION @@ -370,14 +372,7 @@ Package: $NAME" >> ${BUILDDIR}/debian/control fi local DEPS="$(echo "$DEPENDENCIES" | grep -v '^Build-')" test -z "$DEPS" || echo "$DEPS" >> ${BUILDDIR}/debian/control - if [ -z "$DESCRIPTION" ]; then - echo "Description: an autogenerated dummy ${NAME}=${VERSION}/${RELEASE} - If you find such a package installed on your system, - YOU did something horribly wrong! They are autogenerated - und used only by testcases for APT and surf no other propose…" >> ${BUILDDIR}/debian/control - else - echo "Description: $DESCRIPTION" >> ${BUILDDIR}/debian/control - fi + 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' \ @@ -526,7 +521,10 @@ insertpackage() { local VERSION="$4" local DEPENDENCIES="$5" local PRIORITY="${6:-optional}" - local DESCRIPTION="${7}" + local DESCRIPTION="${7:-"Description: an autogenerated dummy ${NAME}=${VERSION}/${RELEASE} + If you find such a package installed on your system, + something went horribly wrong! They are autogenerated + und used only by testcases and surf no other propose…"}" local ARCHS="" for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do if [ "$arch" = 'all' -o "$arch" = 'none' ]; then @@ -548,15 +546,7 @@ Maintainer: Joe Sixpack <joe@example.org>" >> $FILE echo "Version: $VERSION Filename: pool/main/${NAME}/${NAME}_${VERSION}_${arch}.deb" >> $FILE test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> $FILE - echo -n 'Description: ' >> $FILE - if [ -z "$DESCRIPTION" ]; then - echo "an autogenerated dummy ${NAME}=${VERSION}/${RELEASE} - If you find such a package installed on your system, - YOU did something horribly wrong! They are autogenerated - und used only by testcases for APT and surf no other propose…" >> $FILE - else - echo "$DESCRIPTION" >> $FILE - fi + echo "Description: $DESCRIPTION" >> $FILE echo >> $FILE done done @@ -591,6 +581,11 @@ insertinstalledpackage() { local DEPENDENCIES="$4" local PRIORITY="${5:-optional}" local STATUS="${6:-install ok installed}" + local DESCRIPTION="${7:-"Description: an autogenerated dummy ${NAME}=${VERSION}/installed + If you find such a package installed on your system, + something went horribly wrong! They are autogenerated + und used only by testcases and surf no other propose…"}" + local FILE='rootdir/var/lib/dpkg/status' local INFO='rootdir/var/lib/dpkg/info' for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do @@ -603,11 +598,8 @@ Maintainer: Joe Sixpack <joe@example.org> Version: $VERSION" >> $FILE test "$arch" = 'none' || echo "Architecture: $arch" >> $FILE test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> $FILE - echo "Description: an autogenerated dummy ${NAME}=${VERSION}/installed - If you find such a package installed on your system, - YOU did something horribly wrong! They are autogenerated - und used only by testcases for APT and surf no other propose… -" >> $FILE + echo "Description: $DESCRIPTION" >> $FILE + echo >> $FILE if [ "$(dpkg-query -W --showformat='${Multi-Arch}')" = 'same' ]; then echo -n > ${INFO}/${NAME}:${arch}.list else @@ -795,6 +787,13 @@ signreleasefiles() { msgdone "info" } +rewritesourceslist() { + local APTARCHIVE="file://$(readlink -f "${TMPWORKINGDIRECTORY}/aptarchive")" + for LIST in $(find rootdir/etc/apt/sources.list.d/ -name 'apt-test-*.list'); do + sed -i $LIST -e "s#$APTARCHIVE#${1}#" -e "s#http://localhost:8080/#${1}#" -e "s#http://localhost:4433/#${1}#" + done +} + changetowebserver() { local LOG='/dev/null' if test -x ${BUILDDIRECTORY}/aptwebserver; then @@ -806,31 +805,32 @@ changetowebserver() { fi addtrap "kill $PID;" cd - > /dev/null - elif [ $# -gt 0 ]; then - msgdie 'Need the aptwebserver when passing arguments for the webserver' - elif which weborf > /dev/null; then - weborf -xb aptarchive/ >$LOG 2>&1 & - addtrap "kill $!;" - elif which gatling > /dev/null; then - cd aptarchive - gatling -p 8080 -F -S >$LOG 2>&1 & - addtrap "kill $!;" - cd - > /dev/null - elif which lighttpd > /dev/null; then - echo "server.document-root = \"$(readlink -f ./aptarchive)\" -server.port = 8080 -server.stat-cache-engine = \"disable\"" > lighttpd.conf - lighttpd -t -f lighttpd.conf >/dev/null || msgdie 'Can not change to webserver: our lighttpd config is invalid' - lighttpd -D -f lighttpd.conf >$LOG 2>&1 & - addtrap "kill $!;" else msgdie 'You have to build aptwerbserver or install a webserver' fi - local APTARCHIVE="file://$(readlink -f ./aptarchive)" - for LIST in $(find rootdir/etc/apt/sources.list.d/ -name 'apt-test-*.list'); do - sed -i $LIST -e "s#$APTARCHIVE#http://localhost:8080/#" - done - return 0 + if [ "$1" != '--no-rewrite' ]; then + rewritesourceslist 'http://localhost:8080/' + fi +} + +changetohttpswebserver() { + if ! which stunnel4 >/dev/null; then + msgdie 'You need to install stunnel4 for https testcases' + fi + if [ ! -e "${TMPWORKINGDIRECTORY}/aptarchive/aptwebserver.pid" ]; then + changetowebserver --no-rewrite + fi + echo "pid = ${TMPWORKINGDIRECTORY}/aptarchive/stunnel.pid +cert = ${TESTDIRECTORY}/apt.pem + +[https] +accept = 4433 +connect = 8080 +" > ${TMPWORKINGDIRECTORY}/stunnel.conf + stunnel4 "${TMPWORKINGDIRECTORY}/stunnel.conf" + local PID="$(cat ${TMPWORKINGDIRECTORY}/aptarchive/stunnel.pid)" + addtrap 'prefix' "kill ${PID};" + rewritesourceslist 'https://localhost:4433/' } changetocdrom() { @@ -848,6 +848,46 @@ changetocdrom() { find rootdir/etc/apt/sources.list.d/ -name 'apt-test-*.list' -delete } +downloadfile() { + PROTO="$(echo "$1" | cut -d':' -f 1)" + local DOWNLOG="${TMPWORKINGDIRECTORY}/download.log" + rm -f "$DOWNLOG" + touch "$DOWNLOG" + { + echo "601 Configuration +Config-Item: Acquire::https::CaInfo=${TESTDIR}/apt.pem +Config-Item: Debug::Acquire::${PROTO}=1 + +600 Acquire URI +URI: $1 +Filename: ${2} +" + # simple worker keeping stdin open until we are done (201) or error (400) + # and requesting new URIs on try-agains/redirects inbetween + { tail -n 999 -f "$DOWNLOG" & echo "TAILPID: $!"; } | while read f1 f2; do + if [ "$f1" = 'TAILPID:' ]; then + TAILPID="$f2" + elif [ "$f1" = 'New-URI:' ]; then + echo "600 Acquire URI +URI: $f2 +Filename: ${2} +" + elif [ "$f1" = '201' ] || [ "$f1" = '400' ]; then + # tail would only die on next read – which never happens + test -z "$TAILPID" || kill -s HUP "$TAILPID" + break + fi + done + } | LD_LIBRARY_PATH=${BUILDDIRECTORY} ${BUILDDIRECTORY}/methods/${PROTO} 2>&1 | tee "$DOWNLOG" + rm "$DOWNLOG" + # only if the file exists the download was successful + if [ -e "$2" ]; then + return 0 + else + return 1 + fi +} + checkdiff() { local DIFFTEXT="$($(which diff) -u $* | sed -e '/^---/ d' -e '/^+++/ d' -e '/^@@/ d')" if [ -n "$DIFFTEXT" ]; then @@ -893,7 +933,7 @@ testequalor2() { echo "$2" > $COMPAREFILE2 shift 2 msgtest "Test for equality OR of" "$*" - $* >$COMPAREAGAINST 2>&1 + $* >$COMPAREAGAINST 2>&1 || true (checkdiff $COMPAREFILE1 $COMPAREAGAINST 1> /dev/null || checkdiff $COMPAREFILE2 $COMPAREAGAINST 1> /dev/null) && msgpass || ( echo "\n${CINFO}Diff against OR 1${CNORMAL}" "$(checkdiff $COMPAREFILE1 $COMPAREAGAINST)" \ diff --git a/test/integration/test-bug-601016-description-translation b/test/integration/skip-bug-601016-description-translation index 33c209e9d..33c209e9d 100755 --- a/test/integration/test-bug-601016-description-translation +++ b/test/integration/skip-bug-601016-description-translation diff --git a/test/integration/status-bug-723705-tagfile-truncates-fields b/test/integration/status-bug-723705-tagfile-truncates-fields new file mode 100644 index 000000000..fe18506c8 --- /dev/null +++ b/test/integration/status-bug-723705-tagfile-truncates-fields @@ -0,0 +1,62 @@ +Package: libc6 +Status: install ok installed +Priority: required +Section: libs +Installed-Size: 10164 +Maintainer: GNU Libc Maintainers <debian-glibc@lists.debian.org> +Architecture: amd64 +Multi-Arch: same +Source: eglibc (2.17-92) +Version: 2.17-92+b1 +Replaces: libc6-amd64 +Provides: glibc-2.17-1 +Suggests: glibc-doc, debconf | debconf-2.0, locales +Breaks: locales (<< 2.17), locales-all (<< 2.17), lsb-core (<= 3.2-27), nscd (<< 2.17) +Conflicts: prelink (<= 0.0.20090311-1), tzdata (<< 2007k-1), tzdata-etch +Conffiles: + /etc/ld.so.conf.d/x86_64-linux-gnu.conf 593ad12389ab2b6f952e7ede67b8fbbf +Description: Embedded GNU C Library: Shared libraries + Contains the standard libraries that are used by nearly all programs on + the system. This package includes shared versions of the standard C library + and the standard math library, as well as many others. +Homepage: http://www.eglibc.org + +Package: libnewt0.52 +Status: install ok installed +Priority: important +Section: libs +Installed-Size: 820 +Maintainer: Alastair McKinstry <mckinstry@debian.org> +Architecture: amd64 +Multi-Arch: same +Source: newt +Version: 0.52.15-3 +Recommends: libfribidi0 +Conffiles: + /etc/newt/palette.original d41d8cd98f00b204e9800998ecf8427e +Description: Not Erik's Windowing Toolkit - text mode windowing with slang + Newt is a windowing toolkit for text mode built from the slang library. + It allows color text mode applications to easily use stackable windows, + push buttons, check boxes, radio buttons, lists, entry fields, labels, + and displayable text. Scrollbars are supported, and forms may be nested + to provide extra functionality. This package contains the shared library + for programs that have been built with newt. +Homepage: https://fedorahosted.org/newt/ + +Package: libgcc1 +Status: install ok installed +Priority: required +Section: libs +Installed-Size: 128 +Maintainer: Debian GCC Maintainers <debian-gcc@lists.debian.org> +Architecture: amd64 +Multi-Arch: same +Source: gcc-4.8 (4.8.1-10) +Version: 1:4.8.1-10 +Breaks: gcc-4.1, gcc-4.3 (<< 4.3.6-1), gcc-4.4 (<< 4.4.6-4), gcc-4.5 (<< 4.5.3-2) +Description: GCC support library + Shared version of the support library, a library of internal subroutines + that GCC uses to overcome shortcomings of particular machines, or + special needs for some languages. +Homepage: http://gcc.gnu.org/ + diff --git a/test/integration/test-apt-get-autoremove b/test/integration/test-apt-get-autoremove index dc30cde34..68ea1c574 100755 --- a/test/integration/test-apt-get-autoremove +++ b/test/integration/test-apt-get-autoremove @@ -49,3 +49,23 @@ Install: unrelated:i386 (1), debhelper:i386 (8.0.0), po-debconf:i386 (1.0.16, au Remove: debhelper:i386 (8.0.0) Remove: po-debconf:i386 (1.0.16)' + +testsuccess aptget install debhelper -y +testdpkginstalled 'unrelated' 'debhelper' 'po-debconf' +testsuccess aptmark auto debhelper + +testmarkedauto 'debhelper' 'po-debconf' +testequal 'Reading package lists... +Building dependency tree... +Reading state information... +The following packages will be REMOVED: + debhelper po-debconf +0 upgraded, 0 newly installed, 2 to remove and 0 not upgraded. +Remv debhelper [8.0.0] +Remv po-debconf [1.0.16]' aptget autoremove -s + +testsuccess aptmark hold debhelper +testequal 'Reading package lists... +Building dependency tree... +Reading state information... +0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' aptget autoremove -s diff --git a/test/integration/test-apt-get-download b/test/integration/test-apt-get-download index 420b2e380..6eac079f3 100755 --- a/test/integration/test-apt-get-download +++ b/test/integration/test-apt-get-download @@ -20,13 +20,14 @@ testdownload() { fi msgtest "Test download of package file $1 with" "$APT" aptget -qq download ${APT} && test -f $1 && msgpass || msgfail + rm $1 } testdownload apt_1.0_all.deb apt stable testdownload apt_2.0_all.deb apt DEBFILE="$(readlink -f aptarchive)/pool/apt_2.0_all.deb" -testequal "'file://${DEBFILE}' apt_2.0_all.deb $(stat -c%s $DEBFILE) sha512:$(sha512sum $DEBFILE | cut -d' ' -f 1)" aptget download apt --print-uris +testequal "'file://${DEBFILE}' apt_2.0_all.deb $(stat -c%s $DEBFILE) SHA512:$(sha512sum $DEBFILE | cut -d' ' -f 1)" aptget download apt --print-uris # deb:677887 testequal "E: Can't find a source to download version '1.0' of 'vrms:i386'" aptget download vrms diff --git a/test/integration/test-bug-254770-segfault-if-cache-not-buildable b/test/integration/test-bug-254770-segfault-if-cache-not-buildable index 8fa337ccc..59102ddc9 100755 --- a/test/integration/test-bug-254770-segfault-if-cache-not-buildable +++ b/test/integration/test-bug-254770-segfault-if-cache-not-buildable @@ -18,7 +18,7 @@ testsegfault() { msgpass else echo - echo $TEST + echo "$TEST" msgfail fi } diff --git a/test/integration/test-bug-596498-trusted-unsigned-repo b/test/integration/test-bug-596498-trusted-unsigned-repo index 5c643c40e..06c9c8285 100755 --- a/test/integration/test-bug-596498-trusted-unsigned-repo +++ b/test/integration/test-bug-596498-trusted-unsigned-repo @@ -21,6 +21,9 @@ DEBFILE='rootdir/etc/apt/sources.list.d/apt-test-unstable-deb.list' testequal "$PKGTEXT Download complete and in download only mode" aptget install cool --assume-no -d +testequal "$PKGTEXT +Download complete and in download only mode" aptget install cool --assume-no -d --allow-unauthenticated + sed -i -e 's#deb#deb [trusted=no]#' $DEBFILE aptgetupdate @@ -40,6 +43,12 @@ WARNING: The following packages cannot be authenticated! Install these packages without verification? [y/N] N E: Some packages could not be authenticated" aptget install cool --assume-no -d +testequal "$PKGTEXT +WARNING: The following packages cannot be authenticated! + cool +Authentication warning overridden. +Download complete and in download only mode" aptget install cool --assume-no -d --allow-unauthenticated + sed -i -e 's#deb#deb [trusted=yes]#' $DEBFILE aptgetupdate diff --git a/test/integration/test-bug-617690-allow-unauthenticated-makes-all-untrusted b/test/integration/test-bug-617690-allow-unauthenticated-makes-all-untrusted new file mode 100755 index 000000000..633c197c0 --- /dev/null +++ b/test/integration/test-bug-617690-allow-unauthenticated-makes-all-untrusted @@ -0,0 +1,63 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'i386' + +buildsimplenativepackage 'cool' 'i386' '1.0' 'unstable' + +setupaptarchive --no-update + +testfileexists() { + msgtest 'Test for existance of file' "$1" + test -e "$1" && msgpass || msgfail + rm -f "$1" +} + +testfilemissing() { + msgtest 'Test for non-existance of file' "$1" + test -e "$1" && msgfail || msgpass + rm -f "$1" +} + +testrun() { + rm -rf rootdir/var/lib/apt + testsuccess aptget update + + if [ "$1" = 'trusted' ]; then + testsuccess aptget download cool + testfileexists 'cool_1.0_i386.deb' + + testsuccess aptget download cool --allow-unauthenticated + testfileexists 'cool_1.0_i386.deb' + else + testfailure aptget download cool + testfilemissing 'cool_1.0_i386.deb' + + testsuccess aptget download cool --allow-unauthenticated + testfileexists 'cool_1.0_i386.deb' + fi + + mv aptarchive/pool/cool_1.0_i386.deb aptarchive/pool/cool_1.0_i386.deb.bak + echo 'this is not a good package' > aptarchive/pool/cool_1.0_i386.deb + testfailure aptget download cool + testfilemissing cool_1.0_i386.deb + + testfailure aptget download cool --allow-unauthenticated # unauthenticated doesn't mean unchecked + testfilemissing cool_1.0_i386.deb + + rm -f aptarchive/pool/cool_1.0_i386.deb + mv aptarchive/pool/cool_1.0_i386.deb.bak aptarchive/pool/cool_1.0_i386.deb + testsuccess aptget download cool --allow-unauthenticated + testfileexists 'cool_1.0_i386.deb' +} + +testrun 'trusted' + +find aptarchive/ \( -name 'Release.gpg' -o -name 'InRelease' \) -delete +testrun 'untrusted' + +changetowebserver +testrun 'untrusted' diff --git a/test/integration/test-bug-633350-do-not-kill-last-char-in-Release b/test/integration/test-bug-633350-do-not-kill-last-char-in-Release index 2aae7cfcc..988f8c9d0 100755 --- a/test/integration/test-bug-633350-do-not-kill-last-char-in-Release +++ b/test/integration/test-bug-633350-do-not-kill-last-char-in-Release @@ -8,7 +8,7 @@ configarchitecture 'amd64' insertpackage 'unstable' 'cool' 'amd64' '1.0' -setupaptarchive 2> /dev/null +setupaptarchive --no-update echo 'NotAutomatic: yes' >> aptarchive/dists/unstable/Release diff --git a/test/integration/test-bug-679371-apt-get-autoclean-multiarch b/test/integration/test-bug-679371-apt-get-autoclean-multiarch index b62d437aa..3de7d69f9 100755 --- a/test/integration/test-bug-679371-apt-get-autoclean-multiarch +++ b/test/integration/test-bug-679371-apt-get-autoclean-multiarch @@ -17,7 +17,10 @@ changetowebserver testsuccess aptget update testsuccess aptget install pkgall pkgnative pkgforeign -y -testdpkginstalled pkgall pkgnative pkgforeign +# if we work with an old dpkg, pkgforeign will be listed differently, +# so test with aptcache for install status instead +testdpkginstalled pkgall pkgnative +testsuccess aptcache show pkgforeign/installed testequal 'Reading package lists... Building dependency tree... diff --git a/test/integration/test-bug-686346-package-missing-architecture b/test/integration/test-bug-686346-package-missing-architecture index 3b02811ca..dc51861ab 100755 --- a/test/integration/test-bug-686346-package-missing-architecture +++ b/test/integration/test-bug-686346-package-missing-architecture @@ -73,7 +73,7 @@ insertinstalledpackage 'pkgb' 'none' '1' insertinstalledpackage 'pkgf' 'none' '1' 'Conflicts: pkgb' insertinstalledpackage 'pkgg' 'amd64' '1' 'Conflicts: pkgb' insertinstalledpackage 'pkgb' 'amd64' '2' -testequal "Reading package lists... +testequalor2 "Reading package lists... Building dependency tree... Reading state information... You might want to run 'apt-get -f install' to correct these. @@ -84,6 +84,17 @@ The following packages have unmet dependencies: Conflicts: pkgb but 2 is installed pkgg : Conflicts: pkgb but 2 is installed Conflicts: pkgb:none but 1 is installed +E: Unmet dependencies. Try using -f." "Reading package lists... +Building dependency tree... +Reading state information... +You might want to run 'apt-get -f install' to correct these. +The following packages have unmet dependencies: + pkgb : Conflicts: pkgb:none but 1 is installed + pkgb:none : Conflicts: pkgb but 2 is installed + pkgf:none : Conflicts: pkgb but 2 is installed + Conflicts: pkgb:none but 1 is installed + pkgg : Conflicts: pkgb but 2 is installed + Conflicts: pkgb:none but 1 is installed E: Unmet dependencies. Try using -f." aptget check # check that dependencies are generated for none-packages diff --git a/test/integration/test-bug-689582-100-char-long-path-names b/test/integration/test-bug-689582-100-char-long-path-names new file mode 100755 index 000000000..1b4b172b6 --- /dev/null +++ b/test/integration/test-bug-689582-100-char-long-path-names @@ -0,0 +1,35 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' + +mkdir aptarchive/testpkg +cd aptarchive/testpkg + +for i in $(seq 98 102); do + touch "$(printf "%0${i}d" "$i")" +done +tar zcf data.tar.gz 00* + +echo 'Package: testpkg +Version: 1-1 +Architecture: all +Maintainer: Joe Sixpack <joe@example.org> +Description: Package for test +Section: debug +Priority: extra' > control +tar zcf control.tar.gz control + +echo '2.0' > debian-binary +ar cr ../testpkg.deb debian-binary control.tar.gz data.tar.gz + +cd - > /dev/null + +testequal '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000102 testpkg +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101 testpkg +0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100 testpkg +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000099 testpkg +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000098 testpkg' aptftparchive contents aptarchive/ diff --git a/test/integration/test-bug-722207-print-uris-even-if-very-quiet b/test/integration/test-bug-722207-print-uris-even-if-very-quiet new file mode 100755 index 000000000..f2d95da19 --- /dev/null +++ b/test/integration/test-bug-722207-print-uris-even-if-very-quiet @@ -0,0 +1,30 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework + +setupenvironment +configarchitecture 'amd64' + +insertinstalledpackage 'apt' 'all' '1' +insertpackage 'unstable' 'apt' 'all' '2' +insertsource 'unstable' 'apt' 'all' '2' +insertsource 'unstable' 'apt2' 'all' '1' + +setupaptarchive + +APTARCHIVE=$(readlink -f ./aptarchive) + +testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 MD5Sum:" aptget upgrade -qq --print-uris +testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 MD5Sum:" aptget dist-upgrade -qq --print-uris +testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 MD5Sum:" aptget install apt -qq --print-uris +testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 MD5Sum:" aptget download apt -qq --print-uris +testequal "'file://${APTARCHIVE}/apt_2.dsc' apt_2.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e +'file://${APTARCHIVE}/apt_2.tar.gz' apt_2.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source apt -qq --print-uris +testequal "'http://packages.debian.org/changelogs/pool/main/apt/apt_2/changelog'" aptget changelog apt -qq --print-uris + +testequal "'file://${APTARCHIVE}/apt_2.dsc' apt_2.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e +'file://${APTARCHIVE}/apt_2.tar.gz' apt_2.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e +'file://${APTARCHIVE}/apt2_1.dsc' apt2_1.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e +'file://${APTARCHIVE}/apt2_1.tar.gz' apt2_1.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source apt apt2 -qq --print-uris diff --git a/test/integration/test-bug-723586-any-stripped-in-single-arch b/test/integration/test-bug-723586-any-stripped-in-single-arch new file mode 100755 index 000000000..392b88e9f --- /dev/null +++ b/test/integration/test-bug-723586-any-stripped-in-single-arch @@ -0,0 +1,54 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' + +insertinstalledpackage 'python3' 'all' '3.2.3-6' + +insertpackage 'unstable' 'python3' 'amd64' '3.3.2-16' 'Multi-Arch: allowed' +insertpackage 'stable' 'python3-gnupg' 'all' '0.3.5-2' 'Depends: python3:any (>= 3.2.3-3~)' + +insertpackage 'unstable' 'python-mips' 'amd64' '3' 'Depends: python3:mips' + +setupaptarchive + +INSTALLLOG='Reading package lists... +Building dependency tree... +The following extra packages will be installed: + python3 +The following NEW packages will be installed: + python3-gnupg +The following packages will be upgraded: + python3 +1 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. +Inst python3 [3.2.3-6] (3.3.2-16 unstable [amd64]) +Inst python3-gnupg (0.3.5-2 stable [all]) +Conf python3 (3.3.2-16 unstable [amd64]) +Conf python3-gnupg (0.3.5-2 stable [all])' + +FAILLOG='Reading package lists... +Building dependency tree... +Some packages could not be installed. This may mean that you have +requested an impossible situation or if you are using the unstable +distribution that some required packages have not yet been created +or been moved out of Incoming. +The following information may help to resolve the situation: + +The following packages have unmet dependencies: + python-mips : Depends: python3:mips but it is not installable +E: Unable to correct problems, you have held broken packages.' + +testequal "$INSTALLLOG" aptget install python3-gnupg -s +aptcache showpkg python3 > showpkg.log +testequal "$FAILLOG" aptget install python-mips -s + +# same test, but this time in a multi-arch environment +configarchitecture 'amd64' 'armhf' +rm rootdir/var/cache/apt/*.bin + +testequal "$INSTALLLOG" aptget install python3-gnupg -s +testequal "$(sed 's#3.3.2-16 - python3#3.3.2-16 - python3:any:armhf python3#' showpkg.log)" aptcache showpkg python3 +testequal "$FAILLOG" aptget install python-mips -s diff --git a/test/integration/test-bug-723705-tagfile-truncates-fields b/test/integration/test-bug-723705-tagfile-truncates-fields new file mode 100755 index 000000000..3180e7fc9 --- /dev/null +++ b/test/integration/test-bug-723705-tagfile-truncates-fields @@ -0,0 +1,33 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' + +setupaptarchive + +aptget install --print-uris -y cdebconf-newt-terminal cdebconf-gtk-terminal 2>&1 | sed 's#file:///tmp/tmp.[^/]\+#file:///tmp#g' > filename.log + +testfileequal filename.log "Reading package lists... +Building dependency tree... +The following extra packages will be installed: + cdebconf-gtk-udeb cdebconf-newt-udeb cdebconf-udeb libc6-udeb + libglib2.0-udeb libgtk2.0-0-udeb libvte9-udeb +The following NEW packages will be installed: + cdebconf-gtk-terminal cdebconf-gtk-udeb cdebconf-newt-terminal + cdebconf-newt-udeb cdebconf-udeb libc6-udeb libglib2.0-udeb libgtk2.0-0-udeb + libvte9-udeb +0 upgraded, 9 newly installed, 0 to remove and 0 not upgraded. +Need to get 0 B/4774 kB of archives. +After this operation, 19.8 MB of additional disk space will be used. +'file:///tmp/aptarchive/pool/main/c/cdebconf/cdebconf-udeb_0.185_amd64.udeb' cdebconf-udeb_0.185_amd64.udeb 77376 MD5Sum:e3883706fdbf54c2e5ea959c92b2d37f +'file:///tmp/aptarchive/pool/main/c/cdebconf/cdebconf-gtk-udeb_0.185_amd64.udeb' cdebconf-gtk-udeb_0.185_amd64.udeb 27278 MD5Sum:a1bbbc1d4fb8e0615b5621abac021924 +'file:///tmp/aptarchive/pool/main/c/cdebconf/cdebconf-newt-udeb_0.185_amd64.udeb' cdebconf-newt-udeb_0.185_amd64.udeb 19192 MD5Sum:de27807f56dae2f2403b3322d5fe6bd2 +'file:///tmp/aptarchive/pool/main/g/glib2.0/libglib2.0-udeb_2.36.4-1_amd64.udeb' libglib2.0-udeb_2.36.4-1_amd64.udeb 1714604 MD5Sum:72da029f1bbb36057d874f1f82a5d00a +'file:///tmp/aptarchive/pool/main/e/eglibc/libc6-udeb_2.17-92+b1_amd64.udeb' libc6-udeb_2.17-92+b1_amd64.udeb 1056000 MD5Sum:7fd7032eeeecf7f76eff79a0543fbd72 +'file:///tmp/aptarchive/pool/main/g/gtk+2.0/libgtk2.0-0-udeb_2.24.20-1_amd64.udeb' libgtk2.0-0-udeb_2.24.20-1_amd64.udeb 1643046 MD5Sum:25513478eb2e02e5766c0eea0b411ca9 +'file:///tmp/aptarchive/pool/main/v/vte/libvte9-udeb_0.28.2-5_amd64.udeb' libvte9-udeb_1%3a0.28.2-5_amd64.udeb 216968 MD5Sum:7da7201effaf5ced19abd9d0b45aa2c6 +'file:///tmp/aptarchive/pool/main/c/cdebconf-terminal/cdebconf-gtk-terminal_0.22_amd64.udeb' cdebconf-gtk-terminal_0.22_amd64.udeb 14734 MD5Sum:f9c3a7354560cb88e0396e2b7ba54363 +'file:///tmp/aptarchive/pool/main/c/cdebconf-terminal/cdebconf-newt-terminal_0.22_amd64.udeb' cdebconf-newt-terminal_0.22_amd64.udeb 4538 MD5Sum:20db6152fce5081fcbf49c7c08f21246" diff --git a/test/integration/test-partial-file-support b/test/integration/test-partial-file-support new file mode 100755 index 000000000..8d1c51ae0 --- /dev/null +++ b/test/integration/test-partial-file-support @@ -0,0 +1,107 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' + +changetowebserver + +copysource() { + dd if="$1" bs=1 count="$2" of="$3" 2>/dev/null + touch -d "$(stat --format '%y' "${TESTFILE}")" "$3" +} + +testdownloadfile() { + local DOWNLOG='download-testfile.log' + rm -f "$DOWNLOG" + msgtest "Testing download of file $2 with" "$1" + if ! downloadfile "$2" "$3" > "$DOWNLOG"; then + cat "$DOWNLOG" + msgfail + else + msgpass + fi + cat "$DOWNLOG" | 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)";; + *) continue;; + esac + if [ "$4" = '=' ]; then + msgtest 'Test downloaded file for correct' "$field" + else + msgtest 'Test downloaded file does not match in' "$field" + fi + if [ "$EXPECTED" "$4" "$hash" ]; then + msgpass + else + cat "$DOWNLOG" + msgfail "expected: $EXPECTED ; got: $hash" + fi + done +} + +testwebserverlaststatuscode() { + STATUS="$(mktemp)" + addtrap "rm $STATUS;" + msgtest 'Test last status code from the webserver was' "$1" + downloadfile "http://localhost:8080/_config/find/aptwebserver::last-status-code" "$STATUS" >/dev/null + if [ "$(cat "$STATUS")" = "$1" ]; then + msgpass + else + cat download-testfile.log + msgfail "Status was $(cat "$STATUS")" + fi +} + + +TESTFILE='aptarchive/testfile' +cp -a ${TESTDIR}/framework $TESTFILE + +testrun() { + downloadfile "$1/_config/set/aptwebserver::support::range/true" '/dev/null' >/dev/null + testwebserverlaststatuscode '200' + + copysource $TESTFILE 0 ./testfile + testdownloadfile 'no data' "${1}/testfile" './testfile' '=' + testwebserverlaststatuscode '200' + + copysource $TESTFILE 20 ./testfile + testdownloadfile 'valid partial data' "${1}/testfile" './testfile' '=' + testwebserverlaststatuscode '206' + + copysource /dev/zero 20 ./testfile + testdownloadfile 'invalid partial data' "${1}/testfile" './testfile' '!=' + testwebserverlaststatuscode '206' + + copysource $TESTFILE 1M ./testfile + testdownloadfile 'completely downloaded file' "${1}/testfile" './testfile' '=' + testwebserverlaststatuscode '416' + + copysource /dev/zero 1M ./testfile + testdownloadfile 'too-big partial file' "${1}/testfile" './testfile' '=' + testwebserverlaststatuscode '200' + + copysource /dev/zero 20 ./testfile + touch ./testfile + testdownloadfile 'old data' "${1}/testfile" './testfile' '=' + testwebserverlaststatuscode '200' + + downloadfile "$1/_config/set/aptwebserver::support::range/false" '/dev/null' >/dev/null + testwebserverlaststatuscode '200' + + copysource $TESTFILE 20 ./testfile + testdownloadfile 'no server support' "${1}/testfile" './testfile' '=' + testwebserverlaststatuscode '200' +} + +testrun 'http://localhost:8080' + +changetohttpswebserver + +testrun 'https://localhost:4433' diff --git a/test/integration/test-releasefile-verification b/test/integration/test-releasefile-verification index a9f4b9775..9d34a521a 100755 --- a/test/integration/test-releasefile-verification +++ b/test/integration/test-releasefile-verification @@ -11,18 +11,24 @@ buildaptarchive setupflataptarchive changetowebserver +downloadfile "http://localhost:8080/_config/set/aptwebserver::support::range/false" '/dev/null' >/dev/null + prepare() { local DATE="${2:-now}" - if [ "$DATE" = 'now' -a "$1" = "${PKGFILE}-new" ]; then - DATE='now + 6 days' + if [ "$DATE" = 'now' ]; then + if [ "$1" = "${PKGFILE}-new" ]; then + DATE='now - 1 day' + else + DATE='now - 7 day' + fi fi for release in $(find rootdir/var/lib/apt/lists 2> /dev/null); do - touch -d 'now - 6 hours' $release + touch -d 'now - 1 year' $release done aptget clean cp $1 aptarchive/Packages find aptarchive -name 'Release' -delete - compressfile 'aptarchive/Packages' + compressfile 'aptarchive/Packages' "$DATE" generatereleasefiles "$DATE" } @@ -85,13 +91,34 @@ touch aptarchive/apt.deb PKGFILE="${TESTDIR}/$(echo "$(basename $0)" | sed 's#^test-#Packages-#')" +updatesuccess() { + local LOG='update.log' + if aptget update >$LOG 2>&1 || grep -q -E '^(W|E): ' $LOG; then + msgpass + else + cat $LOG + msgfail + fi +} + +updatefailure() { + local LOG='update.log' + aptget update >$LOG 2>&1 || true + if grep -q -E "$1" $LOG; then + msgpass + else + cat $LOG + msgfail + fi +} + runtest() { prepare ${PKGFILE} rm -rf rootdir/var/lib/apt/lists signreleasefiles 'Joe Sixpack' find aptarchive/ -name "$DELETEFILE" -delete msgtest 'Cold archive signed by' 'Joe Sixpack' - aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass + updatesuccess testequal "$(cat ${PKGFILE}) " aptcache show apt installaptold @@ -100,7 +127,7 @@ runtest() { signreleasefiles 'Joe Sixpack' find aptarchive/ -name "$DELETEFILE" -delete msgtest 'Good warm archive signed by' 'Joe Sixpack' - aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass + updatesuccess testequal "$(cat ${PKGFILE}-new) " aptcache show apt installaptnew @@ -111,7 +138,7 @@ runtest() { signreleasefiles 'Rex Expired' find aptarchive/ -name "$DELETEFILE" -delete msgtest 'Cold archive signed by' 'Rex Expired' - aptget update 2>&1 | grep -E '^W: .* KEYEXPIRED' > /dev/null && msgpass || msgfail + updatefailure '^W: .* KEYEXPIRED' testequal "$(cat ${PKGFILE}) " aptcache show apt failaptold @@ -122,7 +149,7 @@ runtest() { signreleasefiles 'Marvin Paranoid' find aptarchive/ -name "$DELETEFILE" -delete msgtest 'Cold archive signed by' 'Marvin Paranoid' - aptget update 2>&1 | grep -E '^W: .* NO_PUBKEY' > /dev/null && msgpass || msgfail + updatefailure '^W: .* NO_PUBKEY' testequal "$(cat ${PKGFILE}) " aptcache show apt failaptold @@ -136,7 +163,7 @@ runtest() { signreleasefiles 'Joe Sixpack' find aptarchive/ -name "$DELETEFILE" -delete msgtest 'Bad warm archive signed by' 'Joe Sixpack' - aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass + updatesuccess testequal "$(cat ${PKGFILE}-new) " aptcache show apt installaptnew @@ -147,7 +174,7 @@ runtest() { signreleasefiles 'Joe Sixpack' find aptarchive/ -name "$DELETEFILE" -delete msgtest 'Cold archive signed by' 'Joe Sixpack' - aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass + updatesuccess testequal "$(cat ${PKGFILE}) " aptcache show apt installaptold @@ -156,7 +183,7 @@ runtest() { signreleasefiles 'Marvin Paranoid' find aptarchive/ -name "$DELETEFILE" -delete msgtest 'Good warm archive signed by' 'Marvin Paranoid' - aptget update 2>&1 | grep -E '^W: .* NO_PUBKEY' > /dev/null && msgpass || msgfail + updatefailure '^W: .* NO_PUBKEY' testequal "$(cat ${PKGFILE}) " aptcache show apt installaptold @@ -166,7 +193,7 @@ runtest() { signreleasefiles 'Rex Expired' find aptarchive/ -name "$DELETEFILE" -delete msgtest 'Good warm archive signed by' 'Rex Expired' - aptget update 2>&1 | grep -E '^W: .* KEYEXPIRED' > /dev/null && msgpass || msgfail + updatefailure '^W: .* KEYEXPIRED' testequal "$(cat ${PKGFILE}) " aptcache show apt installaptold @@ -176,7 +203,7 @@ runtest() { signreleasefiles find aptarchive/ -name "$DELETEFILE" -delete msgtest 'Good warm archive signed by' 'Joe Sixpack' - aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass + updatesuccess testequal "$(cat ${PKGFILE}-new) " aptcache show apt installaptnew @@ -187,7 +214,7 @@ runtest2() { rm -rf rootdir/var/lib/apt/lists signreleasefiles 'Joe Sixpack' msgtest 'Cold archive signed by' 'Joe Sixpack' - aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass + updatesuccess # New .deb but now an unsigned archive. For example MITM to circumvent # package verification. @@ -195,7 +222,7 @@ runtest2() { find aptarchive/ -name InRelease -delete find aptarchive/ -name Release.gpg -delete msgtest 'Warm archive signed by' 'nobody' - aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass + updatesuccess testequal "$(cat ${PKGFILE}-new) " aptcache show apt failaptnew @@ -203,7 +230,7 @@ runtest2() { # Unsigned archive from the beginning must also be detected. rm -rf rootdir/var/lib/apt/lists msgtest 'Cold archive signed by' 'nobody' - aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass + updatesuccess testequal "$(cat ${PKGFILE}-new) " aptcache show apt failaptnew diff --git a/test/integration/test-ubuntu-bug-859188-multiarch-reinstall b/test/integration/test-ubuntu-bug-859188-multiarch-reinstall index 0fdf97485..be86f2e91 100755 --- a/test/integration/test-ubuntu-bug-859188-multiarch-reinstall +++ b/test/integration/test-ubuntu-bug-859188-multiarch-reinstall @@ -8,14 +8,13 @@ configarchitecture 'amd64' 'i386' 'armel' buildsimplenativepackage 'libsame' 'amd64,i386,armel' '1.0' 'unstable' 'Multi-Arch: same' -# FIXME: hack around dpkg's current inability to handle multiarch, a clean install would be better… -insertinstalledpackage 'libsame' 'amd64,i386' '1.0' 'Multi-Arch: same' -sed -e 's#/installed#/unstable#' -e 's#Installed-Size: 42#Installed-Size: 1#' -i rootdir/var/lib/dpkg/status - setupaptarchive +testsuccess aptget install libsame libsame:i386 + REINSTALL='Reading package lists... Building dependency tree... +Reading state information... 0 upgraded, 0 newly installed, 2 reinstalled, 0 to remove and 0 not upgraded. Inst libsame [1.0] (1.0 unstable [amd64]) Inst libsame:i386 [1.0] (1.0 unstable [i386]) diff --git a/test/interactive-helper/aptwebserver.cc b/test/interactive-helper/aptwebserver.cc index fde95fec9..4dae342dd 100644 --- a/test/interactive-helper/aptwebserver.cc +++ b/test/interactive-helper/aptwebserver.cc @@ -100,8 +100,13 @@ bool sendHead(int const client, int const httpcode, std::list<std::string> &head std::string response("HTTP/1.1 "); response.append(httpcodeToStr(httpcode)); headers.push_front(response); + _config->Set("APTWebserver::Last-Status-Code", httpcode); - headers.push_back("Server: APT webserver"); + std::stringstream buffer; + _config->Dump(buffer, "aptwebserver::response-header", "%t: %v%n", false); + std::vector<std::string> addheaders = VectorizeString(buffer.str(), '\n'); + for (std::vector<std::string>::const_iterator h = addheaders.begin(); h != addheaders.end(); ++h) + headers.push_back(*h); std::string date("Date: "); date.append(TimeRFC1123(time(NULL))); @@ -156,15 +161,29 @@ void sendError(int const client, int const httpcode, std::string const &request, std::string response("<html><head><title>"); response.append(httpcodeToStr(httpcode)).append("</title></head>"); response.append("<body><h1>").append(httpcodeToStr(httpcode)).append("</h1>"); - 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>"); + 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>"); + } + 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>"); addDataHeaders(headers, response); sendHead(client, httpcode, headers); if (content == true) sendData(client, response); } +void sendSuccess(int const client, std::string const &request, + bool content, std::string const &error = "") +{ + sendError(client, 200, request, content, error); +} /*}}}*/ void sendRedirect(int const client, int const httpcode, std::string const &uri,/*{{{*/ std::string const &request, bool content) @@ -365,6 +384,49 @@ bool parseFirstLine(int const client, std::string const &request, /*{{{*/ return true; } /*}}}*/ +bool handleOnTheFlyReconfiguration(int const client, std::string const &request, std::vector<std::string> const &parts)/*{{{*/ +{ + 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] + "'!"); + 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); + 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); + return true; + } + sendError(client, 404, request, "Requested Configuration option doesn't exist."); + return false; + } + else if (pcount == 3 && parts[1] == "clear") + { + _config->Clear(parts[2]); + sendSuccess(client, request, true, "Option '" + parts[2] + "' was cleared."); + return true; + } + + sendError(client, 400, request, true, "Unknown on-the-fly configuration request"); + return false; +} + /*}}}*/ int main(int const argc, const char * argv[]) { CommandLine::Args Args[] = { @@ -455,6 +517,9 @@ int main(int const argc, const char * argv[]) listen(sock, 1); /*}}}*/ + _config->CndSet("aptwebserver::response-header::Server", "APT webserver"); + _config->CndSet("aptwebserver::response-header::Accept-Ranges", "bytes"); + std::vector<std::string> messages; int client; while ((client = accept(sock, NULL, NULL)) != -1) @@ -475,6 +540,17 @@ int main(int const argc, const char * argv[]) if (parseFirstLine(client, *m, filename, sendContent, closeConnection) == false) continue; + // special webserver command request + if (filename.length() > 1 && filename[0] == '_') + { + std::vector<std::string> parts = VectorizeString(filename, '/'); + if (parts[0] == "_config") + { + handleOnTheFlyReconfiguration(client, *m, parts); + continue; + } + } + // string replacements in the requested filename ::Configuration::Item const *Replaces = _config->Tree("aptwebserver::redirect::replace"); if (Replaces != NULL) @@ -532,6 +608,60 @@ int main(int const argc, const char * argv[]) } } + if (_config->FindB("aptwebserver::support::range", true) == true) + condition = LookupTag(*m, "Range", ""); + else + condition.clear(); + if (condition.empty() == false && strncmp(condition.c_str(), "bytes=", 6) == 0) + { + time_t cache; + std::string ifrange; + if (_config->FindB("aptwebserver::support::if-range", true) == true) + ifrange = LookupTag(*m, "If-Range", ""); + bool validrange = (ifrange.empty() == true || + (RFC1123StrToTime(ifrange.c_str(), cache) == true && + cache <= data.ModificationTime())); + + // FIXME: support multiple byte-ranges (APT clients do not do this) + if (condition.find(',') == std::string::npos) + { + size_t start = 6; + unsigned long long filestart = strtoull(condition.c_str() + start, NULL, 10); + // FIXME: no support for last-byte-pos being not the end of the file (APT clients do not do this) + size_t dash = condition.find('-') + 1; + unsigned long long fileend = strtoull(condition.c_str() + dash, NULL, 10); + unsigned long long filesize = data.FileSize(); + if ((fileend == 0 || (fileend == filesize && fileend >= filestart)) && + validrange == true) + { + if (filesize > filestart) + { + data.Skip(filestart); + std::ostringstream contentlength; + contentlength << "Content-Length: " << (filesize - filestart); + headers.push_back(contentlength.str()); + std::ostringstream contentrange; + contentrange << "Content-Range: bytes " << filestart << "-" + << filesize - 1 << "/" << filesize; + headers.push_back(contentrange.str()); + sendHead(client, 206, headers); + if (sendContent == true) + sendFile(client, 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; + } + } + } + } + addFileHeaders(headers, data); sendHead(client, 200, headers); if (sendContent == true) diff --git a/test/libapt/hashsums_test.cc b/test/libapt/hashsums_test.cc index e2d0aec5b..3da89052b 100644 --- a/test/libapt/hashsums_test.cc +++ b/test/libapt/hashsums_test.cc @@ -3,6 +3,7 @@ #include <apt-pkg/sha2.h> #include <apt-pkg/strutl.h> #include <apt-pkg/hashes.h> +#include <apt-pkg/fileutl.h> #include <iostream> #include <stdio.h> @@ -108,55 +109,54 @@ int main(int argc, char** argv) Test<SHA512Summation>("The quick brown fox jumps over the lazy dog.", "91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bb" "c6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed"); - FILE* fd = fopen(argv[1], "r"); - if (fd == NULL) { + FileFd fd(argv[1], FileFd::ReadOnly); + if (fd.IsOpen() == false) { std::cerr << "Can't open file for 1. testing: " << argv[1] << std::endl; return 1; } { Hashes hashes; - hashes.AddFD(fileno(fd)); + hashes.AddFD(fd.Fd()); equals(argv[2], hashes.MD5.Result().Value()); equals(argv[3], hashes.SHA1.Result().Value()); equals(argv[4], hashes.SHA256.Result().Value()); equals(argv[5], hashes.SHA512.Result().Value()); } - fseek(fd, 0L, SEEK_END); - unsigned long sz = ftell(fd); - fseek(fd, 0L, SEEK_SET); + unsigned long sz = fd.FileSize(); + fd.Seek(0); { Hashes hashes; - hashes.AddFD(fileno(fd), sz); + hashes.AddFD(fd.Fd(), sz); equals(argv[2], hashes.MD5.Result().Value()); equals(argv[3], hashes.SHA1.Result().Value()); equals(argv[4], hashes.SHA256.Result().Value()); equals(argv[5], hashes.SHA512.Result().Value()); } - fseek(fd, 0L, SEEK_SET); + fd.Seek(0); { MD5Summation md5; - md5.AddFD(fileno(fd)); + md5.AddFD(fd.Fd()); equals(argv[2], md5.Result().Value()); } - fseek(fd, 0L, SEEK_SET); + fd.Seek(0); { SHA1Summation sha1; - sha1.AddFD(fileno(fd)); + sha1.AddFD(fd.Fd()); equals(argv[3], sha1.Result().Value()); } - fseek(fd, 0L, SEEK_SET); + fd.Seek(0); { SHA256Summation sha2; - sha2.AddFD(fileno(fd)); + sha2.AddFD(fd.Fd()); equals(argv[4], sha2.Result().Value()); } - fseek(fd, 0L, SEEK_SET); + fd.Seek(0); { SHA512Summation sha2; - sha2.AddFD(fileno(fd)); + sha2.AddFD(fd.Fd()); equals(argv[5], sha2.Result().Value()); } - fclose(fd); + fd.Close(); // test HashString code { diff --git a/test/libapt/strutil_test.cc b/test/libapt/strutil_test.cc index b044b7f34..110a20d27 100644 --- a/test/libapt/strutil_test.cc +++ b/test/libapt/strutil_test.cc @@ -65,5 +65,9 @@ int main(int argc,char *argv[]) equals(result[0], "x"); equals(result[1], "y:z"); + input = "abc"; + result = StringSplit(input, ""); + equals(result.size(), 0); + return 0; } |