114086849SPavel Labathimport lldb 214086849SPavel Labathimport unittest 314086849SPavel Labathimport os 414086849SPavel Labathimport json 514086849SPavel Labathimport stat 614086849SPavel Labathimport sys 714086849SPavel Labathfrom textwrap import dedent 85c4cb323SPavel Labathimport lldbsuite.test.lldbutil 914086849SPavel Labathfrom lldbsuite.test.lldbtest import * 1014086849SPavel Labathfrom lldbsuite.test.decorators import * 1114086849SPavel Labathfrom lldbsuite.test.gdbclientutils import * 1214086849SPavel Labath 1314086849SPavel Labath 1414086849SPavel Labath@skipIfRemote 1514086849SPavel Labath@skipIfWindows 1614086849SPavel Labathclass TestQemuLaunch(TestBase): 1714086849SPavel Labath NO_DEBUG_INFO_TESTCASE = True 1814086849SPavel Labath 1914086849SPavel Labath def set_emulator_setting(self, name, value): 20*2238dcc3SJonas Devlieghere self.runCmd("settings set -- platform.plugin.qemu-user.%s %s" % (name, value)) 2114086849SPavel Labath 2214086849SPavel Labath def setUp(self): 2314086849SPavel Labath super().setUp() 2414086849SPavel Labath emulator = self.getBuildArtifact("qemu.py") 25*2238dcc3SJonas Devlieghere with os.fdopen( 26*2238dcc3SJonas Devlieghere os.open(emulator, os.O_WRONLY | os.O_CREAT, stat.S_IRWXU), "w" 27*2238dcc3SJonas Devlieghere ) as e: 28*2238dcc3SJonas Devlieghere e.write( 29*2238dcc3SJonas Devlieghere dedent( 30*2238dcc3SJonas Devlieghere """\ 3114086849SPavel Labath #! {exec!s} 3214086849SPavel Labath 3314086849SPavel Labath import runpy 3414086849SPavel Labath import sys 3514086849SPavel Labath 3614086849SPavel Labath sys.path = {path!r} 3714086849SPavel Labath runpy.run_path({source!r}, run_name='__main__') 38*2238dcc3SJonas Devlieghere """ 39*2238dcc3SJonas Devlieghere ).format( 40*2238dcc3SJonas Devlieghere exec=sys.executable, 41*2238dcc3SJonas Devlieghere path=sys.path, 42*2238dcc3SJonas Devlieghere source=self.getSourcePath("qemu.py"), 43*2238dcc3SJonas Devlieghere ) 44*2238dcc3SJonas Devlieghere ) 4514086849SPavel Labath 4614086849SPavel Labath self.set_emulator_setting("architecture", self.getArchitecture()) 4714086849SPavel Labath self.set_emulator_setting("emulator-path", emulator) 4814086849SPavel Labath 4945aa4356SPavel Labath def _create_target(self): 5014086849SPavel Labath self.build() 5114086849SPavel Labath exe = self.getBuildArtifact() 5214086849SPavel Labath 535c4cb323SPavel Labath # Create a target using our platform 5414086849SPavel Labath error = lldb.SBError() 55*2238dcc3SJonas Devlieghere target = self.dbg.CreateTarget(exe, "", "qemu-user", False, error) 5614086849SPavel Labath self.assertSuccess(error) 5714086849SPavel Labath self.assertEqual(target.GetPlatform().GetName(), "qemu-user") 5845aa4356SPavel Labath return target 5945aa4356SPavel Labath 6045aa4356SPavel Labath def _run_and_get_state(self, target=None, info=None): 6145aa4356SPavel Labath if target is None: 6245aa4356SPavel Labath target = self._create_target() 6345aa4356SPavel Labath 6445aa4356SPavel Labath if info is None: 6545aa4356SPavel Labath info = target.GetLaunchInfo() 6614086849SPavel Labath 6714086849SPavel Labath # "Launch" the process. Our fake qemu implementation will pretend it 6814086849SPavel Labath # immediately exited. 6945aa4356SPavel Labath info.SetArguments(["dump:" + self.getBuildArtifact("state.log")], True) 7045aa4356SPavel Labath error = lldb.SBError() 7145aa4356SPavel Labath process = target.Launch(info, error) 7245aa4356SPavel Labath self.assertSuccess(error) 7314086849SPavel Labath self.assertIsNotNone(process) 741b8c7352SJonas Devlieghere self.assertState(process.GetState(), lldb.eStateExited) 7514086849SPavel Labath self.assertEqual(process.GetExitStatus(), 0x47) 7614086849SPavel Labath 7714086849SPavel Labath # Verify the qemu invocation parameters. 7814086849SPavel Labath with open(self.getBuildArtifact("state.log")) as s: 79611fdde4SPavel Labath return json.load(s) 80611fdde4SPavel Labath 81611fdde4SPavel Labath def test_basic_launch(self): 82611fdde4SPavel Labath state = self._run_and_get_state() 83611fdde4SPavel Labath 8414086849SPavel Labath self.assertEqual(state["program"], self.getBuildArtifact()) 85*2238dcc3SJonas Devlieghere self.assertEqual(state["args"], ["dump:" + self.getBuildArtifact("state.log")]) 865c4cb323SPavel Labath 875c4cb323SPavel Labath def test_stdio_pty(self): 8845aa4356SPavel Labath target = self._create_target() 895c4cb323SPavel Labath 9045aa4356SPavel Labath info = target.GetLaunchInfo() 91*2238dcc3SJonas Devlieghere info.SetArguments( 92*2238dcc3SJonas Devlieghere [ 935c4cb323SPavel Labath "stdin:stdin", 945c4cb323SPavel Labath "stdout:STDOUT CONTENT\n", 955c4cb323SPavel Labath "stderr:STDERR CONTENT\n", 965c4cb323SPavel Labath "dump:" + self.getBuildArtifact("state.log"), 97*2238dcc3SJonas Devlieghere ], 98*2238dcc3SJonas Devlieghere False, 99*2238dcc3SJonas Devlieghere ) 1005c4cb323SPavel Labath 1015c4cb323SPavel Labath listener = lldb.SBListener("test_stdio") 1025c4cb323SPavel Labath info.SetListener(listener) 1035c4cb323SPavel Labath 1045c4cb323SPavel Labath self.dbg.SetAsync(True) 10545aa4356SPavel Labath error = lldb.SBError() 1065c4cb323SPavel Labath process = target.Launch(info, error) 1075c4cb323SPavel Labath self.assertSuccess(error) 108*2238dcc3SJonas Devlieghere lldbutil.expect_state_changes(self, listener, process, [lldb.eStateRunning]) 1095c4cb323SPavel Labath 1105c4cb323SPavel Labath process.PutSTDIN("STDIN CONTENT\n") 1115c4cb323SPavel Labath 112*2238dcc3SJonas Devlieghere lldbutil.expect_state_changes(self, listener, process, [lldb.eStateExited]) 1135c4cb323SPavel Labath 1145c4cb323SPavel Labath # Echoed stdin, stdout and stderr. With a pty we cannot split standard 1155c4cb323SPavel Labath # output and error. 116*2238dcc3SJonas Devlieghere self.assertEqual( 117*2238dcc3SJonas Devlieghere process.GetSTDOUT(1000), 118*2238dcc3SJonas Devlieghere "STDIN CONTENT\r\nSTDOUT CONTENT\r\nSTDERR CONTENT\r\n", 119*2238dcc3SJonas Devlieghere ) 1205c4cb323SPavel Labath with open(self.getBuildArtifact("state.log")) as s: 1215c4cb323SPavel Labath state = json.load(s) 1225c4cb323SPavel Labath self.assertEqual(state["stdin"], "STDIN CONTENT\n") 1235c4cb323SPavel Labath 1245c4cb323SPavel Labath def test_stdio_redirect(self): 1255c4cb323SPavel Labath self.build() 1265c4cb323SPavel Labath exe = self.getBuildArtifact() 1275c4cb323SPavel Labath 1285c4cb323SPavel Labath # Create a target using our platform 1295c4cb323SPavel Labath error = lldb.SBError() 130*2238dcc3SJonas Devlieghere target = self.dbg.CreateTarget(exe, "", "qemu-user", False, error) 1315c4cb323SPavel Labath self.assertSuccess(error) 1325c4cb323SPavel Labath 133*2238dcc3SJonas Devlieghere info = lldb.SBLaunchInfo( 134*2238dcc3SJonas Devlieghere [ 1355c4cb323SPavel Labath "stdin:stdin", 1365c4cb323SPavel Labath "stdout:STDOUT CONTENT", 1375c4cb323SPavel Labath "stderr:STDERR CONTENT", 1385c4cb323SPavel Labath "dump:" + self.getBuildArtifact("state.log"), 139*2238dcc3SJonas Devlieghere ] 140*2238dcc3SJonas Devlieghere ) 1415c4cb323SPavel Labath 142*2238dcc3SJonas Devlieghere info.AddOpenFileAction(0, self.getBuildArtifact("stdin.txt"), True, False) 143*2238dcc3SJonas Devlieghere info.AddOpenFileAction(1, self.getBuildArtifact("stdout.txt"), False, True) 144*2238dcc3SJonas Devlieghere info.AddOpenFileAction(2, self.getBuildArtifact("stderr.txt"), False, True) 1455c4cb323SPavel Labath 1465c4cb323SPavel Labath with open(self.getBuildArtifact("stdin.txt"), "w") as f: 1475c4cb323SPavel Labath f.write("STDIN CONTENT") 1485c4cb323SPavel Labath 1495c4cb323SPavel Labath process = target.Launch(info, error) 1505c4cb323SPavel Labath self.assertSuccess(error) 1511b8c7352SJonas Devlieghere self.assertState(process.GetState(), lldb.eStateExited) 1525c4cb323SPavel Labath 1535c4cb323SPavel Labath with open(self.getBuildArtifact("stdout.txt")) as f: 1545c4cb323SPavel Labath self.assertEqual(f.read(), "STDOUT CONTENT") 1555c4cb323SPavel Labath with open(self.getBuildArtifact("stderr.txt")) as f: 1565c4cb323SPavel Labath self.assertEqual(f.read(), "STDERR CONTENT") 1575c4cb323SPavel Labath with open(self.getBuildArtifact("state.log")) as s: 1585c4cb323SPavel Labath state = json.load(s) 1595c4cb323SPavel Labath self.assertEqual(state["stdin"], "STDIN CONTENT") 16014086849SPavel Labath 1619b8f9d33SPavel Labath def test_find_in_PATH(self): 1629b8f9d33SPavel Labath emulator = self.getBuildArtifact("qemu-" + self.getArchitecture()) 1639b8f9d33SPavel Labath os.rename(self.getBuildArtifact("qemu.py"), emulator) 1649b8f9d33SPavel Labath self.set_emulator_setting("emulator-path", "''") 1659b8f9d33SPavel Labath 1669b8f9d33SPavel Labath original_path = os.environ["PATH"] 167*2238dcc3SJonas Devlieghere os.environ["PATH"] = ( 168*2238dcc3SJonas Devlieghere self.getBuildDir() 169*2238dcc3SJonas Devlieghere + self.platformContext.shlib_path_separator 170*2238dcc3SJonas Devlieghere + original_path 171*2238dcc3SJonas Devlieghere ) 172*2238dcc3SJonas Devlieghere 1739b8f9d33SPavel Labath def cleanup(): 1749b8f9d33SPavel Labath os.environ["PATH"] = original_path 1759b8f9d33SPavel Labath 1769b8f9d33SPavel Labath self.addTearDownHook(cleanup) 1779b8f9d33SPavel Labath state = self._run_and_get_state() 1789b8f9d33SPavel Labath 1799b8f9d33SPavel Labath self.assertEqual(state["program"], self.getBuildArtifact()) 180*2238dcc3SJonas Devlieghere self.assertEqual(state["args"], ["dump:" + self.getBuildArtifact("state.log")]) 1819b8f9d33SPavel Labath 18214086849SPavel Labath def test_bad_emulator_path(self): 183*2238dcc3SJonas Devlieghere self.set_emulator_setting( 184*2238dcc3SJonas Devlieghere "emulator-path", self.getBuildArtifact("nonexistent.file") 185*2238dcc3SJonas Devlieghere ) 18614086849SPavel Labath 18745aa4356SPavel Labath target = self._create_target() 18814086849SPavel Labath info = lldb.SBLaunchInfo([]) 18945aa4356SPavel Labath error = lldb.SBError() 19014086849SPavel Labath target.Launch(info, error) 19114086849SPavel Labath self.assertTrue(error.Fail()) 19214086849SPavel Labath self.assertIn("doesn't exist", error.GetCString()) 193611fdde4SPavel Labath 194611fdde4SPavel Labath def test_extra_args(self): 195611fdde4SPavel Labath self.set_emulator_setting("emulator-args", "-fake-arg fake-value") 196611fdde4SPavel Labath state = self._run_and_get_state() 197611fdde4SPavel Labath 198611fdde4SPavel Labath self.assertEqual(state["fake-arg"], "fake-value") 19945aa4356SPavel Labath 200586765c0SPavel Labath def test_env_vars(self): 20145aa4356SPavel Labath # First clear any global environment to have a clean slate for this test 20245aa4356SPavel Labath self.runCmd("settings clear target.env-vars") 20345aa4356SPavel Labath self.runCmd("settings clear target.unset-env-vars") 20445aa4356SPavel Labath 20545aa4356SPavel Labath def var(i): 20645aa4356SPavel Labath return "LLDB_TEST_QEMU_VAR%d" % i 20745aa4356SPavel Labath 20845aa4356SPavel Labath # Set some variables in the host environment. 20945aa4356SPavel Labath for i in range(4): 21045aa4356SPavel Labath os.environ[var(i)] = "from host" 211*2238dcc3SJonas Devlieghere 21245aa4356SPavel Labath def cleanup(): 21345aa4356SPavel Labath for i in range(4): 21445aa4356SPavel Labath del os.environ[var(i)] 215*2238dcc3SJonas Devlieghere 21645aa4356SPavel Labath self.addTearDownHook(cleanup) 21745aa4356SPavel Labath 218586765c0SPavel Labath # Set some emulator-only variables. 219*2238dcc3SJonas Devlieghere self.set_emulator_setting("emulator-env-vars", "%s='emulator only'" % var(4)) 220586765c0SPavel Labath 22145aa4356SPavel Labath # And through the platform setting. 222*2238dcc3SJonas Devlieghere self.set_emulator_setting( 223*2238dcc3SJonas Devlieghere "target-env-vars", 224*2238dcc3SJonas Devlieghere "%s='from platform' %s='from platform'" % (var(1), var(2)), 225*2238dcc3SJonas Devlieghere ) 22645aa4356SPavel Labath 22745aa4356SPavel Labath target = self._create_target() 22845aa4356SPavel Labath info = target.GetLaunchInfo() 22945aa4356SPavel Labath env = info.GetEnvironment() 23045aa4356SPavel Labath 231586765c0SPavel Labath # Platform settings should trump host values. Emulator-only variables 232586765c0SPavel Labath # should not be visible. 23345aa4356SPavel Labath self.assertEqual(env.Get(var(0)), "from host") 23445aa4356SPavel Labath self.assertEqual(env.Get(var(1)), "from platform") 23545aa4356SPavel Labath self.assertEqual(env.Get(var(2)), "from platform") 23645aa4356SPavel Labath self.assertEqual(env.Get(var(3)), "from host") 237586765c0SPavel Labath self.assertIsNone(env.Get(var(4))) 23845aa4356SPavel Labath 23945aa4356SPavel Labath # Finally, make some launch_info specific changes. 240529e03eaSPavel Labath env.Set(var(2), "from target", True) 24145aa4356SPavel Labath env.Unset(var(3)) 242529e03eaSPavel Labath info.SetEnvironment(env, False) 24345aa4356SPavel Labath 24445aa4356SPavel Labath # Now check everything. Launch info changes should trump everything, but 24545aa4356SPavel Labath # only for the target environment -- the emulator should still get the 24645aa4356SPavel Labath # host values. 24745aa4356SPavel Labath state = self._run_and_get_state(target, info) 24845aa4356SPavel Labath for i in range(4): 24945aa4356SPavel Labath self.assertEqual(state["environ"][var(i)], "from host") 250586765c0SPavel Labath self.assertEqual(state["environ"][var(4)], "emulator only") 251*2238dcc3SJonas Devlieghere self.assertEqual( 252*2238dcc3SJonas Devlieghere state["environ"]["QEMU_SET_ENV"], 253*2238dcc3SJonas Devlieghere "%s=from platform,%s=from target" % (var(1), var(2)), 254*2238dcc3SJonas Devlieghere ) 255*2238dcc3SJonas Devlieghere self.assertEqual( 256*2238dcc3SJonas Devlieghere state["environ"]["QEMU_UNSET_ENV"], 257*2238dcc3SJonas Devlieghere "%s,%s,QEMU_SET_ENV,QEMU_UNSET_ENV" % (var(3), var(4)), 258*2238dcc3SJonas Devlieghere ) 259249a5fb0SPavel Labath 260249a5fb0SPavel Labath def test_arg0(self): 261249a5fb0SPavel Labath target = self._create_target() 262249a5fb0SPavel Labath self.runCmd("settings set target.arg0 ARG0") 263249a5fb0SPavel Labath state = self._run_and_get_state(target) 264249a5fb0SPavel Labath 265249a5fb0SPavel Labath self.assertEqual(state["program"], self.getBuildArtifact()) 266249a5fb0SPavel Labath self.assertEqual(state["0"], "ARG0") 267862fffd8SPavel Labath 268862fffd8SPavel Labath def test_sysroot(self): 269862fffd8SPavel Labath sysroot = self.getBuildArtifact("sysroot") 270862fffd8SPavel Labath self.runCmd("platform select qemu-user --sysroot %s" % sysroot) 271862fffd8SPavel Labath state = self._run_and_get_state() 272862fffd8SPavel Labath self.assertEqual(state["environ"]["QEMU_LD_PREFIX"], sysroot) 273*2238dcc3SJonas Devlieghere self.assertIn("QEMU_LD_PREFIX", state["environ"]["QEMU_UNSET_ENV"].split(",")) 274