public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
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()


             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