From b2f117c1a1024ec57250bb4e37e75345b9121b78 Mon Sep 17 00:00:00 2001 From: Simon McVittie <smcv@collabora.com> Date: Wed, 28 Jul 2021 12:19:34 +0100 Subject: [PATCH] tests: Add test coverage for pv-adverb LD_AUDIT, LD_PRELOAD handling Signed-off-by: Simon McVittie <smcv@collabora.com> --- pressure-vessel/adverb.c | 23 +++++-- tests/pressure-vessel/adverb.py | 105 ++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 6 deletions(-) diff --git a/pressure-vessel/adverb.c b/pressure-vessel/adverb.c index b5ef2b9a0..b3e2f4759 100644 --- a/pressure-vessel/adverb.c +++ b/pressure-vessel/adverb.c @@ -480,12 +480,23 @@ generate_lib_temp_dirs (LibTempDirs *lib_temp_dirs, { g_autofree gchar *libdl_platform = NULL; g_autofree gchar *abi_path = NULL; - libdl_platform = srt_system_info_dup_libdl_platform (info, - pv_multiarch_details[abi].tuple, - error); - if (!libdl_platform) - return glnx_prefix_error (error, - "Unknown expansion of the dl string token $PLATFORM"); + + if (g_getenv ("PRESSURE_VESSEL_TEST_STANDARDIZE_PLATFORM") != NULL) + { + /* In unit tests it isn't straightforward to find the real + * ${PLATFORM}, so we use a predictable mock implementation: + * whichever platform happens to be listed first. */ + libdl_platform = g_strdup (pv_multiarch_details[abi].platforms[0]); + } + else + { + libdl_platform = srt_system_info_dup_libdl_platform (info, + pv_multiarch_details[abi].tuple, + error); + if (!libdl_platform) + return glnx_prefix_error (error, + "Unknown expansion of the dl string token $PLATFORM"); + } abi_path = g_build_filename (lib_temp_dirs->root_path, libdl_platform, NULL); diff --git a/tests/pressure-vessel/adverb.py b/tests/pressure-vessel/adverb.py index 9088e43e7..4b466ac88 100755 --- a/tests/pressure-vessel/adverb.py +++ b/tests/pressure-vessel/adverb.py @@ -5,6 +5,7 @@ import logging import os +import re import signal import subprocess import sys @@ -18,6 +19,7 @@ except ImportError: from testutils import ( BaseTest, + run_subprocess, test_main, ) @@ -26,20 +28,123 @@ logger = logging.getLogger('test-adverb') class TestAdverb(BaseTest): + def run_subprocess( + self, + args, # type: typing.Union[typing.List[str], str] + check=False, + input=None, # type: typing.Optional[bytes] + timeout=None, # type: typing.Optional[int] + **kwargs # type: typing.Any + ): + logger.info('Running: %r', args) + return run_subprocess( + args, check=check, input=input, timeout=timeout, **kwargs + ) + def setUp(self) -> None: super().setUp() if 'PRESSURE_VESSEL_UNINSTALLED' in os.environ: self.adverb = self.command_prefix + [ + 'env', + '-u', 'LD_AUDIT', + '-u', 'LD_PRELOAD', + # In unit tests it isn't straightforward to find the real + # ${PLATFORM}, so we use a predictable mock implementation + # that always uses PvMultiarchDetails.platforms[0]. + 'PRESSURE_VESSEL_TEST_STANDARDIZE_PLATFORM=1', os.path.join( self.top_builddir, 'pressure-vessel', 'pressure-vessel-adverb' ), ] + self.helper = self.command_prefix + [ + os.path.join( + self.top_builddir, + 'tests', + 'pressure-vessel', + 'test-helper' + ), + ] else: self.skipTest('Not available as an installed-test') + def test_ld_preload(self) -> None: + completed = run_subprocess( + self.adverb + [ + '--ld-audit=/nonexistent/libaudit.so', + '--ld-preload=/nonexistent/libpreload.so', + '--ld-preload=/nonexistent/ubuntu12_32/gameoverlayrenderer.so', + '--ld-preload=/nonexistent/ubuntu12_64/gameoverlayrenderer.so', + '--', + 'sh', '-euc', + # The hard-coded i686 and xeon_phi here must match up with + # pv_multiarch_details[i].platforms[0], which is what is used + # as a mock implementation under + # PRESSURE_VESSEL_TEST_STANDARDIZE_PLATFORM=1. + r''' + ld_audit="$LD_AUDIT" + ld_preload="$LD_PRELOAD" + unset LD_AUDIT + unset LD_PRELOAD + + echo "LD_AUDIT=$ld_audit" + echo "LD_PRELOAD=$ld_preload" + + IFS=: + for item in $ld_preload; do + case "$item" in + (*\$\{PLATFORM\}*) + i686="$(echo "$item" | + sed -e 's/[$]{PLATFORM}/i686/g')" + xeon_phi="$(echo "$item" | + sed -e 's/[$]{PLATFORM}/xeon_phi/g')" + printf "i686: symlink to " + readlink "$i686" + printf "xeon_phi: symlink to " + readlink "$xeon_phi" + ;; + (*) + echo "literal $item" + ;; + esac + done + ''', + ], + check=True, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=2, + universal_newlines=True, + ) + + stdout = completed.stdout + assert stdout is not None + lines = stdout.splitlines() + self.assertEqual( + lines[0], + 'LD_AUDIT=/nonexistent/libaudit.so', + ) + self.assertEqual( + re.sub(r':/[^:]*?/pressure-vessel-libs-....../', + r':/tmp/pressure-vessel-libs-XXXXXX/', + lines[1]), + ('LD_PRELOAD=/nonexistent/libpreload.so' + ':/tmp/pressure-vessel-libs-XXXXXX/' + '${PLATFORM}/gameoverlayrenderer.so') + ) + self.assertEqual(lines[2], 'literal /nonexistent/libpreload.so') + self.assertEqual( + lines[3], + 'i686: symlink to /nonexistent/ubuntu12_32/gameoverlayrenderer.so', + ) + self.assertEqual( + lines[4], + ('xeon_phi: symlink to ' + '/nonexistent/ubuntu12_64/gameoverlayrenderer.so'), + ) + def test_stdio_passthrough(self) -> None: proc = subprocess.Popen( self.adverb + [ -- GitLab