From 76926159194e180003aa78de97e5f287bf4325a5 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 15 Apr 2024 20:07:41 +0200 Subject: Adding upstream version 2.7.6. Signed-off-by: Daniel Baumann --- tests/__init__.py | 1 + tests/data/aptsources/lsb-release | 4 + tests/data/aptsources/os-release | 10 + tests/data/aptsources/sources.list | 10 + .../sources.list.d.testDistribution/main.sources | 74 + .../sources.list.d.testDuplication/main.sources | 10 + tests/data/aptsources/sources.list.d/main.sources | 32 + .../data/aptsources/sources.list.testDistribution | 14 + tests/data/aptsources/sources.list.testDuplication | 2 + tests/data/aptsources_ports/sources.list | 52 + tests/data/fake-packages/Packages | 21 + tests/data/fake-packages/Packages.gz | Bin 0 -> 555 bytes tests/data/hashsums/hashsum_test.data | 1 + tests/data/hashsums/hashsum_test_with_zero.data | Bin 0 -> 7 bytes tests/data/misc/foo_Release | 492 ++++++ tests/data/tagfile/history.1.log.gz | Bin 0 -> 270 bytes tests/data/tagfile/history.log | 15 + tests/data/test-provides/etc/apt/sources.list | 1 + ..._ubuntu_dists_oneiric_main_binary-i386_Packages | 75 + tests/data/test-provides/var/lib/dpkg/status | 0 tests/data/test-repo/Packages.gz | Bin 0 -> 675 bytes tests/data/test-repo2/Packages.gz | Bin 0 -> 675 bytes tests/data/test-signed-usable-repo/key.gpg.base64 | 62 + tests/data/test-signed-usable-repo/seckey.asc | 158 ++ tests/data/test-signed-usable-repo/signed/Packages | 26 + tests/data/test-signed-usable-repo/signed/Release | 17 + .../test-signed-usable-repo/signed/Release.gpg | 14 + tests/data/test-signed-usable-repo/signed/Sources | 21 + .../signed/signed-not-usable_1.0.dsc | 11 + .../signed/signed-not-usable_1.0_all.deb | 1 + .../signed/signed-usable_1.0.dsc | 11 + .../signed/signed-usable_1.0_all.deb | 1 + .../data/test-signed-usable-repo/unsigned/Packages | 26 + .../data/test-signed-usable-repo/unsigned/Release | 17 + .../data/test-signed-usable-repo/unsigned/Sources | 22 + .../unsigned/unsigned-not-usable_1.0.dsc | 11 + .../unsigned/unsigned-unusable_1.0_all.deb | 1 + .../unsigned/unsigned-usable_1.0.dsc | 11 + .../unsigned/unsigned-usable_1.0_all.deb | 1 + tests/data/test-source-repo/Sources | 25 + tests/data/test_debs/data-tar-broken.deb | Bin 0 -> 626 bytes tests/data/test_debs/data-tar-xz.deb | Bin 0 -> 680 bytes tests/data/test_debs/data-tar.deb | Bin 0 -> 20672 bytes tests/data/test_debs/etc/apt/sources.list | 1 + tests/data/test_debs/gdebi-test1.deb | Bin 0 -> 934 bytes tests/data/test_debs/gdebi-test10.deb | Bin 0 -> 614 bytes tests/data/test_debs/gdebi-test11.deb | Bin 0 -> 634 bytes tests/data/test_debs/gdebi-test12.deb | Bin 0 -> 966 bytes tests/data/test_debs/gdebi-test13.deb | Bin 0 -> 720 bytes tests/data/test_debs/gdebi-test2.deb | Bin 0 -> 554 bytes tests/data/test_debs/gdebi-test3.deb | Bin 0 -> 570 bytes tests/data/test_debs/gdebi-test4.deb | Bin 0 -> 2306 bytes tests/data/test_debs/gdebi-test5.deb | Bin 0 -> 2306 bytes tests/data/test_debs/gdebi-test6.deb | Bin 0 -> 600 bytes tests/data/test_debs/gdebi-test7.deb | Bin 0 -> 578 bytes tests/data/test_debs/gdebi-test8.deb | Bin 0 -> 598 bytes tests/data/test_debs/gdebi-test9.deb | Bin 0 -> 586 bytes tests/data/test_debs/hello_2.5-1.dsc | 34 + .../test_debs/impossible-build-depends_2.5-1.dsc | 33 + .../test_debs/large-package-content_1.0_all.deb | Bin 0 -> 781546 bytes tests/data/test_debs/multiarch-test1_i386.deb | Bin 0 -> 978 bytes .../test_debs/testdep-allowed-any_1.0-1_i386.deb | Bin 0 -> 1128 bytes .../test_debs/testdep-same-arch_1.0-1_i386.deb | Bin 0 -> 1236 bytes tests/data/test_debs/utf8-package_1.0-1_all.deb | Bin 0 -> 1150 bytes ...ubuntu_dists_maverick_main_binary-i386_Packages | 31 + tests/data/test_debs/var/lib/dpkg/status | 92 ++ tests/fakeroot-apt-key | 2 + tests/helper_install_progress_run.py | 15 + tests/old/__init__.py | 11 + tests/old/apt-test.py | 27 + tests/old/cache.py | 51 + tests/old/depcache.py | 57 + tests/old/lock.py | 47 + tests/old/memleak.py | 45 + tests/old/pkgproblemresolver.py | 71 + tests/old/pkgrecords.py | 41 + tests/old/pkgsrcrecords.py | 31 + tests/old/refcount.py | 54 + tests/old/test_enhances.py | 16 + tests/test_all.py | 63 + tests/test_apt_cache.py | 400 +++++ tests/test_aptsources.py | 1573 ++++++++++++++++++++ tests/test_aptsources_deb822.py | 63 + tests/test_aptsources_ports.py | 41 + tests/test_auth.py | 314 ++++ tests/test_cache_invocation.py | 31 + tests/test_configuration.py | 31 + tests/test_cve_2020_27351.py | 149 ++ tests/test_debfile.py | 192 +++ tests/test_debfile_multiarch.py | 63 + tests/test_deps.py | 142 ++ tests/test_group.py | 31 + tests/test_hashes.py | 206 +++ tests/test_hashsums.py | 106 ++ tests/test_install_progress_exec.py | 43 + tests/test_large_file.py | 25 + tests/test_lfs.py | 19 + tests/test_lp659438.py | 80 + tests/test_paths.py | 158 ++ tests/test_pep484.py | 28 + tests/test_policy.py | 70 + tests/test_progress.py | 56 + tests/test_pyflakes.py | 43 + tests/test_signed_usable.py | 403 +++++ tests/test_size_to_str.py | 104 ++ tests/test_sourcerecords.py | 129 ++ tests/test_tagfile.py | 186 +++ tests/test_utils.py | 74 + tests/testcommon.py | 30 + 109 files changed, 6762 insertions(+) create mode 100644 tests/__init__.py create mode 100644 tests/data/aptsources/lsb-release create mode 100644 tests/data/aptsources/os-release create mode 100644 tests/data/aptsources/sources.list create mode 100644 tests/data/aptsources/sources.list.d.testDistribution/main.sources create mode 100644 tests/data/aptsources/sources.list.d.testDuplication/main.sources create mode 100644 tests/data/aptsources/sources.list.d/main.sources create mode 100644 tests/data/aptsources/sources.list.testDistribution create mode 100644 tests/data/aptsources/sources.list.testDuplication create mode 100644 tests/data/aptsources_ports/sources.list create mode 100644 tests/data/fake-packages/Packages create mode 100644 tests/data/fake-packages/Packages.gz create mode 100644 tests/data/hashsums/hashsum_test.data create mode 100644 tests/data/hashsums/hashsum_test_with_zero.data create mode 100644 tests/data/misc/foo_Release create mode 100644 tests/data/tagfile/history.1.log.gz create mode 100644 tests/data/tagfile/history.log create mode 100644 tests/data/test-provides/etc/apt/sources.list create mode 100644 tests/data/test-provides/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_binary-i386_Packages create mode 100644 tests/data/test-provides/var/lib/dpkg/status create mode 100644 tests/data/test-repo/Packages.gz create mode 100644 tests/data/test-repo2/Packages.gz create mode 100644 tests/data/test-signed-usable-repo/key.gpg.base64 create mode 100644 tests/data/test-signed-usable-repo/seckey.asc create mode 100644 tests/data/test-signed-usable-repo/signed/Packages create mode 100644 tests/data/test-signed-usable-repo/signed/Release create mode 100644 tests/data/test-signed-usable-repo/signed/Release.gpg create mode 100644 tests/data/test-signed-usable-repo/signed/Sources create mode 100644 tests/data/test-signed-usable-repo/signed/signed-not-usable_1.0.dsc create mode 100644 tests/data/test-signed-usable-repo/signed/signed-not-usable_1.0_all.deb create mode 100644 tests/data/test-signed-usable-repo/signed/signed-usable_1.0.dsc create mode 100644 tests/data/test-signed-usable-repo/signed/signed-usable_1.0_all.deb create mode 100644 tests/data/test-signed-usable-repo/unsigned/Packages create mode 100644 tests/data/test-signed-usable-repo/unsigned/Release create mode 100644 tests/data/test-signed-usable-repo/unsigned/Sources create mode 100644 tests/data/test-signed-usable-repo/unsigned/unsigned-not-usable_1.0.dsc create mode 100644 tests/data/test-signed-usable-repo/unsigned/unsigned-unusable_1.0_all.deb create mode 100644 tests/data/test-signed-usable-repo/unsigned/unsigned-usable_1.0.dsc create mode 100644 tests/data/test-signed-usable-repo/unsigned/unsigned-usable_1.0_all.deb create mode 100644 tests/data/test-source-repo/Sources create mode 100644 tests/data/test_debs/data-tar-broken.deb create mode 100644 tests/data/test_debs/data-tar-xz.deb create mode 100644 tests/data/test_debs/data-tar.deb create mode 100644 tests/data/test_debs/etc/apt/sources.list create mode 100644 tests/data/test_debs/gdebi-test1.deb create mode 100644 tests/data/test_debs/gdebi-test10.deb create mode 100644 tests/data/test_debs/gdebi-test11.deb create mode 100644 tests/data/test_debs/gdebi-test12.deb create mode 100644 tests/data/test_debs/gdebi-test13.deb create mode 100644 tests/data/test_debs/gdebi-test2.deb create mode 100644 tests/data/test_debs/gdebi-test3.deb create mode 100644 tests/data/test_debs/gdebi-test4.deb create mode 100644 tests/data/test_debs/gdebi-test5.deb create mode 100644 tests/data/test_debs/gdebi-test6.deb create mode 100644 tests/data/test_debs/gdebi-test7.deb create mode 100644 tests/data/test_debs/gdebi-test8.deb create mode 100644 tests/data/test_debs/gdebi-test9.deb create mode 100644 tests/data/test_debs/hello_2.5-1.dsc create mode 100644 tests/data/test_debs/impossible-build-depends_2.5-1.dsc create mode 100644 tests/data/test_debs/large-package-content_1.0_all.deb create mode 100644 tests/data/test_debs/multiarch-test1_i386.deb create mode 100644 tests/data/test_debs/testdep-allowed-any_1.0-1_i386.deb create mode 100644 tests/data/test_debs/testdep-same-arch_1.0-1_i386.deb create mode 100644 tests/data/test_debs/utf8-package_1.0-1_all.deb create mode 100644 tests/data/test_debs/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_maverick_main_binary-i386_Packages create mode 100644 tests/data/test_debs/var/lib/dpkg/status create mode 100755 tests/fakeroot-apt-key create mode 100755 tests/helper_install_progress_run.py create mode 100644 tests/old/__init__.py create mode 100644 tests/old/apt-test.py create mode 100644 tests/old/cache.py create mode 100644 tests/old/depcache.py create mode 100644 tests/old/lock.py create mode 100644 tests/old/memleak.py create mode 100644 tests/old/pkgproblemresolver.py create mode 100644 tests/old/pkgrecords.py create mode 100644 tests/old/pkgsrcrecords.py create mode 100755 tests/old/refcount.py create mode 100644 tests/old/test_enhances.py create mode 100644 tests/test_all.py create mode 100644 tests/test_apt_cache.py create mode 100644 tests/test_aptsources.py create mode 100755 tests/test_aptsources_deb822.py create mode 100644 tests/test_aptsources_ports.py create mode 100644 tests/test_auth.py create mode 100644 tests/test_cache_invocation.py create mode 100644 tests/test_configuration.py create mode 100644 tests/test_cve_2020_27351.py create mode 100644 tests/test_debfile.py create mode 100644 tests/test_debfile_multiarch.py create mode 100644 tests/test_deps.py create mode 100644 tests/test_group.py create mode 100644 tests/test_hashes.py create mode 100644 tests/test_hashsums.py create mode 100644 tests/test_install_progress_exec.py create mode 100644 tests/test_large_file.py create mode 100644 tests/test_lfs.py create mode 100644 tests/test_lp659438.py create mode 100644 tests/test_paths.py create mode 100644 tests/test_pep484.py create mode 100644 tests/test_policy.py create mode 100644 tests/test_progress.py create mode 100644 tests/test_pyflakes.py create mode 100644 tests/test_signed_usable.py create mode 100644 tests/test_size_to_str.py create mode 100644 tests/test_sourcerecords.py create mode 100644 tests/test_tagfile.py create mode 100644 tests/test_utils.py create mode 100644 tests/testcommon.py (limited to 'tests') diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +# diff --git a/tests/data/aptsources/lsb-release b/tests/data/aptsources/lsb-release new file mode 100644 index 0000000..c4b5944 --- /dev/null +++ b/tests/data/aptsources/lsb-release @@ -0,0 +1,4 @@ +DISTRIB_ID=Ubuntu +DISTRIB_RELEASE=16.04 +DISTRIB_CODENAME=xenial +DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS" diff --git a/tests/data/aptsources/os-release b/tests/data/aptsources/os-release new file mode 100644 index 0000000..95a5bcd --- /dev/null +++ b/tests/data/aptsources/os-release @@ -0,0 +1,10 @@ +NAME="KDE neon" +VERSION="16.04 LTS" +ID=neon +ID_LIKE="ubuntu debian" +PRETTY_NAME="KDE neon User Edition on 16.04 LTS" +VERSION_ID="16.04" +HOME_URL="http://neon.kde.org/" +SUPPORT_URL="http://neon.kde.org/" +BUG_REPORT_URL="http://bugs.kde.org/" +UBUNTU_CODENAME=xenial diff --git a/tests/data/aptsources/sources.list b/tests/data/aptsources/sources.list new file mode 100644 index 0000000..8ca6807 --- /dev/null +++ b/tests/data/aptsources/sources.list @@ -0,0 +1,10 @@ +# comment 1 +deb http://de.archive.ubuntu.com/ubuntu/ edgy main +# comment 2 +deb http://de.archive.ubuntu.com/ubuntu/ edgy restricted +# comment 3 +deb http://de.archive.ubuntu.com/ubuntu/ edgy universe + +# multi-arch +deb [arch=amd64,i386] http://de.archive.ubuntu.com/ubuntu/ natty main +deb [arch=amd64,i386 trusted=yes] http://de.archive.ubuntu.com/ubuntu/ natty main diff --git a/tests/data/aptsources/sources.list.d.testDistribution/main.sources b/tests/data/aptsources/sources.list.d.testDistribution/main.sources new file mode 100644 index 0000000..ccdda20 --- /dev/null +++ b/tests/data/aptsources/sources.list.d.testDistribution/main.sources @@ -0,0 +1,74 @@ +Types: deb +URIs: http://de.archive.ubuntu.com/ubuntu/ +Suites: hardy +Components: main + +Types: deb +URIs: http://de.archive.ubuntu.com/ubuntu/ +Suites: hardy +Components: restricted + +Types: deb +URIs: http://de.archive.ubuntu.com/ubuntu/ +Suites: hardy +Components: universe + +Types: deb +URIs: http://de.archive.ubuntu.com/ubuntu/ +Suites: hardy-updates +Components: universe multiverse + +Types: deb +URIs: http://de.archive.ubuntu.com/ubuntu/ +Suites: hardy-updates +Components: restricted + +Types: deb +URIs: http://de.archive.ubuntu.com/ubuntu/ +Suites: hardy-security +Components: main + +Types: deb +URIs: http://de.archive.ubuntu.com/ubuntu/ +Suites: hardy-security +Components: multiverse + +Types: deb +URIs: http://de.archive.ubuntu.com/ubuntu/ +Suites: hardy-security +Components: multiverse + +Types: deb +URIs: http://ftp.debian.org/debian +Suites: sid +Components: main + +Types: deb +URIs: http://archive.tanglu.org/tanglu +Suites: aequorea +Components: main + +Types: deb +URIs: http://ftp.hosteurope.de/mirror/archive.ubuntu.com/ +Suites: hardy +Components: main + +Types: deb +URIs: http://ftp.hosteurope.de/mirror/archive.ubuntu.com/ +Suites: hardy-backports +Components: main + +Types: deb +URIs: http://archive.ubuntu.com/ubuntu/ +Suites: intrepid +Components: main + +Types: deb +URIs: cdrom:[Ubuntu 8.10 _Intrepid Ibex_ - Alpha]/ +Suites: intrepid +Components: main + +Types: deb +URIs: cdrom:[Ubuntu 8.04 _Hardy Heron_] +Suites: hardy +Components: main diff --git a/tests/data/aptsources/sources.list.d.testDuplication/main.sources b/tests/data/aptsources/sources.list.d.testDuplication/main.sources new file mode 100644 index 0000000..5b7765b --- /dev/null +++ b/tests/data/aptsources/sources.list.d.testDuplication/main.sources @@ -0,0 +1,10 @@ +Types: deb +URIs: http://ppa.launchpad.net/me/myproject/ubuntu +Suites: xenial +Components: main + +Types: deb-src +URIs: http://ppa.launchpad.net/me/myproject/ubuntu +Suites: xenial +Components: main +Enabled: no diff --git a/tests/data/aptsources/sources.list.d/main.sources b/tests/data/aptsources/sources.list.d/main.sources new file mode 100644 index 0000000..2495f06 --- /dev/null +++ b/tests/data/aptsources/sources.list.d/main.sources @@ -0,0 +1,32 @@ +# comment 1 +# note that we have deliberate case typos in each paragraph to test case-insensitivity +TyPes: deb +URIs: http://de.archive.ubuntu.com/ubuntu/ +Suites: edgy +Components: main + +# comment 2 +Types: deb +uRIs: http://de.archive.ubuntu.com/ubuntu/ +Suites: edgy +Components: restricted + +# comment 3 +Types: deb +URIs: http://de.archive.ubuntu.com/ubuntu/ +SuiTes: edgy +Components: universe + +# multi-arch +Types: deb +URIs: http://de.archive.ubuntu.com/ubuntu/ +Suites: natty +ComPonents: main +Architectures: amd64 i386 + +Types: deb +URIs: http://de.archive.ubuntu.com/ubuntu/ +Suites: natty +Components: main +ArchiTectures: amd64 i386 +Trusted: yes diff --git a/tests/data/aptsources/sources.list.testDistribution b/tests/data/aptsources/sources.list.testDistribution new file mode 100644 index 0000000..021ee87 --- /dev/null +++ b/tests/data/aptsources/sources.list.testDistribution @@ -0,0 +1,14 @@ +deb http://de.archive.ubuntu.com/ubuntu/ hardy main +deb http://de.archive.ubuntu.com/ubuntu/ hardy restricted +deb http://de.archive.ubuntu.com/ubuntu/ hardy universe +deb http://de.archive.ubuntu.com/ubuntu/ hardy-updates universe multiverse +deb http://de.archive.ubuntu.com/ubuntu/ hardy-updates restricted +deb http://de.archive.ubuntu.com/ubuntu/ hardy-security main +deb http://de.archive.ubuntu.com/ubuntu/ hardy-security multiverse +deb http://ftp.debian.org/debian sid main +deb http://archive.tanglu.org/tanglu aequorea main +deb http://ftp.hosteurope.de/mirror/archive.ubuntu.com/ hardy main +deb http://ftp.hosteurope.de/mirror/archive.ubuntu.com/ hardy-backports main +deb http://archive.ubuntu.com/ubuntu/ intrepid main +deb cdrom:[Ubuntu 8.10 _Intrepid Ibex_ - Alpha]/ intrepid main +deb cdrom:[Ubuntu 8.04 _Hardy Heron_] hardy main diff --git a/tests/data/aptsources/sources.list.testDuplication b/tests/data/aptsources/sources.list.testDuplication new file mode 100644 index 0000000..28a4db2 --- /dev/null +++ b/tests/data/aptsources/sources.list.testDuplication @@ -0,0 +1,2 @@ +deb http://ppa.launchpad.net/me/myproject/ubuntu xenial main +# deb-src http://ppa.launchpad.net/me/myproject/ubuntu xenial main diff --git a/tests/data/aptsources_ports/sources.list b/tests/data/aptsources_ports/sources.list new file mode 100644 index 0000000..0efa282 --- /dev/null +++ b/tests/data/aptsources_ports/sources.list @@ -0,0 +1,52 @@ +# +# deb cdrom:[Ubuntu-Server 8.04.1 _Hardy Heron_ - Release powerpc (20080703)]/ hardy main restricted + +# deb cdrom:[Ubuntu-Server 8.04.1 _Hardy Heron_ - Release powerpc (20080703)]/ hardy main restricted +# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to +# newer versions of the distribution. + +deb http://ports.ubuntu.com/ubuntu-ports/ hardy main restricted +deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy main restricted + +## Major bug fix updates produced after the final release of the +## distribution. +deb http://ports.ubuntu.com/ubuntu-ports/ hardy-updates main restricted +deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy-updates main restricted + +## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu +## team, and may not be under a free licence. Please satisfy yourself as to +## your rights to use the software. Also, please note that software in +## universe WILL NOT receive any review or updates from the Ubuntu security +## team. +deb http://ports.ubuntu.com/ubuntu-ports/ hardy universe +deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy universe +deb http://ports.ubuntu.com/ubuntu-ports/ hardy-updates universe +deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy-updates universe + +## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu +## team, and may not be under a free licence. Please satisfy yourself as to +## your rights to use the software. Also, please note that software in +## multiverse WILL NOT receive any review or updates from the Ubuntu +## security team. +deb http://ports.ubuntu.com/ubuntu-ports/ hardy multiverse +deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy multiverse +deb http://ports.ubuntu.com/ubuntu-ports/ hardy-updates multiverse +deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy-updates multiverse + +## Uncomment the following two lines to add software from the 'backports' +## repository. +## N.B. software from this repository may not have been tested as +## extensively as that contained in the main release, although it includes +## newer versions of some applications which may provide useful features. +## Also, please note that software in backports WILL NOT receive any review +## or updates from the Ubuntu security team. +# deb http://ports.ubuntu.com/ubuntu-ports/ hardy-backports main restricted universe multiverse +# deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy-backports main restricted universe multiverse + +deb http://ports.ubuntu.com/ubuntu-ports/ hardy-security main restricted +deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy-security main restricted +deb http://ports.ubuntu.com/ubuntu-ports/ hardy-security universe +deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy-security universe +deb http://ports.ubuntu.com/ubuntu-ports/ hardy-security multiverse +deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy-security multiverse +deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy-proposed restricted main multiverse universe diff --git a/tests/data/fake-packages/Packages b/tests/data/fake-packages/Packages new file mode 100644 index 0000000..9fbab95 --- /dev/null +++ b/tests/data/fake-packages/Packages @@ -0,0 +1,21 @@ +Package: 2vcard +Priority: optional +Section: universe/utils +Installed-Size: 108 +Maintainer: Arvind Autar +Architecture: amd64 +Version: 0.5-1ubuntu1 +Filename: pool/universe/2/2vcard/2vcard_0.5-1ubuntu1_amd64.deb +Size: 14164 +MD5sum: 105ea91f0a75417d0f9e8e9624513b2a +SHA1: d55beee01c08efc33cd131e106330dca72ee14be +SHA256: 4a72edaf87cdb826e5508b85311fcf0bec9b7e019a55740ded7feb1b9e197f11 +Description: A little perl script to convert an adressbook to VCARD file format + 2vcard is a little perl script that you can use to convert the popular vcard + file format. Currently 2vcard can only convert adressbooks and alias files from + the following formats: abook,eudora,juno,ldif,mutt,mh and pine. + . + The VCARD format is used by gnomecard, for example, which is turn is used by + the balsa email client. +Bugs: mailto:ubuntu-users@lists.ubuntu.com +Origin: Ubuntu diff --git a/tests/data/fake-packages/Packages.gz b/tests/data/fake-packages/Packages.gz new file mode 100644 index 0000000..506bc8d Binary files /dev/null and b/tests/data/fake-packages/Packages.gz differ diff --git a/tests/data/hashsums/hashsum_test.data b/tests/data/hashsums/hashsum_test.data new file mode 100644 index 0000000..1910281 --- /dev/null +++ b/tests/data/hashsums/hashsum_test.data @@ -0,0 +1 @@ +foo \ No newline at end of file diff --git a/tests/data/hashsums/hashsum_test_with_zero.data b/tests/data/hashsums/hashsum_test_with_zero.data new file mode 100644 index 0000000..2ec9a6d Binary files /dev/null and b/tests/data/hashsums/hashsum_test_with_zero.data differ diff --git a/tests/data/misc/foo_Release b/tests/data/misc/foo_Release new file mode 100644 index 0000000..0f42220 --- /dev/null +++ b/tests/data/misc/foo_Release @@ -0,0 +1,492 @@ +Origin: Ubuntu +Label: Ubuntu +Suite: precise +Version: 12.04 +Codename: precise +Date: Wed, 25 Apr 2012 22:49:23 UTC +Architectures: amd64 armel armhf i386 powerpc +Components: main restricted universe multiverse +Description: Ubuntu Precise 12.04 +MD5Sum: + 6a815674c5b3178152d449a9396cb2e5 1640344 main/binary-amd64/Packages.gz + 98140fa3444c9e945f6944acbb9ddcff 7818931 main/binary-amd64/Packages + 846e0e856bcbf9b64d9119c8727cda8c 97 main/binary-amd64/Release + cfd5f57de107941bbe661ffada4dce88 1272844 main/binary-amd64/Packages.bz2 + 5b220aea8056a900c8eaf28e79cdd64a 97 main/binary-armel/Release + 92e3160bbb664f8b5d7d4f2d161dd81c 1619078 main/binary-armel/Packages.gz + 28fbf69ee965639c92c8a54256cd6ba1 1257389 main/binary-armel/Packages.bz2 + 4e3ba67129f73f8afe28186b31eb3112 7743353 main/binary-armel/Packages + 81cfd32bf54d2b007542e14e09953bae 97 main/binary-armhf/Release + ed404b1123d1497cb09aceae8850fc06 7620333 main/binary-armhf/Packages + 64156d29df19fdaa36fa4eafd4c17dc1 1257653 main/binary-armhf/Packages.bz2 + 3d3238bd89cb1e8e23a1a4a5bf574739 1617483 main/binary-armhf/Packages.gz + dc2fe62f05e29f36ffe4e58499796ae6 1273857 main/binary-i386/Packages.bz2 + 7c678c50ce682e9f5cc5ba8f8eb2d6ad 1641082 main/binary-i386/Packages.gz + b6aa9a96c765bbd4202dae7dbaf18cc2 96 main/binary-i386/Release + eb3b4870b877863fecf1d3307c3beb54 7816415 main/binary-i386/Packages + 54658d89b612a38592431fe6b8a780a1 1627734 main/binary-powerpc/Packages.gz + 4185aca6984f00fd65aa0c0de12367d4 99 main/binary-powerpc/Release + fc9bf1959082733fc42c682285bf46e7 1263942 main/binary-powerpc/Packages.bz2 + c32afd79c9163cffe013f98669deb727 7661552 main/binary-powerpc/Packages + ff5434612595a569236f7ba4990a3b63 62166 main/debian-installer/binary-amd64/Packages.gz + 7dd470290bacbacc7bec24830100aade 234592 main/debian-installer/binary-amd64/Packages + 013d9839e9c8f8c102daf6eb77841bf7 48784 main/debian-installer/binary-amd64/Packages.bz2 + 08608ef832f2410970d07fdd802fc4e4 47964 main/debian-installer/binary-armel/Packages.bz2 + 0a0a559023aac4096a38e2fb51870ddf 230310 main/debian-installer/binary-armel/Packages + f79f29b841a05b971ac318a9e0a396e0 61118 main/debian-installer/binary-armel/Packages.gz + 20a72276b6607fa58f52fcc5b7742ff4 62777 main/debian-installer/binary-armhf/Packages.gz + 8da4a15400cec4b06e2aa1bba6cfc2c3 49051 main/debian-installer/binary-armhf/Packages.bz2 + 49f9f82a7c7e9e13c399d15df43148f1 238862 main/debian-installer/binary-armhf/Packages + 3dd181be504206f7abb41039dc508ed9 52279 main/debian-installer/binary-i386/Packages.bz2 + 5c2c6ca586bb6ffb2de414e2cd063c70 259996 main/debian-installer/binary-i386/Packages + ca1b7db323ebef593617ef0a7c833dfb 67180 main/debian-installer/binary-i386/Packages.gz + 876f115ee26518319458fc26ec785485 246636 main/debian-installer/binary-powerpc/Packages + 49402b5b12b10804abfae14629d23f1c 50309 main/debian-installer/binary-powerpc/Packages.bz2 + 29010a7ba3ac1e60a0efaef04f6f2e42 64468 main/debian-installer/binary-powerpc/Packages.gz + adf74189a01512a8f68d4bfc411dc692 3706 main/i18n/Index + 2f2ddab9be4ecc2c9e190bb639304943 4356187 main/source/Sources + 5c2893c352ebbf3ee380ebdab6b5e487 933770 main/source/Sources.bz2 + 323e5ca1ba86c7a503c4c7b0772749b1 1174967 main/source/Sources.gz + 3c3104465b2c7e54f4b8f566ac825339 98 main/source/Release + f75f8a98e9e952194046da388a11c42a 119109 multiverse/binary-amd64/Packages.bz2 + c2df9a9ff319486e3d6f46d9c35a8530 151924 multiverse/binary-amd64/Packages.gz + ece719c6a770134150f158cdb65ca6fc 581550 multiverse/binary-amd64/Packages + d3f34ec2fc86c95e4d3bc4606d751c66 103 multiverse/binary-amd64/Release + f296954282382f88b12dd8c64d813f5c 136295 multiverse/binary-armel/Packages.gz + d0da88f8a408fba12d44d5b6e107cfc0 519605 multiverse/binary-armel/Packages + 6d0c32b1cae4bdcfd6f18fd2d6fbf31f 103 multiverse/binary-armel/Release + 6744aaa8a3457d139348ea18379781ce 106873 multiverse/binary-armel/Packages.bz2 + 1cc2613becf46fd578aa6d52ab12db94 104529 multiverse/binary-armhf/Packages.bz2 + b0f8df0c9d700a1f7d295be4d4c03788 505901 multiverse/binary-armhf/Packages + 73cb5bc3d0c5021e5a4a413a73bcefce 103 multiverse/binary-armhf/Release + 00c07f1601226b8387fe4c9afaf2b044 133117 multiverse/binary-armhf/Packages.gz + bf0237c8c5d06a6df172db28710b8a36 121196 multiverse/binary-i386/Packages.bz2 + cf110f58668bf5731e593ed78af54c27 591662 multiverse/binary-i386/Packages + 8a915986a504c0f3eb95b61ae909c9a4 102 multiverse/binary-i386/Release + c6d89a2752d1154a219c295e6d70b697 154762 multiverse/binary-i386/Packages.gz + ae93681c6b316c95207091b3c91042a7 105 multiverse/binary-powerpc/Release + ec463c2070c515de099f8baa3a4b5993 107209 multiverse/binary-powerpc/Packages.bz2 + 675204a2b4aabeb9e99e406070b2af9b 520882 multiverse/binary-powerpc/Packages + c806ea7584c782d57363df12ddb28839 136930 multiverse/binary-powerpc/Packages.gz + d41d8cd98f00b204e9800998ecf8427e 0 multiverse/debian-installer/binary-amd64/Packages + 4a4dd3598707603b3f76a2378a4504aa 20 multiverse/debian-installer/binary-amd64/Packages.gz + 4059d198768f9f8dc9372dc1c54bc3c3 14 multiverse/debian-installer/binary-amd64/Packages.bz2 + 4059d198768f9f8dc9372dc1c54bc3c3 14 multiverse/debian-installer/binary-armel/Packages.bz2 + d41d8cd98f00b204e9800998ecf8427e 0 multiverse/debian-installer/binary-armel/Packages + 4a4dd3598707603b3f76a2378a4504aa 20 multiverse/debian-installer/binary-armel/Packages.gz + 4a4dd3598707603b3f76a2378a4504aa 20 multiverse/debian-installer/binary-armhf/Packages.gz + d41d8cd98f00b204e9800998ecf8427e 0 multiverse/debian-installer/binary-armhf/Packages + 4059d198768f9f8dc9372dc1c54bc3c3 14 multiverse/debian-installer/binary-armhf/Packages.bz2 + 4059d198768f9f8dc9372dc1c54bc3c3 14 multiverse/debian-installer/binary-i386/Packages.bz2 + 4a4dd3598707603b3f76a2378a4504aa 20 multiverse/debian-installer/binary-i386/Packages.gz + d41d8cd98f00b204e9800998ecf8427e 0 multiverse/debian-installer/binary-i386/Packages + 4a4dd3598707603b3f76a2378a4504aa 20 multiverse/debian-installer/binary-powerpc/Packages.gz + d41d8cd98f00b204e9800998ecf8427e 0 multiverse/debian-installer/binary-powerpc/Packages + 4059d198768f9f8dc9372dc1c54bc3c3 14 multiverse/debian-installer/binary-powerpc/Packages.bz2 + a2bcfa86da39328db94629011506a877 2676 multiverse/i18n/Index + c2ffda2a848000b71573dbc3dc7d4402 154990 multiverse/source/Sources.bz2 + f1d64bb88933686a71108de73b1f2262 628753 multiverse/source/Sources + 3d35747578528fa13640b98184120e51 188325 multiverse/source/Sources.gz + c9828946b46ac900fec682369c52bfa7 104 multiverse/source/Release + 5644835af0d1ed82cc7c14e34c2a543f 9098 restricted/binary-amd64/Packages.gz + d3058923c862e74c2c08b9a4ad7ec51e 134705 restricted/binary-amd64/Packages + 97ecff09a695f1460177843ff5d2b3e6 103 restricted/binary-amd64/Release + f8ed966e5400930411a32a7183357810 8452 restricted/binary-amd64/Packages.bz2 + 60e74c701a6e40b7f869dd83b335ec5c 103 restricted/binary-armel/Release + 4a4dd3598707603b3f76a2378a4504aa 20 restricted/binary-armel/Packages.gz + 4059d198768f9f8dc9372dc1c54bc3c3 14 restricted/binary-armel/Packages.bz2 + d41d8cd98f00b204e9800998ecf8427e 0 restricted/binary-armel/Packages + 55c08a48fc4b3370acc95a391bde1189 103 restricted/binary-armhf/Release + ce2da4621bbbaf55d858ae4243e17715 1103 restricted/binary-armhf/Packages.bz2 + b26814493282faf0c5b269c44b799653 2477 restricted/binary-armhf/Packages + 784050b4fd16ea71e10cf130e47132d9 941 restricted/binary-armhf/Packages.gz + c4280a67444afbb8e2564d6f2249d397 9108 restricted/binary-i386/Packages.gz + 6dfd90555b37a912f82894b4ec3b63a0 8431 restricted/binary-i386/Packages.bz2 + 48d3e36bf54be9b3fc7576cfcd0aac79 134582 restricted/binary-i386/Packages + e49b38cbf4dc409e8c25f6ab4b32fbe4 102 restricted/binary-i386/Release + 4a4dd3598707603b3f76a2378a4504aa 20 restricted/binary-powerpc/Packages.gz + 4059d198768f9f8dc9372dc1c54bc3c3 14 restricted/binary-powerpc/Packages.bz2 + d41d8cd98f00b204e9800998ecf8427e 0 restricted/binary-powerpc/Packages + edb68a453747a9faa9e98389787fb79d 105 restricted/binary-powerpc/Release + d41d8cd98f00b204e9800998ecf8427e 0 restricted/debian-installer/binary-amd64/Packages + 4059d198768f9f8dc9372dc1c54bc3c3 14 restricted/debian-installer/binary-amd64/Packages.bz2 + 4a4dd3598707603b3f76a2378a4504aa 20 restricted/debian-installer/binary-amd64/Packages.gz + 4a4dd3598707603b3f76a2378a4504aa 20 restricted/debian-installer/binary-armel/Packages.gz + 4059d198768f9f8dc9372dc1c54bc3c3 14 restricted/debian-installer/binary-armel/Packages.bz2 + d41d8cd98f00b204e9800998ecf8427e 0 restricted/debian-installer/binary-armel/Packages + 4059d198768f9f8dc9372dc1c54bc3c3 14 restricted/debian-installer/binary-armhf/Packages.bz2 + 4a4dd3598707603b3f76a2378a4504aa 20 restricted/debian-installer/binary-armhf/Packages.gz + d41d8cd98f00b204e9800998ecf8427e 0 restricted/debian-installer/binary-armhf/Packages + 4a4dd3598707603b3f76a2378a4504aa 20 restricted/debian-installer/binary-i386/Packages.gz + 4059d198768f9f8dc9372dc1c54bc3c3 14 restricted/debian-installer/binary-i386/Packages.bz2 + d41d8cd98f00b204e9800998ecf8427e 0 restricted/debian-installer/binary-i386/Packages + 4a4dd3598707603b3f76a2378a4504aa 20 restricted/debian-installer/binary-powerpc/Packages.gz + 4059d198768f9f8dc9372dc1c54bc3c3 14 restricted/debian-installer/binary-powerpc/Packages.bz2 + d41d8cd98f00b204e9800998ecf8427e 0 restricted/debian-installer/binary-powerpc/Packages + 39ef6c1d54f83252b07406f9cc3e9204 2596 restricted/i18n/Index + a76089a7a653d4f2196c38093058d1aa 19001 restricted/source/Sources + 3990b36e6ef2846251b58a58cde3768d 5470 restricted/source/Sources.bz2 + f0a32107aaf12daf3e64b4dc3ee11321 5306 restricted/source/Sources.gz + 7871a3f6f83e033ab93c06bf886e305d 104 restricted/source/Release + 3464b1b15950e714151f8bb43982951e 25546870 universe/binary-amd64/Packages + 9340d5c4051da92820bb5bd5ba05f7a7 4785960 universe/binary-amd64/Packages.bz2 + 1f6974aea9904921afdb4d1c5d0e8578 6166988 universe/binary-amd64/Packages.gz + 75ea366982b4862a41d9640687778dd2 101 universe/binary-amd64/Release + 5492f7f7183461d52f8d58871026c3e8 101 universe/binary-armel/Release + 420abe7ca02b5cb2abcd1b273efcfea9 4667308 universe/binary-armel/Packages.bz2 + 4da3448f54e710222b26646b0bee14e8 6009219 universe/binary-armel/Packages.gz + e99405db74ba425a3f898fdda0a42113 24901082 universe/binary-armel/Packages + d0545845bbcff572a5c852b80582b269 5948128 universe/binary-armhf/Packages.gz + 8f0d262f1eb03fc3523cd80b3112a7e0 101 universe/binary-armhf/Release + a10169d0cc23f526bcee5769d27778b0 4618508 universe/binary-armhf/Packages.bz2 + 952259d2cdb2c85df177702ac92075a0 24642528 universe/binary-armhf/Packages + df43c3b4ec37e79a00023475a09e2bfa 6179579 universe/binary-i386/Packages.gz + cc44a3e2ad759febb38ef2bec15ab29e 25568759 universe/binary-i386/Packages + 826b1d8609f0944a6d2ae95617e4d05a 100 universe/binary-i386/Release + 50690005918dd03ad9b71ffffa678d6f 4795820 universe/binary-i386/Packages.bz2 + 8a1f21204f4178574251a2238c00f317 25188905 universe/binary-powerpc/Packages + 7409876b9e1238d5a147720b41233a26 6080488 universe/binary-powerpc/Packages.gz + 9bcc15c59aa3fbbd15f0d187fe90b353 4716652 universe/binary-powerpc/Packages.bz2 + c3bdb05d2be1efa2dca9d2bac4e85b13 103 universe/binary-powerpc/Release + f8259410f0e1ad66324dbce895fdde2d 15255 universe/debian-installer/binary-amd64/Packages.bz2 + ce60affbf23a069735c29951bfb0b818 17243 universe/debian-installer/binary-amd64/Packages.gz + 13ce59ecd4540ddef3670dbbed73cdbc 61801 universe/debian-installer/binary-amd64/Packages + 988da583db40ce21d400926641fe6ed8 113584 universe/debian-installer/binary-armel/Packages + 75381e3ed15a3a2fa1480fdea72cfd24 23193 universe/debian-installer/binary-armel/Packages.bz2 + 4a8e6a98277f254660e8690fd050b232 27397 universe/debian-installer/binary-armel/Packages.gz + 02e7128ef42cd61e66c768520961fb11 20065 universe/debian-installer/binary-armhf/Packages.gz + 851afb686177a6819b291a714fa15813 17619 universe/debian-installer/binary-armhf/Packages.bz2 + ce3b6645e37226c4047546a40675ecdd 76034 universe/debian-installer/binary-armhf/Packages + 229235ad9979a343e3bea9aedb5af8da 17260 universe/debian-installer/binary-i386/Packages.gz + 8065c9994844e578af00ef8794709b18 15272 universe/debian-installer/binary-i386/Packages.bz2 + f28d6328611ab1e382fb0d0e798aca97 61718 universe/debian-installer/binary-i386/Packages + 60f54adbd38213dbbfe5d638f98a17e9 61121 universe/debian-installer/binary-powerpc/Packages + 1d48a07b3f4214200ff3eb1c5894e4a1 15024 universe/debian-installer/binary-powerpc/Packages.bz2 + 51eb13c4b9baf089e4e8b0e85556b90e 16860 universe/debian-installer/binary-powerpc/Packages.gz + 155e0b646671f37a7fe235c4579e59f2 2922 universe/i18n/Index + 2ef7ccbe106edb394dc69d8511775122 21256524 universe/source/Sources + e52b7cb491cc6a950cd11fa6263d7330 5019105 universe/source/Sources.bz2 + c722166709cfe9c398643b9c1a443610 102 universe/source/Release + 5ddd8bd0dda063b203d1a1da150983a0 6238766 universe/source/Sources.gz +SHA1: + 0b326daa3b2ac8748ca10942aaec15ebdcc78b36 1640344 main/binary-amd64/Packages.gz + 8a6068a75feb86e12b088dad2478600f6670f2d7 7818931 main/binary-amd64/Packages + 19655f20d48d9819ad95f2c9ecc59e5b1d94c3d0 97 main/binary-amd64/Release + f9761ecf8536859ef38b670a7f17d83febec4a37 1272844 main/binary-amd64/Packages.bz2 + a3a5faadbdf0a49d1587f07181b9eca870cb24ce 97 main/binary-armel/Release + 3c5d8f3a401427110adfd7f7d65513bfa47b933a 1619078 main/binary-armel/Packages.gz + 4d54e387978fdf829b4ff7336ed4d02e61c54d6a 1257389 main/binary-armel/Packages.bz2 + 969dfd243cc3f514eea9914de571db28621cd9bd 7743353 main/binary-armel/Packages + f8f33265eab2ff9fd8a6353e014e36a9d318a54d 97 main/binary-armhf/Release + 1d210f8ad3547b771bc8c8d2a9eb5ee99d437d81 7620333 main/binary-armhf/Packages + 5057a8b2d11d2325bb2546ad6613517b208fff18 1257653 main/binary-armhf/Packages.bz2 + 25fc010c2789028727308fbf6132a8da387423b8 1617483 main/binary-armhf/Packages.gz + 79369a31bc481f7f9f71f666906c3bdb356c44d8 1273857 main/binary-i386/Packages.bz2 + aaadaa6eaf0b7e73b0d371cdebae573f28833a43 1641082 main/binary-i386/Packages.gz + 6f8e5e9dd04a2379a7c6d8dc23b4ff8df5584741 96 main/binary-i386/Release + 8509eead0c5e9410e23d4226ee5d190220db1275 7816415 main/binary-i386/Packages + 7da3fd8ad7102912a4cc9882c66fbb1b65edd4c0 1627734 main/binary-powerpc/Packages.gz + 8a0c3b7757b738a89644e8c5a3b9afed806d2f83 99 main/binary-powerpc/Release + 4063338a28f6504f7bc2f9c00fc34ac26fc5a1fa 1263942 main/binary-powerpc/Packages.bz2 + 81844e44aaf0ed255ca200e7316bc9279ef238b6 7661552 main/binary-powerpc/Packages + d17439034551742aaa4762b4c174c1d72881f49f 62166 main/debian-installer/binary-amd64/Packages.gz + 05e024776b06a40253b9e252caad6dc4a13a90b9 234592 main/debian-installer/binary-amd64/Packages + fa692a307ecab69c106a5253107f980527cf58a9 48784 main/debian-installer/binary-amd64/Packages.bz2 + fb8be98ef08265d2f101cf265b9bf37654d750ac 47964 main/debian-installer/binary-armel/Packages.bz2 + 8953964fd2b54539e8276237cd5e4e2d4f9dc2ab 230310 main/debian-installer/binary-armel/Packages + cfdde60bbcbfb25c66fa474d28217e03a4c06789 61118 main/debian-installer/binary-armel/Packages.gz + 468306dc06acc828c50196427ba324c8ce225c79 62777 main/debian-installer/binary-armhf/Packages.gz + 17e7331a837675de31c365529ea9454cc48baf98 49051 main/debian-installer/binary-armhf/Packages.bz2 + 3404140163a5acece9a054912abf72d11a5591d0 238862 main/debian-installer/binary-armhf/Packages + 2bb7e052999eadc333a9f6481bdc20acb238d4c1 52279 main/debian-installer/binary-i386/Packages.bz2 + b2ad69cd6759724461c3566d91c1c5ec209eba07 259996 main/debian-installer/binary-i386/Packages + ebd0ab3923b3df4eca53eb863773bf0a9a4c3a67 67180 main/debian-installer/binary-i386/Packages.gz + eff551b62b72a1c0b183d4903a1452f2be08f3da 246636 main/debian-installer/binary-powerpc/Packages + 5c8aa09d48d7a792d555e7b16f4c89733e8441af 50309 main/debian-installer/binary-powerpc/Packages.bz2 + 582a86208e89e77a7f284e10a50b9cceaf4358ee 64468 main/debian-installer/binary-powerpc/Packages.gz + f426621b1015147e766dc003d1d2f140dc9c062d 3706 main/i18n/Index + b22a946cdae39d29535a63b020c0f2ad74c3c992 4356187 main/source/Sources + 711225fd252e77d85c7bb992aeb5aa5e45414ae1 933770 main/source/Sources.bz2 + a8807bf20dbaceb9d408f959840951131fd7d9f9 1174967 main/source/Sources.gz + cc2d2f6ce53597666df1a5ab216a08f08995f43f 98 main/source/Release + 06b070fc1ae771806c65e791742832320cc588e7 119109 multiverse/binary-amd64/Packages.bz2 + ae591617f4b6f988d6534270d4c32e3f0876166b 151924 multiverse/binary-amd64/Packages.gz + a28786a87a6136fb74a005c480c78a152123b9c0 581550 multiverse/binary-amd64/Packages + 3860a3ce6d87bb8a43803a1048cc96d4de3ae8a7 103 multiverse/binary-amd64/Release + 4bae80c3f5270e45f825141bcadb94d7dd82cd0e 136295 multiverse/binary-armel/Packages.gz + 9534dfc2e4a40386f48eff79062ee1742212b7d3 519605 multiverse/binary-armel/Packages + 92d1536ae99c958afd74299ffe30bdc6800cd8d0 103 multiverse/binary-armel/Release + 8e3ec557dc8f750e82e8ed5cbb0c509182feba79 106873 multiverse/binary-armel/Packages.bz2 + 009531e7cfb08701883a9e7a5f50235325e109cd 104529 multiverse/binary-armhf/Packages.bz2 + 596a666233560852574d9bca0109f4933a12c949 505901 multiverse/binary-armhf/Packages + eca4ab620c41d76c00a9615d8530db5a9c918fe8 103 multiverse/binary-armhf/Release + 53916a24cff0523e218bfee2c5464866d2099042 133117 multiverse/binary-armhf/Packages.gz + a7518b6b3e693d840a49b125020785d2049e75b9 121196 multiverse/binary-i386/Packages.bz2 + 84069f1643bd0092f4ec1b24eb921310532d72b2 591662 multiverse/binary-i386/Packages + 1d42b054d297b33cf69af011fa91f601c6b1a1b9 102 multiverse/binary-i386/Release + 8eae892b29234e9aac4c58a7098b097fe5ebde16 154762 multiverse/binary-i386/Packages.gz + 873bc8f864de428a4a47a3afaf53bc3a3a6e81c0 105 multiverse/binary-powerpc/Release + 665942774934afa56721d082a398735a067afe91 107209 multiverse/binary-powerpc/Packages.bz2 + c965416be0f7bf88c78394becf4a72aee342b829 520882 multiverse/binary-powerpc/Packages + e304951d28df0b75065fd3ef8166c65415a3cad2 136930 multiverse/binary-powerpc/Packages.gz + da39a3ee5e6b4b0d3255bfef95601890afd80709 0 multiverse/debian-installer/binary-amd64/Packages + a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 multiverse/debian-installer/binary-amd64/Packages.gz + 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 multiverse/debian-installer/binary-amd64/Packages.bz2 + 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 multiverse/debian-installer/binary-armel/Packages.bz2 + da39a3ee5e6b4b0d3255bfef95601890afd80709 0 multiverse/debian-installer/binary-armel/Packages + a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 multiverse/debian-installer/binary-armel/Packages.gz + a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 multiverse/debian-installer/binary-armhf/Packages.gz + da39a3ee5e6b4b0d3255bfef95601890afd80709 0 multiverse/debian-installer/binary-armhf/Packages + 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 multiverse/debian-installer/binary-armhf/Packages.bz2 + 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 multiverse/debian-installer/binary-i386/Packages.bz2 + a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 multiverse/debian-installer/binary-i386/Packages.gz + da39a3ee5e6b4b0d3255bfef95601890afd80709 0 multiverse/debian-installer/binary-i386/Packages + a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 multiverse/debian-installer/binary-powerpc/Packages.gz + da39a3ee5e6b4b0d3255bfef95601890afd80709 0 multiverse/debian-installer/binary-powerpc/Packages + 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 multiverse/debian-installer/binary-powerpc/Packages.bz2 + 09a8aff01c419e0eae19749acf3b223e1f95eccc 2676 multiverse/i18n/Index + a088c61bca210afebf4c53904049e2a969d8ece3 154990 multiverse/source/Sources.bz2 + df4078a91645024ce93b1ee363003c83ffa2aa84 628753 multiverse/source/Sources + e6ec0430d594fa7fa2c98cb9a5fa8ac7ed0d506d 188325 multiverse/source/Sources.gz + 0750588f28b1c2cf6a005501c7d027cfa663cce1 104 multiverse/source/Release + 200fdeee1984ac78b6fdabfad34d2b485512ca2d 9098 restricted/binary-amd64/Packages.gz + 0e7ebd3d2690c7f89d19f8b337cf292cac913c18 134705 restricted/binary-amd64/Packages + c968d68baa554ffc7009688ee7d0d3e70663243c 103 restricted/binary-amd64/Release + 4185a5b6c2e702ea4754437ebfef23d828ec67a0 8452 restricted/binary-amd64/Packages.bz2 + 27886dcc6c7d08369cc65d4c35f26b806f57be56 103 restricted/binary-armel/Release + a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 restricted/binary-armel/Packages.gz + 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 restricted/binary-armel/Packages.bz2 + da39a3ee5e6b4b0d3255bfef95601890afd80709 0 restricted/binary-armel/Packages + d83803a5f6c2f5c7321d68d126733b6015c8e2a9 103 restricted/binary-armhf/Release + 6607111b78dcd3de05cb88692c1e2142abf9a4c1 1103 restricted/binary-armhf/Packages.bz2 + b9f55d161632f89b5125a638ca6ad4fe5e9d11fe 2477 restricted/binary-armhf/Packages + d0c0a616aeac580d13256693cfbd507ae7c9b280 941 restricted/binary-armhf/Packages.gz + f3e483bbe77cbf0f64accbd0291df19b4e4d694b 9108 restricted/binary-i386/Packages.gz + 48d76b03a19e4d66d6f7a20339dab91acebaba99 8431 restricted/binary-i386/Packages.bz2 + 3ca46ea8f32b7cbc49ce76dd1c1ab91589900fd7 134582 restricted/binary-i386/Packages + 2aad61f5084ecdd64ff520520d77e980e8b21f81 102 restricted/binary-i386/Release + a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 restricted/binary-powerpc/Packages.gz + 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 restricted/binary-powerpc/Packages.bz2 + da39a3ee5e6b4b0d3255bfef95601890afd80709 0 restricted/binary-powerpc/Packages + 6b0a230bbf47463e3d7e88f535e210aaa96a1251 105 restricted/binary-powerpc/Release + da39a3ee5e6b4b0d3255bfef95601890afd80709 0 restricted/debian-installer/binary-amd64/Packages + 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 restricted/debian-installer/binary-amd64/Packages.bz2 + a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 restricted/debian-installer/binary-amd64/Packages.gz + a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 restricted/debian-installer/binary-armel/Packages.gz + 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 restricted/debian-installer/binary-armel/Packages.bz2 + da39a3ee5e6b4b0d3255bfef95601890afd80709 0 restricted/debian-installer/binary-armel/Packages + 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 restricted/debian-installer/binary-armhf/Packages.bz2 + a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 restricted/debian-installer/binary-armhf/Packages.gz + da39a3ee5e6b4b0d3255bfef95601890afd80709 0 restricted/debian-installer/binary-armhf/Packages + a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 restricted/debian-installer/binary-i386/Packages.gz + 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 restricted/debian-installer/binary-i386/Packages.bz2 + da39a3ee5e6b4b0d3255bfef95601890afd80709 0 restricted/debian-installer/binary-i386/Packages + a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 restricted/debian-installer/binary-powerpc/Packages.gz + 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 restricted/debian-installer/binary-powerpc/Packages.bz2 + da39a3ee5e6b4b0d3255bfef95601890afd80709 0 restricted/debian-installer/binary-powerpc/Packages + d59f5ac2532dcc7cb2f1e5b788c700bf8ab13b66 2596 restricted/i18n/Index + 8a80cdcf50cdcabcf4f47c772d7b252587cc9dc1 19001 restricted/source/Sources + ff7d82cf1d965953c745d224a1d4adc67b586528 5470 restricted/source/Sources.bz2 + f64da9da2038712c5d73ce3337e91d92ee39cd30 5306 restricted/source/Sources.gz + 5c963f5f4d4720afa5fbb914375d0033bcd50078 104 restricted/source/Release + 10c6989f4a241aabe00146905e776391fc4d9ac0 25546870 universe/binary-amd64/Packages + f6900616102430e0eafa8ac89795efff7edc0710 4785960 universe/binary-amd64/Packages.bz2 + 4f938bde9dff32a49bccd917613666017185882d 6166988 universe/binary-amd64/Packages.gz + 9d6cba1ed46b5eee1f6c065934e5f4854b3efee5 101 universe/binary-amd64/Release + 3573e863c714c0a083f9c962ea9136916f796e92 101 universe/binary-armel/Release + bb8f53ead3723737c13950e5343327884f737da9 4667308 universe/binary-armel/Packages.bz2 + 43d9a98706b6e50c21092ce35313b5b034f30d01 6009219 universe/binary-armel/Packages.gz + 7f97dcbe710882d281efcfd2f8d70ca7d4e47265 24901082 universe/binary-armel/Packages + 8f6d42d7f8178a51a7065d7bf3234eecbca12810 5948128 universe/binary-armhf/Packages.gz + ea648f433d0edd47de820582fa6a1cd89ef66681 101 universe/binary-armhf/Release + e6ad9bdb18ce9e09e262b9e6f85b0b307a3456f1 4618508 universe/binary-armhf/Packages.bz2 + ba55530da6c3a9604977ea4a37b4b4d8943ff994 24642528 universe/binary-armhf/Packages + 05de59263866a33c104787943347164e7b124aba 6179579 universe/binary-i386/Packages.gz + 286a3dd2fda0d98d2ff14eafee0bba5c912d6df2 25568759 universe/binary-i386/Packages + 839529b6f6e2a64465e4a825fa5ad46a36f1c73d 100 universe/binary-i386/Release + 70c27be4d8bc87dc26bbe6f21fbb7328dc1c4d01 4795820 universe/binary-i386/Packages.bz2 + 06af7fdef1a54920a7667728a7b810553d00a9c8 25188905 universe/binary-powerpc/Packages + 4df1b07075b25ccae6e60d26d5a5761444ece689 6080488 universe/binary-powerpc/Packages.gz + 15d041ad1284527b07f75218cf6eb32322092f84 4716652 universe/binary-powerpc/Packages.bz2 + 42d6a46ed2e525b219f8f6dc076dadbd06fc7f1b 103 universe/binary-powerpc/Release + 92c3bef6ad40051021a4e9dadb16e5edc7410b57 15255 universe/debian-installer/binary-amd64/Packages.bz2 + 31d8725b0d238c282d9b572bb56b7e45c0ff53f8 17243 universe/debian-installer/binary-amd64/Packages.gz + e334a7c80e14dae3055950d9e45213db65d4087b 61801 universe/debian-installer/binary-amd64/Packages + 1fd1ae2b87eb85525b173ea982d15f3c98e6e33d 113584 universe/debian-installer/binary-armel/Packages + c56579feb77b5aac2d261abbbb6c89a1458ca4d9 23193 universe/debian-installer/binary-armel/Packages.bz2 + e4b08e57397f3ab0599e0bf6a2fbcba3aed438b5 27397 universe/debian-installer/binary-armel/Packages.gz + 5a9608213061eab983392258288e8aec36d006f0 20065 universe/debian-installer/binary-armhf/Packages.gz + dc558d56aef72991a3188909a14f752aabdee325 17619 universe/debian-installer/binary-armhf/Packages.bz2 + c6afa0e14c706aceea60aad033b6a067320fc165 76034 universe/debian-installer/binary-armhf/Packages + f359cf916a19055133546a7b7f3e35c7c260488e 17260 universe/debian-installer/binary-i386/Packages.gz + 23920ee4974d88ba824b0e884f8df6e2711a20db 15272 universe/debian-installer/binary-i386/Packages.bz2 + 21cfd020eefc848307fac14b8f0efe0d6cd9c6ea 61718 universe/debian-installer/binary-i386/Packages + f2ff72c8f1fe4ce40ccf44f8ccd6623cedf4e6f0 61121 universe/debian-installer/binary-powerpc/Packages + bd9c731941b261b22c022d97ca139bfeb1ad70ba 15024 universe/debian-installer/binary-powerpc/Packages.bz2 + e173071bda799068783c9192bff6536db9790a27 16860 universe/debian-installer/binary-powerpc/Packages.gz + 59a86abaed7cab292600b6766b18752b7e7c3d49 2922 universe/i18n/Index + 4b0ed5f327b0fa9b3f9d9410933a3d2afe467a7e 21256524 universe/source/Sources + d0525203f9ad5ec9183996e6765d0ef9a024691f 5019105 universe/source/Sources.bz2 + 00847d46051ba44d436000b0394b218503de125b 102 universe/source/Release + d9706a8ab2ffeadb51b50d042712536a95dc4343 6238766 universe/source/Sources.gz +SHA256: + 0d61aacd269015c0abfe01fe7f90a4f534c368e9c513f7e90d3111af82656b3d 1640344 main/binary-amd64/Packages.gz + a1bc8d839ca9966a0b924e4a4c60f1c23b4d431deb81e1bc529edf95f30fc29d 7818931 main/binary-amd64/Packages + a55d3b2e6e2a175529d73e6ca92989018cf57745e705f7ff675b05f80e5141f7 97 main/binary-amd64/Release + cc0d3a19c51188b4b4acb80e3013264462c6e0f60759bfd46206c60681bd4ba9 1272844 main/binary-amd64/Packages.bz2 + a841750f49bd11f99b9dae6941d2fa6ec1fd87906139d0ceeacf0d4df57a87cf 97 main/binary-armel/Release + e80eaf12c1aa520b353de8ad97e79364779e82ef011cb93db372edc900eb7be9 1619078 main/binary-armel/Packages.gz + 0ab0929c3c44837886e532f8ec4bee77f3664bdcc2cc3192a02b991c52b156ce 1257389 main/binary-armel/Packages.bz2 + ea400cf67f84c12265e4bf419de442a38880fab37d76999985972fc6df3e13b3 7743353 main/binary-armel/Packages + f3c40f057bb085f28ef2ed950f62366483d2a418571435c355dc27c0912dccff 97 main/binary-armhf/Release + cde037224f43e4619213c5195f2ea5c2f91d078f449579652dbd4128793d5062 7620333 main/binary-armhf/Packages + 7c6ea67e609b96dec6f2185df4cd81160e37ba467f9132a9bfb101da3f9a0468 1257653 main/binary-armhf/Packages.bz2 + 2b83bf5501ecae3347e5c96658edae7d48eef42108b4786471a3de241e75e7d3 1617483 main/binary-armhf/Packages.gz + 4d74c53917b84d37cb3277e2b755672a8733e2cfaf949f6e644e6e88094cdaa2 1273857 main/binary-i386/Packages.bz2 + 07f33bddfefdb4a0c44ddee59fd3eca497df2ad0456e0eeade136e4f0302ee3c 1641082 main/binary-i386/Packages.gz + 5182e22f799fe66c8db6dfb073fb040e9e583d88bb9d4d77e058b2afb87e9479 96 main/binary-i386/Release + 4cecfc8c0d2113d51b03afa8fdcdcc963d9ad74474696472ec1cdbdb38b856e2 7816415 main/binary-i386/Packages + 2795904625f466b4a2fb96d41c00b000ab7f2bdc7f288b0c9ef1283d7e110f87 1627734 main/binary-powerpc/Packages.gz + a9247e6d8b0c5977bc1e72be09b1f42a83b5f5a6a70b17f4fef35a0657e3c206 99 main/binary-powerpc/Release + 6e745b7edcd67755fa09f54cc3afdd0ffbd0475302a74293472e97e46ba75ddc 1263942 main/binary-powerpc/Packages.bz2 + 8b953dbae4a14e7ab47151044a47c7b0f0e1dd2a6480170b8172e00d9dad7a2a 7661552 main/binary-powerpc/Packages + a5bdf4116ecfeda052d5b3751138c6153e814ac58b2f551503f3ed90e6c3510c 62166 main/debian-installer/binary-amd64/Packages.gz + 6a9a4837a4a7df3e7e0566b354b7f1dd2dcf46254335ae3d06a72538f85e410a 234592 main/debian-installer/binary-amd64/Packages + 0da4f8190eebfef22103f1f6f7051adbe9489d454ab7224f09d05646407881e8 48784 main/debian-installer/binary-amd64/Packages.bz2 + ea01244357deb22c2a4bd7eaa34a1635c0915b89ce174f312c0e0a4b081eaf30 47964 main/debian-installer/binary-armel/Packages.bz2 + 4177b0519c75f7f950e5a0f0d72d40cc0c4ccf29ebe89fbb9bc1f11a80874526 230310 main/debian-installer/binary-armel/Packages + 2b6f81ef9fa687bfb2eb56bb3e90faef0c012351d096b141caa710fd50846043 61118 main/debian-installer/binary-armel/Packages.gz + 52c834247ff3a5475466e647802f6eff393f85589e5da5fd3e5b497669b8b49c 62777 main/debian-installer/binary-armhf/Packages.gz + 7090f1ad1307a012fbfff883885f16099ed66ebffdeece356f837e632b177a4f 49051 main/debian-installer/binary-armhf/Packages.bz2 + 4bae13f507993e977c279937406fc03e37fede7805a92508f6d3cba76f1aaf95 238862 main/debian-installer/binary-armhf/Packages + d1d23926ff15cfaa6160c5fd0327d181721093fbd2f2e8125be5559a991a81a8 52279 main/debian-installer/binary-i386/Packages.bz2 + 30e0ec7a2c3d47d5501de8414b436482ff523e9c4983b536b2c9911a30618b98 259996 main/debian-installer/binary-i386/Packages + 7a4dcb001ed4bb5fa2458af901de312e11a745bc86a0f877e47567d0f911bc0d 67180 main/debian-installer/binary-i386/Packages.gz + 30c2f590c2dedc9f78dfc7f0026b51bc9baa712ac8c9310404d9d6577af77d90 246636 main/debian-installer/binary-powerpc/Packages + 6c53fab780cf774c5cabb1788eea1e3446c528cde4352d106907f4ec22449370 50309 main/debian-installer/binary-powerpc/Packages.bz2 + b003f3fbf2fa6dbf7d47cf3fbd029ecd86b316ec497a9ac4eea3614cf4ec76af 64468 main/debian-installer/binary-powerpc/Packages.gz + fefed230e286d832ab6eb0fb7b72442165b50df23a68402ae6e9d265a31920a2 3706 main/i18n/Index + bb618cebb361a2a7148be0bad9af012c8d9de23dbc32d6d9ba035fa6ee0078ab 4356187 main/source/Sources + 0aeef2c2258136f9f774c36a158cf759389acf6a35a3153a03d3fa41d4f346d5 933770 main/source/Sources.bz2 + 4a058ba65244e8eaf17d159b72edebe4e621d54c274a82d4a973b358b4af9a28 1174967 main/source/Sources.gz + 864ba9a26e348c6297c08c047d8c228e5ed031ec3d46ef7aad93c3fa550395a8 98 main/source/Release + 85477d2b2e7ea2f46b6a059f7526cf52d75fea1a5120aa3b256c576e904d40ff 119109 multiverse/binary-amd64/Packages.bz2 + 2967ae6c1cc065bec03225d808b4511b138cc13b8de801a0562fec6e30710f36 151924 multiverse/binary-amd64/Packages.gz + 18fcf61bb74ef2a01c3d4a8d4646a75836f43244168b43d6ae202f368167b224 581550 multiverse/binary-amd64/Packages + fbc4931ef84d50a39da65d110f787aee274df8819a758a3c0aa1ff13f0ba6ee0 103 multiverse/binary-amd64/Release + 49f48a34696d08a13a0fdc19a0f6896af2cb477e72860a8880954926c7d45e60 136295 multiverse/binary-armel/Packages.gz + f20d7f0bc32b5b2fbcb442f7c128aaad7e18aece3781d53f560932bb191d6830 519605 multiverse/binary-armel/Packages + f7ea72b2c07af81f2e342414025dce7a658a6a9915c4d8adc13b992cb3b9fd2f 103 multiverse/binary-armel/Release + dd3d4e8a6ec9055d5b553af49822de74648f071ceb0fd314d6cd1aaf7ad6882b 106873 multiverse/binary-armel/Packages.bz2 + 567c1f9d30a4d6650552d66c5fb43d2d8910d3fed69793daed622d2c699f4bc8 104529 multiverse/binary-armhf/Packages.bz2 + a47ef2c0a68adeb70a0bc6b22c94b08402396ff6f5c77664e06c2fb7ee0e7ab0 505901 multiverse/binary-armhf/Packages + 6b95e8edaa2bb799f6e15a4a6aaf223da0faea670cd03340395bdcea90205afc 103 multiverse/binary-armhf/Release + 14721b333f19a6344addb185f161d1cd14e04ac284c8fa9d726064ec228269a8 133117 multiverse/binary-armhf/Packages.gz + 454436f374186007075445c1f206ba5c926f30609baa732c495f1ba456d71e59 121196 multiverse/binary-i386/Packages.bz2 + 9fabd7bfdbfd216968f7a17265e5609cdd72f1ea7c8f50941e294694e76b180d 591662 multiverse/binary-i386/Packages + 7141881b898ac6a78f1ca6f3e81481ee6657f6762fa22768816ab39f6b17e695 102 multiverse/binary-i386/Release + 3f4cae31df741f55d523ecea758d05a7e012a205bb03974ee20eb09e3f4fa63b 154762 multiverse/binary-i386/Packages.gz + 332dde644a8467496eb5f45ffd2d735ca61ea781da21cd205b3267cd83fa0563 105 multiverse/binary-powerpc/Release + 99ef0a611aa32ffa4f16a006d641fbd8dd9e3e73bde3c93b831cd6583746e64b 107209 multiverse/binary-powerpc/Packages.bz2 + 60f2431dab7bd02fe2c2428bf400c3535be49641cc9d5645a8f1b4fd44f5086f 520882 multiverse/binary-powerpc/Packages + cacfd10b40992a617ce32c479f9505531c8cc57e4cf964687d663a5f41f8dcbd 136930 multiverse/binary-powerpc/Packages.gz + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 multiverse/debian-installer/binary-amd64/Packages + f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 multiverse/debian-installer/binary-amd64/Packages.gz + d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 multiverse/debian-installer/binary-amd64/Packages.bz2 + d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 multiverse/debian-installer/binary-armel/Packages.bz2 + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 multiverse/debian-installer/binary-armel/Packages + f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 multiverse/debian-installer/binary-armel/Packages.gz + f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 multiverse/debian-installer/binary-armhf/Packages.gz + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 multiverse/debian-installer/binary-armhf/Packages + d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 multiverse/debian-installer/binary-armhf/Packages.bz2 + d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 multiverse/debian-installer/binary-i386/Packages.bz2 + f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 multiverse/debian-installer/binary-i386/Packages.gz + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 multiverse/debian-installer/binary-i386/Packages + f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 multiverse/debian-installer/binary-powerpc/Packages.gz + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 multiverse/debian-installer/binary-powerpc/Packages + d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 multiverse/debian-installer/binary-powerpc/Packages.bz2 + f0b16a5cfd2d633c9ddecfadfa6742544b18c23ed30023286e2b20ef29f33c73 2676 multiverse/i18n/Index + faa0360612fc00453dfdd55b6a1bb20e4f876e041ad6fca410d5da65608ab31e 154990 multiverse/source/Sources.bz2 + 2f0deae62e2cf7e5257bbd858cb0bf2a94122c4eb82be13e13768d0b9ce84c9e 628753 multiverse/source/Sources + 28f6d95fcba03e442cf24dc547653d5ec60177a29d7cfea771efcc5501077747 188325 multiverse/source/Sources.gz + f35f721bf16691842cc916c3563fab535f6bb83329f40c33ac02f4ba637707d3 104 multiverse/source/Release + 3e872fa356cbce4dfd75a88caa4fc6b47616e1fc7d224f4fc2123650fd7f4be3 9098 restricted/binary-amd64/Packages.gz + 459a26c3ef3cb5db8c8355ea6abfa8cfe0a7a266a197929d86d37686daf8a337 134705 restricted/binary-amd64/Packages + ea47572182da041b46543e471cb7a6fcc4e001fbe19a27740085ebf5d77252a9 103 restricted/binary-amd64/Release + adb08d7f0fa444f2869e8d932db7adb1515839f11af6032284cf1e20060e2dd6 8452 restricted/binary-amd64/Packages.bz2 + 65a5ac0820d61383f7dcf33699aa029b5965b7906bc8341f94f8f7f354cdcd83 103 restricted/binary-armel/Release + f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 restricted/binary-armel/Packages.gz + d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 restricted/binary-armel/Packages.bz2 + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 restricted/binary-armel/Packages + ee447ce81793bd3bc8c127d4e065c6ec24e5901573dffb7cc5abedfbcb86592c 103 restricted/binary-armhf/Release + d88ed7df97cd60cdce35c3ca81de66e2bedf0f22e67ec8922dbd5eca545b5e50 1103 restricted/binary-armhf/Packages.bz2 + 9ade66f4a49598fb371705a79244e5f3abb74c04467f9f9954641ae5acec6766 2477 restricted/binary-armhf/Packages + 03d8b64c445f327ce9e369bca815652844bd6aafb344d0287fb4e71f321d0414 941 restricted/binary-armhf/Packages.gz + 07e344ed07234876c3fddd9aa763e04bfc2e013fc18428738be71abfb9e1ca77 9108 restricted/binary-i386/Packages.gz + 8061335b923c49e72a2b60b437d5bbad1b98a45ac178a68fd8359cec9fad27ec 8431 restricted/binary-i386/Packages.bz2 + 122336146860047af3d5817dbc423f01d57a90cbf41db1ee0ad9235c0559a43e 134582 restricted/binary-i386/Packages + 58634ed42b6fadb280d48f419b960e28151320a62b4486e520ca327719db554a 102 restricted/binary-i386/Release + f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 restricted/binary-powerpc/Packages.gz + d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 restricted/binary-powerpc/Packages.bz2 + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 restricted/binary-powerpc/Packages + d9bce398e46f0eac57d1d33fd8a6caa0bd7ab6334508c0640956cb7adbe1eba1 105 restricted/binary-powerpc/Release + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 restricted/debian-installer/binary-amd64/Packages + d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 restricted/debian-installer/binary-amd64/Packages.bz2 + f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 restricted/debian-installer/binary-amd64/Packages.gz + f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 restricted/debian-installer/binary-armel/Packages.gz + d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 restricted/debian-installer/binary-armel/Packages.bz2 + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 restricted/debian-installer/binary-armel/Packages + d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 restricted/debian-installer/binary-armhf/Packages.bz2 + f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 restricted/debian-installer/binary-armhf/Packages.gz + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 restricted/debian-installer/binary-armhf/Packages + f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 restricted/debian-installer/binary-i386/Packages.gz + d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 restricted/debian-installer/binary-i386/Packages.bz2 + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 restricted/debian-installer/binary-i386/Packages + f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 restricted/debian-installer/binary-powerpc/Packages.gz + d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 restricted/debian-installer/binary-powerpc/Packages.bz2 + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 restricted/debian-installer/binary-powerpc/Packages + 17dde58abfdb4dfdad9c8a82db09c9dbc3d8a7cd84b51dd9167579d6899e9ff5 2596 restricted/i18n/Index + ee3655459e45778fdfa06fb649565e66b25d2dd0870c75890005fb3597bb71d7 19001 restricted/source/Sources + cff18d2ad74ead8712f1b77a23b32e84e54269b03ba2a409ae4227860d1181f5 5470 restricted/source/Sources.bz2 + cf085bdcb323dd2c2a599ddb7a9b3ae7bd37121f42024d68b367a4f735df900f 5306 restricted/source/Sources.gz + 9137393fc24cf64808d55ca7665bc5a7bd46b48918e6720a95ba239a8fab092e 104 restricted/source/Release + 901469729d2354891be94c192dabd8c1d0bc31e1497ea8360b70d2e847c1f3c1 25546870 universe/binary-amd64/Packages + 799347395d4e011a215aa5ce0c9006449d8af884795ffbce7a35767a55f99074 4785960 universe/binary-amd64/Packages.bz2 + 68b08847604c4efe7d6f56ba79f923ce0ab82127dfcc6e8cffaf12af25d7adba 6166988 universe/binary-amd64/Packages.gz + 52ffdd1777a886edc5e1e1ef430b03a72937920f9722fd453ee8243cb0aac860 101 universe/binary-amd64/Release + a78a1304e105b2fe4c950c77c1794f715c1256d14d8541cca8f5cd13db48119e 101 universe/binary-armel/Release + d6d4bfa5d0891086f5a4f2aabfaecd7a1e0c0d8b46aef33b3470e349e7a9210e 4667308 universe/binary-armel/Packages.bz2 + 374d50d0335c655da46f9cd54cd00d9a20058d2fe7c56989aa121b49883cfb88 6009219 universe/binary-armel/Packages.gz + ab5073e90417b729d1fe3b68052e6a8e66e48986c35470944f6a58676e967450 24901082 universe/binary-armel/Packages + af74034d1a3e1f90745dc48b996a98c471d997b12a1d810eb8754088540591d7 5948128 universe/binary-armhf/Packages.gz + 6697d196b35850817476e884fdc013d9670b4bac73310c54a4d62cd810f02c70 101 universe/binary-armhf/Release + 1ca17d3aecec2325cba53e1c299aeb6a1fed01d7acbc40163595de9e651abdeb 4618508 universe/binary-armhf/Packages.bz2 + 2b422ffa77d4374650d4cc543c5a1123b2535effb2c8cdaf25fd77d1dde632c4 24642528 universe/binary-armhf/Packages + cd6b5cb8165553482abee1bf85e5cd3288abadccb6acf34239ec45f79a090784 6179579 universe/binary-i386/Packages.gz + 8ef7db20ba08cf1b4d98a618189c615c69865f4da025ac654e3e6b8a4382a3ae 25568759 universe/binary-i386/Packages + 06af492500145bd64762d885417d167269db6ea03022c6968f1a5d0515ac55dd 100 universe/binary-i386/Release + 530a2efb8051a63ed17431ae0c7243df79ecb418acf1dadc2487cd6fd79fb420 4795820 universe/binary-i386/Packages.bz2 + 1e8fa52a64292d2c73cee0645d0eed5583ea7cc1138af4744838c6833716d638 25188905 universe/binary-powerpc/Packages + 5d2b8e23e0a16f13e25595b63807fb64afd9074aadf7a37b8e238b2011e894b8 6080488 universe/binary-powerpc/Packages.gz + eb482b008c8c882b349230abaa812ed6e545a2ef9132bb0d3d3bffa74da0c6c7 4716652 universe/binary-powerpc/Packages.bz2 + 98d44cc7544f79c18b8e8ea697d476e9b85d91088385b643c82d4064b21f4657 103 universe/binary-powerpc/Release + 3da2d1e57aaca628148e2688a951cbb784a9a54b7f6b1f84d530add1b66fcceb 15255 universe/debian-installer/binary-amd64/Packages.bz2 + 43f891ac590f44fde5854de9ba15222c088b70562f5dc4ff26064909e60cf62e 17243 universe/debian-installer/binary-amd64/Packages.gz + 3084a8a441e961eeb3865ff411557166ec105be86a55df268cdb6725f49e1f67 61801 universe/debian-installer/binary-amd64/Packages + a1ff01f18766744f36d0774a68d8a89355246c585c4b28ee18e5e139fafae530 113584 universe/debian-installer/binary-armel/Packages + e0713f86f5f5121deb60ce61d774951468625184a7ae9576f81d70202ef585b7 23193 universe/debian-installer/binary-armel/Packages.bz2 + 5a8411e2b0648e553fa25ac82ea83fb17dd2d2a77bd10cec14cab12f5582d4c4 27397 universe/debian-installer/binary-armel/Packages.gz + b79c86d926c3129f5c27e50185157a78d85abde8ada90a9910338e660c4318be 20065 universe/debian-installer/binary-armhf/Packages.gz + b2113b25380423be8f6202a4860479e44a00072e46fa035f0da2f3a5a280de20 17619 universe/debian-installer/binary-armhf/Packages.bz2 + 3f023d2cc55d6ebab883f6f2d7305a4e3564f918f63ca4f745d6fd1318e67ab7 76034 universe/debian-installer/binary-armhf/Packages + 5ea61a62a3e8fc755c22e23c9d87b20924707c0986a490458472a3d7e9cbe117 17260 universe/debian-installer/binary-i386/Packages.gz + 7a90b014c655311e92de1ea4cf24e100665c564a2ed699df63d17c82ad9e1349 15272 universe/debian-installer/binary-i386/Packages.bz2 + 7e39417ce073e3a35d048847a29a0414af69c4e923c018dc22438319c79adea5 61718 universe/debian-installer/binary-i386/Packages + cdf17a791544d0c522fa853a23b317deffa76ac643e88bec0b84b0aa5afe957b 61121 universe/debian-installer/binary-powerpc/Packages + b470146da791dc4f4593d2bb00ea4e305d6f55f346a5f3ac6755d890a3318080 15024 universe/debian-installer/binary-powerpc/Packages.bz2 + 810d1590d1cd7298e1fd5465f85ba49b6ae79780b42d8e8b68aebb42283785ea 16860 universe/debian-installer/binary-powerpc/Packages.gz + 563a55a892e1ec8bf565e3294c033b4e8dbbbe4651e73733eac7338db77282f7 2922 universe/i18n/Index + 7bc01d4f10bbcf882ce6931aa9371b2de6b35277efc2ae52e233280dcd12a18d 21256524 universe/source/Sources + 95135631873f4dce05ba657478475033d02462bbb8f7263832585d1decb5c9b8 5019105 universe/source/Sources.bz2 + 0fd2ae580be352cb8ab4bb87e5504b78f78bcb7249b644719b3c2db3b5d3ca8c 102 universe/source/Release + d1dd96015e24dd369ea22413a2b876686a60c5d9d91958a5df3745a66289910f 6238766 universe/source/Sources.gz diff --git a/tests/data/tagfile/history.1.log.gz b/tests/data/tagfile/history.1.log.gz new file mode 100644 index 0000000..4174e02 Binary files /dev/null and b/tests/data/tagfile/history.1.log.gz differ diff --git a/tests/data/tagfile/history.log b/tests/data/tagfile/history.log new file mode 100644 index 0000000..f1d7266 --- /dev/null +++ b/tests/data/tagfile/history.log @@ -0,0 +1,15 @@ + +Start-Date: 2012-02-01 13:54:52 +Commandline: apt-get install chromium-browser +Install: chromium-browser:amd64 (16.0.912.77~r118311-0ubuntu1), chromium-browser-l10n:amd64 (16.0.912.77~r118311-0ubuntu1, automatic), chromium-codecs-ffmpeg:amd64 (16.0.912.77~r118311-0ubuntu1, automatic) +End-Date: 2012-02-01 13:55:01 + +Start-Date: 2012-02-02 10:39:04 +Commandline: apt-get install python-geoclue +Install: python-geoclue:amd64 (0.1.0-4build1) +End-Date: 2012-02-02 10:39:08 + +Start-Date: 2012-02-03 10:20:50 +Commandline: apt-get install python-qt4 +Install: python-qt4:amd64 (4.9-3ubuntu1) +End-Date: 2012-02-03 10:20:55 diff --git a/tests/data/test-provides/etc/apt/sources.list b/tests/data/test-provides/etc/apt/sources.list new file mode 100644 index 0000000..2955b5c --- /dev/null +++ b/tests/data/test-provides/etc/apt/sources.list @@ -0,0 +1 @@ +deb http://archive.ubuntu.com/ubuntu oneiric main diff --git a/tests/data/test-provides/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_binary-i386_Packages b/tests/data/test-provides/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_binary-i386_Packages new file mode 100644 index 0000000..f991cb9 --- /dev/null +++ b/tests/data/test-provides/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_binary-i386_Packages @@ -0,0 +1,75 @@ +Package: exim4-daemon-light +Priority: extra +Section: mail +Installed-Size: 1092 +Maintainer: Ubuntu Developers +Original-Maintainer: Exim4 Maintainers +Architecture: all +Source: exim4 +Version: 4.76-2ubuntu1 +Replaces: mail-transport-agent +Provides: mail-transport-agent +Conflicts: mail-transport-agent +Filename: pool/main/e/exim4/exim4-daemon-light_4.76-2ubuntu1_i386.deb +Size: 451088 +MD5sum: 81795887e233ecfb3471e8a3da4c4b8b +SHA1: da0202f7da88b9e9c5ee326a24c3fdd640543a5d +SHA256: 5ffa03674b5198d1c0e9e0d9e3442cdd7fbe13226c7df91aa53def1f8b6c0d86 +Description: lightweight Exim MTA (v4) daemon + Exim (v4) is a mail transport agent. This package contains the exim4 + daemon with only basic features enabled. It works well with the + standard setups that are provided by Debian and includes support for + TLS encryption and the dlopen patch to allow dynamic loading of a + local_scan function. + . + The Debian exim4 packages have their own web page, + http://pkg-exim4.alioth.debian.org/. There is also a Debian-specific + FAQ list. Information about the way the Debian packages are + configured can be found in + /usr/share/doc/exim4-base/README.Debian.gz, which additionally contains + information about the way the Debian binary packages are built. The + very extensive upstream documentation is shipped in + /usr/share/doc/exim4-base/spec.txt.gz. To repeat the debconf-driven + configuration process in a standard setup, invoke dpkg-reconfigure + exim4-config. There is a Debian-centered mailing list, + pkg-exim4-users@lists.alioth.debian.org. Please ask Debian-specific + questions there, and only write to the upstream exim-users mailing + list if you are sure that your question is not Debian-specific. You + can find the subscription web page on + http://lists.alioth.debian.org/mailman/listinfo/pkg-exim4-users +Homepage: http://www.exim.org/ +Bugs: https://bugs.launchpad.net/ubuntu/+filebug +Origin: Ubuntu +Supported: 18m + +Package: postfix +Priority: optional +Section: mail +Installed-Size: 3472 +Maintainer: Ubuntu Developers +Original-Maintainer: LaMont Jones +Architecture: all +Version: 2.8.3-1ubuntu1 +Replaces: mail-transport-agent +Provides: default-mta, mail-transport-agent +Recommends: python +Suggests: procmail, postfix-mysql, postfix-pgsql, postfix-ldap, postfix-pcre, sasl2-bin, libsasl2-modules, dovecot-common, resolvconf, postfix-cdb, mail-reader, ufw +Conflicts: libnss-db (<< 2.2-3), mail-transport-agent, smail +Filename: pool/main/p/postfix/postfix_2.8.3-1ubuntu1_i386.deb +Size: 1221834 +MD5sum: c4575f03ef0711cc744d394ae36f4a8c +SHA1: f0f636c942981782cf23cee3d8a95aee188081b9 +SHA256: 13a4bfaf10c8addfc7dce01c0ea65bfbd6a759c4a2aaaafbae5855d099925fe0 +Description: High-performance mail transport agent + Postfix is Wietse Venema's mail transport agent that started life as an + alternative to the widely-used Sendmail program. Postfix attempts to + be fast, easy to administer, and secure, while at the same time being + sendmail compatible enough to not upset existing users. Thus, the outside + has a sendmail-ish flavor, but the inside is completely different. +Homepage: http://www.postfix.org +Bugs: https://bugs.launchpad.net/ubuntu/+filebug +Origin: Ubuntu +Supported: 18m +Task: mail-server + + diff --git a/tests/data/test-provides/var/lib/dpkg/status b/tests/data/test-provides/var/lib/dpkg/status new file mode 100644 index 0000000..e69de29 diff --git a/tests/data/test-repo/Packages.gz b/tests/data/test-repo/Packages.gz new file mode 100644 index 0000000..81daf2b Binary files /dev/null and b/tests/data/test-repo/Packages.gz differ diff --git a/tests/data/test-repo2/Packages.gz b/tests/data/test-repo2/Packages.gz new file mode 100644 index 0000000..81daf2b Binary files /dev/null and b/tests/data/test-repo2/Packages.gz differ diff --git a/tests/data/test-signed-usable-repo/key.gpg.base64 b/tests/data/test-signed-usable-repo/key.gpg.base64 new file mode 100644 index 0000000..3bdec88 --- /dev/null +++ b/tests/data/test-signed-usable-repo/key.gpg.base64 @@ -0,0 +1,62 @@ +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 +qipSuMIYrosA diff --git a/tests/data/test-signed-usable-repo/seckey.asc b/tests/data/test-signed-usable-repo/seckey.asc new file mode 100644 index 0000000..bcbf153 --- /dev/null +++ b/tests/data/test-signed-usable-repo/seckey.asc @@ -0,0 +1,158 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +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 +DZeT+S/3tXCwy1Jtoi7vcaoqUrjCGK6LAA== +=mcY/ +-----END PGP PRIVATE KEY BLOCK----- diff --git a/tests/data/test-signed-usable-repo/signed/Packages b/tests/data/test-signed-usable-repo/signed/Packages new file mode 100644 index 0000000..3ca29c9 --- /dev/null +++ b/tests/data/test-signed-usable-repo/signed/Packages @@ -0,0 +1,26 @@ +Package: signed-not-usable +Architecture: all +Version: 1.0 +Multi-Arch: foreign +Priority: optional +Section: misc +Maintainer: Julian Andres Klode +Installed-Size: 9 +Filename: ./signed-not-usable_1.0_all.deb +Size: 35 +MD5sum: f3034b91e355ba6046ff535ed044dcb5 +Description: Dummy package + +Package: signed-usable +Architecture: all +Version: 1.0 +Multi-Arch: foreign +Priority: optional +Section: misc +Maintainer: Julian Andres Klode +Installed-Size: 9 +Filename: ./signed-usable_1.0_all.deb +Size: 31 +MD5sum: 2d5166c110423c2d7c016642af4bd2eb +SHA256: 20edddf30a1bedf669f19caffa347299239b2a700ff428e33abc75e902f1d737 +Description: Dummy package diff --git a/tests/data/test-signed-usable-repo/signed/Release b/tests/data/test-signed-usable-repo/signed/Release new file mode 100644 index 0000000..135ce78 --- /dev/null +++ b/tests/data/test-signed-usable-repo/signed/Release @@ -0,0 +1,17 @@ +Date: Fri, 13 Dec 2019 16:11:05 +0000 +MD5Sum: + 21b1df48cfe01053dd2245763423cefb 668 Packages + 6715b0d77e7ea43fb252c78f1f826096 38 Release + 30432690119177a7f0c822c12f96e665 579 Sources +SHA1: + 910742c214560ce8ecdcb89c86fb1c0afa5a5373 668 Packages + 4a252d8c4ebc30d7330938a7dee06288877c4e3f 38 Release + 3147ec4b880bbb2cfa2a3f903b86d1dd2249488d 579 Sources +SHA256: + 445d75ee95443b89849b17f73ae434423d01c603f03c894a7be7851d36a5365d 668 Packages + c0ac431b6ea236c4d12e904b556bbb1f8d0abc733041cab4d65bfd3fd9704183 38 Release + 99140dde6468a8e073d8830faaf90e40c374957b98c1be446308dc8296ce5934 579 Sources +SHA512: + fdc2f7552c06ea197c8c40a44602218703a08d1b6a86f9319cc13a56ea8e7f7103c10aea6ee221b0bc88432ebb2651e3d2e5a93a3900fec5630db2e41684c57b 668 Packages + 5800d40647c79881b15119bbc576b12926151a2df37b96e18abc5fb04986663fa01867a83a1919225365b590a15e22032d12175eaf76336f167688c5a817ca13 38 Release + d0dd2a03687df03e4728219b9b149d514f8a734fcdeee8e45cb31229fc0f915eab634a50f934a60df42682e6dfbc65b962109bda616af642d6ee4cf821a877a1 579 Sources diff --git a/tests/data/test-signed-usable-repo/signed/Release.gpg b/tests/data/test-signed-usable-repo/signed/Release.gpg new file mode 100644 index 0000000..6b853bf --- /dev/null +++ b/tests/data/test-signed-usable-repo/signed/Release.gpg @@ -0,0 +1,14 @@ +-----BEGIN PGP SIGNATURE----- + +iQHFBAABCgAvFiEEJIBsPhVxGFtaHobENN7p9ZyTYfkFAl3zuBkRHHRlc3RAZXhh +bXBsZS5jb20ACgkQNN7p9ZyTYfkkrwv9HBgaZjSf3Bib9FH2alGZkBHKRcE2gWKf +d4PBXKLGgUutCy2g1Dn+FyBYB4OCf3H7ZsD6JFqrYSmLyGHAo+5QTMaPcRlVGoN8 +GL/fxJOEkRJruyC3k36toZTgXI/DGvSv1882syHTG0jOm8to95wiaQKDysTKOOTp +p1HJbX5DX+Wf2rXA/CL8KdH7rHzkIdhjdL4hucDw+JvNSywPEn0RSfvjtUS04d7G +Rw8H2PXyEnreO6OmMdwEmtImouIVxNZDFEEWUhdwujMnDtxM16uIIRLXa1sWQAzZ +M7RHNIhQHP1EvPuQRnKknacKUwchpg/IklxxruaRtjELSUMF5UOXJdnJFb3t6+pT +HBaW/c5piLfMsIV5U/bjQA76Ta4NccH5hah8x6+SjEZiP5RxSfQ9wpblYQeOmaUB +xi0tF6Ukqp5zfPi1RblziWZbN2/ty5zXpPOYbDT2geWo+8bVEhG6HwtHvpzuVymR +qtjOlCujLlkNZKG5jBHoOhuQjNPm+8RY +=wnyK +-----END PGP SIGNATURE----- diff --git a/tests/data/test-signed-usable-repo/signed/Sources b/tests/data/test-signed-usable-repo/signed/Sources new file mode 100644 index 0000000..52a8ee0 --- /dev/null +++ b/tests/data/test-signed-usable-repo/signed/Sources @@ -0,0 +1,21 @@ +Package: signed-not-usable +Format: 3.0 (native) +Binary: signed-not-usable +Architecture: any all +Version: 1.0 +Package-List: + signed-not-usable deb admin important arch=all +Files: + f2ae6d320641e8e241efcba02b5540fb 323 signed-not-usable_1.0.dsc + +Package: signed-usable +Format: 3.0 (native) +Binary: signed-usable +Architecture: any all +Version: 1.0 +Package-List: + signed-usable deb admin important arch=all +Files: + 491c58f65f493e838880a6ff30064c57 311 signed-usable_1.0.dsc +Checksums-Sha256: + 7a277156805101ce917dbb8d443d7087cc0ad333d25304f284976dba36339487 311 signed-usable_1.0.dsc diff --git a/tests/data/test-signed-usable-repo/signed/signed-not-usable_1.0.dsc b/tests/data/test-signed-usable-repo/signed/signed-not-usable_1.0.dsc new file mode 100644 index 0000000..2ebb766 --- /dev/null +++ b/tests/data/test-signed-usable-repo/signed/signed-not-usable_1.0.dsc @@ -0,0 +1,11 @@ +Format: 3.0 (native) +Source: signed-not-usable +Binary: signed-not-usable +Architecture: any all +Version: 1.0 +Package-List: + signed-not-usable deb admin important arch=all +Checksums-Sha256: + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 test.tar.xz +Files: + d41d8cd98f00b204e9800998ecf8427e 0 test.tar.xz diff --git a/tests/data/test-signed-usable-repo/signed/signed-not-usable_1.0_all.deb b/tests/data/test-signed-usable-repo/signed/signed-not-usable_1.0_all.deb new file mode 100644 index 0000000..e098ca5 --- /dev/null +++ b/tests/data/test-signed-usable-repo/signed/signed-not-usable_1.0_all.deb @@ -0,0 +1 @@ +i am signed-not-usable_1.0_all.deb diff --git a/tests/data/test-signed-usable-repo/signed/signed-usable_1.0.dsc b/tests/data/test-signed-usable-repo/signed/signed-usable_1.0.dsc new file mode 100644 index 0000000..04b4f64 --- /dev/null +++ b/tests/data/test-signed-usable-repo/signed/signed-usable_1.0.dsc @@ -0,0 +1,11 @@ +Format: 3.0 (native) +Source: signed-usable +Binary: signed-usable +Architecture: any all +Version: 1.0 +Package-List: + signed-usable deb admin important arch=all +Checksums-Sha256: + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 test.tar.xz +Files: + d41d8cd98f00b204e9800998ecf8427e 0 test.tar.xz diff --git a/tests/data/test-signed-usable-repo/signed/signed-usable_1.0_all.deb b/tests/data/test-signed-usable-repo/signed/signed-usable_1.0_all.deb new file mode 100644 index 0000000..cd58831 --- /dev/null +++ b/tests/data/test-signed-usable-repo/signed/signed-usable_1.0_all.deb @@ -0,0 +1 @@ +i am signed-usable_1.0_all.deb diff --git a/tests/data/test-signed-usable-repo/unsigned/Packages b/tests/data/test-signed-usable-repo/unsigned/Packages new file mode 100644 index 0000000..22f4fff --- /dev/null +++ b/tests/data/test-signed-usable-repo/unsigned/Packages @@ -0,0 +1,26 @@ +Package: unsigned-unusable +Architecture: all +Version: 1.0 +Multi-Arch: foreign +Priority: optional +Section: misc +Maintainer: Julian Andres Klode +Installed-Size: 9 +Filename: ./unsigned-unusable_1.0_all.deb +Size: 35 +MD5sum: 368e155b22e873eb71ae43b80379c0ea +Description: Dummy package + +Package: unsigned-usable +Architecture: all +Version: 1.0 +Multi-Arch: foreign +Priority: optional +Section: misc +Maintainer: Julian Andres Klode +Installed-Size: 9 +Filename: ./unsigned-usable_1.0_all.deb +Size: 33 +MD5sum: 0a0bb7636879ae8a38b679bc3d09b627 +SHA256: ddc71095223eb039cce782e813782b917502e0f3c99a1142ea2d92b34737a243 +Description: Dummy package diff --git a/tests/data/test-signed-usable-repo/unsigned/Release b/tests/data/test-signed-usable-repo/unsigned/Release new file mode 100644 index 0000000..18552a2 --- /dev/null +++ b/tests/data/test-signed-usable-repo/unsigned/Release @@ -0,0 +1,17 @@ +Date: Fri, 13 Dec 2019 16:04:58 +0000 +MD5Sum: + dd9db6eb770d950241fc5dfd1b94d4c5 672 Packages + 808b5c1ee28bdae1ffe98a8ee632a4ff 38 Release + bb3efd66e75fa995971ddf8d3bdcd6cb 592 Sources +SHA1: + 4b83e0112704ce4aa20d5833dfad0617404cb48f 672 Packages + 9cba73573f2824f5691293802046a707d1493cdf 38 Release + 4e4a503ec704e11c963c042f44a3ad9da7f30b88 592 Sources +SHA256: + e7a1760be467c66c570e3a5feddfb8d82a14cb4a201382353e4d9bf4c8fb530a 672 Packages + b7efc8e49608e74fefd10f93081843b66200cf9b3d12af7e7772138d8d9fd514 38 Release + f1bea3fd5e27e0a2b606ef23690a611b6a1b60baf42284d5469431dfae4c316a 592 Sources +SHA512: + 4d951a837afed5be1aa89e594587b34f533408b28e4f3b0ffd2c69e5edf45873e24ace59126b12c8f83734ca5daa1d901f2f51170ac325b2787b3674e7226d93 672 Packages + 31d2d8013ee14aa414abf831819f2896f2d9c323fbfcfbc24bf7d602e1855a97ae049125397afd909e8a78aa0c016469731742f7dded416680fced49cce4b088 38 Release + e476cf4357f0f5ec00529dd96b782d9ed52e94db06020ad64ec976f4be6f3783151267fd9916857bedd1c3b693a338f53501d09200a0834c004da54f5acbfca0 592 Sources diff --git a/tests/data/test-signed-usable-repo/unsigned/Sources b/tests/data/test-signed-usable-repo/unsigned/Sources new file mode 100644 index 0000000..9eaf48b --- /dev/null +++ b/tests/data/test-signed-usable-repo/unsigned/Sources @@ -0,0 +1,22 @@ +Package: unsigned-unusable +Format: 3.0 (native) +Binary: unsigned-unusable +Architecture: any all +Version: 1.0 +Package-List: + unsigned-unusable deb admin important arch=all +Files: + c9c8d679a878ca08faca12baf5e2398d 323 unsigned-not-usable_1.0.dsc + + +Package: unsigned-usable +Format: 3.0 (native) +Binary: unsigned-usable +Architecture: any all +Version: 1.0 +Package-List: + unsigned-usable deb admin important arch=all +Files: + 864f4834dabbd30e6472902b000d7a76 317 unsigned-usable_1.0.dsc +Checksums-Sha256: + eb6c1ebc468b4687bb6bffe25afd5ab1e1812beb9577fac7560396bcb7775939 317 unsigned-usable_1.0.dsc diff --git a/tests/data/test-signed-usable-repo/unsigned/unsigned-not-usable_1.0.dsc b/tests/data/test-signed-usable-repo/unsigned/unsigned-not-usable_1.0.dsc new file mode 100644 index 0000000..f8156c1 --- /dev/null +++ b/tests/data/test-signed-usable-repo/unsigned/unsigned-not-usable_1.0.dsc @@ -0,0 +1,11 @@ +Format: 3.0 (native) +Source: unsigned-unusable +Binary: unsigned-unusable +Architecture: any all +Version: 1.0 +Package-List: + unsigned-unusable deb admin important arch=all +Checksums-Sha256: + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 test.tar.xz +Files: + d41d8cd98f00b204e9800998ecf8427e 0 test.tar.xz diff --git a/tests/data/test-signed-usable-repo/unsigned/unsigned-unusable_1.0_all.deb b/tests/data/test-signed-usable-repo/unsigned/unsigned-unusable_1.0_all.deb new file mode 100644 index 0000000..7465ec1 --- /dev/null +++ b/tests/data/test-signed-usable-repo/unsigned/unsigned-unusable_1.0_all.deb @@ -0,0 +1 @@ +i am unsigned-unusable_1.0_all.deb diff --git a/tests/data/test-signed-usable-repo/unsigned/unsigned-usable_1.0.dsc b/tests/data/test-signed-usable-repo/unsigned/unsigned-usable_1.0.dsc new file mode 100644 index 0000000..a625bb6 --- /dev/null +++ b/tests/data/test-signed-usable-repo/unsigned/unsigned-usable_1.0.dsc @@ -0,0 +1,11 @@ +Format: 3.0 (native) +Source: unsigned-usable +Binary: unsigned-usable +Architecture: any all +Version: 1.0 +Package-List: + unsigned-usable deb admin important arch=all +Checksums-Sha256: + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 test.tar.xz +Files: + d41d8cd98f00b204e9800998ecf8427e 0 test.tar.xz diff --git a/tests/data/test-signed-usable-repo/unsigned/unsigned-usable_1.0_all.deb b/tests/data/test-signed-usable-repo/unsigned/unsigned-usable_1.0_all.deb new file mode 100644 index 0000000..2f748b0 --- /dev/null +++ b/tests/data/test-signed-usable-repo/unsigned/unsigned-usable_1.0_all.deb @@ -0,0 +1 @@ +i am unsigned-usable_1.0_all.deb diff --git a/tests/data/test-source-repo/Sources b/tests/data/test-source-repo/Sources new file mode 100644 index 0000000..4758871 --- /dev/null +++ b/tests/data/test-source-repo/Sources @@ -0,0 +1,25 @@ +Package: dh-autoreconf +Format: 3.0 (native) +Binary: dh-autoreconf +Architecture: all +Version: 16 +Maintainer: Julian Andres Klode +Standards-Version: 4.1.1 +Build-Depends: debhelper (>= 9) +Vcs-Browser: https://anonscm.debian.org/git/collab-maint/dh-autoreconf.git +Vcs-Git: https://anonscm.debian.org/git/collab-maint/dh-autoreconf.git +Package-List: + dh-autoreconf deb devel optional arch=all +Files: + 6576a28fe1918ce10bd31543ba545901 1578 dh-autoreconf_16.dsc + 302c8bf43db02412e3f2197fd0f2ee0f 7372 dh-autoreconf_16.tar.xz +Checksums-Sha1: + c9bf7a920013021dad5fbd898dfd5a79c7a150f9 1578 dh-autoreconf_16.dsc + 58459600164398ad6807ddd877a6f814c799c62c 7372 dh-autoreconf_16.tar.xz +Checksums-Sha256: + 1c1b2ab5f1ae5496bd50dbb3c30e9b7d181a06c8d02ee8d7e9c35ed6f2a69b5f 1578 dh-autoreconf_16.dsc + 5c6a6a362907327bec77a867ff3fd0eceba8015d1b881b48275aff7e4ce0f629 7372 dh-autoreconf_16.tar.xz +Checksums-Sha512: + 4b1a3299f2a8b01b0c75db97fd16cb39919949c74d19ea6cf28e1bbd4891d3515b3e2b90b96a64df665cebf6d95409e704e670909ae91fcfe92409ee1339bffc 1578 dh-autoreconf_16.dsc + 10448dd179ec12bf4310a9a514110a85f56e51893aa36a97ac3a6f8d7ce99d099e62cfdb78e271e2d94431e8832da0f643de821b6643b80e3f0b0f5d682cf9a9 7372 dh-autoreconf_16.tar.xz + diff --git a/tests/data/test_debs/data-tar-broken.deb b/tests/data/test_debs/data-tar-broken.deb new file mode 100644 index 0000000..4fd42e0 Binary files /dev/null and b/tests/data/test_debs/data-tar-broken.deb differ diff --git a/tests/data/test_debs/data-tar-xz.deb b/tests/data/test_debs/data-tar-xz.deb new file mode 100644 index 0000000..9dd4d67 Binary files /dev/null and b/tests/data/test_debs/data-tar-xz.deb differ diff --git a/tests/data/test_debs/data-tar.deb b/tests/data/test_debs/data-tar.deb new file mode 100644 index 0000000..d8e4a98 Binary files /dev/null and b/tests/data/test_debs/data-tar.deb differ diff --git a/tests/data/test_debs/etc/apt/sources.list b/tests/data/test_debs/etc/apt/sources.list new file mode 100644 index 0000000..3cc95c7 --- /dev/null +++ b/tests/data/test_debs/etc/apt/sources.list @@ -0,0 +1 @@ +deb http://archive.ubuntu.com/ubuntu maverick main diff --git a/tests/data/test_debs/gdebi-test1.deb b/tests/data/test_debs/gdebi-test1.deb new file mode 100644 index 0000000..ea9991a Binary files /dev/null and b/tests/data/test_debs/gdebi-test1.deb differ diff --git a/tests/data/test_debs/gdebi-test10.deb b/tests/data/test_debs/gdebi-test10.deb new file mode 100644 index 0000000..ca43ace Binary files /dev/null and b/tests/data/test_debs/gdebi-test10.deb differ diff --git a/tests/data/test_debs/gdebi-test11.deb b/tests/data/test_debs/gdebi-test11.deb new file mode 100644 index 0000000..af9b441 Binary files /dev/null and b/tests/data/test_debs/gdebi-test11.deb differ diff --git a/tests/data/test_debs/gdebi-test12.deb b/tests/data/test_debs/gdebi-test12.deb new file mode 100644 index 0000000..36544cc Binary files /dev/null and b/tests/data/test_debs/gdebi-test12.deb differ diff --git a/tests/data/test_debs/gdebi-test13.deb b/tests/data/test_debs/gdebi-test13.deb new file mode 100644 index 0000000..4e7a828 Binary files /dev/null and b/tests/data/test_debs/gdebi-test13.deb differ diff --git a/tests/data/test_debs/gdebi-test2.deb b/tests/data/test_debs/gdebi-test2.deb new file mode 100644 index 0000000..307ac68 Binary files /dev/null and b/tests/data/test_debs/gdebi-test2.deb differ diff --git a/tests/data/test_debs/gdebi-test3.deb b/tests/data/test_debs/gdebi-test3.deb new file mode 100644 index 0000000..436b925 Binary files /dev/null and b/tests/data/test_debs/gdebi-test3.deb differ diff --git a/tests/data/test_debs/gdebi-test4.deb b/tests/data/test_debs/gdebi-test4.deb new file mode 100644 index 0000000..9eb92d1 Binary files /dev/null and b/tests/data/test_debs/gdebi-test4.deb differ diff --git a/tests/data/test_debs/gdebi-test5.deb b/tests/data/test_debs/gdebi-test5.deb new file mode 100644 index 0000000..0c98c03 Binary files /dev/null and b/tests/data/test_debs/gdebi-test5.deb differ diff --git a/tests/data/test_debs/gdebi-test6.deb b/tests/data/test_debs/gdebi-test6.deb new file mode 100644 index 0000000..8ceacad Binary files /dev/null and b/tests/data/test_debs/gdebi-test6.deb differ diff --git a/tests/data/test_debs/gdebi-test7.deb b/tests/data/test_debs/gdebi-test7.deb new file mode 100644 index 0000000..c041499 Binary files /dev/null and b/tests/data/test_debs/gdebi-test7.deb differ diff --git a/tests/data/test_debs/gdebi-test8.deb b/tests/data/test_debs/gdebi-test8.deb new file mode 100644 index 0000000..439f8ca Binary files /dev/null and b/tests/data/test_debs/gdebi-test8.deb differ diff --git a/tests/data/test_debs/gdebi-test9.deb b/tests/data/test_debs/gdebi-test9.deb new file mode 100644 index 0000000..9901d90 Binary files /dev/null and b/tests/data/test_debs/gdebi-test9.deb differ diff --git a/tests/data/test_debs/hello_2.5-1.dsc b/tests/data/test_debs/hello_2.5-1.dsc new file mode 100644 index 0000000..d00db52 --- /dev/null +++ b/tests/data/test_debs/hello_2.5-1.dsc @@ -0,0 +1,34 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA256 + +Format: 1.0 +Source: hello +Binary: hello, bello, + cello +Architecture: any +Version: 2.5-1 +Maintainer: Santiago Vila +Homepage: http://www.gnu.org/software/hello +Standards-Version: 3.8.4 +Build-Depends: autotools-dev +Checksums-Sha1: + dfaf92bfc8144141bcd5ffb4a30777cd57501bfa 582535 hello_2.5.orig.tar.gz + a98ab19072b35295ded3560721662131933f7c05 5965 hello_2.5-1.diff.gz +Checksums-Sha256: + 22934a7d3a62f247ce3b5a77a2c7f7dd095ad8aef305efa2d0d15e0fef31c446 582535 hello_2.5.orig.tar.gz + c2f17c08a6a94bdab4f4316beb4687e8468de03a5162f1d694a0bab4b90e5962 5965 hello_2.5-1.diff.gz +Files: + cf4b73d837692b93676ccd723bf6f797 582535 hello_2.5.orig.tar.gz + fa6c41ce60b975294781ed00d67f32fe 5965 hello_2.5-1.diff.gz + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.10 (GNU/Linux) + +iQEcBAEBCAAGBQJLeDJTAAoJEEHOfwufG4syQSAH/0S9vYKRbs71bfGNmKTmRQy6 +TJM1oj3hdjJoE9HBvCBoBhRSB7l5Iz+TDVyvKTcFOnXTWrZfhnNRCoErtOxP8Z0R +MOEeLDTPf3JEvpwaRbfzngp+dRkAXTJSI+equqOvj4jjPd1lrNegWtwTF6VIlXAX +5s+onfBp29/MesxzTGAdviobMYCdazmi2XceC+t5ZEJzEsMMPO6i/v22SrvE/Jkg +LiD/U6gea3/1dovsUY6I7/VyzMhHgdcuUW4dzovr2daLwE+uRp9R90XDtKN5aWUM +oBzk8vBIsw/3EV5kjCKdMtqFGdHBjn4nTKvyoXmJ1SvEzeEd21WvLsBFpcJVKaw= +=YMqG +-----END PGP SIGNATURE----- diff --git a/tests/data/test_debs/impossible-build-depends_2.5-1.dsc b/tests/data/test_debs/impossible-build-depends_2.5-1.dsc new file mode 100644 index 0000000..7f7364a --- /dev/null +++ b/tests/data/test_debs/impossible-build-depends_2.5-1.dsc @@ -0,0 +1,33 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA256 + +Format: 1.0 +Source: hello +Binary: hello +Architecture: any +Version: 2.5-1 +Maintainer: Santiago Vila +Homepage: http://www.gnu.org/software/hello +Standards-Version: 3.8.4 +Build-Depends: debhelper (>> 101) +Checksums-Sha1: + dfaf92bfc8144141bcd5ffb4a30777cd57501bfa 582535 hello_2.5.orig.tar.gz + a98ab19072b35295ded3560721662131933f7c05 5965 hello_2.5-1.diff.gz +Checksums-Sha256: + 22934a7d3a62f247ce3b5a77a2c7f7dd095ad8aef305efa2d0d15e0fef31c446 582535 hello_2.5.orig.tar.gz + c2f17c08a6a94bdab4f4316beb4687e8468de03a5162f1d694a0bab4b90e5962 5965 hello_2.5-1.diff.gz +Files: + cf4b73d837692b93676ccd723bf6f797 582535 hello_2.5.orig.tar.gz + fa6c41ce60b975294781ed00d67f32fe 5965 hello_2.5-1.diff.gz + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.10 (GNU/Linux) + +iQEcBAEBCAAGBQJLeDJTAAoJEEHOfwufG4syQSAH/0S9vYKRbs71bfGNmKTmRQy6 +TJM1oj3hdjJoE9HBvCBoBhRSB7l5Iz+TDVyvKTcFOnXTWrZfhnNRCoErtOxP8Z0R +MOEeLDTPf3JEvpwaRbfzngp+dRkAXTJSI+equqOvj4jjPd1lrNegWtwTF6VIlXAX +5s+onfBp29/MesxzTGAdviobMYCdazmi2XceC+t5ZEJzEsMMPO6i/v22SrvE/Jkg +LiD/U6gea3/1dovsUY6I7/VyzMhHgdcuUW4dzovr2daLwE+uRp9R90XDtKN5aWUM +oBzk8vBIsw/3EV5kjCKdMtqFGdHBjn4nTKvyoXmJ1SvEzeEd21WvLsBFpcJVKaw= +=YMqG +-----END PGP SIGNATURE----- diff --git a/tests/data/test_debs/large-package-content_1.0_all.deb b/tests/data/test_debs/large-package-content_1.0_all.deb new file mode 100644 index 0000000..56bdce3 Binary files /dev/null and b/tests/data/test_debs/large-package-content_1.0_all.deb differ diff --git a/tests/data/test_debs/multiarch-test1_i386.deb b/tests/data/test_debs/multiarch-test1_i386.deb new file mode 100644 index 0000000..439a9f4 Binary files /dev/null and b/tests/data/test_debs/multiarch-test1_i386.deb differ diff --git a/tests/data/test_debs/testdep-allowed-any_1.0-1_i386.deb b/tests/data/test_debs/testdep-allowed-any_1.0-1_i386.deb new file mode 100644 index 0000000..c56f819 Binary files /dev/null and b/tests/data/test_debs/testdep-allowed-any_1.0-1_i386.deb differ diff --git a/tests/data/test_debs/testdep-same-arch_1.0-1_i386.deb b/tests/data/test_debs/testdep-same-arch_1.0-1_i386.deb new file mode 100644 index 0000000..872f3b6 Binary files /dev/null and b/tests/data/test_debs/testdep-same-arch_1.0-1_i386.deb differ diff --git a/tests/data/test_debs/utf8-package_1.0-1_all.deb b/tests/data/test_debs/utf8-package_1.0-1_all.deb new file mode 100644 index 0000000..e0339c2 Binary files /dev/null and b/tests/data/test_debs/utf8-package_1.0-1_all.deb differ diff --git a/tests/data/test_debs/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_maverick_main_binary-i386_Packages b/tests/data/test_debs/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_maverick_main_binary-i386_Packages new file mode 100644 index 0000000..b3b30d0 --- /dev/null +++ b/tests/data/test_debs/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_maverick_main_binary-i386_Packages @@ -0,0 +1,31 @@ +Package: autotools-dev +Priority: optional +Section: devel +Installed-Size: 216 +Maintainer: Ubuntu Developers +Original-Maintainer: Henrique de Moraes Holschuh +Architecture: all +Version: 20100122.1 +Filename: pool/main/a/autotools-dev/autotools-dev_20100122.1_all.deb +Size: 70700 +MD5sum: dc25cef0035a3fc7c64b9f2eeddac5d2 +SHA1: 40bcffb6bc2ec7aeaae747c300a0ad70ef3bb38c +SHA256: 290aaf1d5d5a6c560a128b6fe5557fe981ebb85e105410f3bca2e468ce54aaac +Description: Update infrastructure for config.{guess,sub} files + This package installs an up-to-date version of config.guess and + config.sub, used by the automake and libtool packages. It provides + the canonical copy of those files for other packages as well. + . + It also documents in /usr/share/doc/autotools-dev/README.Debian.gz + best practices and guidelines for using autoconf, automake and + friends on Debian packages. This is a must-read for any developers + packaging software that uses the GNU autotools, or GNU gettext. + . + Additionally this package provides seamless integration into Debhelper + or CDBS, allowing maintainers to easily update config.{guess,sub} files + in their packages. +Enhances: cdbs, debhelper +Homepage: http://savannah.gnu.org/projects/config/ +Bugs: https://bugs.launchpad.net/ubuntu/+filebug +Origin: Ubuntu +Supported: 18m diff --git a/tests/data/test_debs/var/lib/dpkg/status b/tests/data/test_debs/var/lib/dpkg/status new file mode 100644 index 0000000..5c2c48a --- /dev/null +++ b/tests/data/test_debs/var/lib/dpkg/status @@ -0,0 +1,92 @@ +Package: apt +Status: install ok installed +Priority: important +Section: admin +Installed-Size: 5456 +Maintainer: APT Development Team +Architecture: i386 +Version: 0.7.25.3 +Replaces: libapt-pkg-dev (<< 0.3.7), libapt-pkg-doc (<< 0.3.7) +Provides: libapt-pkg-libc6.10-6-4.8 +Description: Advanced front-end for dpkg + This is Debian's next generation front-end for the dpkg package manager. + It provides the apt-get utility and APT dselect method that provides a + simpler, safer way to install and upgrade packages. + . + APT features complete installation ordering, multiple source capability + and several other unique features, see the Users Guide in apt-doc. + +Package: postfix +Status: install ok installed +Priority: extra +Section: mail +Installed-Size: 3488 +Maintainer: LaMont Jones +Architecture: i386 +Version: 2.7.0-1 +Replaces: mail-transport-agent, postfix-tls +Provides: default-mta, mail-transport-agent, postfix-tls +Recommends: python +Conflicts: libnss-db (<< 2.2-3), mail-transport-agent, postfix-tls, smail +Description: High-performance mail transport agent + Postfix is Wietse Venema's mail transport agent that started life as an + alternative to the widely-used Sendmail program. Postfix attempts to + be fast, easy to administer, and secure, while at the same time being + sendmail compatible enough to not upset existing users. Thus, the outside + has a sendmail-ish flavor, but the inside is completely different. + +Package: debconf +Status: install ok installed +Priority: important +Section: admin +Installed-Size: 924 +Maintainer: Debconf Developers +Architecture: all +Version: 1.5.28 +Replaces: debconf-tiny +Provides: debconf-2.0 +Recommends: apt-utils (>= 0.5.1) +Conflicts: apt (<< 0.3.12.1), cdebconf (<< 0.96), debconf-tiny, debconf-utils (<< 1.3.22), dialog (<< 0.9b-20020814-1), menu (<= 2.1.3-1), whiptail (<< 0.51.4-11), whiptail-utf8 (<= 0.50.17-13) +Description: Debian configuration management system + Debconf is a configuration management system for debian packages. Packages + use Debconf to ask questions when they are installed. +Python-Version: 2.6, 3.1 + +Package: testdep-same +Status: install ok installed +Source: testdep +Version: 1.0-1 +Architecture: amd64 +Maintainer: Francois Gouget +Installed-Size: 25 +Provides: testdep-virtual-same +Section: unknown +Priority: extra +Multi-Arch: same +Description: Multi-arch = same package, no dependency + This is a multiarch package that can only satisfy dependencies for the same + architecture. But multiple instances of this package can be co-installed, + one for each architecture. + . + Library and development packages typically fall into this category. + +Package: testdep-allowed +Status: install ok installed +Source: testdep +Version: 1.0-1 +Architecture: amd64 +Maintainer: Francois Gouget +Installed-Size: 25 +Provides: testdep-virtual-allowed +Section: unknown +Priority: extra +Multi-Arch: allowed +Description: Multi-arch = allowed package, no dependency + This is a multiarch package. By default it can only satisfy dependencies for + packages of the same architecture but that can be changed with ':any' + dependencies. + . + It can only be installed for one architecture at a time. Trying to install the + same package for another architecture will remove the first one. + . + Packages providing tools or shells typically fall into this category. diff --git a/tests/fakeroot-apt-key b/tests/fakeroot-apt-key new file mode 100755 index 0000000..997161a --- /dev/null +++ b/tests/fakeroot-apt-key @@ -0,0 +1,2 @@ +#!/bin/sh +exec fakeroot /usr/bin/apt-key $* diff --git a/tests/helper_install_progress_run.py b/tests/helper_install_progress_run.py new file mode 100755 index 0000000..02e601d --- /dev/null +++ b/tests/helper_install_progress_run.py @@ -0,0 +1,15 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2019 Colomban Wendling +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +"""Helper checking argv[1] is a valid, writable, file descriptor""" + +import os +from sys import argv + +assert len(argv) == 2 +with os.fdopen(int(argv[1]), "w") as f: + assert f.write("test") == 4 diff --git a/tests/old/__init__.py b/tests/old/__init__.py new file mode 100644 index 0000000..5311641 --- /dev/null +++ b/tests/old/__init__.py @@ -0,0 +1,11 @@ +import os +import unittest + +if __name__ == "__main__": + os.chdir(os.path.dirname(__file__)) + print(os.getcwd()) + + for path in os.listdir("."): + if path.endswith(".py"): + exec("from %s import *" % path[:-3]) + unittest.main() diff --git a/tests/old/apt-test.py b/tests/old/apt-test.py new file mode 100644 index 0000000..8c66aeb --- /dev/null +++ b/tests/old/apt-test.py @@ -0,0 +1,27 @@ +import warnings + +warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning) +import apt + +if __name__ == "__main__": + progress = apt.progress.OpTextProgress() + cache = apt.Cache(progress) + print(cache) + for pkg in cache: + if pkg.is_upgradable: + pkg.mark_install() + for pkg in cache.get_changes(): + # print pkg.name() + pass + print("Broken: %s " % cache._depcache.broken_count) + print("inst_count: %s " % cache._depcache.inst_count) + + # get a new cache + cache = apt.Cache(progress) + for name in cache.keys(): + import random + + if random.randint(0, 1) == 1: + cache[name].mark_delete() + print("Broken: %s " % cache._depcache.broken_count) + print("del_count: %s " % cache._depcache.del_count) diff --git a/tests/old/cache.py b/tests/old/cache.py new file mode 100644 index 0000000..3f4aa0c --- /dev/null +++ b/tests/old/cache.py @@ -0,0 +1,51 @@ +#!/usr/bin/python3 +# +# Test for the pkgCache code +# + +import sys + +import apt_pkg + + +def main(): + apt_pkg.init() + cache = apt_pkg.Cache() + depcache = apt_pkg.DepCache(cache) + depcache.init() + i = 0 + all = cache.package_count + print("Running Cache test on all packages:") + # first, get all pkgs + for pkg in cache.packages: + i += 1 + pkg.name + # then get each version + for ver in pkg.version_list: + # get some version information + ver.file_list + ver.ver_str + ver.arch + ver.depends_listStr + dl = ver.depends_list + # get all dependencies (a dict of string->list, + # e.g. "depends:" -> [ver1,ver2,..] + for dep in dl.keys(): + # get the list of each dependency object + for depVerList in dl[dep]: + for z in depVerList: + # get all TargetVersions of + # the dependency object + for j in z.all_targets(): + j.file_list + ver.ver_str + ver.arch + ver.depends_listStr + j = ver.depends_list + + print("\r%i/%i=%.3f%% " % (i, all, (float(i) / float(all) * 100))) + + +if __name__ == "__main__": + main() + sys.exit(0) diff --git a/tests/old/depcache.py b/tests/old/depcache.py new file mode 100644 index 0000000..81ca574 --- /dev/null +++ b/tests/old/depcache.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python2.4 +# +# Test for the DepCache code +# + +import sys + +import apt_pkg + + +def main(): + apt_pkg.init() + cache = apt_pkg.Cache() + depcache = apt_pkg.DepCache(cache) + depcache.init() + i = 0 + all = cache.package_count + print("Running DepCache test on all packages") + print("(trying to install each and then mark it keep again):") + # first, get all pkgs + for pkg in cache.packages: + i += 1 + x = pkg.name + # then get each version + ver = depcache.get_candidate_ver(pkg) + if ver is not None: + depcache.mark_install(pkg) + if depcache.inst_count == 0: + if depcache.is_upgradable(pkg): + print("Error marking %s for install" % x) + for p in cache.packages: + if depcache.marked_install(p): + depcache.mark_keep(p) + if depcache.inst_count != 0: + print( + "Error undoing the selection for %s (inst_count: %s)" + % (x, depcache.inst_count) + ) + print("\r%i/%i=%.3f%% " % (i, all, (float(i) / float(all) * 100))) + + print() + print("Trying upgrade:") + depcache.upgrade() + print("To install: %s " % depcache.inst_count) + print("To remove: %s " % depcache.del_count) + print("Kept back: %s " % depcache.keep_count) + + print("Trying DistUpgrade:") + depcache.upgrade(True) + print("To install: %s " % depcache.inst_count) + print("To remove: %s " % depcache.del_count) + print("Kept back: %s " % depcache.keep_count) + + +if __name__ == "__main__": + main() + sys.exit(0) diff --git a/tests/old/lock.py b/tests/old/lock.py new file mode 100644 index 0000000..c09983c --- /dev/null +++ b/tests/old/lock.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python2.4 +# +# Test for the pkgCache code +# + +import os +import sys + +import apt_pkg + +if __name__ == "__main__": + lock = "/tmp/test.lck" + + apt_pkg.init() + + # system-lock + apt_pkg.pkgsystem_lock() + + pid = os.fork() + if pid == 0: + try: + apt_pkg.pkgsystem_lock() + except SystemError as s: + print("Can't get lock: (error text:\n%s)" % s) + sys.exit(0) + + apt_pkg.pkgsystem_unlock() + + # low-level lock + fd = apt_pkg.get_lock(lock, True) + print("Lockfile fd: %s" % fd) + + # try to get lock without error flag + pid = os.fork() + if pid == 0: + # child + fd = apt_pkg.get_lock(lock, False) + print("Lockfile fd (child): %s" % fd) + sys.exit(0) + + # try to get lock with error flag + pid = os.fork() + if pid == 0: + # child + fd = apt_pkg.get_lock(lock, True) + print("Lockfile fd (child): %s" % fd) + sys.exit(0) diff --git a/tests/old/memleak.py b/tests/old/memleak.py new file mode 100644 index 0000000..44b123e --- /dev/null +++ b/tests/old/memleak.py @@ -0,0 +1,45 @@ +#!/usr/bin/python3 + +import gc +import time + +import apt_pkg + +import apt + +cache = apt.Cache() + +# memleak +for i in range(100): + cache.open(None) + print(cache["apt"].name) + time.sleep(1) + gc.collect() + f = open("%s" % i, "w") + for obj in gc.get_objects(): + f.write("%s\n" % str(obj)) + f.close() + +# memleak +# for i in range(100): +# cache = apt.Cache() +# time.sleep(1) +# cache = None +# gc.collect() + +# no memleak, but more or less the apt.Cache.open() code +for i in range(100): + cache = apt_pkg.Cache() + depcache = apt_pkg.DepCache(cache) + records = apt_pkg.PackageRecords(cache) + list = apt_pkg.SourceList() + list.read_main_list() + dict = {} + for pkg in cache.packages: + if len(pkg.version_list) > 0: + dict[pkg.name] = apt.package(cache, depcache, records, list, None, pkg) + + print(cache["apt"]) + time.sleep(1) + + gc.collect() diff --git a/tests/old/pkgproblemresolver.py b/tests/old/pkgproblemresolver.py new file mode 100644 index 0000000..89190cf --- /dev/null +++ b/tests/old/pkgproblemresolver.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python2.4 +# +# Test for the DepCache code +# + +import sys + +import apt_pkg + + +def main(): + apt_pkg.init() + cache = apt_pkg.Cache() + depcache = apt_pkg.DepCache(cache) + depcache.init() + i = 0 + all = cache.package_count + print("Running DepCache test on all packages") + print("(trying to install each and then mark it keep again):") + # first, get all pkgs + for pkg in cache.packages: + i += 1 + x = pkg.name + # then get each version + ver = depcache.get_candidate_ver(pkg) + if ver is not None: + depcache.mark_install(pkg) + if depcache.broken_count > 0: + fixer = apt_pkg.ProblemResolver(depcache) + fixer.clear(pkg) + fixer.protect(pkg) + # we first try to resolve the problem + # with the package that should be installed + # protected + try: + fixer.resolve(True) + except SystemError: + # the pkg seems to be broken, the + # returns a exception + fixer.clear(pkg) + fixer.resolve(True) + if not depcache.marked_install(pkg): + print("broken in archive: %s " % pkg.name) + fixer = None + if depcache.inst_count == 0: + if depcache.is_upgradable(pkg): + print("Error marking %s for install" % x) + for p in cache.packages: + if depcache.marked_install(p) or depcache.marked_upgrade(p): + depcache.mark_keep(p) + if depcache.inst_count != 0: + print("Error undoing the selection for %s" % x) + print("\r%i/%i=%.3f%% " % (i, all, (float(i) / float(all) * 100))) + + print() + print("Trying upgrade:") + depcache.upgrade() + print("To install: %s " % depcache.inst_count) + print("To remove: %s " % depcache.del_count) + print("Kept back: %s " % depcache.keep_count) + + print("Trying DistUpgrade:") + depcache.upgrade(True) + print("To install: %s " % depcache.inst_count) + print("To remove: %s " % depcache.del_count) + print("Kept back: %s " % depcache.keep_count) + + +if __name__ == "__main__": + main() + sys.exit(0) diff --git a/tests/old/pkgrecords.py b/tests/old/pkgrecords.py new file mode 100644 index 0000000..b6be005 --- /dev/null +++ b/tests/old/pkgrecords.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python2.4 +# +# Test for the PkgSrcRecords code +# it segfaults for python-apt < 0.5.37 +# + +import sys + +import apt_pkg + + +def main(): + apt_pkg.init() + cache = apt_pkg.Cache() + depcache = apt_pkg.DepCache(cache) + depcache.init() + i = 0 + print("Running PkgRecords test on all packages:") + for pkg in cache.packages: + i += 1 + records = apt_pkg.PackageRecords(cache) + if len(pkg.version_list) == 0: + # print "no available version, cruft" + continue + version = depcache.get_candidate_ver(pkg) + if not version: + continue + file, index = version.file_list.pop(0) + if records.lookup((file, index)): + # print records.filename + records.filename + records.long_desc + print( + "\r%i/%i=%.3f%% " + % (i, cache.package_count, (float(i) / float(cache.package_count) * 100)) + ) + + +if __name__ == "__main__": + main() + sys.exit(0) diff --git a/tests/old/pkgsrcrecords.py b/tests/old/pkgsrcrecords.py new file mode 100644 index 0000000..ccf791f --- /dev/null +++ b/tests/old/pkgsrcrecords.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python2.4 +# +# Test for the PkgSrcRecords code +# it segfaults for python-apt < 0.5.37 +# + +import sys + +import apt_pkg + + +def main(): + apt_pkg.init() + cache = apt_pkg.Cache() + i = 0 + print("Running PkgSrcRecords test on all packages:") + for x in cache.packages: + i += 1 + src = apt_pkg.SourceRecords() + if src.lookup(x.name): + # print src.package + pass + print( + "\r%i/%i=%.3f%% " + % (i, cache.package_count, (float(i) / float(cache.package_count) * 100)) + ) + + +if __name__ == "__main__": + main() + sys.exit(0) diff --git a/tests/old/refcount.py b/tests/old/refcount.py new file mode 100755 index 0000000..0fad676 --- /dev/null +++ b/tests/old/refcount.py @@ -0,0 +1,54 @@ +#!/usr/bin/python-dbg + +import gc +import sys +from pprint import pprint + +import apt + +# get initial cache +print(sys.gettotalrefcount()) +progress = apt.progress.OpTextProgress() +c = apt.Cache(progress) +print("refcount after first cache instance: ", sys.gettotalrefcount()) + +# test open() +c.open(progress) +print("refcount after cache open: ", sys.gettotalrefcount()) +# pprint(sys.getobjects(10)) + +c.open(apt.progress.OpProgress()) +print("refcount after seconf cache open: ", sys.gettotalrefcount()) +# pprint(sys.getobjects(10)) + +# FIXME: find a way to get a efficient diff +# before = gc.get_objects() +# c.open(apt.progress.OpProgress()) +# after = gc.get_objects() + + +# test update() +print("refcount before cache.update(): ", sys.gettotalrefcount()) +c.update() +gc.collect() +print("refcount after cache.update(): ", sys.gettotalrefcount()) +c.update() +gc.collect() +print("refcount after second cache.update(): ", sys.gettotalrefcount()) +# pprint(sys.getobjects(20)) + + +# test install() +c.open(apt.progress.OpProgress()) +gc.collect() +print("refcount before cache['hello'].mark_install(): ", sys.gettotalrefcount()) +c["hello"].mark_install() +c.commit(apt.progress.FetchProgress(), apt.progress.InstallProgress()) +gc.collect() +print("refcount after: ", sys.gettotalrefcount()) +c.open(apt.progress.OpProgress()) +c["hello"].mark_delete() +c.commit(apt.progress.FetchProgress(), apt.progress.InstallProgress()) +gc.collect() +print("refcount after: ", sys.gettotalrefcount()) +pprint(sys.getobjects(10)) diff --git a/tests/old/test_enhances.py b/tests/old/test_enhances.py new file mode 100644 index 0000000..79aad9a --- /dev/null +++ b/tests/old/test_enhances.py @@ -0,0 +1,16 @@ +#!/usr/bin/python3 + +import apt + +cache = apt.Cache() + +for pkg in cache: + if pkg.installed and pkg.installed.enhances: + s = "%s enhances:" % pkg.name + for or_list in pkg.installed.enhances: + for enhances in or_list.or_dependencies: + s += " %s" % enhances.name + if enhances.name in cache and not cache[enhances.name].is_installed: + s += "(*missing*) " + s += "," + print(s[:-1]) diff --git a/tests/test_all.py b/tests/test_all.py new file mode 100644 index 0000000..c97ed5d --- /dev/null +++ b/tests/test_all.py @@ -0,0 +1,63 @@ +#!/usr/bin/python3 +# Copyright (C) 2009 Julian Andres Klode +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +"""Run all available unit tests.""" +import os +import sys +import unittest +import unittest.runner + +# Python 3 only provides abiflags since 3.2 +if not hasattr(sys, "pydebug"): + if sys.abiflags.startswith("d"): + sys.pydebug = True + else: + sys.pydebug = False + + +def get_library_dir(): + # Find the path to the built apt_pkg and apt_inst extensions + if not os.path.exists("../build"): + return None + from sysconfig import get_platform, get_python_version + + # Set the path to the build directory. + plat_specifier = f".{get_platform()}-{get_python_version()}" + library_dir = "../build/lib{}{}".format( + plat_specifier, + (sys.pydebug and "-pydebug" or ""), + ) + return os.path.abspath(library_dir) + + +class MyTestRunner(unittest.runner.TextTestRunner): + def __init__(self, *args, **kwargs): + kwargs["stream"] = sys.stdout + super().__init__(*args, **kwargs) + + +if __name__ == "__main__": + if not os.access("/etc/apt/sources.list", os.R_OK): + sys.stdout.write("[tests] Skipping because sources.list is not readable\n") + sys.exit(0) + + sys.stdout.write("[tests] Running on %s\n" % sys.version.replace("\n", "")) + dirname = os.path.dirname(__file__) + if dirname: + os.chdir(dirname) + library_dir = get_library_dir() + if "pybuild" in os.getenv("PYTHONPATH", ""): + # pybuild already supplied us with a path to check for + sys.stdout.write("Using pybuild supplied build dir\n") + elif library_dir: + sys.stdout.write("Using library_dir: '%s'\n" % library_dir) + sys.path.insert(0, os.path.abspath(library_dir)) + + for path in os.listdir("."): + if path.endswith(".py") and os.path.isfile(path) and path.startswith("test_"): + exec("from %s import *" % path[:-3]) + + unittest.main(testRunner=MyTestRunner) diff --git a/tests/test_apt_cache.py b/tests/test_apt_cache.py new file mode 100644 index 0000000..cc52400 --- /dev/null +++ b/tests/test_apt_cache.py @@ -0,0 +1,400 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2010 Julian Andres Klode +# 2010 Michael Vogt +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +"""Unit tests for verifying the correctness of check_dep, etc in apt_pkg.""" + +import glob +import logging +import os +import shutil +import sys +import tempfile +import unittest + +from test_all import get_library_dir + +libdir = get_library_dir() +if libdir: + sys.path.insert(0, libdir) + +import apt_pkg +import testcommon + +import apt + + +def if_sources_list_is_readable(f): + def wrapper(*args, **kwargs): + if os.access("/etc/apt/sources.list", os.R_OK): + f(*args, **kwargs) + else: + logging.warning("skipping '%s' because sources.list is not readable" % f) + + return wrapper + + +def get_open_file_descriptors(): + try: + fds = os.listdir("/proc/self/fd") + except OSError: + logging.warning("failed to list /proc/self/fd") + return set() + return set(map(int, fds)) + + +class TestAptCache(testcommon.TestCase): + """test the apt cache""" + + def setUp(self): + testcommon.TestCase.setUp(self) + apt_pkg.config.clear("APT::Update::Post-Invoke") + apt_pkg.config.clear("APT::Update::Post-Invoke-Success") + + @if_sources_list_is_readable + def test_apt_cache(self): + """cache: iterate all packages and all dependencies""" + cache = apt.Cache() + # number is not meaningful and just need to be "big enough", + # the important bit is the test against __len__ + self.assertTrue(len(cache) > 100) + # go over the cache and all dependencies, just to see if + # that is possible and does not crash + for pkg in cache: + if pkg.candidate: + for or_deps in pkg.candidate.dependencies: + for dep in or_deps: + self.assertTrue(dep.name) + self.assertTrue(isinstance(dep.relation, str)) + self.assertTrue(dep.pre_depend in (True, False)) + + # accessing record should take a reasonable time; in + # particular, when using compressed indexes, it should not use + # tons of seek operations + r = pkg.candidate.record + self.assertEqual(r["Package"], pkg.shortname) + self.assertTrue("Version" in r) + self.assertTrue(len(r["Description"]) > 0) + self.assertTrue(str(r).startswith("Package: %s\n" % pkg.shortname)) + + @if_sources_list_is_readable + def test_cache_close_leak_fd(self): + fds_before_open = get_open_file_descriptors() + cache = apt.Cache() + opened_fd = get_open_file_descriptors().difference(fds_before_open) + cache.close() + fds_after_close = get_open_file_descriptors() + unclosed_fd = opened_fd.intersection(fds_after_close) + self.assertEqual(fds_before_open, fds_after_close) + self.assertEqual(unclosed_fd, set()) + + def test_cache_open_twice_leaks_fds(self): + cache = apt.Cache() + fds_before_open = get_open_file_descriptors() + cache.open() + fds_after_open_twice = get_open_file_descriptors() + self.assertEqual(fds_before_open, fds_after_open_twice) + + @if_sources_list_is_readable + def test_cache_close_download_fails(self): + cache = apt.Cache() + self.assertEqual(cache.required_download, 0) + cache.close() + with self.assertRaises(apt.cache.CacheClosedException): + cache.required_download + + def test_get_provided_packages(self): + apt.apt_pkg.config.set("Apt::architecture", "i386") + cache = apt.Cache(rootdir="./data/test-provides/") + cache.open() + if len(cache) == 0: + logging.warning("skipping test_get_provided_packages, cache empty?!?") + return + # a true virtual pkg + li = cache.get_providing_packages("mail-transport-agent") + self.assertTrue(len(li) > 0) + self.assertTrue("postfix" in [p.name for p in li]) + self.assertTrue("mail-transport-agent" in cache["postfix"].candidate.provides) + + def test_low_level_pkg_provides(self): + apt.apt_pkg.config.set("Apt::architecture", "i386") + # create highlevel cache and get the lowlevel one from it + highlevel_cache = apt.Cache(rootdir="./data/test-provides") + if len(highlevel_cache) == 0: + logging.warning("skipping test_log_level_pkg_provides, cache empty?!?") + return + # low level cache provides list of the pkg + cache = highlevel_cache._cache + li = cache["mail-transport-agent"].provides_list + # arbitrary number, just needs to be higher enough + self.assertEqual(len(li), 2) + for providesname, providesver, version in li: + self.assertEqual(providesname, "mail-transport-agent") + if version.parent_pkg.name == "postfix": + break + else: + self.assertNotReached() + + @if_sources_list_is_readable + def test_dpkg_journal_dirty(self): + # create tmp env + tmpdir = tempfile.mkdtemp() + dpkg_dir = os.path.join(tmpdir, "var", "lib", "dpkg") + os.makedirs(os.path.join(dpkg_dir, "updates")) + open(os.path.join(dpkg_dir, "status"), "w").close() + apt_pkg.config.set("Dir::State::status", os.path.join(dpkg_dir, "status")) + cache = apt.Cache() + # test empty + self.assertFalse(cache.dpkg_journal_dirty) + # that is ok, only [0-9] are dpkg jounral entries + open(os.path.join(dpkg_dir, "updates", "xxx"), "w").close() + self.assertFalse(cache.dpkg_journal_dirty) + # that is a dirty journal + open(os.path.join(dpkg_dir, "updates", "000"), "w").close() + self.assertTrue(cache.dpkg_journal_dirty) + + @if_sources_list_is_readable + def test_apt_update(self): + rootdir = "./data/tmp" + if os.path.exists(rootdir): + shutil.rmtree(rootdir) + try: + os.makedirs(os.path.join(rootdir, "var/lib/apt/lists/partial")) + except OSError: + pass + state_dir = os.path.join(rootdir, "var/lib/apt") + lists_dir = os.path.join(rootdir, "var/lib/apt/lists") + old_state = apt_pkg.config.find("dir::state") + apt_pkg.config.set("dir::state", state_dir) + # set a local sources.list that does not need the network + base_sources = os.path.abspath(os.path.join(rootdir, "sources.list")) + old_source_list = apt_pkg.config.find("dir::etc::sourcelist") + old_source_parts = apt_pkg.config.find("dir::etc::sourceparts") + apt_pkg.config.set("dir::etc::sourcelist", base_sources) + # TODO: /dev/null is not a dir, perhaps find something better + apt_pkg.config.set("dir::etc::sourceparts", "/dev/null") + # main sources.list + sources_list = base_sources + with open(sources_list, "w") as f: + repo = os.path.abspath("./data/test-repo2") + f.write("deb [allow-insecure=yes] copy:%s /\n" % repo) + + # test single sources.list fetching + sources_list = os.path.join(rootdir, "test.list") + with open(sources_list, "w") as f: + repo_dir = os.path.abspath("./data/test-repo") + f.write("deb [allow-insecure=yes] copy:%s /\n" % repo_dir) + + self.assertTrue(os.path.exists(sources_list)) + # write marker to ensure listcleaner is not run + open("./data/tmp/var/lib/apt/lists/marker", "w").close() + + # update a single sources.list + cache = apt.Cache() + cache.update(sources_list=sources_list) + # verify we just got the excpected package file + needle_packages = glob.glob(lists_dir + "/*tests_data_test-repo_Packages*") + self.assertEqual(len(needle_packages), 1) + # verify that we *only* got the Packages file from a single source + all_packages = glob.glob(lists_dir + "/*_Packages*") + self.assertEqual(needle_packages, all_packages) + # verify that the listcleaner was not run and the marker file is + # still there + self.assertTrue("marker" in os.listdir(lists_dir)) + # now run update again (without the "normal" sources.list that + # contains test-repo2 and verify that we got the normal sources.list + cache.update() + needle_packages = glob.glob(lists_dir + "/*tests_data_test-repo2_Packages*") + self.assertEqual(len(needle_packages), 1) + all_packages = glob.glob(lists_dir + "/*_Packages*") + self.assertEqual(needle_packages, all_packages) + + # and another update with a single source only + cache = apt.Cache() + cache.update(sources_list=sources_list) + all_packages = glob.glob(lists_dir + "/*_Packages*") + self.assertEqual(len(all_packages), 2) + apt_pkg.config.set("dir::state", old_state) + apt_pkg.config.set("dir::etc::sourcelist", old_source_list) + apt_pkg.config.set("dir::etc::sourceparts", old_source_parts) + + def test_package_cmp(self): + cache = apt.Cache(rootdir="/") + li = [] + li.append(cache["intltool"]) + li.append(cache["python3"]) + li.append(cache["apt"]) + li.sort() + self.assertEqual([p.name for p in li], ["apt", "intltool", "python3"]) + + def test_get_architectures(self): + main_arch = apt.apt_pkg.config.get("APT::Architecture") + arches = apt_pkg.get_architectures() + self.assertTrue(main_arch in arches) + + def test_phasing_applied(self): + """checks the return type of phasing_applied.""" + cache = apt.Cache() + pkg = cache["apt"] + self.assertIsInstance(pkg.phasing_applied, bool) + + def test_is_security_update(self): + """checks the return type of is_security_update.""" + cache = apt.Cache() + pkg = cache["apt"] + self.assertIsInstance(pkg.installed.is_security_update, bool) + + def test_apt_cache_reopen_is_safe(self): + """cache: check that we cannot use old package objects after reopen""" + cache = apt.Cache() + old_depcache = cache._depcache + old_package = cache["apt"] + old_pkg = old_package._pkg + old_version = old_package.candidate + old_ver = old_version._cand + + cache.open() + new_depcache = cache._depcache + new_package = cache["apt"] + new_pkg = new_package._pkg + new_version = new_package.candidate + new_ver = new_version._cand + + # get candidate + self.assertRaises(ValueError, old_depcache.get_candidate_ver, new_pkg) + self.assertRaises(ValueError, new_depcache.get_candidate_ver, old_pkg) + self.assertEqual(new_ver, new_depcache.get_candidate_ver(new_pkg)) + self.assertEqual(old_package.candidate._cand, old_ver) # Remap success + self.assertEqual( + old_package.candidate._cand, new_depcache.get_candidate_ver(new_pkg) + ) + + # set candidate + new_package.candidate = old_version + old_depcache.set_candidate_ver(old_pkg, old_ver) + self.assertRaises(ValueError, old_depcache.set_candidate_ver, old_pkg, new_ver) + self.assertRaises(ValueError, new_depcache.set_candidate_ver, old_pkg, old_ver) + self.assertRaises(ValueError, new_depcache.set_candidate_ver, old_pkg, new_ver) + self.assertRaises(ValueError, new_depcache.set_candidate_ver, new_pkg, old_ver) + new_depcache.set_candidate_ver(new_pkg, new_ver) + + @staticmethod + def write_status_file(packages): + with open(apt_pkg.config["Dir::State::Status"], "w") as fobj: + for package in packages: + print("Package:", package, file=fobj) + print("Status: install ok installed", file=fobj) + print("Priority: optional", file=fobj) + print("Section: admin", file=fobj) + print("Installed-Size: 1", file=fobj) + print("Maintainer: X ", file=fobj) + print("Architecture: all", file=fobj) + print("Version: 1", file=fobj) + print("Description: blah", file=fobj) + print("", file=fobj) + + def test_apt_cache_reopen_is_safe_out_of_bounds(self): + """Check that out of bounds access is remapped correctly.""" + with tempfile.NamedTemporaryFile() as status: + apt_pkg.config["Dir::Etc::SourceList"] = "/dev/null" + apt_pkg.config["Dir::Etc::SourceParts"] = "/dev/null" + apt_pkg.config["Dir::State::Status"] = status.name + apt_pkg.init_system() + + self.write_status_file("abcdefghijklmnopqrstuvwxyz") + c = apt.Cache() + p = c["z"] + p_id = p.id + self.write_status_file("az") + apt_pkg.init_system() + c.open() + self.assertNotEqual(p.id, p_id) + self.assertLess(p.id, 2) + p.mark_delete() + self.assertEqual([p], c.get_changes()) + + def test_apt_cache_reopen_is_safe_out_of_bounds_no_match(self): + """Check that installing gone package raises correct exception""" + with tempfile.NamedTemporaryFile() as status: + apt_pkg.config["Dir::Etc::SourceList"] = "/dev/null" + apt_pkg.config["Dir::Etc::SourceParts"] = "/dev/null" + apt_pkg.config["Dir::State::Status"] = status.name + apt_pkg.init_system() + + self.write_status_file("abcdefghijklmnopqrstuvwxyz") + c = apt.Cache() + p = c["z"] + p_id = p.id + self.write_status_file("a") + apt_pkg.init_system() + c.open() + self.assertEqual(p.id, p_id) # Could not be remapped + self.assertRaises(apt_pkg.CacheMismatchError, p.mark_delete) + + def test_apt_cache_reopen_is_safe_swap(self): + """Check that swapping a and b does not mark the wrong package.""" + with tempfile.NamedTemporaryFile() as status: + apt_pkg.config["Dir::Etc::SourceList"] = "/dev/null" + apt_pkg.config["Dir::Etc::SourceParts"] = "/dev/null" + apt_pkg.config["Dir::State::Status"] = status.name + apt_pkg.init_system() + + self.write_status_file("abcdefghijklmnopqrstuvwxyz") + c = apt.Cache() + p = c["a"] + a_id = p.id + p_hash = hash(p) + set_of_p = {p} + self.write_status_file("baz") + apt_pkg.init_system() + c.open() + # b now has the same id as a in the old cache + self.assertEqual(c["b"].id, a_id) + self.assertNotEqual(p.id, a_id) + # Marking a should still mark a, not b. + p.mark_delete() + self.assertEqual([p], c.get_changes()) + + # Ensure that p can still be found in a set of it, as a test + # for bug https://bugs.launchpad.net/bugs/1780099 + self.assertEqual(hash(p), p_hash) + self.assertIn(p, set_of_p) + + def test_apt_cache_iteration_safe(self): + """Check that iterating does not produce different results. + + This failed in 1.7.0~alpha2, because one part of the code + looked up packages in the weak dict using the pretty name, + and the other using the full name.""" + + with tempfile.NamedTemporaryFile() as status: + apt_pkg.config["Dir::Etc::SourceList"] = "/dev/null" + apt_pkg.config["Dir::Etc::SourceParts"] = "/dev/null" + apt_pkg.config["Dir::State::Status"] = status.name + apt_pkg.init_system() + + self.write_status_file("abcdefghijklmnopqrstuvwxyz") + + c = apt.Cache() + c["a"].mark_delete() + self.assertEqual([c["a"]], [p for p in c if p.marked_delete]) + + def test_problemresolver_keep_phased_updates(self): + """Check that the c++ function can be called.""" + with tempfile.NamedTemporaryFile() as status: + apt_pkg.config["Dir::Etc::SourceList"] = "/dev/null" + apt_pkg.config["Dir::Etc::SourceParts"] = "/dev/null" + apt_pkg.config["Dir::State::Status"] = status.name + apt_pkg.init_system() + + cache = apt.Cache() + problemresolver = apt.ProblemResolver(cache) + self.assertIsNone(problemresolver.keep_phased_updates()) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_aptsources.py b/tests/test_aptsources.py new file mode 100644 index 0000000..1e04552 --- /dev/null +++ b/tests/test_aptsources.py @@ -0,0 +1,1573 @@ +#!/usr/bin/python3 + +import copy +import os +import tempfile +import unittest + +import apt_pkg +import testcommon + +import aptsources.distro +import aptsources.sourceslist + + +class TestAptSources(testcommon.TestCase): + def setUp(self): + testcommon.TestCase.setUp(self) + if apt_pkg.config["APT::Architecture"] not in ("i386", "amd64"): + apt_pkg.config.set("APT::Architecture", "i386") + apt_pkg.config.set("Dir::Etc", os.getcwd()) + apt_pkg.config.set("Dir::Etc::sourceparts", tempfile.mkdtemp()) + if os.path.exists("./build/data/templates"): + self.templates = os.path.abspath("./build/data/templates") + elif os.path.exists("../build/data/templates"): + self.templates = os.path.abspath("../build/data/templates") + else: + self.templates = "/usr/share/python-apt/templates/" + + def tearDown(self): + aptsources.distro._OSRelease.OS_RELEASE_FILE = ( + aptsources.distro._OSRelease.DEFAULT_OS_RELEASE_FILE + ) + if "LSB_ETC_LSB_RELEASE" in os.environ: + del os.environ["LSB_ETC_LSB_RELEASE"] + + def testIsMirror(self): + """aptsources: Test mirror detection.""" + yes = aptsources.sourceslist.is_mirror( + "http://archive.ubuntu.com", "http://de.archive.ubuntu.com" + ) + no = aptsources.sourceslist.is_mirror( + "http://archive.ubuntu.com", "http://ftp.debian.org" + ) + self.assertTrue(yes) + self.assertFalse(no) + + def testSourcesListReading(self): + """aptsources: Test sources.list parsing.""" + apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list") + sources = aptsources.sourceslist.SourcesList(True, self.templates) + self.assertEqual(len(sources.list), 10) + # test load + sources.list = [] + sources.load("data/aptsources/sources.list") + self.assertEqual(len(sources.list), 10) + + def testSourcesListReading_deb822(self): + """aptsources: Test sources.list parsing.""" + apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d") + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + self.assertEqual(len(sources.list), 5) + # test load + sources.list = [] + sources.load("data/aptsources/sources.list.d/main.sources") + self.assertEqual(len(sources.list), 5) + + for entry in sources.list: + self.assertFalse(entry.invalid) + self.assertFalse(entry.disabled) + self.assertEqual(entry.types, ["deb"]) + self.assertEqual(entry.type, "deb") + self.assertEqual(entry.uris, ["http://de.archive.ubuntu.com/ubuntu/"]) + self.assertEqual(entry.uri, "http://de.archive.ubuntu.com/ubuntu/") + + self.assertEqual(sources.list[0].comps, ["main"]) + self.assertEqual(sources.list[1].comps, ["restricted"]) + self.assertEqual(sources.list[2].comps, ["universe"]) + self.assertEqual(sources.list[3].comps, ["main"]) + self.assertEqual(sources.list[4].comps, ["main"]) + + for entry in sources.list[:-1]: + self.assertIsNone(entry.trusted) + + self.assertTrue(sources.list[-1].trusted) + + for entry in sources.list[:-2]: + self.assertEqual(entry.architectures, []) + self.assertEqual(entry.suites, ["edgy"]) + self.assertEqual(entry.dist, "edgy") + + for entry in sources.list[-2:]: + self.assertEqual(entry.suites, ["natty"]) + self.assertEqual(entry.dist, "natty") + self.assertEqual(entry.architectures, ["amd64", "i386"]) + + def testSourcesListWriting_deb822(self): + """aptsources: Test sources.list parsing.""" + apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d") + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + with tempfile.TemporaryDirectory() as tmpdir: + for entry in sources.list: + entry.file = os.path.join(tmpdir, os.path.basename(entry.file)) + + sources.save() + + maxDiff = self.maxDiff + self.maxDiff = None + for file in os.listdir("data/aptsources/sources.list.d"): + with open(os.path.join("data/aptsources/sources.list.d", file)) as a: + with open(os.path.join(tmpdir, file)) as b: + self.assertEqual(a.read(), b.read(), f"file {file}") + self.maxDiff = maxDiff + + def testSourcesListAdding(self): + """aptsources: Test additions to sources.list""" + apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list") + sources = aptsources.sourceslist.SourcesList(True, self.templates) + # test to add something that is already there (main) + before = copy.deepcopy(sources) + sources.add("deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["main"]) + self.assertTrue(sources.list == before.list) + # test to add something that is already there (restricted) + before = copy.deepcopy(sources) + sources.add( + "deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["restricted"] + ) + self.assertTrue(sources.list == before.list) + + before = copy.deepcopy(sources) + sources.add( + "deb", + "http://de.archive.ubuntu.com/ubuntu/", + "natty", + ["main"], + architectures=["amd64", "i386"], + ) + self.assertTrue(sources.list == before.list) + + # test to add something new: multiverse + sources.add( + "deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["multiverse"] + ) + found = False + for entry in sources: + if ( + entry.type == "deb" + and entry.uri == "http://de.archive.ubuntu.com/ubuntu/" + and entry.dist == "edgy" + and "multiverse" in entry.comps + ): + found = True + break + self.assertTrue(found) + + # add a new natty entry without architecture specification + sources.add( + "deb", "http://de.archive.ubuntu.com/ubuntu/", "natty", ["multiverse"] + ) + found = False + for entry in sources: + if ( + entry.type == "deb" + and entry.uri == "http://de.archive.ubuntu.com/ubuntu/" + and entry.dist == "natty" + and entry.architectures == [] + and "multiverse" in entry.comps + ): + found = True + break + self.assertTrue(found) + + # Add universe to existing multi-arch line + sources.add( + "deb", + "http://de.archive.ubuntu.com/ubuntu/", + "natty", + ["universe"], + architectures=["i386", "amd64"], + ) + found = False + for entry in sources: + if ( + entry.type == "deb" + and entry.uri == "http://de.archive.ubuntu.com/ubuntu/" + and entry.dist == "natty" + and set(entry.architectures) == {"amd64", "i386"} + and set(entry.comps) == {"main", "universe"} + ): + found = True + break + self.assertTrue(found) + # test to add something new: multiverse *and* + # something that is already there + before = copy.deepcopy(sources) + sources.add( + "deb", + "http://de.archive.ubuntu.com/ubuntu/", + "edgy", + ["universe", "something"], + ) + found_universe = 0 + found_something = 0 + for entry in sources: + if ( + entry.type == "deb" + and entry.uri == "http://de.archive.ubuntu.com/ubuntu/" + and entry.dist == "edgy" + ): + for c in entry.comps: + if c == "universe": + found_universe += 1 + if c == "something": + found_something += 1 + # print "\n".join([s.str() for s in sources]) + self.assertEqual(found_something, 1) + self.assertEqual(found_universe, 1) + + def testSourcesListAdding_deb822(self): + """aptsources: Test additions to sources.list""" + apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d") + + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + # test to add something that is already there (main) + before = copy.deepcopy(sources) + sources.add("deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["main"]) + self.assertEqual(sources.list, before.list) + # test to add something that is already there (restricted) + before = copy.deepcopy(sources) + sources.add( + "deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["restricted"] + ) + self.assertTrue(sources.list == before.list) + + before = copy.deepcopy(sources) + sources.add( + "deb", + "http://de.archive.ubuntu.com/ubuntu/", + "natty", + ["main"], + architectures=["amd64", "i386"], + ) + self.assertEqual( + [e.str() for e in sources.list], [e.str() for e in before.list] + ) + + # test to add something new: multiverse + sources.add( + "deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["multiverse"] + ) + found = False + for entry in sources: + if ( + entry.type == "deb" + and entry.uri == "http://de.archive.ubuntu.com/ubuntu/" + and entry.dist == "edgy" + and "multiverse" in entry.comps + ): + found = True + break + self.assertTrue(found) + + # add a new natty entry without architecture specification + sources.add( + "deb", "http://de.archive.ubuntu.com/ubuntu/", "natty", ["multiverse"] + ) + found = False + for entry in sources: + if ( + entry.type == "deb" + and entry.uri == "http://de.archive.ubuntu.com/ubuntu/" + and entry.dist == "natty" + and entry.architectures == [] + and "multiverse" in entry.comps + ): + found = True + break + self.assertTrue(found) + + # Add universe to existing multi-arch line + sources.add( + "deb", + "http://de.archive.ubuntu.com/ubuntu/", + "natty", + ["universe"], + architectures=["i386", "amd64"], + ) + found = False + for entry in sources: + if ( + entry.type == "deb" + and entry.uri == "http://de.archive.ubuntu.com/ubuntu/" + and entry.dist == "natty" + and set(entry.architectures) == {"amd64", "i386"} + and set(entry.comps) == {"main", "universe"} + ): + found = True + break + self.assertTrue(found) + # test to add something new: multiverse *and* + # something that is already there + before = copy.deepcopy(sources) + sources.add( + "deb", + "http://de.archive.ubuntu.com/ubuntu/", + "edgy", + ["universe", "something"], + ) + found_universe = 0 + found_something = 0 + for entry in sources: + if ( + entry.type == "deb" + and entry.uri == "http://de.archive.ubuntu.com/ubuntu/" + and entry.dist == "edgy" + ): + for c in entry.comps: + if c == "universe": + found_universe += 1 + if c == "something": + found_something += 1 + # print "\n".join([s.str() for s in sources]) + self.assertEqual(found_something, 1) + self.assertEqual(found_universe, 1) + + def testAddingWithComment_deb822(self): + apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d") + self._commonTestAddingWithComment() + + def testAddingWithComment_short(self): + apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list") + self._commonTestAddingWithComment() + + def _commonTestAddingWithComment(self): + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + + # test to add something that is already there (main); loses comment + before = copy.deepcopy(sources) + sources.add( + "deb", + "http://de.archive.ubuntu.com/ubuntu/", + "edgy", + ["main"], + comment="this will be lost", + ) + self.assertTrue(sources.list == before.list) + for entry in sources: + self.assertNotEqual(entry.comment, "this will be lost") + + # test to add component to existing entry: multiverse; loses comment + sources.add( + "deb", + "http://de.archive.ubuntu.com/ubuntu/", + "edgy", + ["multiverse"], + comment="this will be lost", + ) + for entry in sources: + self.assertNotEqual(entry.comment, "this will be lost") + + before = copy.deepcopy(sources) + # test to add entirely new entry; retains comment + sources.add( + "deb-src", + "http://de.archive.ubuntu.com/ubuntu/", + "edgy", + ["main"], + comment="this will appear", + file=sources.list[0].file, # make sure we test the deb822 code path + ) + self.assertNotEqual(sources.list, before.list) + self.assertEqual(len(sources.list), len(before.list) + 1) + found = False + for entry in sources: + if ( + entry.type == "deb-src" + and entry.uri == "http://de.archive.ubuntu.com/ubuntu/" + and entry.dist == "edgy" + and entry.comment == "this will appear" + and "main" in entry.comps + ): + found = True + break + self.assertTrue(found) + + def testInsertion_deb822(self): + apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d") + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + + # test to insert something that is already there (universe); does not + # move existing entry (remains at index 2) + before = copy.deepcopy(sources) + sources.add( + "deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["universe"], pos=0 + ) + self.assertTrue(sources.list == before.list) + entry = list(sources)[2] + self.assertEqual(entry.type, "deb") + self.assertEqual(entry.uri, "http://de.archive.ubuntu.com/ubuntu/") + self.assertEqual(entry.dist, "edgy") + self.assertIn("universe", entry.comps) + + # test add component to existing entry: multiverse; does not move + # entry to which it is appended (remains at index 0) + sources.add( + "deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["multiverse"], pos=2 + ) + entry = list(sources)[0] + self.assertTrue( + entry.type == "deb" + and entry.uri == "http://de.archive.ubuntu.com/ubuntu/" + and entry.dist == "edgy" + and {"main", "multiverse"} <= set(entry.comps) + ) + + # test to add entirely new entry; inserted at 0 + sources.add( + "deb-src", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["main"], pos=0 + ) + entry = list(sources)[0] + self.assertTrue( + entry.type == "deb-src" + and entry.uri == "http://de.archive.ubuntu.com/ubuntu/" + and entry.dist == "edgy" + and "main" in entry.comps + ) + + def testInsertion(self): + apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list") + sources = aptsources.sourceslist.SourcesList(True, self.templates) + + # test to insert something that is already there (universe); does not + # move existing entry (remains at index 2) + before = copy.deepcopy(sources) + sources.add( + "deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["universe"], pos=0 + ) + self.assertTrue(sources.list == before.list) + entry = list(sources)[5] + self.assertTrue( + entry.type == "deb" + and entry.uri == "http://de.archive.ubuntu.com/ubuntu/" + and entry.dist == "edgy" + and "universe" in entry.comps + ) + + # test add component to existing entry: multiverse; does not move + # entry to which it is appended (remains at index 0) + sources.add( + "deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["multiverse"], pos=2 + ) + entry = list(sources)[1] + self.assertTrue( + entry.type == "deb" + and entry.uri == "http://de.archive.ubuntu.com/ubuntu/" + and entry.dist == "edgy" + and {"main", "multiverse"} <= set(entry.comps) + ) + + # test to add entirely new entry; inserted at 0 + sources.add( + "deb-src", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["main"], pos=0 + ) + entry = list(sources)[0] + self.assertTrue( + entry.type == "deb-src" + and entry.uri == "http://de.archive.ubuntu.com/ubuntu/" + and entry.dist == "edgy" + and "main" in entry.comps + ) + + def testDuplication_short(self): + apt_pkg.config.set( + "Dir::Etc::sourcelist", "data/aptsources/sources.list.testDuplication" + ) + return self.commonTestDuplication() + + def testDuplication_deb822(self): + apt_pkg.config.set( + "Dir::Etc::sourceparts", "data/aptsources/sources.list.d.testDuplication" + ) + return self.commonTestDuplication() + + def commonTestDuplication(self): + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + test_url = "http://ppa.launchpad.net/me/myproject/ubuntu" + # test to add something that is already there (enabled) + before = copy.deepcopy(sources) + sources.add("deb", test_url, "xenial", ["main"]) + self.assertEqual(sources.list, before.list) + # test to add something that is already there (disabled) + sources.add("# deb-src", test_url, "xenial", ["main"]) + self.assertEqual(sources.list, before.list) + # test to enable something that is already there + sources.add("deb-src", test_url, "xenial", ["main"]) + found = False + self.assertEqual(len(sources.list), 2) + for entry in sources: + if ( + entry.type == "deb-src" + and not entry.disabled + and entry.uri == test_url + and entry.dist == "xenial" + and entry.architectures == [] + and entry.comps == ["main"] + ): + found = True + break + self.assertTrue(found) + + def testMatcher_short(self): + """aptsources: Test matcher""" + apt_pkg.config.set( + "Dir::Etc::sourcelist", "data/aptsources/" "sources.list.testDistribution" + ) + return self.commonTestMatcher() + + def testMatcher_deb822(self): + """aptsources: Test matcher""" + apt_pkg.config.set( + "Dir::Etc::sourceparts", + "data/aptsources/" "sources.list.d.testDistribution", + ) + return self.commonTestMatcher() + + def commonTestMatcher(self): + """aptsources: Test matcher""" + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + distro = aptsources.distro.get_distro( + id="Ubuntu", + codename="bionic", + description="Ubuntu 18.04 LTS", + release="18.04", + ) + distro.get_sources(sources) + # test if all suits of the current distro were detected correctly + self.assertNotEqual(sources.list, []) + for s in sources: + if not s.template: + self.fail("source entry '%s' has no matcher" % s) + + # Hack in a check for splitting of fields here. + if sources.list[-1].file.endswith(".sources"): + self.assertEqual( + sources.list[-1].uris, ["cdrom:[Ubuntu 8.04 _Hardy Heron_]"] + ) + self.assertEqual(sources.list[-1].uri, "cdrom:[Ubuntu 8.04 _Hardy Heron_]") + + def testMultiArch(self): + """aptsources: Test multi-arch parsing""" + + apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list") + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + assert not sources.list[8].invalid + assert sources.list[8].type == "deb" + assert sources.list[8].architectures == ["amd64", "i386"] + assert sources.list[8].uri == "http://de.archive.ubuntu.com/ubuntu/" + assert sources.list[8].dist == "natty" + assert sources.list[8].comps == ["main"] + assert sources.list[8].line.strip() == str(sources.list[8]) + assert sources.list[8].trusted is None + + def testMultiArch_deb822(self): + """aptsources: Test multi-arch parsing""" + + apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d") + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + assert not sources.list[3].invalid + assert sources.list[3].type == "deb" + assert sources.list[3].architectures == ["amd64", "i386"] + assert sources.list[3].uri == "http://de.archive.ubuntu.com/ubuntu/" + assert sources.list[3].dist == "natty" + assert sources.list[3].comps == ["main"] + self.assertEqual(sources.list[3].line.strip(), str(sources.list[3])) + self.assertIsNone(sources.list[3].trusted) + + def testMultipleOptions(self): + """aptsources: Test multi-arch parsing""" + + apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list") + sources = aptsources.sourceslist.SourcesList(True, self.templates) + assert sources.list[9].invalid is False + assert sources.list[9].type == "deb" + assert sources.list[9].architectures == ["amd64", "i386"] + self.assertEqual(sources.list[9].uri, "http://de.archive.ubuntu.com/ubuntu/") + assert sources.list[9].dist == "natty" + assert sources.list[9].comps == ["main"] + assert sources.list[9].trusted + assert sources.list[9].line.strip() == str(sources.list[9]) + + def testMultipleOptions_deb822(self): + """aptsources: Test multi-arch parsing""" + + apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d") + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + assert sources.list[4].invalid is False + assert sources.list[4].type == "deb" + assert sources.list[4].architectures == ["amd64", "i386"] + self.assertEqual(sources.list[4].uri, "http://de.archive.ubuntu.com/ubuntu/") + assert sources.list[4].dist == "natty" + assert sources.list[4].comps == ["main"] + assert sources.list[4].trusted + assert sources.list[4].line.strip() == str(sources.list[4]) + + def test_enable_component(self): + target = "./data/aptsources/sources.list.enable_comps" + line = "deb http://archive.ubuntu.com/ubuntu lucid main\n" + with open(target, "w") as target_file: + target_file.write(line) + apt_pkg.config.set("Dir::Etc::sourcelist", target) + sources = aptsources.sourceslist.SourcesList(True, self.templates) + distro = aptsources.distro.get_distro( + id="Ubuntu", codename="lucid", release="10.04", description="Ubuntu 10.04" + ) + # and get the sources + distro.get_sources(sources) + # test enable_component + comp = "multiverse" + distro.enable_component(comp) + comps = set() + for entry in sources: + comps = comps.union(set(entry.comps)) + self.assertTrue("multiverse" in comps) + self.assertTrue("universe" in comps) + + def test_enable_component_deb822(self): + target = ( + apt_pkg.config.find_dir("dir::etc::sourceparts") + "enable_comps.sources" + ) + line = "Types: deb\nURIs: http://archive.ubuntu.com/ubuntu\nSuites: lucid\nComponents: main\n" + with open(target, "w") as target_file: + target_file.write(line) + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + distro = aptsources.distro.get_distro( + id="Ubuntu", codename="lucid", release="10.04", description="Ubuntu 10.04" + ) + # and get the sources + distro.get_sources(sources) + # test enable_component + comp = "multiverse" + distro.enable_component(comp) + comps = set() + for entry in sources: + comps = comps.union(set(entry.comps)) + self.assertTrue("multiverse" in comps) + self.assertTrue("universe" in comps) + + def test_enable_component_deb822_multi(self): + apt_pkg.config.set("Dir::Etc::sourcelist", "/dev/null") + + target = ( + apt_pkg.config.find_dir("dir::etc::sourceparts") + "enable_comps.sources" + ) + line = "Types: deb\nURIs: http://archive.ubuntu.com/ubuntu\nSuites: lucid lucid-updates\nComponents: main\n" + with open(target, "w") as target_file: + target_file.write(line) + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + distro = aptsources.distro.get_distro( + id="Ubuntu", codename="lucid", release="10.04", description="Ubuntu 10.04" + ) + # and get the sources + distro.get_sources(sources) + self.assertEqual(len(distro.main_sources), 1) + self.assertEqual(len(sources.list), 1) + # test enable_component + comp = "multiverse" + distro.enable_component(comp) + self.assertEqual(len(sources.list), 2) # split into two + + self.assertEqual( + "Types: deb\n" + "URIs: http://archive.ubuntu.com/ubuntu\n" + "Suites: lucid\n" + "Components: main multiverse universe", + str(sources.list[0]), + ) + self.assertEqual( + "Types: deb\n" + "URIs: http://archive.ubuntu.com/ubuntu\n" + "Suites: lucid-updates\n" + "Components: main multiverse universe", + str(sources.list[1]), + ) + + comps = set() + for entry in sources: + comps = comps.union(set(entry.comps)) + self.assertTrue("multiverse" in comps) + self.assertTrue("universe" in comps) + + sources.save() + self.assertEqual( + "Types: deb\n" + "URIs: http://archive.ubuntu.com/ubuntu\n" + "Suites: lucid lucid-updates\n" + "Components: main multiverse universe", + str(sources.list[0]), + ) + + def test_enable_component_deb822_multi_mixed_origin(self): + apt_pkg.config.set("Dir::Etc::sourcelist", "/dev/null") + + target = ( + apt_pkg.config.find_dir("dir::etc::sourceparts") + "enable_comps.sources" + ) + line = "Types: deb\nURIs: http://archive.ubuntu.com/ubuntu http://example.com/\nSuites: lucid\nComponents: main\n" + with open(target, "w") as target_file: + target_file.write(line) + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + distro = aptsources.distro.get_distro( + id="Ubuntu", codename="lucid", release="10.04", description="Ubuntu 10.04" + ) + # and get the sources + distro.get_sources(sources) + self.assertEqual(len(distro.main_sources), 2) + self.assertEqual(len(sources.list), 1) + # test enable_component + comp = "multiverse" + distro.enable_component(comp) + self.assertEqual(len(sources.list), 2) # split into two + + self.assertEqual( + "Types: deb\n" + "URIs: http://archive.ubuntu.com/ubuntu\n" + "Suites: lucid\n" + "Components: main multiverse universe", + str(sources.list[0]), + ) + self.assertEqual( + "Types: deb\n" + "URIs: http://example.com/\n" + "Suites: lucid\n" + "Components: main", + str(sources.list[1]), + ) + + sources.save() + self.assertEqual( + "Types: deb\n" + "URIs: http://archive.ubuntu.com/ubuntu\n" + "Suites: lucid\n" + "Components: main multiverse universe", + str(sources.list[0]), + ) + self.assertEqual( + "Types: deb\n" + "URIs: http://example.com/\n" + "Suites: lucid\n" + "Components: main", + str(sources.list[1]), + ) + + def test_enable_component_deb822_multi_mixed_ultimate(self): + apt_pkg.config.set("Dir::Etc::sourcelist", "/dev/null") + + target = ( + apt_pkg.config.find_dir("dir::etc::sourceparts") + "enable_comps.sources" + ) + line = "Types: deb deb-src\nURIs: http://archive.ubuntu.com/ubuntu http://example.com/\nSuites: lucid lucid-updates notalucid\nComponents: main\n" + with open(target, "w") as target_file: + target_file.write(line) + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + distro = aptsources.distro.get_distro( + id="Ubuntu", codename="lucid", release="10.04", description="Ubuntu 10.04" + ) + # and get the sources + distro.get_sources(sources) + self.assertEqual(len(distro.main_sources), 1) + self.assertEqual(len(sources.list), 1) + self.assertEqual(len(sources.exploded_list()), 12) + # test enable_component + comp = "multiverse" + distro.enable_component(comp) + self.assertEqual(len(sources.list), 12) # split into two + + expected = [] + for typ in "deb", "deb-src": + for uri in "http://archive.ubuntu.com/ubuntu", "http://example.com/": + for suite in "lucid", "lucid-updates", "notalucid": + comps = "main multiverse universe" + # unofficial source ends up without enablement + if uri == "http://example.com/" or suite == "notalucid": + comps = "main" + expected.append( + f"Types: {typ}\n" + f"URIs: {uri}\n" + f"Suites: {suite}\n" + f"Components: {comps}" + ) + + self.maxDiff = None + self.assertEqual(expected, list(map(str, sources.list))) + sources.save() + + expected = [ + "Types: deb deb-src\n" + "URIs: http://archive.ubuntu.com/ubuntu\n" + "Suites: lucid lucid-updates\n" + "Components: main multiverse universe", + # unofficial suite + "Types: deb deb-src\n" + "URIs: http://archive.ubuntu.com/ubuntu http://example.com/\n" + "Suites: notalucid\n" + "Components: main", + # unofficial mirror, FIXME: We'd rather merge the notalucid into here + "Types: deb deb-src\n" + "URIs: http://example.com/\n" + "Suites: lucid lucid-updates\n" + "Components: main", + ] + self.maxDiff = None + self.assertEqual(expected, list(map(str, sources.list))) + + def test_deb822_explode(self): + apt_pkg.config.set("Dir::Etc::sourcelist", "/dev/null") + target = ( + apt_pkg.config.find_dir("dir::etc::sourceparts") + "enable_comps.sources" + ) + line = "Types: deb\nURIs: http://archive.ubuntu.com/ubuntu\nSuites: lucid\nComponents: main\n" + with open(target, "w") as target_file: + target_file.write(line) + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + + self.assertEqual(len(sources.list), 1) + self.assertEqual(len(sources.exploded_list()), 1) + self.assertIsInstance( + sources.exploded_list()[0], aptsources.sourceslist.Deb822SourceEntry + ) + + sources.list[0].suites += ["fakesuite"] + self.assertEqual(len(sources.list), 1) + self.assertEqual(len(sources.exploded_list()), 2) + self.assertIsInstance( + sources.exploded_list()[0], aptsources.sourceslist.ExplodedDeb822SourceEntry + ) + self.assertIsInstance( + sources.exploded_list()[1], aptsources.sourceslist.ExplodedDeb822SourceEntry + ) + self.assertEqual(sources.list[0].suites, ["lucid", "fakesuite"]) + sources.remove(sources.exploded_list()[1]) + self.assertEqual(len(sources.list), 1) + self.assertEqual(len(sources.exploded_list()), 1) + self.assertEqual(sources.list[0].suites, ["lucid"]) + + sources.list[0].types += ["deb-src"] + self.assertEqual(len(sources.list), 1) + self.assertEqual(len(sources.exploded_list()), 2) + self.assertIsInstance( + sources.exploded_list()[0], aptsources.sourceslist.ExplodedDeb822SourceEntry + ) + self.assertIsInstance( + sources.exploded_list()[1], aptsources.sourceslist.ExplodedDeb822SourceEntry + ) + self.assertEqual(sources.list[0].types, ["deb", "deb-src"]) + sources.remove(sources.exploded_list()[1]) + self.assertEqual(len(sources.list), 1) + self.assertEqual(len(sources.exploded_list()), 1) + self.assertEqual(sources.list[0].types, ["deb"]) + + sources.list[0].uris += ["http://example.com"] + self.assertEqual(len(sources.list), 1) + self.assertEqual(len(sources.exploded_list()), 2) + self.assertIsInstance( + sources.exploded_list()[0], aptsources.sourceslist.ExplodedDeb822SourceEntry + ) + self.assertIsInstance( + sources.exploded_list()[1], aptsources.sourceslist.ExplodedDeb822SourceEntry + ) + self.assertEqual( + sources.list[0].uris, + ["http://archive.ubuntu.com/ubuntu", "http://example.com"], + ) + sources.remove(sources.exploded_list()[1]) + self.assertEqual(len(sources.list), 1) + self.assertEqual(len(sources.exploded_list()), 1) + self.assertEqual(sources.list[0].uris, ["http://archive.ubuntu.com/ubuntu"]) + + # test setting attributes + sources.list[0].uris += ["http://example.com"] + with self.assertRaises(AttributeError): + sources.exploded_list()[0].types = ["does not work"] + with self.assertRaises(AttributeError): + sources.exploded_list()[0].uris = ["does not work"] + with self.assertRaises(AttributeError): + sources.exploded_list()[0].suites = ["does not work"] + with self.assertRaises(AttributeError): + sources.exploded_list()[0].doesnotexist = ["does not work"] + + # test overriding + sources.exploded_list()[0].type = "faketype" + self.assertEqual(sources.list[0].type, "faketype") + self.assertEqual(sources.list[1].type, "deb") + sources.exploded_list()[0].type = "deb" + self.assertEqual(sources.list[0].type, "deb") + self.assertEqual(sources.list[1].type, "deb") + sources.save() + self.assertEqual(len(sources.list), 1) + + def testDistribution_short(self): + """aptsources: Test distribution detection.""" + apt_pkg.config.set( + "Dir::Etc::sourcelist", "data/aptsources/" "sources.list.testDistribution" + ) + return self.commonTestDistribution() + + def testDistribution_deb822(self): + """aptsources: Test distribution detection.""" + apt_pkg.config.set( + "Dir::Etc::sourceparts", + "data/aptsources/" "sources.list.d.testDistribution", + ) + return self.commonTestDistribution() + + def commonTestDistribution(self): + """aptsources: Test distribution detection.""" + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + distro = aptsources.distro.get_distro( + id="Ubuntu", + codename="bionic", + description="Ubuntu 18.04 LTS", + release="18.04", + ) + distro.get_sources(sources) + # test if all suits of the current distro were detected correctly + dist_templates = set() + for s in sources: + if s.template: + dist_templates.add(s.template.name) + # print dist_templates + for d in ( + "hardy", + "hardy-security", + "hardy-updates", + "intrepid", + "hardy-backports", + ): + self.assertTrue(d in dist_templates) + # test enable + comp = "restricted" + distro.enable_component(comp) + found = {} + for entry in sources: + if ( + entry.type == "deb" + and entry.uri == "http://de.archive.ubuntu.com/ubuntu/" + and "edgy" in entry.dist + ): + for c in entry.comps: + if c == comp: + if entry.dist not in found: + found[entry.dist] = 0 + found[entry.dist] += 1 + # print "".join([s.str() for s in sources]) + for key in found: + self.assertEqual(found[key], 1) + + # add a not-already available component + comp = "multiverse" + distro.enable_component(comp) + found = {} + for entry in sources: + if entry.type == "deb" and entry.template and entry.template.name == "edgy": + for c in entry.comps: + if c == comp: + if entry.dist not in found.has_key: + found[entry.dist] = 0 + found[entry.dist] += 1 + # print "".join([s.str() for s in sources]) + for key in found: + self.assertEqual(found[key], 1) + + @unittest.skip("lsb-release test broken when it was added") + def test_os_release_distribution(self): + """os-release file can be read and is_like is populated accordingly""" + os.environ["LSB_ETC_LSB_RELEASE"] = os.path.abspath( + "./data/aptsources/lsb-release" + ) + aptsources.distro._OSRelease.OS_RELEASE_FILE = os.path.abspath( + "./data/aptsources/os-release" + ) + distro = aptsources.distro.get_distro() + # Everything but is_like comes from lsb_release, see TODO in + # get_distro. + self.assertEqual("Ubuntu", distro.id) + self.assertEqual("xenial", distro.codename) + self.assertEqual("Ubuntu 16.04.1 LTS", distro.description) + self.assertEqual("16.04", distro.release) + self.assertEqual(["ubuntu", "debian"], distro.is_like) + + def test_enable_disabled_short(self): + """LP: #1042916: Test enabling disabled entry.""" + apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list") + return self.common_test_enable_disabled() + + def test_enable_disabled_deb822(self): + """LP: #1042916: Test enabling disabled entry.""" + apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d") + return self.common_test_enable_disabled() + + def common_test_enable_disabled(self): + """LP: #1042916: Test enabling disabled entry.""" + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + disabled = sources.add( + "deb", + "http://fi.archive.ubuntu.com/ubuntu/", + "precise", + ["main"], + file=sources.list[0].file, # if we use deb822, enable deb822 + ) + disabled.set_enabled(False) + enabled = sources.add( + "deb", + "http://fi.archive.ubuntu.com/ubuntu/", + "precise", + ["main"], + file=sources.list[0].file, # if we use deb822, enable deb822 + ) + self.assertEqual(disabled, enabled) + self.assertFalse(disabled.disabled) + + def test_duplicate_uri_with_trailing_slash_short(self): + """Test replacing entry with same uri except trailing slash""" + apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list") + return self.common_test_duplicate_uri_with_trailing_slash() + + def test_duplicate_uri_with_trailing_slash_deb822(self): + """Test replacing entry with same uri except trailing slash""" + apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d") + return self.common_test_duplicate_uri_with_trailing_slash() + + def common_test_duplicate_uri_with_trailing_slash(self): + """Test replacing entry with same uri except trailing slash""" + sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True) + line_wslash = "deb http://rslash.ubuntu.com/ubuntu/ precise main" + line_woslash = "deb http://rslash.ubuntu.com/ubuntu precise main" + entry_wslash = aptsources.sourceslist.SourceEntry(line_wslash) + entry_woslash = aptsources.sourceslist.SourceEntry(line_woslash) + self.assertEqual(entry_wslash, entry_woslash) + count = len(sources.list) + sourceslist_wslash = sources.add( + entry_wslash.type, entry_wslash.uri, entry_wslash.dist, entry_wslash.comps + ) + self.assertEqual(count + 1, len(sources.list)) + count = len(sources.list) + sourceslist_woslash = sources.add( + entry_woslash.type, + entry_woslash.uri, + entry_woslash.dist, + entry_woslash.comps, + ) + self.assertEqual(count, len(sources.list)) + self.assertEqual(sourceslist_wslash, sourceslist_woslash) + + def test_deb822_distro_enable_disable_component(self): + """Test enabling and disabling a component in the distro sources. + + This ensures reasonable behavior when enabling and then disabling a component""" + with tempfile.NamedTemporaryFile("w", suffix=".sources") as file: + file.write( + "# main archive\n" + "Types: deb deb-src\n" + "URIs: http://archive.ubuntu.com/ubuntu/\n" + "Suites: noble noble-updates\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# security\n" + "Types: deb deb-src\n" + "URIs: http://security.ubuntu.com/ubuntu/\n" + "Suites: noble-security\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + ) + file.flush() + + apt_pkg.config.set("Dir::Etc::sourcelist", file.name) + sources = aptsources.sourceslist.SourcesList( + True, self.templates, deb822=True + ) + distro = aptsources.distro.get_distro( + id="Ubuntu", + codename="noble", + description="Ubuntu 24.04 LTS", + release="24.04", + ) + + self.assertEqual(len(sources.list), 2) + distro.get_sources(sources) + distro.enable_component("multiverse") + sources.save() + + with open(file.name) as readonly: + self.maxDiff = None + self.assertEqual( + readonly.read(), + "# main archive\n" + "Types: deb deb-src\n" + "URIs: http://archive.ubuntu.com/ubuntu/\n" + "Suites: noble noble-updates\n" + "Components: main universe multiverse\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# security\n" + "Types: deb deb-src\n" + "URIs: http://security.ubuntu.com/ubuntu/\n" + "Suites: noble-security\n" + "Components: main universe multiverse\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n", + ) + + # Disable it again + # FIXME: The child entries will no longer be valid at this point, so we have to call + # get_sources(), but it's not clear whether this should be considered a bug - + # there may have been other changes rendering entries no longer valid that distro + # is holding on to. + distro.get_sources(sources) + distro.disable_component("multiverse") + sources.save() + + with open(file.name) as readonly: + self.maxDiff = None + self.assertEqual( + readonly.read(), + "# main archive\n" + "Types: deb deb-src\n" + "URIs: http://archive.ubuntu.com/ubuntu/\n" + "Suites: noble noble-updates\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# security\n" + "Types: deb deb-src\n" + "URIs: http://security.ubuntu.com/ubuntu/\n" + "Suites: noble-security\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n", + ) + + # Disable universe as well + distro.get_sources(sources) + distro.disable_component("universe") + sources.save() + + with open(file.name) as readonly: + self.maxDiff = None + self.assertEqual( + readonly.read(), + "# main archive\n" + "Types: deb deb-src\n" + "URIs: http://archive.ubuntu.com/ubuntu/\n" + "Suites: noble noble-updates\n" + "Components: main\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# security\n" + "Types: deb deb-src\n" + "URIs: http://security.ubuntu.com/ubuntu/\n" + "Suites: noble-security\n" + "Components: main\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n", + ) + + def test_deb822_distro_enable_disable_component_mixed_origin(self): + """Test enabling and disabling a component in the distro sources, with mixed origin + + Here we ensure that we still get idempotent behavior of disable after enable even if the + entry we were modifying also had a non-official repository in it.""" + with tempfile.NamedTemporaryFile("w", suffix=".sources") as file: + file.write( + "# main archive\n" + "Types: deb deb-src\n" + "URIs: http://archive.ubuntu.com/ubuntu/ http://unofficial.example.com/\n" + "Suites: noble noble-updates\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# security\n" + "Types: deb deb-src\n" + "URIs: http://security.ubuntu.com/ubuntu/\n" + "Suites: noble-security\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + ) + file.flush() + + apt_pkg.config.set("Dir::Etc::sourcelist", file.name) + sources = aptsources.sourceslist.SourcesList( + True, self.templates, deb822=True + ) + distro = aptsources.distro.get_distro( + id="Ubuntu", + codename="noble", + description="Ubuntu 24.04 LTS", + release="24.04", + ) + + self.assertEqual(len(sources.list), 2) + distro.get_sources(sources) + distro.enable_component("multiverse") + sources.save() + + with open(file.name) as readonly: + self.maxDiff = None + self.assertEqual( + readonly.read(), + "# main archive\n" + "Types: deb deb-src\n" + "URIs: http://archive.ubuntu.com/ubuntu/\n" + "Suites: noble noble-updates\n" + "Components: main universe multiverse\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# main archive\n" + "Types: deb deb-src\n" + "URIs: http://unofficial.example.com/\n" + "Suites: noble noble-updates\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# security\n" + "Types: deb deb-src\n" + "URIs: http://security.ubuntu.com/ubuntu/\n" + "Suites: noble-security\n" + "Components: main universe multiverse\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n", + ) + + # Disable it again + # FIXME: The child entries will no longer be valid at this point, so we have to call + # get_sources(), but it's not clear whether this should be considered a bug - + # there may have been other changes rendering entries no longer valid that distro + # is holding on to. + distro.get_sources(sources) + distro.disable_component("multiverse") + sources.save() + + with open(file.name) as readonly: + self.maxDiff = None + self.assertEqual( + readonly.read(), + "# main archive\n" + "Types: deb deb-src\n" + "URIs: http://archive.ubuntu.com/ubuntu/ http://unofficial.example.com/\n" + "Suites: noble noble-updates\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# security\n" + "Types: deb deb-src\n" + "URIs: http://security.ubuntu.com/ubuntu/\n" + "Suites: noble-security\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n", + ) + + # Disable universe too. The behaviour here is interesting: Distro only disables + # universe for the official source, so we end up with the non-official source split out. + distro.get_sources(sources) + distro.disable_component("universe") + sources.save() + + with open(file.name) as readonly: + self.maxDiff = None + self.assertEqual( + readonly.read(), + "# main archive\n" + "Types: deb deb-src\n" + "URIs: http://archive.ubuntu.com/ubuntu/\n" + "Suites: noble noble-updates\n" + "Components: main\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# main archive\n" # note it keeps the comment on the split out child + "Types: deb deb-src\n" + "URIs: http://unofficial.example.com/\n" + "Suites: noble noble-updates\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# security\n" + "Types: deb deb-src\n" + "URIs: http://security.ubuntu.com/ubuntu/\n" + "Suites: noble-security\n" + "Components: main\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n", + ) + + def test_deb822_distro_enable_disable_child_source_mixed_origins(self): + """Test enabling and disabling a child source (proposed) in the distro sources, with mixed origin + + Here we ensure that we still get idempotent behavior of disable after enable even if the + entry we were modifying also had a non-official repository in it.""" + with tempfile.NamedTemporaryFile("w", suffix=".sources") as file: + file.write( + "# main archive\n" + "Types: deb deb-src\n" + "URIs: http://archive.ubuntu.com/ubuntu/ http://unofficial.example.com/\n" + "Suites: noble noble-updates\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# security\n" + "Types: deb deb-src\n" + "URIs: http://security.ubuntu.com/ubuntu/\n" + "Suites: noble-security\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + ) + file.flush() + + apt_pkg.config.set("Dir::Etc::sourcelist", file.name) + sources = aptsources.sourceslist.SourcesList( + True, self.templates, deb822=True + ) + distro = aptsources.distro.get_distro( + id="Ubuntu", + codename="noble", + description="Ubuntu 24.04 LTS", + release="24.04", + ) + + self.assertEqual(len(sources.list), 2) + distro.get_sources(sources) + distro.get_source_code = True + distro.add_source(dist="noble-proposed") + + # FIXME: Component ordering is not stable right now + for entry in sources.list: + entry.comps = sorted(entry.comps) + sources.save() + + with open(file.name) as readonly: + self.maxDiff = None + + # FIXME: In an optimal world it would look like this + self.assertNotEqual( + readonly.read(), + "# main archive\n" + "Types: deb deb-src\n" + "URIs: http://archive.ubuntu.com/ubuntu/\n" + "Suites: noble noble-updates noble-proposed\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# main archive\n" + "Types: deb deb-src\n" + "URIs: http://unofficial.example.com/\n" + "Suites: noble noble-updates\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# security\n" + "Types: deb deb-src\n" + "URIs: http://security.ubuntu.com/ubuntu/\n" + "Suites: noble-security\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n", + ) + + with open(file.name) as readonly: + self.maxDiff = None + # Sadly our merge algorithm does not always produce optimal merges, because it merges the unofficial entry first + self.assertEqual( + readonly.read(), + "# main archive\n" + "Types: deb deb-src\n" + "URIs: http://archive.ubuntu.com/ubuntu/ http://unofficial.example.com/\n" + "Suites: noble noble-updates\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# security\n" + "Types: deb deb-src\n" + "URIs: http://security.ubuntu.com/ubuntu/\n" + "Suites: noble-security\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "Types: deb deb-src\n" + "URIs: http://archive.ubuntu.com/ubuntu/\n" + "Suites: noble-proposed\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n", + ) + + # Disable it again + # FIXME: The child entries will no longer be valid at this point, so we have to call + # get_sources(), but it's not clear whether this should be considered a bug - + # there may have been other changes rendering entries no longer valid that distro + # is holding on to. + distro.get_sources(sources) + for child in distro.child_sources + distro.source_code_sources: + if child.dist.endswith("proposed"): + sources.remove(child) + sources.save() + + with open(file.name) as readonly: + self.maxDiff = None + self.assertEqual( + readonly.read(), + "# main archive\n" + "Types: deb deb-src\n" + "URIs: http://archive.ubuntu.com/ubuntu/ http://unofficial.example.com/\n" + "Suites: noble noble-updates\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# security\n" + "Types: deb deb-src\n" + "URIs: http://security.ubuntu.com/ubuntu/\n" + "Suites: noble-security\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n", + ) + + def test_deb822_distro_enable_disable_child_source_mixed_origins_no_source_code( + self, + ): + """Test enabling and disabling a child source (proposed) in the distro sources, with mixed origin + + Here we ensure that we still get idempotent behavior of disable after enable even if the + entry we were modifying also had a non-official repository in it.""" + with tempfile.NamedTemporaryFile("w", suffix=".sources") as file: + file.write( + "# main archive\n" + "Types: deb\n" + "URIs: http://archive.ubuntu.com/ubuntu/ http://unofficial.example.com/\n" + "Suites: noble noble-updates\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# security\n" + "Types: deb\n" + "URIs: http://security.ubuntu.com/ubuntu/\n" + "Suites: noble-security\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + ) + file.flush() + + apt_pkg.config.set("Dir::Etc::sourcelist", file.name) + sources = aptsources.sourceslist.SourcesList( + True, self.templates, deb822=True + ) + distro = aptsources.distro.get_distro( + id="Ubuntu", + codename="noble", + description="Ubuntu 24.04 LTS", + release="24.04", + ) + + self.assertEqual(len(sources.list), 2) + distro.get_sources(sources) + self.assertEqual( + [(s.type, s.uri, s.dist, s.comps) for s in distro.main_sources] + + ["separator"] + + [(s.type, s.uri, s.dist, s.comps) for s in distro.child_sources], + [ + ( + "deb", + "http://archive.ubuntu.com/ubuntu/", + "noble", + ["main", "universe"], + ), + "separator", + ( + "deb", + "http://archive.ubuntu.com/ubuntu/", + "noble-updates", + ["main", "universe"], + ), + ( + "deb", + "http://security.ubuntu.com/ubuntu/", + "noble-security", + ["main", "universe"], + ), + ], + ) + distro.add_source(dist="noble-proposed") + + # FIXME: Component ordering is not stable right now + for entry in sources.list: + entry.comps = sorted(entry.comps) + sources.save() + + with open(file.name) as readonly: + self.maxDiff = None + + # FIXME: In an optimal world it would look like this + self.assertNotEqual( + readonly.read(), + "# main archive\n" + "Types: deb\n" + "URIs: http://archive.ubuntu.com/ubuntu/\n" + "Suites: noble noble-updates noble-proposed\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# main archive\n" + "Types: deb\n" + "URIs: http://unofficial.example.com/\n" + "Suites: noble noble-updates\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# security\n" + "Types: deb\n" + "URIs: http://security.ubuntu.com/ubuntu/\n" + "Suites: noble-security\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n", + ) + + with open(file.name) as readonly: + self.maxDiff = None + # Sadly our merge algorithm does not always produce optimal merges, because it merges the unofficial entry first + self.assertEqual( + readonly.read(), + "# main archive\n" + "Types: deb\n" + "URIs: http://archive.ubuntu.com/ubuntu/ http://unofficial.example.com/\n" + "Suites: noble noble-updates\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# security\n" + "Types: deb\n" + "URIs: http://security.ubuntu.com/ubuntu/\n" + "Suites: noble-security\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "Types: deb\n" + "URIs: http://archive.ubuntu.com/ubuntu/\n" + "Suites: noble-proposed\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n", + ) + + # Disable it again + # FIXME: The child entries will no longer be valid at this point, so we have to call + # get_sources(), but it's not clear whether this should be considered a bug - + # there may have been other changes rendering entries no longer valid that distro + # is holding on to. + distro.get_sources(sources) + for child in distro.child_sources + distro.source_code_sources: + if child.dist.endswith("proposed"): + sources.remove(child) + sources.save() + + with open(file.name) as readonly: + self.maxDiff = None + self.assertEqual( + readonly.read(), + "# main archive\n" + "Types: deb\n" + "URIs: http://archive.ubuntu.com/ubuntu/ http://unofficial.example.com/\n" + "Suites: noble noble-updates\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n" + "\n" + "# security\n" + "Types: deb\n" + "URIs: http://security.ubuntu.com/ubuntu/\n" + "Suites: noble-security\n" + "Components: main universe\n" + "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n", + ) + + +if __name__ == "__main__": + os.chdir(os.path.dirname(__file__)) + unittest.main() diff --git a/tests/test_aptsources_deb822.py b/tests/test_aptsources_deb822.py new file mode 100755 index 0000000..6a1bb61 --- /dev/null +++ b/tests/test_aptsources_deb822.py @@ -0,0 +1,63 @@ +#!/usr/bin/python3 + +import io +import os +import tempfile +import unittest + +import apt_pkg +import testcommon + +import aptsources.distro +import aptsources.sourceslist + + +class TestAptSources(testcommon.TestCase): + def setUp(self): + testcommon.TestCase.setUp(self) + self.tempfile = tempfile.NamedTemporaryFile(suffix=".sources") + apt_pkg.config.set("Dir::Etc::sourcelist", self.tempfile.name) + apt_pkg.config.set("Dir::Etc::sourceparts", "/dev/null") + + def tearDown(self): + self.tempfile.close() + + def testEmptyDeb822(self): + """aptsources: Test sources.list parsing.""" + sources = aptsources.sourceslist.SourcesList(True) + self.assertListEqual(sources.list, []) + + def testDeb822SectionRecognizedWithoutEndLine(self): + """aptsources: Test sources.list parsing.""" + section = aptsources._deb822.Section("key: value\notherkey: othervalue") + + # Writing it back out gives us an extra newline at the end + self.assertEqual(section["key"], "value") + self.assertEqual(section["otherkey"], "othervalue") + self.assertEqual(str(section), "key: value\notherkey: othervalue\n") + + file = aptsources._deb822.File(io.StringIO("key: value\notherkey: othervalue")) + self.assertEqual(len(file.sections), 1) + + section = next(iter(file)) + self.assertEqual(section["key"], "value") + self.assertEqual(section["otherkey"], "othervalue") + self.assertEqual(str(section), "key: value\notherkey: othervalue\n") + + def testDeb822MultipleLinesSeparator(self): + """aptsources: Test sources.list parsing.""" + for separator in "\n\n\n\n", "\n\n\n", "\n\n": + with self.subTest(f"{len(separator)} separators"): + file = aptsources._deb822.File( + io.StringIO("key: value" + separator + "otherkey: othervalue\n") + ) + self.assertEqual(len(file.sections), 2) + + self.assertEqual(file.sections[0]["key"], "value") + self.assertEqual(file.sections[1]["otherkey"], "othervalue") + self.assertEqual(str(file), "key: value\n\notherkey: othervalue\n") + + +if __name__ == "__main__": + os.chdir(os.path.dirname(__file__)) + unittest.main() diff --git a/tests/test_aptsources_ports.py b/tests/test_aptsources_ports.py new file mode 100644 index 0000000..234135b --- /dev/null +++ b/tests/test_aptsources_ports.py @@ -0,0 +1,41 @@ +#!/usr/bin/python3 +import os +import tempfile +import unittest + +import apt_pkg +import testcommon + +import aptsources.distro +import aptsources.sourceslist + + +class TestAptSourcesPorts(testcommon.TestCase): + """Test aptsources on ports.ubuntu.com.""" + + def setUp(self): + testcommon.TestCase.setUp(self) + apt_pkg.config.set("APT::Architecture", "powerpc") + apt_pkg.config.set("Dir::Etc", os.path.abspath("data/aptsources_ports")) + apt_pkg.config.set("Dir::Etc::sourceparts", tempfile.mkdtemp()) + if os.path.exists("../build/data/templates"): + self.templates = os.path.abspath("../build/data/templates") + else: + self.templates = "/usr/share/python-apt/templates/" + + def testMatcher(self): + """aptsources_ports: Test matcher.""" + apt_pkg.config.set("Dir::Etc::sourcelist", "sources.list") + sources = aptsources.sourceslist.SourcesList(True, self.templates) + distro = aptsources.distro.get_distro("Ubuntu", "hardy", "desc", "8.04") + distro.get_sources(sources) + # test if all suits of the current distro were detected correctly + for s in sources: + if not s.line.strip() or s.line.startswith("#"): + continue + if not s.template: + self.fail("source entry '%s' has no matcher" % s) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_auth.py b/tests/test_auth.py new file mode 100644 index 0000000..811cbb9 --- /dev/null +++ b/tests/test_auth.py @@ -0,0 +1,314 @@ +#!/usr/bin/python3 + +import contextlib +import errno +import itertools +import os +import shutil +import sys +import tempfile +import time +import unittest +from http.server import HTTPServer +from http.server import SimpleHTTPRequestHandler as HTTPRequestHandler + +import apt_pkg +import testcommon + +import apt.auth + +WHEEZY_KEYID = "8B48AD6246925553" +WHEEZY_KEYDATE = "1335553717" +WHEEZY_KEY = """-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.12 (GNU/Linux) + +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 +DHcut3Yey8o= +=id4q +-----END PGP PUBLIC KEY BLOCK-----""" + + +def normalize_key(keystr): + """Remove the Version: header from a key block""" + lines = keystr.split("\n") + if lines[1].startswith("Version:"): + return lines[:1] + lines[2:] + return lines + + +class TestAuthKeys(testcommon.TestCase): + + """Test handling of keys for signed repositories.""" + + def setUp(self): + testcommon.TestCase.setUp(self) + + self.tmpdir = tempfile.mkdtemp() + self.addCleanup(shutil.rmtree, self.tmpdir) + apt_pkg.config.set("Dir", self.tmpdir) + apt_pkg.config.set("Dir::Bin::Apt-key", "fakeroot-apt-key") + apt_pkg.config.set("Dir::Etc", "etc/apt/") + trustedparts_dir = apt_pkg.config.find_dir("Dir::Etc::Trustedparts") + confparts_dir = apt_pkg.config.find_dir("Dir::Etc::parts") + self.assertTrue(trustedparts_dir.startswith(self.tmpdir)) + os.makedirs(trustedparts_dir) + os.makedirs(confparts_dir) + shutil.copy("fakeroot-apt-key", self.tmpdir) + + @contextlib.contextmanager + def _discard_stderr(self): + stderr_fd = sys.stderr.fileno() + stderr_save = os.dup(stderr_fd) + try: + devnull = os.open("/dev/null", os.O_WRONLY) + try: + os.dup2(devnull, stderr_fd) + yield + finally: + os.close(devnull) + finally: + os.dup2(stderr_save, stderr_fd) + os.close(stderr_save) + + def testAddAndExportKey(self): + """Add an example key.""" + apt.auth.add_key(WHEEZY_KEY) + # Strip the headers from the keys to avoid test errors because + # the exported key used a differenct GnuPG version than the + # original example key + self.assertEqual( + normalize_key(apt.auth.export_key(WHEEZY_KEYID)), normalize_key(WHEEZY_KEY) + ) + + def testAddAndListKey(self): + """Add an example key and test if it is correctly returned by + list_keys() + """ + apt.auth.add_key(WHEEZY_KEY) + ret = apt.auth.list_keys() + self.assertEqual(len(ret), 1) + key = ret[0] + self.assertEqual( + key.name, + "Debian Archive Automatic Signing Key (7.0/wheezy) " + "", + ) + self.assertEqual(key.keyid, WHEEZY_KEYID) + self.assertEqual(key.date, WHEEZY_KEYDATE) + + def testAddKeyFromFile(self): + """Test adding a key from file.""" + keyfd, keyname = tempfile.mkstemp() + self.addCleanup(os.close, keyfd) + os.write(keyfd, WHEEZY_KEY.encode("UTF-8")) + + apt.auth.add_key_from_file(keyname) + + ret = apt.auth.list_keys() + self.assertEqual(len(ret), 1) + key = ret[0] + self.assertEqual( + key.name, + "Debian Archive Automatic Signing Key (7.0/wheezy) " + "", + ) + self.assertEqual(key.keyid, WHEEZY_KEYID) + self.assertEqual(key.date, WHEEZY_KEYDATE) + + def test_add_key_from_keyserver_too_short(self): + """Ensure that short keyids are not imported""" + with self.assertRaises(apt.auth.AptKeyIDTooShortError): + apt.auth.add_key_from_keyserver(WHEEZY_KEYID, "hkp://localhost:19191") + with self.assertRaises(apt.auth.AptKeyIDTooShortError): + apt.auth.add_key_from_keyserver( + "0101010178F7FE5C3E65D8AF8B48AD624692555", "hkp://localhost:19191" + ) + with self.assertRaises(apt.auth.AptKeyIDTooShortError): + apt.auth.add_key_from_keyserver( + "0x0101010178F7FE5C3E65D8AF8B48AD624692555", "hkp://localhost:19191" + ) + with self.assertRaises(apt.auth.AptKeyIDTooShortError): + apt.auth.add_key_from_keyserver( + "0101 0101 78F7 FE5C 3E65 D8AF 8B48 AD62 4692 555", + "hkp://localhost:19191", + ) + + def test_add_key_from_server_mitm(self): + """Verify that the key fingerprint is verified after download""" + self._start_keyserver() + self.addCleanup(self._stop_keyserver) + with self.assertRaises(apt.auth.AptKeyError) as cm: + with self._discard_stderr(): + apt.auth.add_key_from_keyserver( + "0101010178F7FE5C3E65D8AF8B48AD6246925553", + "hkp://localhost:%d" % self.keyserver_port, + ) + self.assertTrue( + str(cm.exception).startswith( + "recv from 'hkp://localhost:%d' failed for '%s'" + % (self.keyserver_port, "0101010178F7FE5C3E65D8AF8B48AD6246925553") + ), + cm.exception, + ) + + def testAddKeyFromServer(self): + """Install a GnuPG key from a remote server.""" + self._start_keyserver() + self.addCleanup(self._stop_keyserver) + + with self._discard_stderr(): + apt.auth.add_key_from_keyserver( + "0xa1bD8E9D78F7FE5C3E65D8AF8B48AD6246925553", + "hkp://localhost:%d" % self.keyserver_port, + ) + + ret = apt.auth.list_keys() + self.assertEqual(len(ret), 1) + key = ret[0] + self.assertEqual( + key.name, + "Debian Archive Automatic Signing Key (7.0/wheezy) " + "", + ) + self.assertEqual(key.keyid, WHEEZY_KEYID) + self.assertEqual(key.date, WHEEZY_KEYDATE) + + def _start_keyserver(self): + """Start a fake keyserver on http://localhost:19191 + If port 19191 is unavailable, try successive ports until one is. + Store the port actually in use in self.keyserver_port. + Thanks pitti. + """ + dir = tempfile.mkdtemp() + self.addCleanup(shutil.rmtree, dir) + os.mkdir(os.path.join(dir, "pks")) + with open(os.path.join(dir, "pks", "lookup"), "w") as key_file: + key_file.write(WHEEZY_KEY) + + keyserver_pipe = os.pipe() + self.keyserver_pid = os.fork() + if self.keyserver_pid == 0: + os.close(keyserver_pipe[0]) + # quiesce server log + os.dup2(os.open("/dev/null", os.O_WRONLY), sys.stderr.fileno()) + os.chdir(dir) + for port in itertools.count(19191): + try: + httpd = HTTPServer(("localhost", port), HTTPRequestHandler) + break + except OSError as e: + if e.errno != errno.EADDRINUSE: + raise + keyserver_write = os.fdopen(keyserver_pipe[1], "w") + print(port, file=keyserver_write) + keyserver_write.close() + httpd.serve_forever() + os._exit(0) + + os.close(keyserver_pipe[1]) + keyserver_read = os.fdopen(keyserver_pipe[0]) + self.keyserver_port = int(keyserver_read.readline()) + keyserver_read.close() + + # temporarily disable proxy, as gnupg does not get along with that + # (LP #789049) + self.orig_proxy = os.environ.get("http_proxy") + try: + del os.environ["http_proxy"] + except KeyError: + pass + + # wait a bit until server is ready + time.sleep(0.5) + + def _stop_keyserver(self): + """Stop fake keyserver""" + assert self.keyserver_pid + + os.kill(self.keyserver_pid, 15) + os.wait() + + # restore proxy + if self.orig_proxy is not None: + os.environ["http_proxy"] = self.orig_proxy + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_cache_invocation.py b/tests/test_cache_invocation.py new file mode 100644 index 0000000..a608034 --- /dev/null +++ b/tests/test_cache_invocation.py @@ -0,0 +1,31 @@ +#!/usr/bin/python3 +import unittest + +import apt_pkg +import testcommon + +import apt.progress.base + + +class TestCache(testcommon.TestCase): + """Test invocation of apt_pkg.Cache()""" + + def test_wrong_invocation(self): + """cache_invocation: Test wrong invocation.""" + apt_cache = apt_pkg.Cache(progress=None) + + self.assertRaises(ValueError, apt_pkg.Cache, apt_cache) + self.assertRaises( + ValueError, apt_pkg.Cache, apt.progress.base.AcquireProgress() + ) + self.assertRaises(ValueError, apt_pkg.Cache, 0) + + def test_proper_invocation(self): + """cache_invocation: Test correct invocation.""" + apt_cache = apt_pkg.Cache(progress=None) + apt_depcache = apt_pkg.DepCache(apt_cache) + self.assertNotEqual(apt_depcache, None) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_configuration.py b/tests/test_configuration.py new file mode 100644 index 0000000..c59acfa --- /dev/null +++ b/tests/test_configuration.py @@ -0,0 +1,31 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2011 Julian Andres Klode +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +"""Unit tests for verifying the correctness of apt_pkg.Configuration""" +import unittest + +import apt_pkg +import testcommon + + +class TestConfiguration(testcommon.TestCase): + """Test various configuration things""" + + def test_lp707416(self): + """configuration: Test empty arguments (LP: #707416)""" + self.assertRaises(ValueError, apt_pkg.parse_commandline, apt_pkg.config, [], []) + self.assertRaises( + SystemError, + apt_pkg.parse_commandline, + apt_pkg.config, + [], + ["cmd", "--arg0"], + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_cve_2020_27351.py b/tests/test_cve_2020_27351.py new file mode 100644 index 0000000..1ec1c76 --- /dev/null +++ b/tests/test_cve_2020_27351.py @@ -0,0 +1,149 @@ +#!/usr/bin/python +# +# Copyright (C) 2020 Canonical Ltd +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +"""Unit tests for verifying the correctness of DebFile descriptor handling.""" +import os +import sys +import unittest + +from test_all import get_library_dir + +libdir = get_library_dir() +if libdir: + sys.path.insert(0, libdir) +import gc +import subprocess +import tempfile +import warnings + +import apt_inst + + +@unittest.skipIf(not os.path.exists("/proc/self/fd"), "no /proc/self/fd available") +class TestCVE_2020_27351(unittest.TestCase): + """test the debfile""" + + GOOD_DEB = "data/test_debs/utf8-package_1.0-1_all.deb" + + def test_success(self): + """opening package successfully should not leak fd""" + before = os.listdir("/proc/self/fd") + apt_inst.DebFile(self.GOOD_DEB) + after = os.listdir("/proc/self/fd") + self.assertEqual(before, after) + + def test_regression_bug_977000(self): + """opening with a file handle should work correctly""" + with open(self.GOOD_DEB) as good_deb: + apt_inst.DebFile(good_deb).control.extractdata("control") + + def test_regression_bug_977000_2(self): + """file object <-> debfile cycles should be collected by gc.""" + + class Cycle: + def __init__(self, fname): + self.file = open(fname) + self.deb = apt_inst.DebFile(self) + + def fileno(self): + return self.file.fileno() + + before = os.listdir("/proc/self/fd") + Cycle(self.GOOD_DEB).deb.control.extractdata("control") + warnings.filterwarnings("ignore", category=ResourceWarning) + gc.collect() + warnings.resetwarnings() + after = os.listdir("/proc/self/fd") + self.assertEqual(before, after) + + def test_regression_bug_977000_2_ar(self): + """file object <-> debfile cycles should be collected by gc.""" + + class Cycle: + def __init__(self, fname): + self.file = open(fname) + self.deb = apt_inst.ArArchive(self) + + def fileno(self): + return self.file.fileno() + + before = os.listdir("/proc/self/fd") + Cycle(self.GOOD_DEB).deb.gettar("control.tar.gz", "gzip").extractdata("control") + warnings.filterwarnings("ignore", category=ResourceWarning) + gc.collect() + warnings.resetwarnings() + after = os.listdir("/proc/self/fd") + self.assertEqual(before, after) + + def test_success_a_member(self): + """fd should be kept around as long as a tarfile member""" + before = os.listdir("/proc/self/fd") + data = apt_inst.DebFile(self.GOOD_DEB).data + after = os.listdir("/proc/self/fd") + self.assertEqual(len(before), len(after) - 1) + del data + after = os.listdir("/proc/self/fd") + self.assertEqual(before, after) + + def _create_deb_without(self, member): + temp = tempfile.NamedTemporaryFile(mode="wb") + try: + with open(self.GOOD_DEB, "rb") as deb: + temp.write(deb.read()) + temp.flush() + subprocess.check_call(["ar", "d", temp.name, member]) + return temp + except Exception as e: + temp.close() + raise e + + def test_nocontrol(self): + """opening package without control.tar.gz should not leak fd""" + before = os.listdir("/proc/self/fd") + with self._create_deb_without("control.tar.gz") as temp: + try: + apt_inst.DebFile(temp.name) + except SystemError as e: + self.assertIn("control.tar", str(e)) + else: + self.fail("Did not raise an exception") + + after = os.listdir("/proc/self/fd") + self.assertEqual(before, after) + + def test_nodata(self): + """opening package without data.tar.gz should not leak fd""" + before = os.listdir("/proc/self/fd") + with self._create_deb_without("data.tar.gz") as temp: + try: + apt_inst.DebFile(temp.name) + except SystemError as e: + self.assertIn("data.tar", str(e)) + else: + self.fail("Did not raise an exception") + + after = os.listdir("/proc/self/fd") + self.assertEqual(before, after) + + def test_no_debian_binary(self): + """opening package without debian-binary should not leak fd""" + before = os.listdir("/proc/self/fd") + with self._create_deb_without("debian-binary") as temp: + try: + apt_inst.DebFile(temp.name) + except SystemError as e: + self.assertIn("missing debian-binary", str(e)) + else: + self.fail("Did not raise an exception") + + after = os.listdir("/proc/self/fd") + self.assertEqual(before, after) + + +if __name__ == "__main__": + # logging.basicConfig(level=logging.DEBUG) + unittest.main() diff --git a/tests/test_debfile.py b/tests/test_debfile.py new file mode 100644 index 0000000..bb65a94 --- /dev/null +++ b/tests/test_debfile.py @@ -0,0 +1,192 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2010 Michael Vogt +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +"""Unit tests for verifying the correctness of DebPackage in apt.debfile.""" +import logging +import os +import sys +import unittest + +from test_all import get_library_dir + +libdir = get_library_dir() +if libdir: + sys.path.insert(0, libdir) +import apt_pkg +import testcommon + +import apt.debfile + + +class TestDebfile(testcommon.TestCase): + """test the debfile""" + + TEST_DEBS = [ + # conflicts with apt + ("gdebi-test1.deb", False), + # impossible dependency + ("gdebi-test2.deb", False), + # or-group (impossible-dependency|apt) + ("gdebi-test3.deb", True), + # Conflicts: apt (<= 0.1) + ("gdebi-test4.deb", True), + # Conflicts: apt (>= 0.1) + ("gdebi-test5.deb", False), + # invalid unicode in descr + ("gdebi-test6.deb", True), + # provides/conflicts against "foobarbaz" + ("gdebi-test7.deb", True), + # provides/conflicts/replaces against "mail-transport-agent" + # (should fails if mail-transport-agent is installed) + ("gdebi-test8.deb", False), + # provides/conflicts against real pkg + ("gdebi-test9.deb", True), + # provides debconf-tiny and the real debconf conflicts with + ("gdebi-test10.deb", False), + ] + + def setUp(self): + testcommon.TestCase.setUp(self) + apt_pkg.config.set("APT::Architecture", "i386") + # FIXME: When run via test_all.py, the tests fail without this if it + # is set in the system. + apt_pkg.config.clear("APT::Architectures") + apt_pkg.config.set("Dir::State::status", "./data/test_debs/var/lib/dpkg/status") + apt_pkg.config.set("Dir::State::lists", "./data/test_debs/var/lib/apt/lists") + apt_pkg.config.set( + "Dir::Etc::sourcelist", "./data/test_debs/etc/apt/sources.list" + ) + apt_pkg.init_system() + self.cache = apt.Cache() + + def test_dsc_file(self): + filename = "hello_2.5-1.dsc" + deb = apt.debfile.DscSrcPackage(cache=self.cache) + deb.open(os.path.join("data", "test_debs", filename)) + self.assertTrue(deb.check(), "got failure '%s'" % deb._failure_string) + missing = {"autotools-dev"} + self.assertEqual(set(deb.missing_deps), missing) + # specialized properties + self.assertEqual(deb.pkgname, "hello") + self.assertEqual(deb.binaries, ["hello", "bello", "cello"]) + self.assertEqual(deb.filelist, ["hello_2.5.orig.tar.gz", "hello_2.5-1.diff.gz"]) + self.assertEqual(deb.depends, [[("autotools-dev", "", "")]]) + # tag fields are available as a dict + self.assertEqual(deb["Format"], "1.0") + self.assertEqual(deb["Source"], "hello") + self.assertEqual(deb["Binary"], "hello, bello,\n cello") + self.assertEqual(deb["Architecture"], "any") + self.assertEqual(deb["Version"], "2.5-1") + self.assertEqual(deb["Maintainer"], "Santiago Vila ") + self.assertEqual(deb["Homepage"], "http://www.gnu.org/software/hello") + self.assertEqual(deb["Standards-Version"], "3.8.4") + + def test_dsc_file_with_impossible_build_dep(self): + filename = "impossible-build-depends_2.5-1.dsc" + deb = apt.debfile.DscSrcPackage(cache=self.cache) + deb.open(os.path.join("data", "test_debs", filename)) + self.assertFalse(deb.check()) + self.assertEqual(deb.depends, [[("debhelper", "101", ">")]]) + + def test_deb_file(self): + deb = apt.debfile.DebPackage(cache=self.cache) + for filename, expected_res in self.TEST_DEBS: + logging.debug(f"testing {filename}, expecting {expected_res}") + deb.open(os.path.join("data", "test_debs", filename)) + res = deb.check() + self.assertEqual( + res, + expected_res, + "Unexpected result for package '%s' (got %s wanted %s)\n%s" + % (filename, res, expected_res, deb._failure_string), + ) + + def test_utf8_sections(self): + deb = apt.debfile.DebPackage(cache=self.cache) + deb.open(os.path.join("data", "test_debs", "utf8-package_1.0-1_all.deb")) + self.assertEqual(deb["Maintainer"], "Samuel Lidén Borell ") + + def test_content(self): + # normal + deb = apt.debfile.DebPackage(cache=self.cache) + deb.open(os.path.join("data", "test_debs", "gdebi-test11.deb")) + self.assertEqual('#!/bin/sh\necho "test"\n', deb.data_content("usr/bin/test")) + # binary + deb = apt.debfile.DebPackage(cache=self.cache) + deb.open(os.path.join("data", "test_debs", "gdebi-test12.deb")) + content = deb.data_content("usr/bin/binary") + self.assertTrue( + content.startswith("Automatically converted to printable ascii:\n\x7fELF ") + ) + # control file + needle = """Package: gdebi-test12 +Version: 1.0 +Architecture: all +Description: testpackage for gdebi - contains usr/bin/binary for file reading + This tests the binary file reading for debfile.py +""" + content = deb.control_content("./control") + self.assertEqual(content, needle) + content = deb.control_content("control") + self.assertEqual(content, needle) + + def test_xz_data(self): + deb = apt.debfile.DebPackage("./data/test_debs/data-tar-xz.deb") + self.assertEqual(deb.filelist, ["./", "usr/", "usr/bin/"]) + + @unittest.skipIf( + apt_pkg.version_compare(apt_pkg.VERSION, "0.9.15.4~") < 0, + "APT too old for uncompressed control.tar/data.tar", + ) + def test_uncompressed_data(self): + deb = apt.debfile.DebPackage("./data/test_debs/data-tar.deb") + self.assertEqual(deb.filelist, ["./", "usr/", "usr/bin/"]) + + def test_check_exception(self): + deb = apt.debfile.DebPackage("./data/test_debs/data-tar-xz.deb") + self.assertRaises(AttributeError, lambda: deb.missing_deps) + deb.check() + deb.missing_deps + + def test_no_supported_data_tar(self): + with self.assertRaises(SystemError): + apt.debfile.DebPackage("./data/test_debs/data-tar-broken.deb") + + def test_contains(self): + deb = apt.debfile.DebPackage("./data/test_debs/data-tar-xz.deb") + self.assertTrue("Package" in deb) + + def test_multi_arch_allowed(self): + apt_pkg.config["APT::Architectures::"] = "i386" + apt_pkg.config["APT::Architectures::"] = "amd64" + apt_pkg.config["APT::Architecture"] = "amd64" + apt_pkg.init_system() + + allowed_any = apt.debfile.DebPackage( + "./data/test_debs/testdep-allowed-any_1.0-1_i386.deb" + ) + self.assertTrue(allowed_any.check(), allowed_any._failure_string) + + def test_multi_arch_same(self): + apt_pkg.config["APT::Architectures::"] = "i386" + apt_pkg.config["APT::Architectures::"] = "amd64" + apt_pkg.config["APT::Architecture"] = "amd64" + apt_pkg.init_system() + same = apt.debfile.DebPackage( + "./data/test_debs/testdep-same-arch_1.0-1_i386.deb" + ) + self.assertTrue(same.check(), same._failure_string) + + def test_get_content_gzip_data(self): + deb = apt.debfile.DebPackage("./data/test_debs/gdebi-test13.deb") + data = deb.data_content("./lala.gz") + self.assertEqual(data, "Automatically decompressed:\n\nlala\n") + + +if __name__ == "__main__": + # logging.basicConfig(level=logging.DEBUG) + unittest.main() diff --git a/tests/test_debfile_multiarch.py b/tests/test_debfile_multiarch.py new file mode 100644 index 0000000..24f0265 --- /dev/null +++ b/tests/test_debfile_multiarch.py @@ -0,0 +1,63 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2010 Michael Vogt +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +"""Unit tests for verifying the correctness of DebPackage in apt.debfile.""" +import sys +import unittest + +from test_all import get_library_dir + +libdir = get_library_dir() +if libdir: + sys.path.insert(0, libdir) +import apt_pkg +import testcommon + +import apt +import apt.debfile + + +class TestDebfileMultiarch(testcommon.TestCase): + """test the multiarch debfile""" + + def test_multiarch_deb_check(self): + if apt_pkg.get_architectures() != ["amd64", "i386"]: + # TODO: use unittest.skip + # logging.warning("skipping test because running on a " + # "non-multiarch system") + return + deb = apt.debfile.DebPackage("./data/test_debs/multiarch-test1_i386.deb") + deb.check() + missing = deb.missing_deps + # print missing + self.assertFalse("dpkg:i386" in missing) + + @unittest.skip("BROKEN, lib3ds-1-3 is m-a now") + def test_multiarch_conflicts(self): + cache = apt.Cache() + # WARNING: this assumes that lib3ds-1-3 is a non-multiarch lib + # use "lib3ds-1-3" as a test to see if non-multiach lib conflicts work + canary = "lib3ds-1-3" + if canary not in cache: + # TODO: use unittest.skip + # logging.warning("skipping test because %s is missing" % canary) + return + cache[canary].mark_install() + deb = apt.debfile.DebPackage( + "./data/test_debs/multiarch-test1_i386.deb", cache=cache + ) + # this deb should now not be installable + installable = deb.check() + # print deb._failure_string + self.assertFalse(installable) + self.assertEqual( + deb._failure_string, "Conflicts with the installed package 'lib3ds-1-3'" + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_deps.py b/tests/test_deps.py new file mode 100644 index 0000000..860856c --- /dev/null +++ b/tests/test_deps.py @@ -0,0 +1,142 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2010 Julian Andres Klode +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +"""Unit tests for verifying the correctness of check_dep, etc in apt_pkg.""" +import itertools +import unittest + +import apt_pkg +import testcommon + +import apt.package + + +class TestDependencies(testcommon.TestCase): + def testCheckDep(self): + """dependencies: Test apt_pkg.CheckDep() for '<' and '>' + + The CheckDep function should treat '<' as '<=' and '>' as '>=', for + compatibility reasons.""" + if not hasattr(apt_pkg, "CheckDep"): + return + self.assertFalse(apt_pkg.CheckDep("1", "<", "0")) + self.assertTrue(apt_pkg.CheckDep("1", "<", "1")) + self.assertTrue(apt_pkg.CheckDep("1", "<", "2")) + + self.assertFalse(apt_pkg.CheckDep("0", ">", "1")) + self.assertTrue(apt_pkg.CheckDep("1", ">", "1")) + self.assertTrue(apt_pkg.CheckDep("2", ">", "1")) + + def test_check_dep(self): + "dependencies: Test apt_pkg.check_dep()" + self.assertFalse(apt_pkg.check_dep("1", "<<", "0")) + self.assertFalse(apt_pkg.check_dep("1", "<<", "1")) + self.assertTrue(apt_pkg.check_dep("1", "<<", "2")) + + self.assertFalse(apt_pkg.check_dep("1", "<", "0")) + self.assertFalse(apt_pkg.check_dep("1", "<", "1")) + self.assertTrue(apt_pkg.check_dep("1", "<", "2")) + + self.assertFalse(apt_pkg.check_dep("1", "<=", "0")) + self.assertTrue(apt_pkg.check_dep("1", "<=", "1")) + self.assertTrue(apt_pkg.check_dep("1", "<=", "2")) + + self.assertFalse(apt_pkg.check_dep("0", "=", "1")) + self.assertTrue(apt_pkg.check_dep("1", "=", "1")) + self.assertFalse(apt_pkg.check_dep("2", "=", "1")) + + self.assertFalse(apt_pkg.check_dep("0", ">=", "1")) + self.assertTrue(apt_pkg.check_dep("1", ">=", "1")) + self.assertTrue(apt_pkg.check_dep("2", ">=", "1")) + + self.assertFalse(apt_pkg.check_dep("0", ">", "1")) + self.assertFalse(apt_pkg.check_dep("1", ">", "1")) + self.assertTrue(apt_pkg.check_dep("2", ">", "1")) + + self.assertFalse(apt_pkg.check_dep("0", ">>", "1")) + self.assertFalse(apt_pkg.check_dep("1", ">>", "1")) + self.assertTrue(apt_pkg.check_dep("2", ">>", "1")) + + def test_parse_depends_multiarch(self): + # strip multiarch + deps = apt_pkg.parse_depends("po4a:native", True) + self.assertEqual(deps[0][0][0], "po4a") + # do not strip multiarch + deps = apt_pkg.parse_depends("po4a:native", False) + self.assertEqual(deps[0][0][0], "po4a:native") + + def test_parse_depends(self): + """dependencies: Test apt_pkg.parse_depends()""" + deps = apt_pkg.parse_depends("p1a (<< 1a) | p1b (>> 1b)") + self.assertTrue(isinstance(deps, list)) + self.assertEqual(len(deps), 1) + self.assertTrue(isinstance(deps[0], list)) + self.assertEqual(len(deps[0]), 2) + self.assertEqual(len(deps[0][0]), 3) + self.assertEqual(len(deps[0][1]), 3) + self.assertEqual(deps[0][0][0], "p1a") + self.assertEqual(deps[0][0][1], "1a") + self.assertEqual(deps[0][0][2], "<") + self.assertEqual(deps[0][1][0], "p1b") + self.assertEqual(deps[0][1][1], "1b") + self.assertEqual(deps[0][1][2], ">") + + # Check that the type of comparison is parsed correctly. + self.assertEqual("<", apt_pkg.parse_depends("p1 (<< 1)")[0][0][2]) + self.assertEqual("<=", apt_pkg.parse_depends("p1 (< 1)")[0][0][2]) + self.assertEqual("<=", apt_pkg.parse_depends("p1 (<= 1)")[0][0][2]) + self.assertEqual("=", apt_pkg.parse_depends("p1 (= 1)")[0][0][2]) + self.assertEqual(">=", apt_pkg.parse_depends("p1 (>= 1)")[0][0][2]) + self.assertEqual(">=", apt_pkg.parse_depends("p1 (> 1)")[0][0][2]) + self.assertEqual(">", apt_pkg.parse_depends("p1 (>> 1)")[0][0][2]) + + def test_parse_src_depends(self): + """dependencies: Test apt_pkg.parse_src_depends().""" + # Check that architecture exclusion works + # depends_this: Current architecture is included + # depends_this_too: Another architecture is excluded + # depends_other: The current architecture is excluded + # depends_other: Another architecture is requested. + architecture = apt_pkg.config["APT::Architecture"] + depends_this = apt_pkg.parse_src_depends("p [%s]" % architecture) + depends_this_too = apt_pkg.parse_src_depends("p [!not-existing-arch]") + depends_other = apt_pkg.parse_src_depends("p [!%s]" % architecture) + depends_other_too = apt_pkg.parse_src_depends("p [not-existing-arch]") + + self.assertEqual(len(depends_this), len(depends_this_too), 1) + self.assertEqual(len(depends_other), len(depends_other_too), 0) + + def test_dstr(self): + """Test apt.package.BaseDependency.__dstr""" + dstr = apt.package.BaseDependency._BaseDependency__dstr + equal = {"<": {"<<", "<"}, "=": {"==", "="}, ">": {">>", ">"}} + operators = ["<<", "<", "<=", "!=", "=", "==", ">=", ">", ">>"] + + for a, b in itertools.product(equal.keys(), operators): + if b in equal[a]: + self.assertEqual(dstr(a), b) + self.assertEqual(b, dstr(a)) + else: + self.assertNotEqual(dstr(a), b) + self.assertNotEqual(b, dstr(a)) + + def testParseDepends(self): + """dependencies: Test apt_pkg.ParseDepends().""" + if not hasattr(apt_pkg, "ParseDepends"): + return + # Check that the type of comparison is parsed correctly. + self.assertEqual("<<", apt_pkg.ParseDepends("p1 (<< 1)")[0][0][2]) + self.assertEqual("<=", apt_pkg.ParseDepends("p1 (< 1)")[0][0][2]) + self.assertEqual("<=", apt_pkg.ParseDepends("p1 (<= 1)")[0][0][2]) + self.assertEqual("=", apt_pkg.ParseDepends("p1 (= 1)")[0][0][2]) + self.assertEqual(">=", apt_pkg.ParseDepends("p1 (>= 1)")[0][0][2]) + self.assertEqual(">=", apt_pkg.ParseDepends("p1 (> 1)")[0][0][2]) + self.assertEqual(">>", apt_pkg.ParseDepends("p1 (>> 1)")[0][0][2]) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_group.py b/tests/test_group.py new file mode 100644 index 0000000..d08ed06 --- /dev/null +++ b/tests/test_group.py @@ -0,0 +1,31 @@ +import unittest + +import apt_pkg +import testcommon + + +class TestGroup(testcommon.TestCase): + def setUp(self): + testcommon.TestCase.setUp(self) + self.cache = apt_pkg.Cache(progress=None) + + def test_pkgingroup(self): + """Check that each package belongs to the corresponding group""" + for pkg in self.cache.packages: + group = apt_pkg.Group(self.cache, pkg.name) + assert any(pkg.id == p.id for p in group) + + def test_iteration(self): + """Check that iteration works correctly.""" + for pkg in self.cache.packages: + group = apt_pkg.Group(self.cache, pkg.name) + + list(group) == list(group) + + def test_cache_groups(self): + """group: Iterate over all groups""" + assert len(list(self.cache.groups)) == self.cache.group_count + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_hashes.py b/tests/test_hashes.py new file mode 100644 index 0000000..d322a1f --- /dev/null +++ b/tests/test_hashes.py @@ -0,0 +1,206 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2009 Julian Andres Klode +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +"""Unit tests for verifying the correctness of hashsums in apt_pkg. + +Unit tests to verify the correctness of Hashes, HashString and the various +functions like md5sum.""" +import hashlib +import unittest +import warnings + +import apt_pkg +import testcommon + + +class TestHashes(testcommon.TestCase): + """Test apt_pkg.Hashes() and the various apt_pkg.*sum() functions.""" + + def setUp(self): + """Prepare the tests, create reference values...""" + testcommon.TestCase.setUp(self) + self.file = open(apt_pkg.__file__, "rb") + self.value = self.file.read() + self.hashes = apt_pkg.Hashes(self.value) + self.file.seek(0) + self.fhashes = apt_pkg.Hashes(self.file) + # Reference values. + self.md5 = hashlib.md5(self.value).hexdigest() + self.sha1 = hashlib.sha1(self.value).hexdigest() + self.sha256 = hashlib.sha256(self.value).hexdigest() + self.file.seek(0) + + warnings.filterwarnings("ignore", category=DeprecationWarning) + + def tearDown(self): + """Cleanup, Close the file object used for the tests.""" + testcommon.TestCase.tearDown(self) + warnings.resetwarnings() + self.file.close() + + def test_md5sum(self): + """hashes: Test apt_pkg.md5sum()""" + self.assertEqual(apt_pkg.md5sum(self.value), self.md5) + self.assertEqual(apt_pkg.md5sum(self.file), self.md5) + + def test_sha1sum(self): + """hashes: Test apt_pkg.sha1sum()""" + self.assertEqual(apt_pkg.sha1sum(self.value), self.sha1) + self.assertEqual(apt_pkg.sha1sum(self.file), self.sha1) + + def test_sha256sum(self): + """hashes: Test apt_pkg.sha256sum()""" + self.assertEqual(apt_pkg.sha256sum(self.value), self.sha256) + self.assertEqual(apt_pkg.sha256sum(self.file), self.sha256) + + def test_bytes(self): + """hashes: Test apt_pkg.Hashes(bytes)""" + self.assertEqual(self.hashes.hashes.find("md5sum").hashvalue, self.md5) + self.assertEqual( + self.hashes.hashes.find("md5sum"), apt_pkg.HashString("MD5Sum", self.md5) + ) + self.assertEqual( + self.hashes.hashes.find("sha1"), apt_pkg.HashString("SHA1", self.sha1) + ) + self.assertEqual( + self.hashes.hashes.find("sha256"), apt_pkg.HashString("SHA256", self.sha256) + ) + self.assertRaises(KeyError, self.hashes.hashes.find, "md5") + + def test_file(self): + """hashes: Test apt_pkg.Hashes(file).""" + self.assertEqual(self.fhashes.hashes.find("md5sum").hashvalue, self.md5) + self.assertEqual( + self.fhashes.hashes.find("md5sum"), apt_pkg.HashString("MD5Sum", self.md5) + ) + self.assertEqual( + self.fhashes.hashes.find("sha1"), apt_pkg.HashString("SHA1", self.sha1) + ) + self.assertEqual( + self.fhashes.hashes.find("sha256"), + apt_pkg.HashString("SHA256", self.sha256), + ) + + def test_unicode(self): + """hashes: Test apt_pkg.Hashes(unicode).""" + self.assertRaises(TypeError, apt_pkg.Hashes, "D") + self.assertRaises(TypeError, apt_pkg.md5sum, "D") + self.assertRaises(TypeError, apt_pkg.sha1sum, "D") + self.assertRaises(TypeError, apt_pkg.sha256sum, "D") + + +class TestHashString(testcommon.TestCase): + """Test apt_pkg.HashString().""" + + def setUp(self): + """Prepare the test by reading the file.""" + testcommon.TestCase.setUp(self) + self.file = open(apt_pkg.__file__) + self.hashes = apt_pkg.Hashes(self.file) + + self.md5 = self.hashes.hashes.find("md5sum") + self.sha1 = self.hashes.hashes.find("sha1") + self.sha256 = self.hashes.hashes.find("sha256") + + def tearDown(self): + """Cleanup, Close the file object used for the tests.""" + self.file.close() + + def test_md5(self): + """hashes: Test apt_pkg.HashString().md5""" + self.assertIn("MD5Sum:", str(self.md5)) + self.assertTrue(self.md5.verify_file(apt_pkg.__file__)) + + def test_sha1(self): + """hashes: Test apt_pkg.HashString().sha1""" + self.assertIn("SHA1:", str(self.sha1)) + self.assertTrue(self.sha1.verify_file(apt_pkg.__file__)) + + def test_sha256(self): + """hashes: Test apt_pkg.HashString().sha256""" + self.assertIn("SHA256:", str(self.sha256)) + self.assertTrue(self.sha256.verify_file(apt_pkg.__file__)) + + def test_wrong(self): + """hashes: Test apt_pkg.HashString(wrong_type).""" + self.assertRaises(TypeError, apt_pkg.HashString, 0) + self.assertRaises(TypeError, apt_pkg.HashString, b"") + + +class TestHashStringList(testcommon.TestCase): + """Test apt_pkg.HashStringList()""" + + def test_file_size(self): + hsl = apt_pkg.HashStringList() + self.assertEqual(hsl.file_size, 0) + hsl.file_size = 42 + self.assertEqual(hsl.file_size, 42) + self.assertEqual(len(hsl), 1) + + # Verify that I can re-assign value (this handles the long case on + # Python 2). + hsl.file_size = hsl.file_size + + with self.assertRaises(OverflowError): + hsl.file_size = -1 + + hsl.file_size = 0 + + def test_append(self): + """Testing whether append works correctly.""" + hs1 = apt_pkg.HashString("MD5Sum", "a60599e6200b60050d7a30721e3532ed") + hs2 = apt_pkg.HashString("SHA1", "ef113338e654b1ada807a939ad47b3a67633391b") + + hsl = apt_pkg.HashStringList() + hsl.append(hs1) + hsl.append(hs2) + self.assertEqual(len(hsl), 2) + self.assertEqual(hsl[0].hashtype, "MD5Sum") + self.assertEqual(hsl[1].hashtype, "SHA1") + self.assertEqual(str(hsl[0]), str(hs1)) + self.assertEqual(str(hsl[1]), str(hs2)) + + def test_find(self): + """Testing whether append works correctly.""" + hs1 = apt_pkg.HashString("MD5Sum", "a60599e6200b60050d7a30721e3532ed") + hs2 = apt_pkg.HashString("SHA1", "ef113338e654b1ada807a939ad47b3a67633391b") + + hsl = apt_pkg.HashStringList() + hsl.append(hs1) + hsl.append(hs2) + + self.assertEqual(hsl.find("MD5Sum").hashtype, "MD5Sum") + self.assertEqual(hsl.find("SHA1").hashtype, "SHA1") + self.assertEqual(hsl.find().hashtype, "SHA1") + + def test_verify_file(self): + with open(apt_pkg.__file__) as fobj: + hashes = apt_pkg.Hashes(fobj) + with warnings.catch_warnings(record=True): + warnings.simplefilter("always") + sha1 = hashes.hashes.find("sha1") + sha256 = hashes.hashes.find("sha256") + + hsl = apt_pkg.HashStringList() + hsl.append(sha1) + hsl.append(sha256) + + self.assertTrue(hsl.verify_file(apt_pkg.__file__)) + + md5sum = apt_pkg.HashString("MD5Sum", "a60599e6200b60050d7a30721e3532ed") + hsl.append(md5sum) + + self.assertFalse(hsl.verify_file(apt_pkg.__file__)) + + hsl2 = hashes.hashes + self.assertIsInstance(hsl2, apt_pkg.HashStringList) + self.assertGreater(len(hsl2), 0) + self.assertTrue(hsl2.verify_file(apt_pkg.__file__)) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_hashsums.py b/tests/test_hashsums.py new file mode 100644 index 0000000..1d7cc0e --- /dev/null +++ b/tests/test_hashsums.py @@ -0,0 +1,106 @@ +#!/usr/bin/python3 + +import unittest +import warnings + +import apt_pkg +import testcommon + + +class testHashes(testcommon.TestCase): + "test the hashsum functions against strings and files" + + DATA_PATH = "data/hashsums/hashsum_test.data" + DATA_WITH_ZERO_PATH = "data/hashsums/hashsum_test_with_zero.data" + + def setUp(self): + testcommon.TestCase.setUp(self) + warnings.filterwarnings("ignore", category=DeprecationWarning) + + def tearDown(self): + testcommon.TestCase.tearDown(self) + warnings.resetwarnings() + + def testMD5(self): + # simple + s = b"foo" + s_md5 = "acbd18db4cc2f85cedef654fccc4a4d8" + res = apt_pkg.md5sum(s) + self.assertEqual(res, s_md5) + # file + with open(self.DATA_PATH) as fobj: + self.assertEqual(apt_pkg.md5sum(fobj), s_md5) + # with zero (\0) in the string + s = b"foo\0bar" + s_md5 = "f6f5f8cd0cb63668898ba29025ae824e" + res = apt_pkg.md5sum(s) + self.assertEqual(res, s_md5) + # file + with open(self.DATA_WITH_ZERO_PATH) as fobj: + self.assertEqual(apt_pkg.md5sum(fobj), s_md5) + + def testSHA1(self): + # simple + s = b"foo" + s_hash = "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" + res = apt_pkg.sha1sum(s) + self.assertEqual(res, s_hash) + # file + with open(self.DATA_PATH) as fobj: + self.assertEqual(apt_pkg.sha1sum(fobj), s_hash) + # with zero (\0) in the string + s = b"foo\0bar" + s_hash = "e2c300a39311a2dfcaff799528415cb74c19317f" + res = apt_pkg.sha1sum(s) + self.assertEqual(res, s_hash) + # file + with open(self.DATA_WITH_ZERO_PATH) as fobj: + self.assertEqual(apt_pkg.sha1sum(fobj), s_hash) + + def testSHA256(self): + # simple + s = b"foo" + s_hash = "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae" + res = apt_pkg.sha256sum(s) + self.assertEqual(res, s_hash) + # file + with open(self.DATA_PATH) as fobj: + self.assertEqual(apt_pkg.sha256sum(fobj), s_hash) + # with zero (\0) in the string + s = b"foo\0bar" + s_hash = "d6b681bfce7155d44721afb79c296ef4f0fa80a9dd6b43c5cf74dd0f64c85512" + res = apt_pkg.sha256sum(s) + self.assertEqual(res, s_hash) + # file + with open(self.DATA_WITH_ZERO_PATH) as fobj: + self.assertEqual(apt_pkg.sha256sum(fobj), s_hash) + + def testSHA512(self): + # simple + s = b"foo" + s_hash = ( + "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d" + "0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19" + "594a7eb539453e1ed7" + ) + res = apt_pkg.sha512sum(s) + self.assertEqual(res, s_hash) + # file + with open(self.DATA_PATH) as fobj: + self.assertEqual(apt_pkg.sha512sum(fobj), s_hash) + # with zero (\0) in the string + s = b"foo\0bar" + s_hash = ( + "8c5e791db8f6bfb40eba884f70c9ac52231f01a393e4e55b4576d45" + "9a827f34f77e41e7fac806724517b9e96bb42387c5f9bbf325d2f99" + "ed52a4aa6abebc3350" + ) + res = apt_pkg.sha512sum(s) + self.assertEqual(res, s_hash) + # file + with open(self.DATA_WITH_ZERO_PATH) as fobj: + self.assertEqual(apt_pkg.sha512sum(fobj), s_hash) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_install_progress_exec.py b/tests/test_install_progress_exec.py new file mode 100644 index 0000000..064eb81 --- /dev/null +++ b/tests/test_install_progress_exec.py @@ -0,0 +1,43 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2019 Colomban Wendling +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +"""Unit tests for verifying InstallProgress works when spawning dpkg directly +(i.e. when installing standalone .debs).""" +import os +import sys +import unittest + +from test_all import get_library_dir + +libdir = get_library_dir() +if libdir: + sys.path.insert(0, libdir) +import testcommon + +from apt.progress.base import InstallProgress + + +class RunHelper: + def __init__(self): + self.script = "helper_install_progress_run.py" + + def do_install(self, fd): + return os.spawnl(os.P_WAIT, self.script, self.script, str(fd)) + + +class TestInstallProgressExec(testcommon.TestCase): + """test that InstallProgress.run() passes a valid file descriptor to + a child process""" + + def test_run(self): + with InstallProgress() as prog: + self.assertEqual(prog.run(RunHelper()), 0) + + +if __name__ == "__main__": + os.chdir(os.path.dirname(__file__)) + unittest.main() diff --git a/tests/test_large_file.py b/tests/test_large_file.py new file mode 100644 index 0000000..87bc9b6 --- /dev/null +++ b/tests/test_large_file.py @@ -0,0 +1,25 @@ +#!/usr/bin/python3 + +import sys +import unittest + +import apt_inst +import testcommon + +IS_NOT_32BIT = sys.maxsize > 2**32 + + +@unittest.skipIf(IS_NOT_32BIT, "Large File support is for 32 bit systems") +class testHashes(testcommon.TestCase): + "test the hashsum functions against strings and files" + + LARGE_PACKAGE_CONTENT = "data/test_debs/large-package-content_1.0_all.deb" + + def testExtractData(self): + deb = apt_inst.DebFile(self.LARGE_PACKAGE_CONTENT) + + self.assertRaises(MemoryError, deb.data.extractdata, "large-file") + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_lfs.py b/tests/test_lfs.py new file mode 100644 index 0000000..d82e762 --- /dev/null +++ b/tests/test_lfs.py @@ -0,0 +1,19 @@ +#!/usr/bin/python3 +import unittest + +import apt_pkg +import testcommon + + +class TestLargeFileSupport(testcommon.TestCase): + """Test large file support""" + + def test_acquire_file(self): + """Test apt_pkg.AcquireFile() accepts large file size""" + acq = apt_pkg.Acquire() + fil = apt_pkg.AcquireFile(acq, "http://foo", "foo", size=2875204834) + self.assertEqual(fil.filesize, 2875204834) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_lp659438.py b/tests/test_lp659438.py new file mode 100644 index 0000000..21ad061 --- /dev/null +++ b/tests/test_lp659438.py @@ -0,0 +1,80 @@ +#!/usr/bin/python3 +"""Regression test for LP: #981896, LP: #659438""" +# Copyright (C) 2012 Sebastian Heinlein +# +# Licensed under the GNU General Public License Version 2 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Licensed under the GNU General Public License Version 2 + +__author__ = "Sebastian Heinlein " + +import os +import shutil +import tempfile +import unittest + +import apt_pkg +import testcommon + +import apt + + +class RegressionTestCase(testcommon.TestCase): + + """Test suite for LP: #981896, LP: #659438 + 'Cannot locate a file for package X' + """ + + def setUp(self): + testcommon.TestCase.setUp(self) + apt_pkg.config.clear("APT::Update::Post-Invoke") + apt_pkg.config.clear("APT::Update::Post-Invoke-Success") + self.chroot_path = chroot_path = tempfile.mkdtemp() + # Create a damaged status file + self.cache = apt.cache.Cache(rootdir=chroot_path) + with open(apt_pkg.config.find_file("Dir::State::status"), "a") as status: + status.write( + """Package: abrowser +Status: install reinstreq half-installed +Priority: optional +Section: admin +Version: 3.6.9+build1+nobinonly-0ubuntu1 +Architecture: all""" + ) + sources_list_path = apt_pkg.config.find_file("Dir::Etc::sourcelist") + repo_path = os.path.abspath("./data/test-repo") + with open(sources_list_path, "w") as sources_list: + sources_list.write("deb [allow-insecure=yes] copy:%s /\n" % repo_path) + # os.makedirs(os.path.join(chroot_path, "etc/apt/sources.list.d/")) + self.cache.update(sources_list=sources_list_path) + self.cache.open() + + def tearDown(self): + # this resets the rootdir apt_pkg.config to ensure it does not + # "pollute" the later tests + apt.cache.Cache(rootdir="/") + shutil.rmtree(self.chroot_path) + + def test_survive_reqreinst(self): + """Test that we survive a package in require reinstallation state""" + # this should be 82324L but python3.2 gets unhappy about the "L" + self.assertEqual(self.cache.required_download, 82324) + + +if __name__ == "__main__": + unittest.main() + +# vim: ts=4 et sts=4 diff --git a/tests/test_paths.py b/tests/test_paths.py new file mode 100644 index 0000000..4920a25 --- /dev/null +++ b/tests/test_paths.py @@ -0,0 +1,158 @@ +# +# Test that both unicode and bytes path names work +# +import os +import shutil +import unittest + +import apt_inst +import apt_pkg +import testcommon + + +class TestPath(testcommon.TestCase): + dir_unicode = "data/tmp" + dir_bytes = b"data/tmp" + file_unicode = "data/tmp/python-apt-test" + file_bytes = b"data/tmp/python-apt-test" + + def setUp(self): + testcommon.TestCase.setUp(self) + if os.path.exists(self.dir_bytes): + shutil.rmtree(self.dir_bytes) + + os.mkdir(self.dir_bytes) + + def tearDown(self): + apt_pkg.config["dir"] = "/" + shutil.rmtree(self.dir_bytes) + + def test_acquire(self): + apt_pkg.AcquireFile( + apt_pkg.Acquire(), + "http://example.com", + destdir=self.file_bytes, + destfile=self.file_bytes, + ) + apt_pkg.AcquireFile( + apt_pkg.Acquire(), + "http://example.com", + destdir=self.file_unicode, + destfile=self.file_unicode, + ) + + def test_acquire_hashes(self): + hs = apt_pkg.HashString("d41d8cd98f00b204e9800998ecf8427e") + hsl = apt_pkg.HashStringList() + hsl.append(hs) + apt_pkg.AcquireFile( + apt_pkg.Acquire(), + "http://example.com", + hash=hsl, + destdir=self.file_unicode, + destfile=self.file_unicode, + ) + apt_pkg.AcquireFile( + apt_pkg.Acquire(), + "http://example.com", + hash=str(hs), + destdir=self.file_unicode, + destfile=self.file_unicode, + ) + self.assertRaises( + TypeError, + apt_pkg.AcquireFile, + apt_pkg.Acquire(), + "http://example.com", + hash=hs, + destdir=self.file_unicode, + destfile=self.file_unicode, + ) + + def test_ararchive(self): + archive = apt_inst.ArArchive("data/test_debs/data-tar-xz.deb") + + apt_inst.ArArchive(b"data/test_debs/data-tar-xz.deb") + + archive.extract("debian-binary", "data/tmp") + archive.extract(b"debian-binary", b"data/tmp") + archive.extractall("data/tmp") + archive.extractall(b"data/tmp") + self.assertEqual(archive.extractdata("debian-binary"), b"2.0\n") + self.assertEqual(archive.extractdata(b"debian-binary"), b"2.0\n") + self.assertTrue(archive.getmember("debian-binary")) + self.assertTrue(archive.getmember(b"debian-binary")) + self.assertTrue("debian-binary" in archive) + self.assertTrue(b"debian-binary" in archive) + self.assertTrue(archive[b"debian-binary"]) + self.assertTrue(archive["debian-binary"]) + + tar = archive.gettar("control.tar.xz", "xz") + tar = archive.gettar(b"control.tar.xz", "xz") + + tar.extractall(self.dir_unicode) + tar.extractall(self.dir_bytes) + self.assertRaises(LookupError, tar.extractdata, "Do-not-exist") + self.assertRaises(LookupError, tar.extractdata, b"Do-not-exist") + tar.extractdata(b"control") + tar.extractdata("control") + + apt_inst.TarFile(os.path.join(self.dir_unicode, "control.tar.xz")) + apt_inst.TarFile(os.path.join(self.dir_bytes, b"control.tar.xz")) + + def test_configuration(self): + with open(self.file_unicode, "w") as config: + config.write("Hello { World 1; };") + apt_pkg.read_config_file(apt_pkg.config, self.file_bytes) + apt_pkg.read_config_file(apt_pkg.config, self.file_unicode) + apt_pkg.read_config_file_isc(apt_pkg.config, self.file_bytes) + apt_pkg.read_config_file_isc(apt_pkg.config, self.file_unicode) + apt_pkg.read_config_dir(apt_pkg.config, self.dir_unicode) + apt_pkg.read_config_dir(apt_pkg.config, b"/etc/apt/apt.conf.d") + + def test_index_file(self): + apt_pkg.config["dir"] = "data/test_debs" + slist = apt_pkg.SourceList() + slist.read_main_list() + + for meta in slist.list: + for index in meta.index_files: + index.archive_uri(self.file_bytes) + index.archive_uri(self.file_unicode) + + def test_lock(self): + apt_pkg.get_lock(self.file_unicode, True) + apt_pkg.get_lock(self.file_bytes, True) + + with apt_pkg.FileLock(self.file_unicode): + pass + with apt_pkg.FileLock(self.file_bytes): + pass + + def test_policy(self): + apt_pkg.config["dir"] = "data/test_debs" + cache = apt_pkg.Cache(None) + policy = apt_pkg.Policy(cache) + file_unicode = os.path.join(self.dir_unicode, "test.prefs") + file_bytes = os.path.join(self.dir_bytes, b"test.prefs") + + self.assertTrue(policy.read_pinfile(file_unicode)) + self.assertTrue(policy.read_pinfile(file_bytes)) + self.assertTrue(policy.read_pindir(self.dir_unicode)) + self.assertTrue(policy.read_pindir(self.dir_bytes)) + + def test_tag(self): + with open(self.file_bytes, "w") as tag: + tag.write("Key: value\n") + tag1 = apt_pkg.TagFile(self.file_unicode) + tag2 = apt_pkg.TagFile(self.file_bytes) + + self.assertEqual(next(tag1)["Key"], "value") + self.assertEqual(next(tag2)["Key"], "value") + + self.assertRaises(StopIteration, next, tag1) + self.assertRaises(StopIteration, next, tag2) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_pep484.py b/tests/test_pep484.py new file mode 100644 index 0000000..01711dc --- /dev/null +++ b/tests/test_pep484.py @@ -0,0 +1,28 @@ +#!/usr/bin/python3 + +import os +import subprocess +import unittest + + +def hasMyPy(): + try: + subprocess.check_call(["mypy", "--version"]) + except Exception: + return False + return True + + +class PackagePep484TestCase(unittest.TestCase): + @unittest.skipIf(not hasMyPy(), "no mypy available") + def test_pep484_clean(self): + # FIXME: check all of it + top_src_dir = os.path.join(os.path.dirname(__file__), "..", "apt") + os.environ["MYPYPATH"] = os.path.join( + os.path.dirname(__file__), "..", "typehinting" + ) + self.assertEqual(subprocess.call(["mypy", "--strict", top_src_dir]), 0) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_policy.py b/tests/test_policy.py new file mode 100644 index 0000000..ad0032c --- /dev/null +++ b/tests/test_policy.py @@ -0,0 +1,70 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2012 Michael Vogt +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. + +import unittest + +import apt_pkg +import testcommon + +import apt + + +class TestAptPolicy(testcommon.TestCase): + def test_apt_policy_lowlevel(self): + return # TODO: Make tests independent of system state + # get a policy + cache = apt.Cache() + policy = cache._depcache.policy + self.assertNotEqual(policy, None) + # basic tests + pkg = cache["apt"] + self.assertEqual(policy.get_priority(pkg._pkg), 0) + # get priority for all pkgfiles + for ver in pkg.versions: + lowlevel_ver = ver._cand + for pkgfile, i in lowlevel_ver.file_list: + # print pkgfile, i, policy.get_priority(pkgfile) + self.assertTrue(policy.get_priority(pkgfile) >= 1) + self.assertTrue(policy.get_priority(pkgfile) < 1001) + + def test_apt_policy_lowlevel_files(self): + cache = apt_pkg.Cache() + depcache = apt_pkg.DepCache(cache) + policy = cache.policy + dpolicy = depcache.policy + self.assertNotEqual(policy, None) + self.assertNotEqual(dpolicy, None) + + for f in cache.file_list: + policy.get_priority(f) + dpolicy.get_priority(f) + + def test_apt_policy_lowlevel_versions(self): + cache = apt_pkg.Cache() + depcache = apt_pkg.DepCache(cache) + policy = cache.policy + dpolicy = depcache.policy + self.assertNotEqual(policy, None) + self.assertNotEqual(dpolicy, None) + + for pkg in cache.packages: + for ver in pkg.version_list: + policy.get_priority(ver) + dpolicy.get_priority(ver) + + def test_apt_policy_highlevel(self): + return # TODO: Make tests independent of system state + cache = apt.Cache() + pkg = cache["apt"] + self.assertTrue( + pkg.candidate.policy_priority > 1 and pkg.candidate.policy_priority < 1001 + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_progress.py b/tests/test_progress.py new file mode 100644 index 0000000..c823019 --- /dev/null +++ b/tests/test_progress.py @@ -0,0 +1,56 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2010 Michael Vogt +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +"""Unit tests for verifying the correctness of apt.progress""" +import os +import unittest + +import apt_pkg +import testcommon + +import apt + + +class TestAcquireProgress(apt.progress.base.AcquireProgress): + def pulse(self, owner): + self.pulsed = True + # there should be a return value here, either (True,False) + # but often this is forgoten (and causes odd error messages) + # so the lib supports it. we test the lack of support value here + + +class TestProgress(testcommon.TestCase): + def setUp(self): + testcommon.TestCase.setUp(self) + basedir = os.path.abspath(os.path.dirname(__file__)) + # setup apt_pkg config + apt_pkg.init() + apt_pkg.config.set("APT::Architecture", "amd64") + apt_pkg.config.set("Dir::Etc", basedir) + # TODO: /dev/null is not a dir, perhaps find something better + apt_pkg.config.set("Dir::Etc::sourceparts", "/dev/null") + # setup lists dir + if not os.path.exists("./tmp/partial"): + os.makedirs("./tmp/partial") + apt_pkg.config.set("Dir::state::lists", "./tmp") + # create artifical line + deb_line = "deb [allow-insecure=yes] file:%s/data/fake-packages/ /\n" % basedir + with open("fetch_sources.list", "w") as fobj: + fobj.write(deb_line) + apt_pkg.config.set("Dir::Etc::sourcelist", "fetch_sources.list") + apt_pkg.config.clear("APT::Update::Post-Invoke") + apt_pkg.config.clear("APT::Update::Post-Invoke-Success") + + def test_acquire_progress(self): + progress = TestAcquireProgress() + cache = apt.Cache() + cache.update(progress) + self.assertTrue(progress.pulsed) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_pyflakes.py b/tests/test_pyflakes.py new file mode 100644 index 0000000..f26433a --- /dev/null +++ b/tests/test_pyflakes.py @@ -0,0 +1,43 @@ +#!/usr/bin/python3 + +import os +import subprocess +import unittest + +import testcommon + + +class TestPyflakesClean(testcommon.TestCase): + EXCLUDES = ["build", "tests/old", ".pybuild"] + TOPLEVEL = os.path.normpath( + os.path.join(os.path.dirname(os.path.abspath(__file__)), "..") + ) + + def is_excluded_path(self, path): + for exclude in self.EXCLUDES: + if path.startswith(os.path.join(self.TOPLEVEL, exclude)): + return True + return False + + def get_py_files(self, toplevel): + files = [] + for path, dirnames, filenames in os.walk(self.TOPLEVEL): + if self.is_excluded_path(path): + continue + for filename in filenames: + if os.path.splitext(filename)[1] == ".py": + files.append(os.path.join(path, filename)) + return files + + def test_pyflakes_clean(self): + cmd = ["pyflakes3"] + self.get_py_files(self.TOPLEVEL) + res = subprocess.call(cmd) + if res != 0: + self.fail("pyflakes failed with: %s" % res) + + +if __name__ == "__main__": + import logging + + logging.basicConfig(level=logging.DEBUG) + unittest.main() diff --git a/tests/test_signed_usable.py b/tests/test_signed_usable.py new file mode 100644 index 0000000..1bd5087 --- /dev/null +++ b/tests/test_signed_usable.py @@ -0,0 +1,403 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2019 Canonical Ltd +# +# SPDX-License-Identifier: GPL-2.0+ + + +import base64 +import os +import shutil +import tempfile +import unittest + +import apt_pkg +import testcommon + +import apt +import apt.progress.base +import apt.progress.text + +# A change in APT to early fail acquire items with weak hashes caused it +# to call progress methods before calling Start(), which confused python-apt's +# locking handling. Hence we need to skip such tests for now, until we can test +# against an apt version with the fix: +# +# https://salsa.debian.org/apt-team/apt/commit/84176f6c +# +RUN_CRASHING_TESTS = False + +# Message APT gives us when hashes are too weak +CACHE_MSG_WEAK_HASH = ( + "Insufficient information available to perform this download securely" +) + + +class TestSignedUsable(testcommon.TestCase): + """Test fetch_binary() and fetch_source() signature checking.""" + + def setUp(self): + testcommon.TestCase.setUp(self) + apt_pkg.config.clear("APT::Update::Post-Invoke") + apt_pkg.config.clear("APT::Update::Post-Invoke-Success") + self.chroot_path = chroot_path = tempfile.mkdtemp() + repo_path = os.path.abspath("./data/test-signed-usable-repo/") + # Inits the dirs for us + apt.cache.Cache(rootdir=chroot_path) + # Change directory + self.cwd = os.getcwd() + os.chdir(chroot_path) + with open( + os.path.join(self.chroot_path, "etc/apt/sources.list"), "w" + ) as sources_list: + sources_list.write("deb copy:%s/signed/ /\n" % repo_path) + sources_list.write("deb copy:%s/unsigned/ /\n" % repo_path) + sources_list.write("deb-src copy:%s/signed/ /\n" % repo_path) + sources_list.write("deb-src copy:%s/unsigned/ /\n" % repo_path) + + with open(os.path.join(repo_path, "key.gpg.base64"), "rb") as pubkey64: + with open( + os.path.join(self.chroot_path, "etc/apt/trusted.gpg"), "wb" + ) as tgt: + tgt.write(base64.b64decode(pubkey64.read())) + + self.cache = apt.cache.Cache(rootdir=chroot_path) + apt_pkg.config["Acquire::AllowInsecureRepositories"] = "true" + self.cache.update() + apt_pkg.config["Acquire::AllowInsecureRepositories"] = "false" + self.cache.open() + + self.progress = apt.progress.text.AcquireProgress + apt.progress.text.AcquireProgress = apt.progress.base.AcquireProgress + + # Disable actual installation of downloaded items + self.cache.install_archives = ( + lambda *a, **b: apt_pkg.PackageManager.RESULT_COMPLETED + ) + + def tearDown(self): + # this resets the rootdir apt_pkg.config to ensure it does not + # "pollute" the later tests + apt.cache.Cache(rootdir="/") + os.chdir(self.cwd) + shutil.rmtree(self.chroot_path) + + apt.progress.text.AcquireProgress = self.progress + + def doInstall(self, name, bargs): + self.cache[name].mark_install() + try: + with apt.progress.base.InstallProgress() as ip: + self.cache.commit(install_progress=ip, **bargs) + finally: + for fname in os.listdir( + os.path.join(self.chroot_path, "var/cache/apt/archives") + ): + if os.path.isfile( + os.path.join(self.chroot_path, "var/cache/apt/archives", fname) + ): + os.unlink( + os.path.join(self.chroot_path, "var/cache/apt/archives", fname) + ) + self.cache[name].mark_keep() + + def doFetchArchives(self, name, bargs): + fetcher = apt_pkg.Acquire() + self.cache[name].mark_install() + try: + self.cache.fetch_archives(fetcher=fetcher, **bargs) + finally: + for fname in os.listdir( + os.path.join(self.chroot_path, "var/cache/apt/archives") + ): + if fname.endswith(".deb"): + os.unlink( + os.path.join(self.chroot_path, "var/cache/apt/archives", fname) + ) + self.cache[name].mark_keep() + + def testDefaultDenyButExplicitAllowUnauthenticated(self): + """Deny by config (default), but pass allow_unauthenticated=True""" + + bargs = dict(allow_unauthenticated=True) + sargs = dict(allow_unauthenticated=True, unpack=False) + + self.doInstall("signed-usable", bargs) + if RUN_CRASHING_TESTS: + self.assertRaisesRegex( + apt.cache.FetchFailedException, + CACHE_MSG_WEAK_HASH, + self.doInstall, + "signed-not-usable", + bargs, + ) + + self.doInstall("unsigned-usable", bargs) + if RUN_CRASHING_TESTS: + self.assertRaisesRegex( + apt.cache.FetchFailedException, + CACHE_MSG_WEAK_HASH, + self.doInstall, + "unsigned-unusable", + bargs, + ) + + self.doFetchArchives("signed-usable", bargs) + self.doFetchArchives("unsigned-usable", bargs) + self.assertRaisesRegex( + apt.cache.FetchFailedException, + CACHE_MSG_WEAK_HASH, + self.doFetchArchives, + "signed-not-usable", + bargs, + ) + self.assertRaisesRegex( + apt.cache.FetchFailedException, + CACHE_MSG_WEAK_HASH, + self.doFetchArchives, + "unsigned-unusable", + bargs, + ) + + self.cache["signed-usable"].candidate.fetch_binary(**bargs) + self.cache["signed-usable"].candidate.fetch_source(**sargs) + self.cache["signed-not-usable"].candidate.fetch_binary(**bargs) + self.cache["signed-not-usable"].candidate.fetch_source(**sargs) + self.cache["unsigned-usable"].candidate.fetch_binary(**bargs) + self.cache["unsigned-usable"].candidate.fetch_source(**sargs) + self.cache["unsigned-unusable"].candidate.fetch_binary(**bargs) + self.cache["unsigned-unusable"].candidate.fetch_source(**sargs) + + def testDefaultAllow(self): + """Allow by config APT::Get::AllowUnauthenticated = True""" + apt_pkg.config["APT::Get::AllowUnauthenticated"] = "true" + + bargs = dict() + sargs = dict(unpack=False) + + self.doInstall("signed-usable", bargs) + if RUN_CRASHING_TESTS: + self.assertRaisesRegex( + apt.cache.FetchFailedException, + CACHE_MSG_WEAK_HASH, + self.doInstall, + "signed-not-usable", + bargs, + ) + self.doInstall("unsigned-usable", bargs) + if RUN_CRASHING_TESTS: + self.assertRaisesRegex( + apt.cache.FetchFailedException, + CACHE_MSG_WEAK_HASH, + self.doInstall, + "unsigned-unusable", + bargs, + ) + + self.doFetchArchives("signed-usable", bargs) + self.doFetchArchives("unsigned-usable", bargs) + self.assertRaisesRegex( + apt.cache.FetchFailedException, + CACHE_MSG_WEAK_HASH, + self.doFetchArchives, + "signed-not-usable", + bargs, + ) + self.assertRaisesRegex( + apt.cache.FetchFailedException, + CACHE_MSG_WEAK_HASH, + self.doFetchArchives, + "unsigned-unusable", + bargs, + ) + + self.cache["signed-usable"].candidate.fetch_binary(**bargs) + self.cache["signed-usable"].candidate.fetch_source(**sargs) + self.cache["signed-not-usable"].candidate.fetch_binary(**bargs) + self.cache["signed-not-usable"].candidate.fetch_source(**sargs) + self.cache["unsigned-usable"].candidate.fetch_binary(**bargs) + self.cache["unsigned-usable"].candidate.fetch_source(**sargs) + self.cache["unsigned-unusable"].candidate.fetch_binary(**bargs) + self.cache["unsigned-unusable"].candidate.fetch_source(**sargs) + + def testDefaultDeny(self): + """Test APT::Get::AllowUnauthenticated = False (default)""" + self.doInstall("signed-usable", {}) + if RUN_CRASHING_TESTS: + self.assertRaisesRegex( + apt.cache.FetchFailedException, + CACHE_MSG_WEAK_HASH, + self.doInstall, + "signed-not-usable", + {}, + ) + self.assertRaisesRegex( + apt.cache.UntrustedException, + "Untrusted packages:", + self.doInstall, + "unsigned-usable", + {}, + ) + self.assertRaisesRegex( + apt.cache.UntrustedException, + "Untrusted packages:", + self.doInstall, + "unsigned-unusable", + {}, + ) + + self.doFetchArchives("signed-usable", {}) + self.assertRaisesRegex( + apt.cache.FetchFailedException, + CACHE_MSG_WEAK_HASH, + self.doFetchArchives, + "signed-not-usable", + {}, + ) + self.assertRaisesRegex( + apt.cache.UntrustedException, + "Untrusted packages:", + self.doFetchArchives, + "unsigned-usable", + {}, + ) + self.assertRaisesRegex( + apt.cache.UntrustedException, + "Untrusted packages:", + self.doFetchArchives, + "unsigned-unusable", + {}, + ) + + self.cache["signed-usable"].candidate.fetch_binary() + self.cache["signed-usable"].candidate.fetch_source(unpack=False) + self.assertRaisesRegex( + apt.package.UntrustedError, + ": No trusted hash", + self.cache["signed-not-usable"].candidate.fetch_binary, + ) + self.assertRaisesRegex( + apt.package.UntrustedError, + ": No trusted hash", + self.cache["signed-not-usable"].candidate.fetch_source, + unpack=False, + ) + self.assertRaisesRegex( + apt.package.UntrustedError, + ": Source", + self.cache["unsigned-usable"].candidate.fetch_binary, + ) + self.assertRaisesRegex( + apt.package.UntrustedError, + ": Source", + self.cache["unsigned-usable"].candidate.fetch_source, + unpack=False, + ) + self.assertRaisesRegex( + apt.package.UntrustedError, + ": Source", + self.cache["unsigned-unusable"].candidate.fetch_binary, + ) + self.assertRaisesRegex( + apt.package.UntrustedError, + ": Source", + self.cache["unsigned-unusable"].candidate.fetch_source, + unpack=False, + ) + + def testDefaultAllowButExplicitDeny(self): + """Allow by config, but pass allow_unauthenticated=False""" + apt_pkg.config["APT::Get::AllowUnauthenticated"] = "true" + + bargs = dict(allow_unauthenticated=False) + sargs = dict(allow_unauthenticated=False, unpack=False) + + self.doInstall("signed-usable", bargs) + if RUN_CRASHING_TESTS: + self.assertRaisesRegex( + apt.cache.FetchFailedException, + CACHE_MSG_WEAK_HASH, + self.doInstall, + "signed-not-usable", + bargs, + ) + self.assertRaisesRegex( + apt.cache.UntrustedException, + "Untrusted packages:", + self.doInstall, + "unsigned-usable", + bargs, + ) + self.assertRaisesRegex( + apt.cache.UntrustedException, + "Untrusted packages:", + self.doInstall, + "unsigned-unusable", + bargs, + ) + + self.doFetchArchives("signed-usable", bargs) + self.assertRaisesRegex( + apt.cache.FetchFailedException, + CACHE_MSG_WEAK_HASH, + self.doFetchArchives, + "signed-not-usable", + bargs, + ) + self.assertRaisesRegex( + apt.cache.UntrustedException, + "Untrusted packages:", + self.doFetchArchives, + "unsigned-usable", + bargs, + ) + self.assertRaisesRegex( + apt.cache.UntrustedException, + "Untrusted packages:", + self.doFetchArchives, + "unsigned-unusable", + bargs, + ) + + self.cache["signed-usable"].candidate.fetch_binary(**bargs) + self.cache["signed-usable"].candidate.fetch_source(**sargs) + self.assertRaisesRegex( + apt.package.UntrustedError, + ": No trusted hash", + self.cache["signed-not-usable"].candidate.fetch_binary, + **bargs + ) + self.assertRaisesRegex( + apt.package.UntrustedError, + ": No trusted hash", + self.cache["signed-not-usable"].candidate.fetch_source, + **sargs + ) + self.assertRaisesRegex( + apt.package.UntrustedError, + ": Source", + self.cache["unsigned-usable"].candidate.fetch_binary, + **bargs + ) + self.assertRaisesRegex( + apt.package.UntrustedError, + ": Source", + self.cache["unsigned-usable"].candidate.fetch_source, + **sargs + ) + self.assertRaisesRegex( + apt.package.UntrustedError, + ": Source", + self.cache["unsigned-unusable"].candidate.fetch_binary, + **bargs + ) + self.assertRaisesRegex( + apt.package.UntrustedError, + ": Source", + self.cache["unsigned-unusable"].candidate.fetch_source, + **sargs + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_size_to_str.py b/tests/test_size_to_str.py new file mode 100644 index 0000000..6320e39 --- /dev/null +++ b/tests/test_size_to_str.py @@ -0,0 +1,104 @@ +#!/usr/bin/python3 + +__author__ = "Barry Warsaw , James Hunt, Michael Vogt" + +import unittest + +import apt_pkg +import testcommon + + +class SizeToStrTestCase(testcommon.TestCase): + """Test apt_pkg.size_to_str""" + + DATA = { + # XXX: note the trailing spaces for some of these entries! + 10**1: "10 ", + 10**2: "100 ", + 10**3: "1000 ", + 10**4: "10.0 k", + 10**5: "100 k", + 10**6: "1000 k", + 10**7: "10.0 M", + 10**8: "100 M", + 10**9: "1000 M", + 10**10: "10.0 G", + 10**11: "100 G", + 10**12: "1000 G", + 10**13: "10.0 T", + 10**14: "100 T", + 10**15: "1000 T", + 10**16: "10.0 P", + 10**17: "100 P", + 10**18: "1000 P", + 10**19: "10.0 E", + 10**20: "100 E", + 10**21: "1000 E", + 10**22: "10.0 Z", + 10**23: "100.0 Z", + 10**24: "1000 Z", + # 10 ** 25: "10.0 Y", + 10**26: "100 Y", + 10**27: "1000 Y", + # That's our limit :) + 10**28: "10000 Y", + 0: "0 ", + 1: "1 ", + 1024: "1024 ", + 10240: "10.2 k", + 102400: "102 k", + 1024000: "1024 k", + 10240000: "10.2 M", + 102400000: "102 M", + 2147483647: "2147 M", + 2147483648: "2147 M", + 1024000000: "1024 M", + 10240000000: "10.2 G", + 9: "9 ", + 99: "99 ", + 999: "999 ", + 9999: "9999 ", + 99999: "100.0 k", + 999999: "1000 k", + 9999999: "10000 k", + 99999999: "100.0 M", + 999999999: "1000 M", + 9999999999: "10000 M", + 99999999999: "100.0 G", + 999999999999: "1000 G", + 9999999999999: "10000 G", + 99999999999999: "100.0 T", + 999999999999999: "1000 T", + 9999999999999999: "10.0 P", + 99999999999999999: "100 P", + 999999999999999999: "1000 P", + 9999999999999999999: "10.0 E", + 99999999999999999999: "100 E", + 999999999999999999999: "1000 E", + 9999999999999999999999: "10.0 Z", + 999999999999999999999999: "1000 Z", + } + + def test_from_data(self): + for k, v in self.DATA.items(): + size = apt_pkg.size_to_str(k) + msg = f"size_to_str({k}) returned '{size}', expected '{v}'" + self.assertEqual(size, v, msg) + + def test_raise_on_unsupported(self): + for v in ["hello", None, {}, [], ()]: + with self.assertRaises(TypeError): + apt_pkg.size_to_str(v) + + +class RegressionTestCase(testcommon.TestCase): + """Regression test for LP: #1030278""" + + def test_no_overflow_error(self): + # LP: #1030278 produces an overflow error in size_to_str() with a big + # value under Python 3. + self.assertEqual(apt_pkg.size_to_str(2147483648000000000000), "2147 E") + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_sourcerecords.py b/tests/test_sourcerecords.py new file mode 100644 index 0000000..4b0e6fb --- /dev/null +++ b/tests/test_sourcerecords.py @@ -0,0 +1,129 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2018 Michael Vogt +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +"""Unit tests for verifying the correctness of source records in apt_pkg.""" + +import os +import shutil +import sys +import unittest + +from test_all import get_library_dir + +libdir = get_library_dir() +if libdir: + sys.path.insert(0, libdir) + +import apt_pkg +import testcommon + +import apt + + +class TestSourceRecords(testcommon.TestCase): + def setUp(self): + testcommon.TestCase.setUp(self) + + rootdir = "./data/tmp" + if os.path.exists(rootdir): + shutil.rmtree(rootdir) + try: + os.makedirs(os.path.join(rootdir, "etc", "apt")) + except OSError: + pass + + for k in apt_pkg.config.keys(): + apt_pkg.config.clear(k) + + apt_pkg.config["Dir"] = os.path.abspath(rootdir) + apt_pkg.init_config() + + # set a local sources.list that does not need the network + base_sources = os.path.abspath( + os.path.join(rootdir, "etc", "apt", "sources.list") + ) + # main sources.list + sources_list = base_sources + with open(sources_list, "w") as f: + repo = os.path.abspath("./data/test-source-repo") + f.write("deb-src [trusted=yes] copy:%s /\n" % repo) + + self.assertTrue(os.path.exists(sources_list)) + + # update a single sources.list + cache = apt.Cache(rootdir=rootdir) + cache.update(sources_list=sources_list) + + def test_source_records_smoke(self): + src = apt_pkg.SourceRecords() + self.assertTrue(src.step()) + + self.assertEqual(src.maintainer, "Julian Andres Klode ") # noqa + self.assertEqual(src.binaries, ["dh-autoreconf"]) + self.assertEqual(src.package, "dh-autoreconf") + + self.assertEqual(2, len(src.files)) + + # unpacking as a tuple works as before + md5, size, path, type_ = f = src.files[0] + self.assertEqual(md5, None) + self.assertEqual(size, 1578) + self.assertEqual(path, "dh-autoreconf_16.dsc") + self.assertEqual(type_, "dsc") + # access using getters + self.assertTrue(isinstance(f.hashes, apt_pkg.HashStringList)) + self.assertEqual( + str(f.hashes[0]), + "SHA512:4b1a3299f2a8b01b0c75db97fd16cb39919949c74d19ea6cf28e1bbd4891d3515b3e2b90b96a64df665cebf6d95409e704e670909ae91fcfe92409ee1339bffc", + ) # noqa + self.assertEqual(str(f.hashes[1]), "Checksum-FileSize:1578") + self.assertEqual( + str(f.hashes[2]), + "SHA256:1c1b2ab5f1ae5496bd50dbb3c30e9b7d181a06c8d02ee8d7e9c35ed6f2a69b5f", + ) # noqa + self.assertEqual( + str(f.hashes[3]), "SHA1:c9bf7a920013021dad5fbd898dfd5a79c7a150f9" + ) # noqa + self.assertEqual( + str(f.hashes[4]), "MD5Sum:6576a28fe1918ce10bd31543ba545901" + ) # noqa + self.assertEqual(f.size, 1578) + self.assertEqual(f.path, "dh-autoreconf_16.dsc") + self.assertEqual(f.type, "dsc") + + # unpacking as a tuple works as before + md5, size, path, type_ = f = src.files[1] + self.assertEqual(md5, None) + self.assertEqual(size, 7372) + self.assertEqual(path, "dh-autoreconf_16.tar.xz") + self.assertEqual(type_, "tar") + # access using getters + self.assertTrue(isinstance(f.hashes, apt_pkg.HashStringList)) + self.assertEqual( + str(f.hashes[0]), + "SHA512:10448dd179ec12bf4310a9a514110a85f56e51893aa36a97ac3a6f8d7ce99d099e62cfdb78e271e2d94431e8832da0f643de821b6643b80e3f0b0f5d682cf9a9", + ) # noqa + self.assertEqual(str(f.hashes[1]), "Checksum-FileSize:7372") # noqa + self.assertEqual( + str(f.hashes[2]), + "SHA256:5c6a6a362907327bec77a867ff3fd0eceba8015d1b881b48275aff7e4ce0f629", + ) # noqa + self.assertEqual( + str(f.hashes[3]), "SHA1:58459600164398ad6807ddd877a6f814c799c62c" + ) # noqa + self.assertEqual( + str(f.hashes[4]), "MD5Sum:302c8bf43db02412e3f2197fd0f2ee0f" + ) # noqa + self.assertEqual(f.size, 7372) + self.assertEqual(f.path, "dh-autoreconf_16.tar.xz") + self.assertEqual(f.type, "tar") + + self.assertFalse(src.step()) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_tagfile.py b/tests/test_tagfile.py new file mode 100644 index 0000000..29bf9e8 --- /dev/null +++ b/tests/test_tagfile.py @@ -0,0 +1,186 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2010 Michael Vogt +# Copyright (C) 2012 Canonical Ltd. +# Author: Colin Watson +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +"""Unit tests for verifying the correctness of apt_pkg.TagFile""" + +import glob +import os +import shutil +import sys +import tempfile +import unittest + +from test_all import get_library_dir + +libdir = get_library_dir() +if libdir: + sys.path.insert(0, libdir) + +import apt_pkg +import testcommon + + +class TestOpenMaybeClearSigned(testcommon.TestCase): + def test_open_trivial(self): + basepath = os.path.dirname(__file__) + fd = apt_pkg.open_maybe_clear_signed_file( + os.path.join(basepath, "./data/test_debs/hello_2.5-1.dsc") + ) + with os.fdopen(fd) as f: + data = f.read() + self.assertTrue(data.startswith("Format: 1.0\n")) + + def test_open_normal(self): + basepath = os.path.dirname(__file__) + fd = apt_pkg.open_maybe_clear_signed_file( + os.path.join(basepath, "./data/misc/foo_Release") + ) + with os.fdopen(fd) as f: + data = f.read() + self.assertTrue(data.startswith("Origin: Ubuntu\n")) + + def xtest_open_does_not_exit(self): + with self.assertRaises(SystemError): + apt_pkg.open_maybe_clear_signed_file("does-not-exists") + + +class TestTagFile(testcommon.TestCase): + """test the apt_pkg.TagFile""" + + def setUp(self): + testcommon.TestCase.setUp(self) + self.temp_dir = tempfile.mkdtemp() + + def tearDown(self): + shutil.rmtree(self.temp_dir) + + def test_tag_file(self): + basepath = os.path.dirname(__file__) + tagfilepath = os.path.join(basepath, "./data/tagfile/*") + # test once for compressed and uncompressed + for testfile in glob.glob(tagfilepath): + # test once using the open() method and once using the path + tagfile = apt_pkg.TagFile(testfile) + for i, stanza in enumerate(tagfile): + pass + self.assertEqual(i, 2) + with open(testfile) as f: + tagfile = apt_pkg.TagFile(f) + for i, stanza in enumerate(tagfile): + pass + self.assertEqual(i, 2) + + def test_errors(self): + # Raises SystemError via lbiapt + self.assertRaises(SystemError, apt_pkg.TagFile, "not-there-no-no") + # Raises Type error + self.assertRaises(TypeError, apt_pkg.TagFile, object()) + + def test_utf8(self): + value = "Tést Persön " + packages = os.path.join(self.temp_dir, "Packages") + with open(packages, "w", encoding="UTF-8") as packages_file: + print("Maintainer: %s" % value, file=packages_file) + print("", file=packages_file) + with open(packages, encoding="UTF-8") as packages_file: + tagfile = apt_pkg.TagFile(packages_file) + tagfile.step() + self.assertEqual(value, tagfile.section["Maintainer"]) + + def test_latin1(self): + value = "Tést Persön " + packages = os.path.join(self.temp_dir, "Packages") + with open(packages, "w", encoding="ISO-8859-1") as packages_file: + print("Maintainer: %s" % value, file=packages_file) + print("", file=packages_file) + with open(packages) as packages_file: + tagfile = apt_pkg.TagFile(packages_file, bytes=True) + tagfile.step() + self.assertEqual(value.encode("ISO-8859-1"), tagfile.section["Maintainer"]) + with open(packages, encoding="ISO-8859-1") as packages_file: + tagfile = apt_pkg.TagFile(packages_file) + tagfile.step() + self.assertEqual(value, tagfile.section["Maintainer"]) + + def test_mixed(self): + value = "Tést Persön " + packages = os.path.join(self.temp_dir, "Packages") + with open(packages, "w", encoding="UTF-8") as packages_file: + print("Maintainer: %s" % value, file=packages_file) + print("", file=packages_file) + with open(packages, "a", encoding="ISO-8859-1") as packages_file: + print("Maintainer: %s" % value, file=packages_file) + print("", file=packages_file) + with open(packages) as packages_file: + tagfile = apt_pkg.TagFile(packages_file, bytes=True) + tagfile.step() + self.assertEqual(value.encode("UTF-8"), tagfile.section["Maintainer"]) + tagfile.step() + self.assertEqual(value.encode("ISO-8859-1"), tagfile.section["Maintainer"]) + + +class TestTagSection(testcommon.TestCase): + """test the apt_pkg.TagFile""" + + def setUp(self): + testcommon.TestCase.setUp(self) + self.temp_dir = tempfile.mkdtemp() + + def tearDown(self): + shutil.rmtree(self.temp_dir) + + def test_write(self): + ts = apt_pkg.TagSection("a: 1\nb: 2\nc: 3\n") + outpath = os.path.join(self.temp_dir, "test") + with open(outpath, "w") as outfile: + ts.write(outfile, [], []) + with open(outpath) as outfile: + self.assertEqual(outfile.read(), "a: 1\nb: 2\nc: 3\n") + + def test_write_order(self): + ts = apt_pkg.TagSection("a: 1\nb: 2\nc: 3\n") + outpath = os.path.join(self.temp_dir, "test") + with open(outpath, "w") as outfile: + ts.write(outfile, ["a", "c", "b"], []) + with open(outpath) as outfile: + self.assertEqual(outfile.read(), "a: 1\nc: 3\nb: 2\n") + + def test_write_invalid_order(self): + ts = apt_pkg.TagSection("a: 1\nb: 2\nc: 3\n") + outpath = os.path.join(self.temp_dir, "test") + with open(outpath, "w") as outfile: + self.assertRaises(TypeError, ts.write, outfile, ["a", 1, "b"], []) + + def test_write_remove(self): + ts = apt_pkg.TagSection("a: 1\nb: 2\nc: 3\n") + outpath = os.path.join(self.temp_dir, "test") + with open(outpath, "w") as outfile: + ts.write(outfile, ["a", "c", "b"], [apt_pkg.TagRemove("a")]) + with open(outpath) as outfile: + self.assertEqual(outfile.read(), "c: 3\nb: 2\n") + + def test_write_rewrite(self): + ts = apt_pkg.TagSection("a: 1\nb: 2\nc: 3\n") + outpath = os.path.join(self.temp_dir, "test") + with open(outpath, "w") as outfile: + ts.write(outfile, ["a", "c", "b"], [apt_pkg.TagRewrite("a", "AA")]) + with open(outpath) as outfile: + self.assertEqual(outfile.read(), "a: AA\nc: 3\nb: 2\n") + + def test_write_rename(self): + ts = apt_pkg.TagSection("a: 1\nb: 2\nc: 3\n") + outpath = os.path.join(self.temp_dir, "test") + with open(outpath, "w") as outfile: + ts.write(outfile, ["a", "z", "b"], [apt_pkg.TagRename("c", "z")]) + with open(outpath) as outfile: + self.assertEqual(outfile.read(), "a: 1\nz: 3\nb: 2\n") + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..6f582bb --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,74 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2010 Michael Vogt +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. + +import datetime +import os +import unittest + +import testcommon + +from apt.utils import get_maintenance_end_date, get_release_date_from_release_file + + +class TestUtils(testcommon.TestCase): + def test_get_release_date_from_release_file(self): + path = os.path.join(os.path.dirname(__file__), "data", "misc", "foo_Release") + t = get_release_date_from_release_file(path) + self.assertEqual( + str(datetime.datetime.fromtimestamp(t, datetime.UTC)), + "2012-04-25 22:49:23+00:00", + ) + + def test_maintenance_time(self): + months_of_support = 18 + # test historic releases, jaunty + release_date = datetime.datetime(2009, 4, 23) + (end_year, end_month) = get_maintenance_end_date( + release_date, months_of_support + ) + self.assertEqual(end_year, 2010) + self.assertEqual(end_month, 10) + # test historic releases, karmic + release_date = datetime.datetime(2009, 10, 29) + (end_year, end_month) = get_maintenance_end_date( + release_date, months_of_support + ) + self.assertEqual(end_year, 2011) + self.assertEqual(end_month, 4) + # test maverick + release_date = datetime.datetime(2010, 10, 10) + (end_year, end_month) = get_maintenance_end_date( + release_date, months_of_support + ) + self.assertEqual(end_year, 2012) + self.assertEqual(end_month, 4) + + # test with modulo zero + release_date = datetime.datetime(2010, 6, 10) + (end_year, end_month) = get_maintenance_end_date( + release_date, months_of_support + ) + self.assertEqual(end_year, 2011) + self.assertEqual(end_month, 12) + + # test dapper + months_of_support = 60 + release_date = datetime.datetime(2008, 4, 24) + (end_year, end_month) = get_maintenance_end_date( + release_date, months_of_support + ) + self.assertEqual(end_year, 2013) + self.assertEqual(end_month, 4) + + # what datetime says + # d = datetime.timedelta(18*30) + # print "end date: ", release_date + d + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/testcommon.py b/tests/testcommon.py new file mode 100644 index 0000000..29917a7 --- /dev/null +++ b/tests/testcommon.py @@ -0,0 +1,30 @@ +"""Common testing stuff""" + +import os +import unittest + +import apt_pkg + + +class TestCase(unittest.TestCase): + """Base class for python-apt unittests""" + + def setUp(self): + self.resetConfig() + + def resetConfig(self): + apt_pkg.config.clear("") + for key in apt_pkg.config.list(): + apt_pkg.config.clear(key) + + # Avoid loading any host config files + os.unsetenv("APT_CONFIG") + apt_pkg.config["Dir::Etc::main"] = "/dev/null" + apt_pkg.config["Dir::Etc::parts"] = "/dev/null" + + apt_pkg.init_config() + apt_pkg.init_system() + + # Restore default values + apt_pkg.config["Dir::Etc::main"] = "apt.conf" + apt_pkg.config["Dir::Etc::parts"] = "apt.conf.d" -- cgit v1.2.3