blob: f363dbf191d5e425ccccdb343f0d118162b44945 [file] [log] [blame]
Johnny Chen49cb85d2011-11-28 21:39:07 +00001"""Test Python APIs for process IO."""
2
3import os, sys, time
4import unittest2
5import lldb
6from lldbtest import *
Greg Claytonb8e9b8b2014-10-14 20:18:05 +00007import lldbutil
Johnny Chen49cb85d2011-11-28 21:39:07 +00008
9class ProcessIOTestCase(TestBase):
10
Greg Clayton4570d3e2013-12-10 23:19:29 +000011 mydir = TestBase.compute_mydir(__file__)
Johnny Chen49cb85d2011-11-28 21:39:07 +000012
13 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
14 @python_api_test
Johnny Chen24086bc2012-04-06 19:54:10 +000015 @dsym_test
Greg Claytonb8e9b8b2014-10-14 20:18:05 +000016 def test_stdin_by_api_with_dsym(self):
Johnny Chen49cb85d2011-11-28 21:39:07 +000017 """Exercise SBProcess.PutSTDIN()."""
18 self.buildDsym()
Greg Claytonb8e9b8b2014-10-14 20:18:05 +000019 self.do_stdin_by_api()
Johnny Chen49cb85d2011-11-28 21:39:07 +000020
21 @python_api_test
Johnny Chen24086bc2012-04-06 19:54:10 +000022 @dwarf_test
Greg Claytonb8e9b8b2014-10-14 20:18:05 +000023 def test_stdin_by_api_with_dwarf(self):
Johnny Chen49cb85d2011-11-28 21:39:07 +000024 """Exercise SBProcess.PutSTDIN()."""
25 self.buildDwarf()
Greg Claytonb8e9b8b2014-10-14 20:18:05 +000026 self.do_stdin_by_api()
27
28 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
29 @python_api_test
30 @dsym_test
31 def test_stdin_redirection_with_dsym(self):
32 """Exercise SBLaunchInfo::AddOpenFileAction() for STDIN without specifying STDOUT or STDERR."""
33 self.buildDsym()
34 self.do_stdin_redirection()
35
36 @python_api_test
37 @dwarf_test
38 def test_stdin_redirection_with_dwarf(self):
39 """Exercise SBLaunchInfo::AddOpenFileAction() for STDIN without specifying STDOUT or STDERR."""
40 self.buildDwarf()
41 self.do_stdin_redirection()
42
43 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
44 @python_api_test
45 @dsym_test
46 def test_stdout_redirection_with_dsym(self):
47 """Exercise SBLaunchInfo::AddOpenFileAction() for STDOUT without specifying STDIN or STDERR."""
48 self.buildDsym()
49 self.do_stdout_redirection()
50
51 @python_api_test
52 @dwarf_test
53 def test_stdout_redirection_with_dwarf(self):
54 """Exercise SBLaunchInfo::AddOpenFileAction() for STDOUT without specifying STDIN or STDERR."""
55 self.buildDwarf()
56 self.do_stdout_redirection()
57
58 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
59 @python_api_test
60 @dsym_test
61 def test_stderr_redirection_with_dsym(self):
62 """Exercise SBLaunchInfo::AddOpenFileAction() for STDERR without specifying STDIN or STDOUT."""
63 self.buildDsym()
64 self.do_stderr_redirection()
65
66 @python_api_test
67 @dwarf_test
68 def test_stderr_redirection_with_dwarf(self):
69 """Exercise SBLaunchInfo::AddOpenFileAction() for STDERR without specifying STDIN or STDOUT."""
70 self.buildDwarf()
71 self.do_stderr_redirection()
72
73 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
74 @python_api_test
75 @dsym_test
76 def test_stdout_stderr_redirection_with_dsym(self):
77 """Exercise SBLaunchInfo::AddOpenFileAction() for STDOUT and STDERR without redirecting STDIN."""
78 self.buildDsym()
79 self.do_stdout_stderr_redirection()
80
81 @python_api_test
82 @dwarf_test
83 def test_stdout_stderr_redirection_with_dwarf(self):
84 """Exercise SBLaunchInfo::AddOpenFileAction() for STDOUT and STDERR without redirecting STDIN."""
85 self.buildDwarf()
86 self.do_stdout_stderr_redirection()
Johnny Chen49cb85d2011-11-28 21:39:07 +000087
88 def setUp(self):
89 # Call super's setUp().
90 TestBase.setUp(self)
91 # Get the full path to our executable to be debugged.
92 self.exe = os.path.join(os.getcwd(), "process_io")
Greg Claytonb8e9b8b2014-10-14 20:18:05 +000093 self.input_file = os.path.join(os.getcwd(), "input.txt")
94 self.output_file = os.path.join(os.getcwd(), "output.txt")
95 self.error_file = os.path.join(os.getcwd(), "error.txt")
96 self.lines = ["Line 1", "Line 2", "Line 3"]
97
98 def read_output_file_and_delete (self):
99 self.assertTrue(os.path.exists(self.output_file), "Make sure output.txt file exists")
100 f = open(self.output_file, 'r')
101 contents = f.read()
102 f.close()
103 os.unlink(self.output_file)
104 return contents
Johnny Chen49cb85d2011-11-28 21:39:07 +0000105
Greg Claytonb8e9b8b2014-10-14 20:18:05 +0000106 def read_error_file_and_delete(self):
107 self.assertTrue(os.path.exists(self.error_file), "Make sure error.txt file exists")
108 f = open(self.error_file, 'r')
109 contents = f.read()
110 f.close()
111 os.unlink(self.error_file)
112 return contents
113
114 def create_target(self):
115 '''Create the target and launch info that will be used by all tests'''
116 self.target = self.dbg.CreateTarget(self.exe)
117 self.launch_info = lldb.SBLaunchInfo([self.exe])
118 self.launch_info.SetWorkingDirectory(self.get_process_working_directory())
119
120 def redirect_stdin(self):
121 '''Redirect STDIN (file descriptor 0) to use our input.txt file
122
123 Make the input.txt file to use when redirecting STDIN, setup a cleanup action
124 to delete the input.txt at the end of the test in case exceptions are thrown,
125 and redirect STDIN in the launch info.'''
126 f = open(self.input_file, 'w')
127 for line in self.lines:
128 f.write(line + "\n")
129 f.close()
130 # This is the function to remove the custom formats in order to have a
131 # clean slate for the next test case.
132 def cleanup():
133 os.unlink(self.input_file)
134
135 # Execute the cleanup function during test case tear down.
136 self.addTearDownHook(cleanup)
137 self.launch_info.AddOpenFileAction(0, self.input_file, True, False);
138
139 def redirect_stdout(self):
140 '''Redirect STDOUT (file descriptor 1) to use our output.txt file'''
141 self.launch_info.AddOpenFileAction(1, self.output_file, False, True);
142
143 def redirect_stderr(self):
144 '''Redirect STDERR (file descriptor 2) to use our error.txt file'''
145 self.launch_info.AddOpenFileAction(2, self.error_file, False, True);
146
147 def do_stdin_redirection(self):
148 """Exercise SBLaunchInfo::AddOpenFileAction() for STDIN without specifying STDOUT or STDERR."""
149 self.create_target()
150 self.redirect_stdin()
151 self.run_process(False)
152 output = self.process.GetSTDOUT(1000)
153 self.check_process_output(output, output)
154
155 def do_stdout_redirection(self):
156 """Exercise SBLaunchInfo::AddOpenFileAction() for STDOUT without specifying STDIN or STDERR."""
157 self.create_target()
158 self.redirect_stdout()
159 self.run_process(True)
160 output = self.read_output_file_and_delete()
161 error = self.process.GetSTDOUT(1000)
162 self.check_process_output(output, error)
163
164 def do_stderr_redirection(self):
165 """Exercise SBLaunchInfo::AddOpenFileAction() for STDERR without specifying STDIN or STDOUT."""
166 self.create_target()
167 self.redirect_stderr()
168 self.run_process(True)
169 output = self.process.GetSTDOUT(1000)
170 error = self.read_error_file_and_delete()
171 self.check_process_output(output, error)
172
173 def do_stdout_stderr_redirection(self):
174 """Exercise SBLaunchInfo::AddOpenFileAction() for STDOUT and STDERR without redirecting STDIN."""
175 self.create_target()
176 self.redirect_stdout()
177 self.redirect_stderr()
178 self.run_process(True)
179 output = self.read_output_file_and_delete()
180 error = self.read_error_file_and_delete()
181 self.check_process_output(output, error)
182
183 def do_stdin_stdout_stderr_redirection(self):
184 """Exercise SBLaunchInfo::AddOpenFileAction() for STDIN, STDOUT and STDERR."""
185 # Make the input.txt file to use
186 self.create_target()
187 self.redirect_stdin()
188 self.redirect_stdout()
189 self.redirect_stderr()
190 self.run_process(True)
191 output = self.read_output_file_and_delete()
192 error = self.read_error_file_and_delete()
193 self.check_process_output(output, error)
194
195 def do_stdin_by_api(self):
Johnny Chen49cb85d2011-11-28 21:39:07 +0000196 """Launch a process and use SBProcess.PutSTDIN() to write data to it."""
Greg Claytonb8e9b8b2014-10-14 20:18:05 +0000197 self.create_target()
198 self.run_process(True)
199 output = self.process.GetSTDOUT(1000)
200 self.check_process_output(output, output)
201
202 def run_process(self, put_stdin):
203 '''Run the process to completion and optionally put lines to STDIN via the API if "put_stdin" is True'''
204 # Set the breakpoints
205 self.breakpoint = self.target.BreakpointCreateBySourceRegex('Set breakpoint here', lldb.SBFileSpec("main.c"))
206 self.assertTrue(self.breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT)
Johnny Chen49cb85d2011-11-28 21:39:07 +0000207
Greg Claytonb8e9b8b2014-10-14 20:18:05 +0000208 # Launch the process, and do not stop at the entry point.
209 error = lldb.SBError()
210 # This should launch the process and it should exit by the time we get back
211 # because we have synchronous mode enabled
212 self.process = self.target.Launch (self.launch_info, error)
Johnny Chen49cb85d2011-11-28 21:39:07 +0000213
Greg Claytonb8e9b8b2014-10-14 20:18:05 +0000214 self.assertTrue(error.Success(), "Make sure process launched successfully")
215 self.assertTrue(self.process, PROCESS_IS_VALID)
Daniel Malea249287a2013-02-19 16:08:57 +0000216
Johnny Chen49cb85d2011-11-28 21:39:07 +0000217 if self.TraceOn():
218 print "process launched."
219
Greg Claytonb8e9b8b2014-10-14 20:18:05 +0000220 # Frame #0 should be at our breakpoint.
221 threads = lldbutil.get_threads_stopped_at_breakpoint (self.process, self.breakpoint)
222
223 self.assertTrue(len(threads) == 1)
224 self.thread = threads[0]
225 self.frame = self.thread.frames[0]
226 self.assertTrue(self.frame, "Frame 0 is valid.")
Johnny Chen49cb85d2011-11-28 21:39:07 +0000227
Greg Claytonb8e9b8b2014-10-14 20:18:05 +0000228 if self.TraceOn():
229 print "process stopped at breakpoint, sending STDIN via LLDB API."
Johnny Chen49cb85d2011-11-28 21:39:07 +0000230
Greg Claytonb8e9b8b2014-10-14 20:18:05 +0000231 # Write data to stdin via the public API if we were asked to
232 if put_stdin:
233 for line in self.lines:
234 self.process.PutSTDIN(line + "\n")
235
236 # Let process continue so it will exit
237 self.process.Continue()
238 state = self.process.GetState()
239 self.assertTrue(state == lldb.eStateExited, PROCESS_IS_VALID)
240
241 def check_process_output (self, output, error):
Johnny Chen5886fb52012-01-12 00:29:46 +0000242 # Since we launched the process without specifying stdin/out/err,
243 # a pseudo terminal is used for stdout/err, and we are satisfied
244 # once "input line=>1" appears in stdout.
Johnny Chen49cb85d2011-11-28 21:39:07 +0000245 # See also main.c.
Greg Claytonb8e9b8b2014-10-14 20:18:05 +0000246 if self.TraceOn():
247 print "output = '%s'" % output
248 print "error = '%s'" % error
249
250 for line in self.lines:
251 check_line = 'input line to stdout: %s' % (line)
252 self.assertTrue(check_line in output, "verify stdout line shows up in STDOUT")
253 for line in self.lines:
254 check_line = 'input line to stderr: %s' % (line)
255 self.assertTrue(check_line in error, "verify stderr line shows up in STDERR")
Johnny Chen49cb85d2011-11-28 21:39:07 +0000256
257if __name__ == '__main__':
258 import atexit
259 lldb.SBDebugger.Initialize()
260 atexit.register(lambda: lldb.SBDebugger.Terminate())
261 unittest2.main()