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