From: "Sam James" <sam@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/portage:master commit in: lib/portage/tests/emerge/
Date: Wed, 3 Jan 2024 19:59:54 +0000 (UTC) [thread overview]
Message-ID: <1704311991.14ec6c259ca5bd7439ede37216bbb0d160e909e9.sam@gentoo> (raw)
commit: 14ec6c259ca5bd7439ede37216bbb0d160e909e9
Author: Sam James <sam <AT> gentoo <DOT> org>
AuthorDate: Wed Jan 3 04:22:24 2024 +0000
Commit: Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Wed Jan 3 19:59:51 2024 +0000
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=14ec6c25
tests: add getbinpkg file:// sync testcase for BUILD_ID
We do a bit of a strange dance here where we:
1) create a binpkg;
2) shift the PKGDIR so that it becomes a "remote" one for use with file:///;
3) try to merge the binpkg but defer checking the exit status;
4) check if the downloaded filename was unnecessarily incremented (-2). if it is,
fail.
5) check the deferred exit status from 3) so that we fail if the merge failed
for another reason (e.g. failed injection).
Bug: https://bugs.gentoo.org/921208
Signed-off-by: Sam James <sam <AT> gentoo.org>
lib/portage/tests/emerge/meson.build | 1 +
lib/portage/tests/emerge/test_binpkg_fetch.py | 226 ++++++++++++++++++++++++++
2 files changed, 227 insertions(+)
diff --git a/lib/portage/tests/emerge/meson.build b/lib/portage/tests/emerge/meson.build
index 0d34cbecf7..0e0a419740 100644
--- a/lib/portage/tests/emerge/meson.build
+++ b/lib/portage/tests/emerge/meson.build
@@ -1,6 +1,7 @@
py.install_sources(
[
'test_actions.py',
+ 'test_binpkg_fetch.py',
'test_config_protect.py',
'test_emerge_blocker_file_collision.py',
'test_emerge_slot_abi.py',
diff --git a/lib/portage/tests/emerge/test_binpkg_fetch.py b/lib/portage/tests/emerge/test_binpkg_fetch.py
new file mode 100644
index 0000000000..731711bad8
--- /dev/null
+++ b/lib/portage/tests/emerge/test_binpkg_fetch.py
@@ -0,0 +1,226 @@
+# Copyright 2024 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+import shutil
+import subprocess
+import sys
+import tempfile
+
+import portage
+from portage import _unicode_decode, os
+from portage.const import (
+ PORTAGE_PYM_PATH,
+ USER_CONFIG_PATH,
+)
+from portage.process import find_binary
+from portage.tests import TestCase
+from portage.tests.resolver.ResolverPlayground import ResolverPlayground
+from portage.util import ensure_dirs
+
+
+class BinpkgFetchtestCase(TestCase):
+ def testLocalFilePkgSyncUpdate(self):
+ """
+ Check handling of local file:// sync-uri and unnecessary BUILD_ID
+ increments (bug #921208).
+ """
+ debug = False
+
+ ebuilds = {
+ "dev-libs/A-1::local": {
+ "EAPI": "7",
+ "SLOT": "0",
+ },
+ }
+
+ playground = ResolverPlayground(ebuilds=ebuilds, debug=debug)
+ settings = playground.settings
+ eprefix = settings["EPREFIX"]
+ eroot = settings["EROOT"]
+ trees = playground.trees
+ bindb = trees[eroot]["bintree"].dbapi
+ var_cache_edb = os.path.join(eprefix, "var", "cache", "edb")
+ user_config_dir = os.path.join(eprefix, USER_CONFIG_PATH)
+
+ portage_python = portage._python_interpreter
+ emerge_cmd = (
+ portage_python,
+ "-b",
+ "-Wd",
+ os.path.join(str(self.bindir), "emerge"),
+ )
+
+ tmppkgdir = tempfile.TemporaryDirectory()
+ tmppkgdir_suffix = os.path.join(tmppkgdir.name, "binpkg")
+
+ test_commands = (
+ # Create a trivial binpkg first.
+ emerge_cmd
+ + (
+ "--oneshot",
+ "--verbose",
+ "--buildpkg",
+ "dev-libs/A",
+ ),
+ # Copy to a new PKGDIR which we'll use as PORTAGE_BINHOST then delete the old PKGDIR.
+ (
+ (
+ lambda: shutil.copytree(bindb.bintree.pkgdir, tmppkgdir_suffix)
+ or True,
+ )
+ ),
+ (
+ (
+ lambda: os.unlink(
+ os.path.join(
+ bindb.bintree.pkgdir, "dev-libs", "A", "A-1-1.gpkg.tar"
+ )
+ )
+ or True,
+ )
+ ),
+ )
+ test_commands_nonfatal = (
+ # This should succeed if we've correctly saved it as A-1-1.gpkg.tar, not
+ # A-1-2.gpkg.tar, and then also try to unpack the right filename, but
+ # we defer checking the exit code to get a better error if the binpkg
+ # was downloaded with the wrong filename.
+ emerge_cmd
+ + (
+ "--oneshot",
+ "--verbose",
+ "--getbinpkgonly",
+ "dev-libs/A",
+ ),
+ )
+ test_commands_final = (
+ # Check whether the downloaded binpkg in PKGDIR has the correct
+ # filename (-1) or an unnecessarily-incremented one (-2).
+ (
+ lambda: os.path.exists(
+ os.path.join(
+ bindb.bintree.pkgdir, "dev-libs", "A", "A-1-1.gpkg.tar"
+ )
+ ),
+ ),
+ )
+
+ fake_bin = os.path.join(eprefix, "bin")
+ portage_tmpdir = os.path.join(eprefix, "var", "tmp", "portage")
+
+ path = settings.get("PATH")
+ if path is not None and not path.strip():
+ path = None
+ if path is None:
+ path = ""
+ else:
+ path = ":" + path
+ path = fake_bin + path
+
+ pythonpath = os.environ.get("PYTHONPATH")
+ if pythonpath is not None and not pythonpath.strip():
+ pythonpath = None
+ if pythonpath is not None and pythonpath.split(":")[0] == PORTAGE_PYM_PATH:
+ pass
+ else:
+ if pythonpath is None:
+ pythonpath = ""
+ else:
+ pythonpath = ":" + pythonpath
+ pythonpath = PORTAGE_PYM_PATH + pythonpath
+
+ env = {
+ "PORTAGE_OVERRIDE_EPREFIX": eprefix,
+ "PATH": path,
+ "PORTAGE_PYTHON": portage_python,
+ "PORTAGE_REPOSITORIES": settings.repositories.config_string(),
+ "PYTHONDONTWRITEBYTECODE": os.environ.get("PYTHONDONTWRITEBYTECODE", ""),
+ "PYTHONPATH": pythonpath,
+ "PORTAGE_INST_GID": str(os.getgid()),
+ "PORTAGE_INST_UID": str(os.getuid()),
+ "FEATURES": "-pkgdir-index-trusted",
+ }
+
+ dirs = [
+ playground.distdir,
+ fake_bin,
+ portage_tmpdir,
+ user_config_dir,
+ var_cache_edb,
+ ]
+
+ true_symlinks = ["chown", "chgrp"]
+
+ needed_binaries = {
+ "true": (find_binary("true"), True),
+ }
+
+ def run_commands(test_commands, require_success=True):
+ all_successful = True
+
+ for i, args in enumerate(test_commands):
+ if hasattr(args[0], "__call__"):
+ if require_success:
+ self.assertTrue(args[0](), f"callable at index {i} failed")
+ continue
+
+ if isinstance(args[0], dict):
+ local_env = env.copy()
+ local_env.update(args[0])
+ args = args[1:]
+ else:
+ local_env = env
+
+ local_env["PORTAGE_BINHOST"] = f"file:///{tmppkgdir_suffix}"
+ proc = subprocess.Popen(args, env=local_env, stdout=stdout)
+
+ if debug:
+ proc.wait()
+ else:
+ output = proc.stdout.readlines()
+ proc.wait()
+ proc.stdout.close()
+ if proc.returncode != os.EX_OK:
+ for line in output:
+ sys.stderr.write(_unicode_decode(line))
+
+ if all_successful and proc.returncode != os.EX_OK:
+ all_successful = False
+
+ if require_success:
+ self.assertEqual(
+ os.EX_OK, proc.returncode, f"emerge failed with args {args}"
+ )
+
+ return all_successful
+
+ try:
+ for d in dirs:
+ ensure_dirs(d)
+ for x in true_symlinks:
+ os.symlink(needed_binaries["true"][0], os.path.join(fake_bin, x))
+
+ with open(os.path.join(var_cache_edb, "counter"), "wb") as f:
+ f.write(b"100")
+
+ if debug:
+ # The subprocess inherits both stdout and stderr, for
+ # debugging purposes.
+ stdout = None
+ else:
+ # The subprocess inherits stderr so that any warnings
+ # triggered by python -Wd will be visible.
+ stdout = subprocess.PIPE
+
+ run_commands(test_commands)
+ deferred_success = run_commands(test_commands_nonfatal, False)
+ run_commands(test_commands_final)
+
+ # Check the return value of test_commands_nonfatal later on so
+ # we can get a better error message from test_commands_final
+ # if possible.
+ self.assertTrue(deferred_success, f"{test_commands_nonfatal} failed")
+ finally:
+ playground.debug = False
+ playground.cleanup()
+ tmppkgdir.cleanup()
next reply other threads:[~2024-01-03 19:59 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-03 19:59 Sam James [this message]
-- strict thread matches above, loose matches on Subject: below --
2024-02-25 8:25 [gentoo-commits] proj/portage:master commit in: lib/portage/tests/emerge/ Sam James
2024-02-24 3:36 Zac Medico
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-10-30 3:14 Sam James
2023-05-26 15:45 Sam James
2023-05-26 15:45 Sam James
2022-09-25 19:12 Mike Gilbert
2021-01-18 12:20 Zac Medico
2020-10-17 9:21 Zac Medico
2020-10-12 18:03 Zac Medico
2020-08-03 23:28 Zac Medico
2020-08-03 19:30 Zac Medico
2020-03-08 22:29 Zac Medico
2020-03-08 7:33 Zac Medico
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1704311991.14ec6c259ca5bd7439ede37216bbb0d160e909e9.sam@gentoo \
--to=sam@gentoo.org \
--cc=gentoo-commits@lists.gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox