xref: /llvm-project/lldb/test/API/commands/process/launch/TestProcessLaunch.py (revision 99451b4453688a94c6014cac233d371ab4cc342d)
1"""
2Test lldb process launch flags.
3"""
4
5from __future__ import print_function
6
7import os
8
9import lldb
10from lldbsuite.test.decorators import *
11from lldbsuite.test.lldbtest import *
12from lldbsuite.test import lldbutil
13
14import six
15
16
17class ProcessLaunchTestCase(TestBase):
18
19    mydir = TestBase.compute_mydir(__file__)
20    NO_DEBUG_INFO_TESTCASE = True
21
22    def setUp(self):
23        # Call super's setUp().
24        TestBase.setUp(self)
25        self.runCmd("settings set auto-confirm true")
26
27    def tearDown(self):
28        self.runCmd("settings clear auto-confirm")
29        TestBase.tearDown(self)
30
31    @not_remote_testsuite_ready
32    def test_io(self):
33        """Test that process launch I/O redirection flags work properly."""
34        self.build()
35        exe = self.getBuildArtifact("a.out")
36        self.expect("file " + exe,
37                    patterns=["Current executable set to .*a.out"])
38
39        in_file = os.path.join(self.getSourceDir(), "input-file.txt")
40        out_file = lldbutil.append_to_process_working_directory(self, "output-test.out")
41        err_file = lldbutil.append_to_process_working_directory(self, "output-test.err")
42
43        # Make sure the output files do not exist before launching the process
44        try:
45            os.remove(out_file)
46        except OSError:
47            pass
48
49        try:
50            os.remove(err_file)
51        except OSError:
52            pass
53
54        launch_command = "process launch -i '{0}' -o '{1}' -e '{2}' -w '{3}'".format(
55                in_file, out_file, err_file, self.get_process_working_directory())
56
57        if lldb.remote_platform:
58            self.runCmd('platform put-file "{local}" "{remote}"'.format(
59                local=in_file, remote=in_file))
60
61        self.expect(launch_command,
62                    patterns=["Process .* launched: .*a.out"])
63
64        success = True
65        err_msg = ""
66
67        out = lldbutil.read_file_on_target(self, out_file)
68        if out != "This should go to stdout.\n":
69            success = False
70            err_msg = err_msg + "    ERROR: stdout file does not contain correct output.\n"
71
72
73        err = lldbutil.read_file_on_target(self, err_file)
74        if err != "This should go to stderr.\n":
75            success = False
76            err_msg = err_msg + "    ERROR: stderr file does not contain correct output.\n"
77
78        if not success:
79            self.fail(err_msg)
80
81    # rdar://problem/9056462
82    # The process launch flag '-w' for setting the current working directory
83    # not working?
84    @not_remote_testsuite_ready
85    @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr20265")
86    @expectedFailureNetBSD
87    def test_set_working_dir_nonexisting(self):
88        """Test that '-w dir' fails to set the working dir when running the inferior with a dir which doesn't exist."""
89        d = {'CXX_SOURCES': 'print_cwd.cpp'}
90        self.build(dictionary=d)
91        self.setTearDownCleanup(d)
92        exe = self.getBuildArtifact("a.out")
93        self.runCmd("file " + exe)
94
95        mywd = 'my_working_dir'
96        out_file_name = "my_working_dir_test.out"
97        err_file_name = "my_working_dir_test.err"
98
99        my_working_dir_path = self.getBuildArtifact(mywd)
100        out_file_path = os.path.join(my_working_dir_path, out_file_name)
101        err_file_path = os.path.join(my_working_dir_path, err_file_name)
102
103        # Check that we get an error when we have a nonexisting path
104        invalid_dir_path = mywd + 'z'
105        launch_command = "process launch -w %s -o %s -e %s" % (
106            invalid_dir_path, out_file_path, err_file_path)
107
108        self.expect(
109            launch_command, error=True, patterns=[
110                "error:.* No such file or directory: %s" %
111                invalid_dir_path])
112
113    @not_remote_testsuite_ready
114    def test_set_working_dir_existing(self):
115        """Test that '-w dir' sets the working dir when running the inferior."""
116        d = {'CXX_SOURCES': 'print_cwd.cpp'}
117        self.build(dictionary=d)
118        self.setTearDownCleanup(d)
119        exe = self.getBuildArtifact("a.out")
120        self.runCmd("file " + exe)
121
122        mywd = 'my_working_dir'
123        out_file_name = "my_working_dir_test.out"
124        err_file_name = "my_working_dir_test.err"
125
126        my_working_dir_path = self.getBuildArtifact(mywd)
127        lldbutil.mkdir_p(my_working_dir_path)
128        out_file_path = os.path.join(my_working_dir_path, out_file_name)
129        err_file_path = os.path.join(my_working_dir_path, err_file_name)
130
131        # Make sure the output files do not exist before launching the process
132        try:
133            os.remove(out_file_path)
134            os.remove(err_file_path)
135        except OSError:
136            pass
137
138        launch_command = "process launch -w %s -o %s -e %s" % (
139            my_working_dir_path, out_file_path, err_file_path)
140
141        self.expect(launch_command,
142                    patterns=["Process .* launched: .*a.out"])
143
144        success = True
145        err_msg = ""
146
147        # Check to see if the 'stdout' file was created
148        try:
149            out_f = open(out_file_path)
150        except IOError:
151            success = False
152            err_msg = err_msg + "ERROR: stdout file was not created.\n"
153        else:
154            # Check to see if the 'stdout' file contains the right output
155            line = out_f.readline()
156            if self.TraceOn():
157                print("line:", line)
158            if not re.search(mywd, line):
159                success = False
160                err_msg = err_msg + "The current working directory was not set correctly.\n"
161                out_f.close()
162
163        # Try to delete the 'stdout' and 'stderr' files
164        try:
165            os.remove(out_file_path)
166            os.remove(err_file_path)
167        except OSError:
168            pass
169
170        if not success:
171            self.fail(err_msg)
172
173    def test_environment_with_special_char(self):
174        """Test that environment variables containing '*' and '}' are handled correctly by the inferior."""
175        source = 'print_env.cpp'
176        d = {'CXX_SOURCES': source}
177        self.build(dictionary=d)
178        self.setTearDownCleanup(d)
179        exe = self.getBuildArtifact("a.out")
180
181        evil_var = 'INIT*MIDDLE}TAIL'
182
183        target = self.dbg.CreateTarget(exe)
184        main_source_spec = lldb.SBFileSpec(source)
185        breakpoint = target.BreakpointCreateBySourceRegex(
186            '// Set breakpoint here.', main_source_spec)
187
188        process = target.LaunchSimple(None,
189                                      ['EVIL=' + evil_var],
190                                      self.get_process_working_directory())
191        self.assertEqual(
192            process.GetState(),
193            lldb.eStateStopped,
194            PROCESS_STOPPED)
195
196        threads = lldbutil.get_threads_stopped_at_breakpoint(
197            process, breakpoint)
198        self.assertEqual(len(threads), 1)
199        frame = threads[0].GetFrameAtIndex(0)
200        sbvalue = frame.EvaluateExpression("evil")
201        value = sbvalue.GetSummary().strip('"')
202
203        self.assertEqual(value, evil_var)
204        process.Continue()
205        self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED)
206