199451b44SJordan Rupprecht""" 299451b44SJordan RupprechtTest lldb process launch flags. 399451b44SJordan Rupprecht""" 499451b44SJordan Rupprecht 599451b44SJordan Rupprechtimport os 699451b44SJordan Rupprecht 799451b44SJordan Rupprechtimport lldb 899451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 999451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 1099451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil 11*e952728fSwalter erquinigofrom pathlib import Path 1299451b44SJordan Rupprecht 1399451b44SJordan Rupprecht 1499451b44SJordan Rupprechtclass ProcessLaunchTestCase(TestBase): 1599451b44SJordan Rupprecht NO_DEBUG_INFO_TESTCASE = True 1699451b44SJordan Rupprecht 1799451b44SJordan Rupprecht def setUp(self): 1899451b44SJordan Rupprecht # Call super's setUp(). 1999451b44SJordan Rupprecht TestBase.setUp(self) 2099451b44SJordan Rupprecht self.runCmd("settings set auto-confirm true") 2199451b44SJordan Rupprecht 2299451b44SJordan Rupprecht def tearDown(self): 2399451b44SJordan Rupprecht self.runCmd("settings clear auto-confirm") 2499451b44SJordan Rupprecht TestBase.tearDown(self) 2599451b44SJordan Rupprecht 2666ae40ebSRaphael Isemann @skipIfRemote 2799451b44SJordan Rupprecht def test_io(self): 2899451b44SJordan Rupprecht """Test that process launch I/O redirection flags work properly.""" 2999451b44SJordan Rupprecht self.build() 3099451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 312238dcc3SJonas Devlieghere self.expect("file " + exe, patterns=["Current executable set to .*a.out"]) 3299451b44SJordan Rupprecht 3399451b44SJordan Rupprecht in_file = os.path.join(self.getSourceDir(), "input-file.txt") 3499451b44SJordan Rupprecht out_file = lldbutil.append_to_process_working_directory(self, "output-test.out") 3599451b44SJordan Rupprecht err_file = lldbutil.append_to_process_working_directory(self, "output-test.err") 3699451b44SJordan Rupprecht 3799451b44SJordan Rupprecht # Make sure the output files do not exist before launching the process 3899451b44SJordan Rupprecht try: 3999451b44SJordan Rupprecht os.remove(out_file) 4099451b44SJordan Rupprecht except OSError: 4199451b44SJordan Rupprecht pass 4299451b44SJordan Rupprecht 4399451b44SJordan Rupprecht try: 4499451b44SJordan Rupprecht os.remove(err_file) 4599451b44SJordan Rupprecht except OSError: 4699451b44SJordan Rupprecht pass 4799451b44SJordan Rupprecht 4899451b44SJordan Rupprecht launch_command = "process launch -i '{0}' -o '{1}' -e '{2}' -w '{3}'".format( 492238dcc3SJonas Devlieghere in_file, out_file, err_file, self.get_process_working_directory() 502238dcc3SJonas Devlieghere ) 5199451b44SJordan Rupprecht 5299451b44SJordan Rupprecht if lldb.remote_platform: 532238dcc3SJonas Devlieghere self.runCmd( 542238dcc3SJonas Devlieghere 'platform put-file "{local}" "{remote}"'.format( 552238dcc3SJonas Devlieghere local=in_file, remote=in_file 562238dcc3SJonas Devlieghere ) 572238dcc3SJonas Devlieghere ) 5899451b44SJordan Rupprecht 592238dcc3SJonas Devlieghere self.expect(launch_command, patterns=["Process .* launched: .*a.out"]) 6099451b44SJordan Rupprecht 6199451b44SJordan Rupprecht success = True 6299451b44SJordan Rupprecht err_msg = "" 6399451b44SJordan Rupprecht 6499451b44SJordan Rupprecht out = lldbutil.read_file_on_target(self, out_file) 6599451b44SJordan Rupprecht if out != "This should go to stdout.\n": 6699451b44SJordan Rupprecht success = False 672238dcc3SJonas Devlieghere err_msg = ( 682238dcc3SJonas Devlieghere err_msg + " ERROR: stdout file does not contain correct output.\n" 692238dcc3SJonas Devlieghere ) 7099451b44SJordan Rupprecht 7199451b44SJordan Rupprecht err = lldbutil.read_file_on_target(self, err_file) 7299451b44SJordan Rupprecht if err != "This should go to stderr.\n": 7399451b44SJordan Rupprecht success = False 742238dcc3SJonas Devlieghere err_msg = ( 752238dcc3SJonas Devlieghere err_msg + " ERROR: stderr file does not contain correct output.\n" 762238dcc3SJonas Devlieghere ) 7799451b44SJordan Rupprecht 7899451b44SJordan Rupprecht if not success: 7999451b44SJordan Rupprecht self.fail(err_msg) 8099451b44SJordan Rupprecht 8199451b44SJordan Rupprecht # rdar://problem/9056462 8299451b44SJordan Rupprecht # The process launch flag '-w' for setting the current working directory 8399451b44SJordan Rupprecht # not working? 8466ae40ebSRaphael Isemann @skipIfRemote 8598257c30SMichał Górny @expectedFailureAll(oslist=["freebsd", "linux"], bugnumber="llvm.org/pr20265") 8699451b44SJordan Rupprecht @expectedFailureNetBSD 8799451b44SJordan Rupprecht def test_set_working_dir_nonexisting(self): 8899451b44SJordan Rupprecht """Test that '-w dir' fails to set the working dir when running the inferior with a dir which doesn't exist.""" 892238dcc3SJonas Devlieghere d = {"CXX_SOURCES": "print_cwd.cpp"} 9099451b44SJordan Rupprecht self.build(dictionary=d) 9199451b44SJordan Rupprecht self.setTearDownCleanup(d) 9299451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 9399451b44SJordan Rupprecht self.runCmd("file " + exe) 9499451b44SJordan Rupprecht 952238dcc3SJonas Devlieghere mywd = "my_working_dir" 9699451b44SJordan Rupprecht out_file_name = "my_working_dir_test.out" 9799451b44SJordan Rupprecht err_file_name = "my_working_dir_test.err" 9899451b44SJordan Rupprecht 9999451b44SJordan Rupprecht my_working_dir_path = self.getBuildArtifact(mywd) 10099451b44SJordan Rupprecht out_file_path = os.path.join(my_working_dir_path, out_file_name) 10199451b44SJordan Rupprecht err_file_path = os.path.join(my_working_dir_path, err_file_name) 10299451b44SJordan Rupprecht 10399451b44SJordan Rupprecht # Check that we get an error when we have a nonexisting path 1042238dcc3SJonas Devlieghere invalid_dir_path = mywd + "z" 10599451b44SJordan Rupprecht launch_command = "process launch -w %s -o %s -e %s" % ( 1062238dcc3SJonas Devlieghere invalid_dir_path, 1072238dcc3SJonas Devlieghere out_file_path, 1082238dcc3SJonas Devlieghere err_file_path, 1092238dcc3SJonas Devlieghere ) 11099451b44SJordan Rupprecht 11199451b44SJordan Rupprecht self.expect( 1122238dcc3SJonas Devlieghere launch_command, 1132238dcc3SJonas Devlieghere error=True, 1142238dcc3SJonas Devlieghere patterns=["error:.* No such file or directory: %s" % invalid_dir_path], 1152238dcc3SJonas Devlieghere ) 11699451b44SJordan Rupprecht 11766ae40ebSRaphael Isemann @skipIfRemote 11899451b44SJordan Rupprecht def test_set_working_dir_existing(self): 11999451b44SJordan Rupprecht """Test that '-w dir' sets the working dir when running the inferior.""" 1202238dcc3SJonas Devlieghere d = {"CXX_SOURCES": "print_cwd.cpp"} 12199451b44SJordan Rupprecht self.build(dictionary=d) 12299451b44SJordan Rupprecht self.setTearDownCleanup(d) 12399451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 12499451b44SJordan Rupprecht self.runCmd("file " + exe) 12599451b44SJordan Rupprecht 1262238dcc3SJonas Devlieghere mywd = "my_working_dir" 12799451b44SJordan Rupprecht out_file_name = "my_working_dir_test.out" 12899451b44SJordan Rupprecht err_file_name = "my_working_dir_test.err" 12999451b44SJordan Rupprecht 13099451b44SJordan Rupprecht my_working_dir_path = self.getBuildArtifact(mywd) 13199451b44SJordan Rupprecht lldbutil.mkdir_p(my_working_dir_path) 13299451b44SJordan Rupprecht out_file_path = os.path.join(my_working_dir_path, out_file_name) 13399451b44SJordan Rupprecht err_file_path = os.path.join(my_working_dir_path, err_file_name) 13499451b44SJordan Rupprecht 13599451b44SJordan Rupprecht # Make sure the output files do not exist before launching the process 13699451b44SJordan Rupprecht try: 13799451b44SJordan Rupprecht os.remove(out_file_path) 13899451b44SJordan Rupprecht os.remove(err_file_path) 13999451b44SJordan Rupprecht except OSError: 14099451b44SJordan Rupprecht pass 14199451b44SJordan Rupprecht 14299451b44SJordan Rupprecht launch_command = "process launch -w %s -o %s -e %s" % ( 1432238dcc3SJonas Devlieghere my_working_dir_path, 1442238dcc3SJonas Devlieghere out_file_path, 1452238dcc3SJonas Devlieghere err_file_path, 1462238dcc3SJonas Devlieghere ) 14799451b44SJordan Rupprecht 1482238dcc3SJonas Devlieghere self.expect(launch_command, patterns=["Process .* launched: .*a.out"]) 14999451b44SJordan Rupprecht 15099451b44SJordan Rupprecht success = True 15199451b44SJordan Rupprecht err_msg = "" 15299451b44SJordan Rupprecht 15399451b44SJordan Rupprecht # Check to see if the 'stdout' file was created 15499451b44SJordan Rupprecht try: 15599451b44SJordan Rupprecht out_f = open(out_file_path) 15699451b44SJordan Rupprecht except IOError: 15799451b44SJordan Rupprecht success = False 15899451b44SJordan Rupprecht err_msg = err_msg + "ERROR: stdout file was not created.\n" 15999451b44SJordan Rupprecht else: 16099451b44SJordan Rupprecht # Check to see if the 'stdout' file contains the right output 16199451b44SJordan Rupprecht line = out_f.readline() 16299451b44SJordan Rupprecht if self.TraceOn(): 16399451b44SJordan Rupprecht print("line:", line) 16499451b44SJordan Rupprecht if not re.search(mywd, line): 16599451b44SJordan Rupprecht success = False 1662238dcc3SJonas Devlieghere err_msg = ( 1672238dcc3SJonas Devlieghere err_msg + "The current working directory was not set correctly.\n" 1682238dcc3SJonas Devlieghere ) 16999451b44SJordan Rupprecht out_f.close() 17099451b44SJordan Rupprecht 17199451b44SJordan Rupprecht # Try to delete the 'stdout' and 'stderr' files 17299451b44SJordan Rupprecht try: 17399451b44SJordan Rupprecht os.remove(out_file_path) 17499451b44SJordan Rupprecht os.remove(err_file_path) 17599451b44SJordan Rupprecht except OSError: 17699451b44SJordan Rupprecht pass 17799451b44SJordan Rupprecht 17899451b44SJordan Rupprecht if not success: 17999451b44SJordan Rupprecht self.fail(err_msg) 18099451b44SJordan Rupprecht 18199451b44SJordan Rupprecht def test_environment_with_special_char(self): 18299451b44SJordan Rupprecht """Test that environment variables containing '*' and '}' are handled correctly by the inferior.""" 1832238dcc3SJonas Devlieghere source = "print_env.cpp" 1842238dcc3SJonas Devlieghere d = {"CXX_SOURCES": source} 18599451b44SJordan Rupprecht self.build(dictionary=d) 18699451b44SJordan Rupprecht self.setTearDownCleanup(d) 18799451b44SJordan Rupprecht 1882238dcc3SJonas Devlieghere evil_var = "INIT*MIDDLE}TAIL" 18999451b44SJordan Rupprecht 19054c26872SRaphael Isemann target = self.createTestTarget() 19199451b44SJordan Rupprecht main_source_spec = lldb.SBFileSpec(source) 19299451b44SJordan Rupprecht breakpoint = target.BreakpointCreateBySourceRegex( 1932238dcc3SJonas Devlieghere "// Set breakpoint here.", main_source_spec 1942238dcc3SJonas Devlieghere ) 19599451b44SJordan Rupprecht 1962238dcc3SJonas Devlieghere process = target.LaunchSimple( 1972238dcc3SJonas Devlieghere None, ["EVIL=" + evil_var], self.get_process_working_directory() 1982238dcc3SJonas Devlieghere ) 1992238dcc3SJonas Devlieghere self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) 20099451b44SJordan Rupprecht 2012238dcc3SJonas Devlieghere threads = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint) 20299451b44SJordan Rupprecht self.assertEqual(len(threads), 1) 20399451b44SJordan Rupprecht frame = threads[0].GetFrameAtIndex(0) 20499451b44SJordan Rupprecht sbvalue = frame.EvaluateExpression("evil") 20599451b44SJordan Rupprecht value = sbvalue.GetSummary().strip('"') 20699451b44SJordan Rupprecht 20799451b44SJordan Rupprecht self.assertEqual(value, evil_var) 20899451b44SJordan Rupprecht process.Continue() 2091b8c7352SJonas Devlieghere self.assertState(process.GetState(), lldb.eStateExited, PROCESS_EXITED) 210*e952728fSwalter erquinigo 211*e952728fSwalter erquinigo @skipIfRemote 212*e952728fSwalter erquinigo def test_target_launch_working_dir_prop(self): 213*e952728fSwalter erquinigo """Test that the setting `target.launch-working-dir` is correctly used when launching a process.""" 214*e952728fSwalter erquinigo d = {"CXX_SOURCES": "print_cwd.cpp"} 215*e952728fSwalter erquinigo self.build(dictionary=d) 216*e952728fSwalter erquinigo self.setTearDownCleanup(d) 217*e952728fSwalter erquinigo exe = self.getBuildArtifact("a.out") 218*e952728fSwalter erquinigo self.runCmd("file " + exe) 219*e952728fSwalter erquinigo 220*e952728fSwalter erquinigo mywd = "my_working_dir" 221*e952728fSwalter erquinigo out_file_name = "my_working_dir_test.out" 222*e952728fSwalter erquinigo 223*e952728fSwalter erquinigo my_working_dir_path = self.getBuildArtifact(mywd) 224*e952728fSwalter erquinigo lldbutil.mkdir_p(my_working_dir_path) 225*e952728fSwalter erquinigo out_file_path = os.path.join(my_working_dir_path, out_file_name) 226*e952728fSwalter erquinigo another_working_dir_path = Path( 227*e952728fSwalter erquinigo os.path.join(my_working_dir_path, "..") 228*e952728fSwalter erquinigo ).resolve() 229*e952728fSwalter erquinigo 230*e952728fSwalter erquinigo # If -w is not passed to process launch, then the setting will be used. 231*e952728fSwalter erquinigo self.runCmd( 232*e952728fSwalter erquinigo f"settings set target.launch-working-dir {another_working_dir_path}" 233*e952728fSwalter erquinigo ) 234*e952728fSwalter erquinigo launch_command = f"process launch -o {out_file_path}" 235*e952728fSwalter erquinigo 236*e952728fSwalter erquinigo self.expect( 237*e952728fSwalter erquinigo launch_command, 238*e952728fSwalter erquinigo patterns=["Process .* launched: .*a.out"], 239*e952728fSwalter erquinigo ) 240*e952728fSwalter erquinigo 241*e952728fSwalter erquinigo out = lldbutil.read_file_on_target(self, out_file_path) 242*e952728fSwalter erquinigo 243*e952728fSwalter erquinigo self.assertIn(f"stdout: {another_working_dir_path}", out) 244*e952728fSwalter erquinigo 245*e952728fSwalter erquinigo # If -w is passed to process launch, that value will be used instead of the setting. 246*e952728fSwalter erquinigo launch_command = f"process launch -w {my_working_dir_path} -o {out_file_path}" 247*e952728fSwalter erquinigo 248*e952728fSwalter erquinigo self.expect( 249*e952728fSwalter erquinigo launch_command, 250*e952728fSwalter erquinigo patterns=["Process .* launched: .*a.out"], 251*e952728fSwalter erquinigo ) 252*e952728fSwalter erquinigo 253*e952728fSwalter erquinigo out = lldbutil.read_file_on_target(self, out_file_path) 254*e952728fSwalter erquinigo self.assertIn(f"stdout: {my_working_dir_path}", out) 255*e952728fSwalter erquinigo 256*e952728fSwalter erquinigo # If set to empty, then LLDB's cwd will be used to launch the process. 257*e952728fSwalter erquinigo self.runCmd(f"settings set target.launch-working-dir ''") 258*e952728fSwalter erquinigo launch_command = f"process launch -o {out_file_path}" 259*e952728fSwalter erquinigo 260*e952728fSwalter erquinigo self.expect( 261*e952728fSwalter erquinigo launch_command, 262*e952728fSwalter erquinigo patterns=["Process .* launched: .*a.out"], 263*e952728fSwalter erquinigo ) 264*e952728fSwalter erquinigo 265*e952728fSwalter erquinigo out = lldbutil.read_file_on_target(self, out_file_path) 266*e952728fSwalter erquinigo self.assertNotIn(f"stdout: {another_working_dir_path}", out) 267