[PATCH v2 2/8] tests/cooker: add a shared bitbake-subprocess test base class
AdrianF <[email protected]>
| Newsgroups | org.openembedded.lists.bitbake-devel |
|---|---|
| Message-ID | <[email protected]> |
From: Adrian Freihofer <[email protected]> Tests that run bitbake or tinfoil in a subprocess against a temporary build directory can leave behind a memory-resident bitbake server (and, if BB_HASHSERVE=auto, a hashserv) rooted at TOPDIR. That server must release the directory before the caller's TemporaryDirectory context manager can safely remove it, or cleanup can race a still-running server holding files open there. Add _BitbakeSubprocessTestCase with _run_subprocess()/_shutdown() to provide this consistently, so the tests added on top of it in the next commits don't each have to hand-roll the subprocess/wait boilerplate - and, more importantly, don't get a chance to forget the wait. AI-Generated: Uses GitHub Copilot Signed-off-by: Adrian Freihofer <[email protected]> --- lib/bb/tests/cooker.py | 52 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/lib/bb/tests/cooker.py b/lib/bb/tests/cooker.py index 9e524ae34..c49375ed8 100644 --- a/lib/bb/tests/cooker.py +++ b/lib/bb/tests/cooker.py @@ -7,12 +7,62 @@ # import unittest +import contextlib import os +import subprocess +import sys +import tempfile +import time import bb, bb.cooker import re import logging -# Cooker tests + +class _BitbakeSubprocessTestCase(unittest.TestCase): + """Common helpers for tests that run bitbake/tinfoil in a subprocess. + + Shared because every such subprocess can start a memory-resident bitbake + server (and, if BB_HASHSERVE=auto, a hashserv) rooted at TOPDIR, and both + must release that directory before the caller's TemporaryDirectory can be + safely removed. + """ + + def _run_subprocess(self, cmd, env, cwd): + proc = subprocess.run( + cmd, + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + cwd=cwd, + ) + if proc.returncode: + self.fail('%s failed: %s' % (cmd, proc.stdout)) + return proc.stdout + + def _shutdown(self, builddir): + """Wait for the bitbake server and hashserv to release builddir. + + Must run before the caller's TemporaryDirectory is removed, so it + cannot be a tearDown(). + """ + deadline = time.monotonic() + 30 + while time.monotonic() < deadline: + if not any(os.path.exists(os.path.join(builddir, p)) + for p in ('hashserve.sock', 'bitbake.lock')): + return + time.sleep(0.5) + + @contextlib.contextmanager + def _build_dir(self, prefix='tinfoiltest'): + """TemporaryDirectory that also waits out _shutdown() before removal.""" + with tempfile.TemporaryDirectory(prefix=prefix) as builddir: + try: + yield builddir + finally: + self._shutdown(builddir) + + class CookerTest(unittest.TestCase): def setUp(self): # At least one variable needs to be set -- 2.55.0