brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.4 KiB · be37c83 Raw
274 lines · python
1import lldb2import unittest3import os4import json5import stat6import sys7from textwrap import dedent8import lldbsuite.test.lldbutil9from lldbsuite.test.lldbtest import *10from lldbsuite.test.decorators import *11from lldbsuite.test.gdbclientutils import *12 13 14@skipIfRemote15@skipIfWindows16class TestQemuLaunch(TestBase):17    NO_DEBUG_INFO_TESTCASE = True18 19    def set_emulator_setting(self, name, value):20        self.runCmd("settings set -- platform.plugin.qemu-user.%s %s" % (name, value))21 22    def setUp(self):23        super().setUp()24        emulator = self.getBuildArtifact("qemu.py")25        with os.fdopen(26            os.open(emulator, os.O_WRONLY | os.O_CREAT, stat.S_IRWXU), "w"27        ) as e:28            e.write(29                dedent(30                    """\31                    #! {exec!s}32 33                    import runpy34                    import sys35 36                    sys.path = {path!r}37                    runpy.run_path({source!r}, run_name='__main__')38                    """39                ).format(40                    exec=sys.executable,41                    path=sys.path,42                    source=self.getSourcePath("qemu.py"),43                )44            )45 46        self.set_emulator_setting("architecture", self.getArchitecture())47        self.set_emulator_setting("emulator-path", emulator)48 49    def _create_target(self):50        self.build()51        exe = self.getBuildArtifact()52 53        # Create a target using our platform54        error = lldb.SBError()55        target = self.dbg.CreateTarget(exe, "", "qemu-user", False, error)56        self.assertSuccess(error)57        self.assertEqual(target.GetPlatform().GetName(), "qemu-user")58        return target59 60    def _run_and_get_state(self, target=None, info=None):61        if target is None:62            target = self._create_target()63 64        if info is None:65            info = target.GetLaunchInfo()66 67        # "Launch" the process. Our fake qemu implementation will pretend it68        # immediately exited.69        info.SetArguments(["dump:" + self.getBuildArtifact("state.log")], True)70        error = lldb.SBError()71        process = target.Launch(info, error)72        self.assertSuccess(error)73        self.assertIsNotNone(process)74        self.assertState(process.GetState(), lldb.eStateExited)75        self.assertEqual(process.GetExitStatus(), 0x47)76 77        # Verify the qemu invocation parameters.78        with open(self.getBuildArtifact("state.log")) as s:79            return json.load(s)80 81    def test_basic_launch(self):82        state = self._run_and_get_state()83 84        self.assertEqual(state["program"], self.getBuildArtifact())85        self.assertEqual(state["args"], ["dump:" + self.getBuildArtifact("state.log")])86 87    def test_stdio_pty(self):88        target = self._create_target()89 90        info = target.GetLaunchInfo()91        info.SetArguments(92            [93                "stdin:stdin",94                "stdout:STDOUT CONTENT\n",95                "stderr:STDERR CONTENT\n",96                "dump:" + self.getBuildArtifact("state.log"),97            ],98            False,99        )100 101        listener = lldb.SBListener("test_stdio")102        info.SetListener(listener)103 104        self.dbg.SetAsync(True)105        error = lldb.SBError()106        process = target.Launch(info, error)107        self.assertSuccess(error)108        lldbutil.expect_state_changes(self, listener, process, [lldb.eStateRunning])109 110        process.PutSTDIN("STDIN CONTENT\n")111 112        lldbutil.expect_state_changes(self, listener, process, [lldb.eStateExited])113 114        # Echoed stdin, stdout and stderr. With a pty we cannot split standard115        # output and error.116        self.assertEqual(117            process.GetSTDOUT(1000),118            "STDIN CONTENT\r\nSTDOUT CONTENT\r\nSTDERR CONTENT\r\n",119        )120        with open(self.getBuildArtifact("state.log")) as s:121            state = json.load(s)122        self.assertEqual(state["stdin"], "STDIN CONTENT\n")123 124    def test_stdio_redirect(self):125        self.build()126        exe = self.getBuildArtifact()127 128        # Create a target using our platform129        error = lldb.SBError()130        target = self.dbg.CreateTarget(exe, "", "qemu-user", False, error)131        self.assertSuccess(error)132 133        info = lldb.SBLaunchInfo(134            [135                "stdin:stdin",136                "stdout:STDOUT CONTENT",137                "stderr:STDERR CONTENT",138                "dump:" + self.getBuildArtifact("state.log"),139            ]140        )141 142        info.AddOpenFileAction(0, self.getBuildArtifact("stdin.txt"), True, False)143        info.AddOpenFileAction(1, self.getBuildArtifact("stdout.txt"), False, True)144        info.AddOpenFileAction(2, self.getBuildArtifact("stderr.txt"), False, True)145 146        with open(self.getBuildArtifact("stdin.txt"), "w") as f:147            f.write("STDIN CONTENT")148 149        process = target.Launch(info, error)150        self.assertSuccess(error)151        self.assertState(process.GetState(), lldb.eStateExited)152 153        with open(self.getBuildArtifact("stdout.txt")) as f:154            self.assertEqual(f.read(), "STDOUT CONTENT")155        with open(self.getBuildArtifact("stderr.txt")) as f:156            self.assertEqual(f.read(), "STDERR CONTENT")157        with open(self.getBuildArtifact("state.log")) as s:158            state = json.load(s)159        self.assertEqual(state["stdin"], "STDIN CONTENT")160 161    def test_find_in_PATH(self):162        emulator = self.getBuildArtifact("qemu-" + self.getArchitecture())163        os.rename(self.getBuildArtifact("qemu.py"), emulator)164        self.set_emulator_setting("emulator-path", "''")165 166        original_path = os.environ["PATH"]167        os.environ["PATH"] = (168            self.getBuildDir()169            + self.platformContext.shlib_path_separator170            + original_path171        )172 173        def cleanup():174            os.environ["PATH"] = original_path175 176        self.addTearDownHook(cleanup)177        state = self._run_and_get_state()178 179        self.assertEqual(state["program"], self.getBuildArtifact())180        self.assertEqual(state["args"], ["dump:" + self.getBuildArtifact("state.log")])181 182    def test_bad_emulator_path(self):183        self.set_emulator_setting(184            "emulator-path", self.getBuildArtifact("nonexistent.file")185        )186 187        target = self._create_target()188        info = lldb.SBLaunchInfo([])189        error = lldb.SBError()190        target.Launch(info, error)191        self.assertTrue(error.Fail())192        self.assertIn("doesn't exist", error.GetCString())193 194    def test_extra_args(self):195        self.set_emulator_setting("emulator-args", "-fake-arg fake-value")196        state = self._run_and_get_state()197 198        self.assertEqual(state["fake-arg"], "fake-value")199 200    def test_env_vars(self):201        # First clear any global environment to have a clean slate for this test202        self.runCmd("settings clear target.env-vars")203        self.runCmd("settings clear target.unset-env-vars")204 205        def var(i):206            return "LLDB_TEST_QEMU_VAR%d" % i207 208        # Set some variables in the host environment.209        for i in range(4):210            os.environ[var(i)] = "from host"211 212        def cleanup():213            for i in range(4):214                del os.environ[var(i)]215 216        self.addTearDownHook(cleanup)217 218        # Set some emulator-only variables.219        self.set_emulator_setting("emulator-env-vars", "%s='emulator only'" % var(4))220 221        # And through the platform setting.222        self.set_emulator_setting(223            "target-env-vars",224            "%s='from platform' %s='from platform'" % (var(1), var(2)),225        )226 227        target = self._create_target()228        info = target.GetLaunchInfo()229        env = info.GetEnvironment()230 231        # Platform settings should trump host values. Emulator-only variables232        # should not be visible.233        self.assertEqual(env.Get(var(0)), "from host")234        self.assertEqual(env.Get(var(1)), "from platform")235        self.assertEqual(env.Get(var(2)), "from platform")236        self.assertEqual(env.Get(var(3)), "from host")237        self.assertIsNone(env.Get(var(4)))238 239        # Finally, make some launch_info specific changes.240        env.Set(var(2), "from target", True)241        env.Unset(var(3))242        info.SetEnvironment(env, False)243 244        # Now check everything. Launch info changes should trump everything, but245        # only for the target environment -- the emulator should still get the246        # host values.247        state = self._run_and_get_state(target, info)248        for i in range(4):249            self.assertEqual(state["environ"][var(i)], "from host")250        self.assertEqual(state["environ"][var(4)], "emulator only")251        self.assertEqual(252            state["environ"]["QEMU_SET_ENV"],253            "%s=from platform,%s=from target" % (var(1), var(2)),254        )255        self.assertEqual(256            state["environ"]["QEMU_UNSET_ENV"],257            "%s,%s,QEMU_SET_ENV,QEMU_UNSET_ENV" % (var(3), var(4)),258        )259 260    def test_arg0(self):261        target = self._create_target()262        self.runCmd("settings set target.arg0 ARG0")263        state = self._run_and_get_state(target)264 265        self.assertEqual(state["program"], self.getBuildArtifact())266        self.assertEqual(state["0"], "ARG0")267 268    def test_sysroot(self):269        sysroot = self.getBuildArtifact("sysroot")270        self.runCmd("platform select qemu-user --sysroot %s" % sysroot)271        state = self._run_and_get_state()272        self.assertEqual(state["environ"]["QEMU_LD_PREFIX"], sysroot)273        self.assertIn("QEMU_LD_PREFIX", state["environ"]["QEMU_UNSET_ENV"].split(","))274