diff mbox series

[03/14] oe-selftest: devtool ide-sdk: Add new test classes for ide-sdk tests

Message ID 20260816194127.86607-4-adrian.freihofer@siemens.com
State New
Headers show
Series devtool: ide-sdk: robust attach-mode debugging and test cleanup | expand

Commit Message

AdrianF Aug. 16, 2026, 7:40 p.m. UTC
From: Adrian Freihofer <adrian.freihofer@siemens.com>

This allows to run the ide-sdk tests with different toolchains
(gcc, clang) and build systems (cmake, meson) in parallel.

Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
---
 meta/lib/oeqa/selftest/cases/devtool.py | 211 +++++++++++++-----------
 1 file changed, 111 insertions(+), 100 deletions(-)
diff mbox series

Patch

diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index 77965e480c..b1539c342c 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -3005,6 +3005,105 @@  class DevtoolIdeSdkTests(DevtoolBase):
             exe_break_line=56 + LINE_SHIFT, exe_list_line=55 + LINE_SHIFT,
             hpp_break_line=21 + LINE_SHIFT, lib_break_line=31 + LINE_SHIFT)
 
+    def _verify_cmake_preset(self, tempdir):
+        """Verify the generated cmake preset works as expected
+
+        Check if compiling works
+        Check if unit tests can be executed in qemu (not qemu-system)
+        """
+        with open(os.path.join(tempdir, 'CMakeUserPresets.json')) as cmake_preset_j:
+            cmake_preset_d = json.load(cmake_preset_j)
+        config_presets = cmake_preset_d["configurePresets"]
+        self.assertEqual(len(config_presets), 1)
+        cmake_exe = config_presets[0]["cmakeExecutable"]
+        preset_name = config_presets[0]["name"]
+        compile_cmd = '%s --build --preset %s' % (cmake_exe, preset_name)
+
+        # Verify the wrapper for cmake native is available
+        self.assertExists(cmake_exe)
+
+        # Verify the cmake preset generated by devtool ide-sdk is available
+        result = runCmd('%s --list-presets' % cmake_exe, cwd=tempdir, output_log=self._cmd_logger)
+        self.assertIn(preset_name, result.output)
+
+        # Verify cmake re-uses the o files compiled by bitbake
+        result = runCmd(compile_cmd, cwd=tempdir, output_log=self._cmd_logger)
+        self.assertIn("ninja: no work to do.", result.output)
+
+        # Verify the unit tests work (in Qemu user mode)
+        result = runCmd('%s --target test' % compile_cmd, cwd=tempdir, output_log=self._cmd_logger)
+        self.assertIn("100% tests passed", result.output)
+
+        # Verify re-building and testing works again
+        result = runCmd('%s --target clean' % compile_cmd, cwd=tempdir, output_log=self._cmd_logger)
+        self.assertIn("Cleaning", result.output)
+        result = runCmd(compile_cmd, cwd=tempdir, output_log=self._cmd_logger)
+        self.assertIn("Building", result.output)
+        self.assertIn("Linking", result.output)
+        result = runCmd('%s --target test' % compile_cmd, cwd=tempdir, output_log=self._cmd_logger)
+        self.assertIn("Running tests...", result.output)
+        self.assertIn("100% tests passed", result.output)
+
+        return compile_cmd
+
+    def _verify_meson_build(self, tempdir, recipe_name):
+        """Verify meson works as expected
+
+        Check if compiling works
+        Check if unit tests can be executed in qemu (not qemu-system)
+        """
+        meson_exe = os.path.join(self._workspace_scripts_dir(recipe_name), "meson")
+        self.assertExists(meson_exe)
+        build_dir = os.path.join(self._sources_workdir_dir(tempdir), recipe_name + "-1.0")
+        compile_cmd = '%s compile -C %s' % (meson_exe, build_dir)
+
+        # Verify meson re-uses the o files compiled by bitbake
+        result = runCmd(compile_cmd, cwd=tempdir, output_log=self._cmd_logger)
+        self.assertIn("ninja: no work to do.", result.output)
+
+        # Verify the unit tests work (in Qemu user mode)
+        result = runCmd('%s test -C %s' % (meson_exe, build_dir),
+                        cwd=tempdir, output_log=self._cmd_logger)
+        self.assertEqual(result.status, 0)
+        self.assertRegex(result.output, r"Fail:\s+0")
+
+        # Verify re-building and testing works again
+        result = runCmd('%s compile -C %s --clean' % (meson_exe, build_dir),
+                        cwd=tempdir, output_log=self._cmd_logger)
+        self.assertIn("Cleaning...", result.output)
+        result = runCmd(compile_cmd, cwd=tempdir, output_log=self._cmd_logger)
+        self.assertIn("Linking target", result.output)
+        result = runCmd('%s test -C %s' % (meson_exe, build_dir),
+                        cwd=tempdir, output_log=self._cmd_logger)
+        self.assertEqual(result.status, 0)
+        self.assertRegex(result.output, r"Fail:\s+0")
+
+        return compile_cmd
+
+    def _verify_service_running(self, qemu, service_name):
+        """Helper to verify a service is running in Qemu"""
+        # Use anchored regex (^name$) instead of pgrep -x because the target
+        # may have busybox pgrep which does not support the -x flag.
+        status, output = qemu.run("pgrep '^%s$'" % service_name)
+        self.assertEqual(status, 0, msg="%s service not running: %s" %
+                         (service_name, output))
+        self.assertTrue(output.strip().isdigit(),
+                        f"pgrep output should be a PID integer, got: {output.strip()}")
+
+    def _verify_conf_file(self, qemu, conf_file, owner, group):
+        """Helper to verify a configuration file is owned by the proper user and group"""
+        stat_cmd = "stat -c '%%U %%G' %s" % conf_file
+        status, output = qemu.run(stat_cmd)
+        self.assertEqual(status, 0, msg="Failed to stat %s: %s" % (conf_file, output))
+        actual_owner, actual_group = output.strip().split()
+        self.assertEqual(actual_owner, owner,
+                         msg="%s not owned by user %s: got %s" % (conf_file, owner, actual_owner))
+        self.assertEqual(actual_group, group,
+                         msg="%s not owned by group %s: got %s" % (conf_file, group, actual_group))
+
+
+class DevtoolIdeSdkGccTests(DevtoolIdeSdkTests):
+
     def _gdb_cross(self):
         """Verify gdb-cross is provided by devtool ide-sdk"""
         target_arch = self.td["TARGET_ARCH"]
@@ -3148,102 +3247,6 @@  class DevtoolIdeSdkTests(DevtoolBase):
         self.assertEqual(r.status, 0)
         self.assertNotIn("gdbserver ", r.output)
 
-    def _verify_cmake_preset(self, tempdir):
-        """Verify the generated cmake preset works as expected
-
-        Check if compiling works
-        Check if unit tests can be executed in qemu (not qemu-system)
-        """
-        with open(os.path.join(tempdir, 'CMakeUserPresets.json')) as cmake_preset_j:
-            cmake_preset_d = json.load(cmake_preset_j)
-        config_presets = cmake_preset_d["configurePresets"]
-        self.assertEqual(len(config_presets), 1)
-        cmake_exe = config_presets[0]["cmakeExecutable"]
-        preset_name = config_presets[0]["name"]
-        compile_cmd = '%s --build --preset %s' % (cmake_exe, preset_name)
-
-        # Verify the wrapper for cmake native is available
-        self.assertExists(cmake_exe)
-
-        # Verify the cmake preset generated by devtool ide-sdk is available
-        result = runCmd('%s --list-presets' % cmake_exe, cwd=tempdir, output_log=self._cmd_logger)
-        self.assertIn(preset_name, result.output)
-
-        # Verify cmake re-uses the o files compiled by bitbake
-        result = runCmd(compile_cmd, cwd=tempdir, output_log=self._cmd_logger)
-        self.assertIn("ninja: no work to do.", result.output)
-
-        # Verify the unit tests work (in Qemu user mode)
-        result = runCmd('%s --target test' % compile_cmd, cwd=tempdir, output_log=self._cmd_logger)
-        self.assertIn("100% tests passed", result.output)
-
-        # Verify re-building and testing works again
-        result = runCmd('%s --target clean' % compile_cmd, cwd=tempdir, output_log=self._cmd_logger)
-        self.assertIn("Cleaning", result.output)
-        result = runCmd(compile_cmd, cwd=tempdir, output_log=self._cmd_logger)
-        self.assertIn("Building", result.output)
-        self.assertIn("Linking", result.output)
-        result = runCmd('%s --target test' % compile_cmd, cwd=tempdir, output_log=self._cmd_logger)
-        self.assertIn("Running tests...", result.output)
-        self.assertIn("100% tests passed", result.output)
-
-        return compile_cmd
-
-    def _verify_meson_build(self, tempdir, recipe_name):
-        """Verify meson works as expected
-
-        Check if compiling works
-        Check if unit tests can be executed in qemu (not qemu-system)
-        """
-        meson_exe = os.path.join(self._workspace_scripts_dir(recipe_name), "meson")
-        self.assertExists(meson_exe)
-        build_dir = os.path.join(self._sources_workdir_dir(tempdir), recipe_name + "-1.0")
-        compile_cmd = '%s compile -C %s' % (meson_exe, build_dir)
-
-        # Verify meson re-uses the o files compiled by bitbake
-        result = runCmd(compile_cmd, cwd=tempdir, output_log=self._cmd_logger)
-        self.assertIn("ninja: no work to do.", result.output)
-
-        # Verify the unit tests work (in Qemu user mode)
-        result = runCmd('%s test -C %s' % (meson_exe, build_dir),
-                        cwd=tempdir, output_log=self._cmd_logger)
-        self.assertEqual(result.status, 0)
-        self.assertRegex(result.output, r"Fail:\s+0")
-
-        # Verify re-building and testing works again
-        result = runCmd('%s compile -C %s --clean' % (meson_exe, build_dir),
-                        cwd=tempdir, output_log=self._cmd_logger)
-        self.assertIn("Cleaning...", result.output)
-        result = runCmd(compile_cmd, cwd=tempdir, output_log=self._cmd_logger)
-        self.assertIn("Linking target", result.output)
-        result = runCmd('%s test -C %s' % (meson_exe, build_dir),
-                        cwd=tempdir, output_log=self._cmd_logger)
-        self.assertEqual(result.status, 0)
-        self.assertRegex(result.output, r"Fail:\s+0")
-
-        return compile_cmd
-
-    def _verify_service_running(self, qemu, service_name):
-        """Helper to verify a service is running in Qemu"""
-        # Use anchored regex (^name$) instead of pgrep -x because the target
-        # may have busybox pgrep which does not support the -x flag.
-        status, output = qemu.run("pgrep '^%s$'" % service_name)
-        self.assertEqual(status, 0, msg="%s service not running: %s" %
-                         (service_name, output))
-        self.assertTrue(output.strip().isdigit(),
-                        f"pgrep output should be a PID integer, got: {output.strip()}")
-
-    def _verify_conf_file(self, qemu, conf_file, owner, group):
-        """Helper to verify a configuration file is owned by the proper user and group"""
-        stat_cmd = "stat -c '%%U %%G' %s" % conf_file
-        status, output = qemu.run(stat_cmd)
-        self.assertEqual(status, 0, msg="Failed to stat %s: %s" % (conf_file, output))
-        actual_owner, actual_group = output.strip().split()
-        self.assertEqual(actual_owner, owner,
-                         msg="%s not owned by user %s: got %s" % (conf_file, owner, actual_owner))
-        self.assertEqual(actual_group, group,
-                         msg="%s not owned by group %s: got %s" % (conf_file, group, actual_group))
-
     @OETestTag("runqemu")
     def test_devtool_ide_sdk_none_qemu(self):
         """Start qemu-system and run tests for multiple recipes. ide=none is used."""
@@ -3642,6 +3645,8 @@  class DevtoolIdeSdkTests(DevtoolBase):
             # Verify deployment and remote debugging works
             self._verify_launch_json_debugging(tempdir, qemu, example_exe)
 
+class DevtoolIdeSdkKernelTests(DevtoolIdeSdkTests):
+
     @OETestTag("runqemu")
     def test_devtool_ide_sdk_code_kernel_module(self):
         """Verify a kernel module recipe works with ide=code mode
@@ -3857,6 +3862,8 @@  class DevtoolIdeSdkTests(DevtoolBase):
             self.assertIn(MAGIC_STRING_NEW, output,
                           'New magic string not found in sysfs after rebuild: %s' % output)
 
+class DevtoolIdeSdkSharedTests(DevtoolIdeSdkTests):
+
     def test_devtool_ide_sdk_shared_sysroots(self):
         """Verify the shared sysroot SDK"""
 
@@ -3918,6 +3925,8 @@  class DevtoolIdeSdkTests(DevtoolBase):
         runCmdEnv('meson setup %s' % tempdir_meson, cwd=cpp_example_src, output_log=self._cmd_logger)
         runCmdEnv('meson compile', cwd=tempdir_meson, output_log=self._cmd_logger)
 
+class DevtoolIdeSdkClangTests(DevtoolIdeSdkTests):
+
     def _verify_launch_json_lldb(self, tempdir):
         """Verify the launch.json file contains valid CodeLLDB (type: lldb) configurations."""
         launch_json_path = os.path.join(tempdir, '.vscode', 'launch.json')
@@ -4261,7 +4270,7 @@  class DevtoolIdeSdkTests(DevtoolBase):
         self._lldb_debug_cpp_example_check(r.output, magic_string)
 
     @OETestTag("runqemu")
-    def test_devtool_ide_sdk_code_cmake_clang(self):
+    def test_devtool_ide_sdk_code_cmake(self):
         """Verify a cmake recipe built with clang works with ide=code (CodeLLDB debugging).
 
         This test uses the cmake-example-clang recipe which is a cmake-example variant
@@ -4316,7 +4325,7 @@  class DevtoolIdeSdkTests(DevtoolBase):
                     tempdir, qemu, magic_string))
 
     @OETestTag("runqemu")
-    def test_devtool_ide_sdk_code_meson_clang(self):
+    def test_devtool_ide_sdk_code_meson(self):
         """Verify a meson recipe built with clang works with ide=code (CodeLLDB debugging).
 
         This is the meson/ninja counterpart of test_devtool_ide_sdk_code_cmake_clang.
@@ -4439,7 +4448,7 @@  class DevtoolIdeSdkTests(DevtoolBase):
         self.assertNotIn('lldb-server', r.output)
 
     @OETestTag("runqemu")
-    def test_devtool_ide_sdk_none_cmake_clang(self):
+    def test_devtool_ide_sdk_none_cmake(self):
         """Verify ide=none generates correct LLDB scripts for a clang cmake recipe.
 
         Uses cmake-example-clang (TOOLCHAIN = "clang") which is built with the
@@ -4502,7 +4511,7 @@  class DevtoolIdeSdkTests(DevtoolBase):
                     tempdir, qemu, recipe_name, example_exe, magic_string))
 
     @OETestTag("runqemu")
-    def test_devtool_ide_sdk_none_meson_clang(self):
+    def test_devtool_ide_sdk_none_meson(self):
         """Verify ide=none generates correct LLDB scripts for a clang meson recipe.
 
         This is the meson/ninja counterpart of test_devtool_ide_sdk_none_cmake_clang.
@@ -4570,6 +4579,8 @@  class DevtoolIdeSdkTests(DevtoolBase):
                 lambda magic_string: self._lldb_none_debugging_multi(
                     tempdir, qemu, recipe_name, example_exe, magic_string))
 
+class DevtoolIdeSdkMiscTests(DevtoolIdeSdkTests):
+
     def test_devtool_ide_sdk_plugins(self):
         """Test that devtool ide-sdk can use plugins from other layers."""