1*99451b44SJordan Rupprecht"""
2*99451b44SJordan RupprechtTest lldb Python API for file handles.
3*99451b44SJordan Rupprecht"""
4*99451b44SJordan Rupprecht
5*99451b44SJordan Rupprecht
6*99451b44SJordan Rupprechtimport os
7*99451b44SJordan Rupprechtimport io
8*99451b44SJordan Rupprechtimport re
9*99451b44SJordan Rupprechtimport sys
10*99451b44SJordan Rupprechtfrom contextlib import contextmanager
11*99451b44SJordan Rupprecht
12*99451b44SJordan Rupprechtimport lldb
13*99451b44SJordan Rupprechtfrom lldbsuite.test import  lldbtest
14*99451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
15*99451b44SJordan Rupprecht
16*99451b44SJordan Rupprechtclass OhNoe(Exception):
17*99451b44SJordan Rupprecht    pass
18*99451b44SJordan Rupprecht
19*99451b44SJordan Rupprechtclass BadIO(io.TextIOBase):
20*99451b44SJordan Rupprecht    @property
21*99451b44SJordan Rupprecht    def closed(self):
22*99451b44SJordan Rupprecht        return False
23*99451b44SJordan Rupprecht    def writable(self):
24*99451b44SJordan Rupprecht        return True
25*99451b44SJordan Rupprecht    def readable(self):
26*99451b44SJordan Rupprecht        return True
27*99451b44SJordan Rupprecht    def write(self, s):
28*99451b44SJordan Rupprecht        raise OhNoe('OH NOE')
29*99451b44SJordan Rupprecht    def read(self, n):
30*99451b44SJordan Rupprecht        raise OhNoe("OH NOE")
31*99451b44SJordan Rupprecht    def flush(self):
32*99451b44SJordan Rupprecht        raise OhNoe('OH NOE')
33*99451b44SJordan Rupprecht
34*99451b44SJordan Rupprecht# This class will raise an exception while it's being
35*99451b44SJordan Rupprecht# converted into a C++ object by swig
36*99451b44SJordan Rupprechtclass ReallyBadIO(io.TextIOBase):
37*99451b44SJordan Rupprecht    def fileno(self):
38*99451b44SJordan Rupprecht        return 999
39*99451b44SJordan Rupprecht    def writable(self):
40*99451b44SJordan Rupprecht        raise OhNoe("OH NOE!!!")
41*99451b44SJordan Rupprecht
42*99451b44SJordan Rupprechtclass MutableBool():
43*99451b44SJordan Rupprecht    def __init__(self, value):
44*99451b44SJordan Rupprecht        self.value = value
45*99451b44SJordan Rupprecht    def set(self, value):
46*99451b44SJordan Rupprecht        self.value = bool(value)
47*99451b44SJordan Rupprecht    def __bool__(self):
48*99451b44SJordan Rupprecht        return self.value
49*99451b44SJordan Rupprecht
50*99451b44SJordan Rupprechtclass FlushTestIO(io.StringIO):
51*99451b44SJordan Rupprecht    def __init__(self, mutable_flushed, mutable_closed):
52*99451b44SJordan Rupprecht        super(FlushTestIO, self).__init__()
53*99451b44SJordan Rupprecht        self.mut_flushed = mutable_flushed
54*99451b44SJordan Rupprecht        self.mut_closed = mutable_closed
55*99451b44SJordan Rupprecht    def close(self):
56*99451b44SJordan Rupprecht        self.mut_closed.set(True)
57*99451b44SJordan Rupprecht        return super(FlushTestIO, self).close()
58*99451b44SJordan Rupprecht    def flush(self):
59*99451b44SJordan Rupprecht        self.mut_flushed.set(True)
60*99451b44SJordan Rupprecht        return super(FlushTestIO, self).flush()
61*99451b44SJordan Rupprecht
62*99451b44SJordan Rupprecht@contextmanager
63*99451b44SJordan Rupprechtdef replace_stdout(new):
64*99451b44SJordan Rupprecht    old = sys.stdout
65*99451b44SJordan Rupprecht    sys.stdout = new
66*99451b44SJordan Rupprecht    try:
67*99451b44SJordan Rupprecht        yield
68*99451b44SJordan Rupprecht    finally:
69*99451b44SJordan Rupprecht        sys.stdout = old
70*99451b44SJordan Rupprecht
71*99451b44SJordan Rupprechtdef readStrippedLines(f):
72*99451b44SJordan Rupprecht    def i():
73*99451b44SJordan Rupprecht        for line in f:
74*99451b44SJordan Rupprecht            line = line.strip()
75*99451b44SJordan Rupprecht            if line:
76*99451b44SJordan Rupprecht                yield line
77*99451b44SJordan Rupprecht    return list(i())
78*99451b44SJordan Rupprecht
79*99451b44SJordan Rupprecht
80*99451b44SJordan Rupprechtclass FileHandleTestCase(lldbtest.TestBase):
81*99451b44SJordan Rupprecht
82*99451b44SJordan Rupprecht    NO_DEBUG_INFO_TESTCASE = True
83*99451b44SJordan Rupprecht    mydir = lldbtest.Base.compute_mydir(__file__)
84*99451b44SJordan Rupprecht
85*99451b44SJordan Rupprecht    # The way this class interacts with the debugger is different
86*99451b44SJordan Rupprecht    # than normal.   Most of these test cases will mess with the
87*99451b44SJordan Rupprecht    # debugger I/O streams, so we want a fresh debugger for each
88*99451b44SJordan Rupprecht    # test so those mutations don't interfere with each other.
89*99451b44SJordan Rupprecht    #
90*99451b44SJordan Rupprecht    # Also, the way normal tests evaluate debugger commands is
91*99451b44SJordan Rupprecht    # by using a SBCommandInterpreter directly, which captures
92*99451b44SJordan Rupprecht    # the output in a result object.   For many of tests tests
93*99451b44SJordan Rupprecht    # we want the debugger to write the  output directly to
94*99451b44SJordan Rupprecht    # its I/O streams like it would have done interactively.
95*99451b44SJordan Rupprecht    #
96*99451b44SJordan Rupprecht    # For this reason we also define handleCmd() here, even though
97*99451b44SJordan Rupprecht    # it is similar to runCmd().
98*99451b44SJordan Rupprecht
99*99451b44SJordan Rupprecht    def setUp(self):
100*99451b44SJordan Rupprecht        super(FileHandleTestCase, self).setUp()
101*99451b44SJordan Rupprecht        self.debugger = lldb.SBDebugger.Create()
102*99451b44SJordan Rupprecht        self.out_filename = self.getBuildArtifact('output')
103*99451b44SJordan Rupprecht        self.in_filename = self.getBuildArtifact('input')
104*99451b44SJordan Rupprecht
105*99451b44SJordan Rupprecht    def tearDown(self):
106*99451b44SJordan Rupprecht        lldb.SBDebugger.Destroy(self.debugger)
107*99451b44SJordan Rupprecht        super(FileHandleTestCase, self).tearDown()
108*99451b44SJordan Rupprecht        for name in (self.out_filename, self.in_filename):
109*99451b44SJordan Rupprecht            if os.path.exists(name):
110*99451b44SJordan Rupprecht                os.unlink(name)
111*99451b44SJordan Rupprecht
112*99451b44SJordan Rupprecht    # Similar to runCmd(), but this uses the per-test debugger, and it
113*99451b44SJordan Rupprecht    # supports, letting the debugger just print the results instead
114*99451b44SJordan Rupprecht    # of collecting them.
115*99451b44SJordan Rupprecht    def handleCmd(self, cmd, check=True, collect_result=True):
116*99451b44SJordan Rupprecht        assert not check or collect_result
117*99451b44SJordan Rupprecht        ret = lldb.SBCommandReturnObject()
118*99451b44SJordan Rupprecht        if collect_result:
119*99451b44SJordan Rupprecht            interpreter = self.debugger.GetCommandInterpreter()
120*99451b44SJordan Rupprecht            interpreter.HandleCommand(cmd, ret)
121*99451b44SJordan Rupprecht        else:
122*99451b44SJordan Rupprecht            self.debugger.HandleCommand(cmd)
123*99451b44SJordan Rupprecht        self.debugger.GetOutputFile().Flush()
124*99451b44SJordan Rupprecht        self.debugger.GetErrorFile().Flush()
125*99451b44SJordan Rupprecht        if collect_result and check:
126*99451b44SJordan Rupprecht            self.assertTrue(ret.Succeeded())
127*99451b44SJordan Rupprecht        return ret.GetOutput()
128*99451b44SJordan Rupprecht
129*99451b44SJordan Rupprecht
130*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
131*99451b44SJordan Rupprecht    def test_legacy_file_out_script(self):
132*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
133*99451b44SJordan Rupprecht            self.debugger.SetOutputFileHandle(f, False)
134*99451b44SJordan Rupprecht            # scripts print to output even if you capture the results
135*99451b44SJordan Rupprecht            # I'm not sure I love that behavior, but that's the way
136*99451b44SJordan Rupprecht            # it's been for a long time.  That's why this test works
137*99451b44SJordan Rupprecht            # even with collect_result=True.
138*99451b44SJordan Rupprecht            self.handleCmd('script 1+1')
139*99451b44SJordan Rupprecht            self.debugger.GetOutputFileHandle().write('FOO\n')
140*99451b44SJordan Rupprecht        lldb.SBDebugger.Destroy(self.debugger)
141*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
142*99451b44SJordan Rupprecht            self.assertEqual(readStrippedLines(f), ['2', 'FOO'])
143*99451b44SJordan Rupprecht
144*99451b44SJordan Rupprecht
145*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
146*99451b44SJordan Rupprecht    def test_legacy_file_out(self):
147*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
148*99451b44SJordan Rupprecht            self.debugger.SetOutputFileHandle(f, False)
149*99451b44SJordan Rupprecht            self.handleCmd('p/x 3735928559', collect_result=False, check=False)
150*99451b44SJordan Rupprecht        lldb.SBDebugger.Destroy(self.debugger)
151*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
152*99451b44SJordan Rupprecht            self.assertIn('deadbeef', f.read())
153*99451b44SJordan Rupprecht
154*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
155*99451b44SJordan Rupprecht    def test_legacy_file_err_with_get(self):
156*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
157*99451b44SJordan Rupprecht            self.debugger.SetErrorFileHandle(f, False)
158*99451b44SJordan Rupprecht            self.handleCmd('lolwut', check=False, collect_result=False)
159*99451b44SJordan Rupprecht            f2 = self.debugger.GetErrorFileHandle()
160*99451b44SJordan Rupprecht            f2.write('FOOBAR\n')
161*99451b44SJordan Rupprecht            f2.flush()
162*99451b44SJordan Rupprecht        lldb.SBDebugger.Destroy(self.debugger)
163*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
164*99451b44SJordan Rupprecht            errors = f.read()
165*99451b44SJordan Rupprecht            self.assertTrue(re.search(r'error:.*lolwut', errors))
166*99451b44SJordan Rupprecht            self.assertTrue(re.search(r'FOOBAR', errors))
167*99451b44SJordan Rupprecht
168*99451b44SJordan Rupprecht
169*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
170*99451b44SJordan Rupprecht    def test_legacy_file_err(self):
171*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
172*99451b44SJordan Rupprecht            self.debugger.SetErrorFileHandle(f, False)
173*99451b44SJordan Rupprecht            self.handleCmd('lol', check=False, collect_result=False)
174*99451b44SJordan Rupprecht        lldb.SBDebugger.Destroy(self.debugger)
175*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
176*99451b44SJordan Rupprecht            self.assertIn("is not a valid command", f.read())
177*99451b44SJordan Rupprecht
178*99451b44SJordan Rupprecht
179*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
180*99451b44SJordan Rupprecht    def test_legacy_file_error(self):
181*99451b44SJordan Rupprecht        debugger = self.debugger
182*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
183*99451b44SJordan Rupprecht            debugger.SetErrorFileHandle(f, False)
184*99451b44SJordan Rupprecht            self.handleCmd('lolwut', check=False, collect_result=False)
185*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
186*99451b44SJordan Rupprecht            errors = f.read()
187*99451b44SJordan Rupprecht            self.assertTrue(re.search(r'error:.*lolwut', errors))
188*99451b44SJordan Rupprecht
189*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
190*99451b44SJordan Rupprecht    def test_sbfile_type_errors(self):
191*99451b44SJordan Rupprecht        sbf = lldb.SBFile()
192*99451b44SJordan Rupprecht        self.assertRaises(Exception, sbf.Write, None)
193*99451b44SJordan Rupprecht        self.assertRaises(Exception, sbf.Read, None)
194*99451b44SJordan Rupprecht        self.assertRaises(Exception, sbf.Read, b'this bytes is not mutable')
195*99451b44SJordan Rupprecht        self.assertRaises(Exception, sbf.Write, u"ham sandwich")
196*99451b44SJordan Rupprecht        self.assertRaises(Exception, sbf.Read, u"ham sandwich")
197*99451b44SJordan Rupprecht
198*99451b44SJordan Rupprecht
199*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
200*99451b44SJordan Rupprecht    def test_sbfile_write_fileno(self):
201*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
202*99451b44SJordan Rupprecht            sbf = lldb.SBFile(f.fileno(), "w", False)
203*99451b44SJordan Rupprecht            self.assertTrue(sbf.IsValid())
204*99451b44SJordan Rupprecht            e, n = sbf.Write(b'FOO\nBAR')
205*99451b44SJordan Rupprecht            self.assertTrue(e.Success())
206*99451b44SJordan Rupprecht            self.assertEqual(n, 7)
207*99451b44SJordan Rupprecht            sbf.Close()
208*99451b44SJordan Rupprecht            self.assertFalse(sbf.IsValid())
209*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
210*99451b44SJordan Rupprecht            self.assertEqual(readStrippedLines(f), ['FOO', 'BAR'])
211*99451b44SJordan Rupprecht
212*99451b44SJordan Rupprecht
213*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
214*99451b44SJordan Rupprecht    def test_sbfile_write(self):
215*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
216*99451b44SJordan Rupprecht            sbf = lldb.SBFile(f)
217*99451b44SJordan Rupprecht            e, n = sbf.Write(b'FOO\n')
218*99451b44SJordan Rupprecht            self.assertTrue(e.Success())
219*99451b44SJordan Rupprecht            self.assertEqual(n, 4)
220*99451b44SJordan Rupprecht            sbf.Close()
221*99451b44SJordan Rupprecht            self.assertTrue(f.closed)
222*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
223*99451b44SJordan Rupprecht            self.assertEqual(f.read().strip(), 'FOO')
224*99451b44SJordan Rupprecht
225*99451b44SJordan Rupprecht
226*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
227*99451b44SJordan Rupprecht    def test_sbfile_read_fileno(self):
228*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
229*99451b44SJordan Rupprecht            f.write('FOO')
230*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
231*99451b44SJordan Rupprecht            sbf = lldb.SBFile(f.fileno(), "r", False)
232*99451b44SJordan Rupprecht            self.assertTrue(sbf.IsValid())
233*99451b44SJordan Rupprecht            buffer = bytearray(100)
234*99451b44SJordan Rupprecht            e, n = sbf.Read(buffer)
235*99451b44SJordan Rupprecht            self.assertTrue(e.Success())
236*99451b44SJordan Rupprecht            self.assertEqual(buffer[:n], b'FOO')
237*99451b44SJordan Rupprecht
238*99451b44SJordan Rupprecht
239*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
240*99451b44SJordan Rupprecht    def test_sbfile_read(self):
241*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
242*99451b44SJordan Rupprecht            f.write('foo')
243*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
244*99451b44SJordan Rupprecht            sbf = lldb.SBFile(f)
245*99451b44SJordan Rupprecht            buf = bytearray(100)
246*99451b44SJordan Rupprecht            e, n = sbf.Read(buf)
247*99451b44SJordan Rupprecht            self.assertTrue(e.Success())
248*99451b44SJordan Rupprecht            self.assertEqual(n, 3)
249*99451b44SJordan Rupprecht            self.assertEqual(buf[:n], b'foo')
250*99451b44SJordan Rupprecht            sbf.Close()
251*99451b44SJordan Rupprecht            self.assertTrue(f.closed)
252*99451b44SJordan Rupprecht
253*99451b44SJordan Rupprecht
254*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
255*99451b44SJordan Rupprecht    def test_fileno_out(self):
256*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
257*99451b44SJordan Rupprecht            sbf = lldb.SBFile(f.fileno(), "w", False)
258*99451b44SJordan Rupprecht            status = self.debugger.SetOutputFile(sbf)
259*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
260*99451b44SJordan Rupprecht            self.handleCmd('script 1+2')
261*99451b44SJordan Rupprecht            self.debugger.GetOutputFile().Write(b'quux')
262*99451b44SJordan Rupprecht
263*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
264*99451b44SJordan Rupprecht            self.assertEqual(readStrippedLines(f), ['3', 'quux'])
265*99451b44SJordan Rupprecht
266*99451b44SJordan Rupprecht
267*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
268*99451b44SJordan Rupprecht    def test_fileno_help(self):
269*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
270*99451b44SJordan Rupprecht            sbf = lldb.SBFile(f.fileno(), "w", False)
271*99451b44SJordan Rupprecht            status = self.debugger.SetOutputFile(sbf)
272*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
273*99451b44SJordan Rupprecht            self.handleCmd("help help", collect_result=False, check=False)
274*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
275*99451b44SJordan Rupprecht            self.assertTrue(re.search(r'Show a list of all debugger commands', f.read()))
276*99451b44SJordan Rupprecht
277*99451b44SJordan Rupprecht
278*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
279*99451b44SJordan Rupprecht    def test_help(self):
280*99451b44SJordan Rupprecht        debugger = self.debugger
281*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
282*99451b44SJordan Rupprecht            status = debugger.SetOutputFile(lldb.SBFile(f))
283*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
284*99451b44SJordan Rupprecht            self.handleCmd("help help", check=False, collect_result=False)
285*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
286*99451b44SJordan Rupprecht            self.assertIn('Show a list of all debugger commands', f.read())
287*99451b44SJordan Rupprecht
288*99451b44SJordan Rupprecht
289*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
290*99451b44SJordan Rupprecht    def test_immediate(self):
291*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
292*99451b44SJordan Rupprecht            ret = lldb.SBCommandReturnObject()
293*99451b44SJordan Rupprecht            ret.SetImmediateOutputFile(f)
294*99451b44SJordan Rupprecht            interpreter = self.debugger.GetCommandInterpreter()
295*99451b44SJordan Rupprecht            interpreter.HandleCommand("help help", ret)
296*99451b44SJordan Rupprecht            # make sure the file wasn't closed early.
297*99451b44SJordan Rupprecht            f.write("\nQUUX\n")
298*99451b44SJordan Rupprecht        ret = None # call destructor and flush streams
299*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
300*99451b44SJordan Rupprecht            output = f.read()
301*99451b44SJordan Rupprecht            self.assertTrue(re.search(r'Show a list of all debugger commands', output))
302*99451b44SJordan Rupprecht            self.assertTrue(re.search(r'QUUX', output))
303*99451b44SJordan Rupprecht
304*99451b44SJordan Rupprecht
305*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
306*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
307*99451b44SJordan Rupprecht    def test_immediate_string(self):
308*99451b44SJordan Rupprecht        f = io.StringIO()
309*99451b44SJordan Rupprecht        ret = lldb.SBCommandReturnObject()
310*99451b44SJordan Rupprecht        ret.SetImmediateOutputFile(f)
311*99451b44SJordan Rupprecht        interpreter = self.debugger.GetCommandInterpreter()
312*99451b44SJordan Rupprecht        interpreter.HandleCommand("help help", ret)
313*99451b44SJordan Rupprecht        # make sure the file wasn't closed early.
314*99451b44SJordan Rupprecht        f.write("\nQUUX\n")
315*99451b44SJordan Rupprecht        ret = None # call destructor and flush streams
316*99451b44SJordan Rupprecht        output = f.getvalue()
317*99451b44SJordan Rupprecht        self.assertTrue(re.search(r'Show a list of all debugger commands', output))
318*99451b44SJordan Rupprecht        self.assertTrue(re.search(r'QUUX', output))
319*99451b44SJordan Rupprecht
320*99451b44SJordan Rupprecht
321*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
322*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
323*99451b44SJordan Rupprecht    def test_immediate_sbfile_string(self):
324*99451b44SJordan Rupprecht        f = io.StringIO()
325*99451b44SJordan Rupprecht        ret = lldb.SBCommandReturnObject()
326*99451b44SJordan Rupprecht        ret.SetImmediateOutputFile(lldb.SBFile(f))
327*99451b44SJordan Rupprecht        interpreter = self.debugger.GetCommandInterpreter()
328*99451b44SJordan Rupprecht        interpreter.HandleCommand("help help", ret)
329*99451b44SJordan Rupprecht        output = f.getvalue()
330*99451b44SJordan Rupprecht        ret = None # call destructor and flush streams
331*99451b44SJordan Rupprecht        # sbfile default constructor doesn't borrow the file
332*99451b44SJordan Rupprecht        self.assertTrue(f.closed)
333*99451b44SJordan Rupprecht        self.assertTrue(re.search(r'Show a list of all debugger commands', output))
334*99451b44SJordan Rupprecht
335*99451b44SJordan Rupprecht
336*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
337*99451b44SJordan Rupprecht    def test_fileno_inout(self):
338*99451b44SJordan Rupprecht        with open(self.in_filename, 'w') as f:
339*99451b44SJordan Rupprecht            f.write("help help\n")
340*99451b44SJordan Rupprecht
341*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as outf, open(self.in_filename, 'r') as inf:
342*99451b44SJordan Rupprecht
343*99451b44SJordan Rupprecht            outsbf = lldb.SBFile(outf.fileno(), "w", False)
344*99451b44SJordan Rupprecht            status = self.debugger.SetOutputFile(outsbf)
345*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
346*99451b44SJordan Rupprecht
347*99451b44SJordan Rupprecht            insbf = lldb.SBFile(inf.fileno(), "r", False)
348*99451b44SJordan Rupprecht            status = self.debugger.SetInputFile(insbf)
349*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
350*99451b44SJordan Rupprecht
351*99451b44SJordan Rupprecht            opts = lldb.SBCommandInterpreterRunOptions()
352*99451b44SJordan Rupprecht            self.debugger.RunCommandInterpreter(True, False, opts, 0, False, False)
353*99451b44SJordan Rupprecht            self.debugger.GetOutputFile().Flush()
354*99451b44SJordan Rupprecht
355*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
356*99451b44SJordan Rupprecht            self.assertTrue(re.search(r'Show a list of all debugger commands', f.read()))
357*99451b44SJordan Rupprecht
358*99451b44SJordan Rupprecht
359*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
360*99451b44SJordan Rupprecht    def test_inout(self):
361*99451b44SJordan Rupprecht        with open(self.in_filename, 'w') as f:
362*99451b44SJordan Rupprecht            f.write("help help\n")
363*99451b44SJordan Rupprecht        with  open(self.out_filename, 'w') as outf, \
364*99451b44SJordan Rupprecht              open(self.in_filename, 'r') as inf:
365*99451b44SJordan Rupprecht            status = self.debugger.SetOutputFile(lldb.SBFile(outf))
366*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
367*99451b44SJordan Rupprecht            status = self.debugger.SetInputFile(lldb.SBFile(inf))
368*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
369*99451b44SJordan Rupprecht            opts = lldb.SBCommandInterpreterRunOptions()
370*99451b44SJordan Rupprecht            self.debugger.RunCommandInterpreter(True, False, opts, 0, False, False)
371*99451b44SJordan Rupprecht            self.debugger.GetOutputFile().Flush()
372*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
373*99451b44SJordan Rupprecht            output = f.read()
374*99451b44SJordan Rupprecht            self.assertIn('Show a list of all debugger commands', output)
375*99451b44SJordan Rupprecht
376*99451b44SJordan Rupprecht
377*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
378*99451b44SJordan Rupprecht    def test_binary_inout(self):
379*99451b44SJordan Rupprecht        debugger = self.debugger
380*99451b44SJordan Rupprecht        with open(self.in_filename, 'w') as f:
381*99451b44SJordan Rupprecht            f.write("help help\n")
382*99451b44SJordan Rupprecht        with  open(self.out_filename, 'wb') as outf, \
383*99451b44SJordan Rupprecht              open(self.in_filename, 'rb') as inf:
384*99451b44SJordan Rupprecht            status = debugger.SetOutputFile(lldb.SBFile(outf))
385*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
386*99451b44SJordan Rupprecht            status = debugger.SetInputFile(lldb.SBFile(inf))
387*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
388*99451b44SJordan Rupprecht            opts = lldb.SBCommandInterpreterRunOptions()
389*99451b44SJordan Rupprecht            debugger.RunCommandInterpreter(True, False, opts, 0, False, False)
390*99451b44SJordan Rupprecht            debugger.GetOutputFile().Flush()
391*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
392*99451b44SJordan Rupprecht            output = f.read()
393*99451b44SJordan Rupprecht            self.assertIn('Show a list of all debugger commands', output)
394*99451b44SJordan Rupprecht
395*99451b44SJordan Rupprecht
396*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
397*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
398*99451b44SJordan Rupprecht    def test_string_inout(self):
399*99451b44SJordan Rupprecht        inf = io.StringIO("help help\np/x ~0\n")
400*99451b44SJordan Rupprecht        outf = io.StringIO()
401*99451b44SJordan Rupprecht        status = self.debugger.SetOutputFile(lldb.SBFile(outf))
402*99451b44SJordan Rupprecht        self.assertTrue(status.Success())
403*99451b44SJordan Rupprecht        status = self.debugger.SetInputFile(lldb.SBFile(inf))
404*99451b44SJordan Rupprecht        self.assertTrue(status.Success())
405*99451b44SJordan Rupprecht        opts = lldb.SBCommandInterpreterRunOptions()
406*99451b44SJordan Rupprecht        self.debugger.RunCommandInterpreter(True, False, opts, 0, False, False)
407*99451b44SJordan Rupprecht        self.debugger.GetOutputFile().Flush()
408*99451b44SJordan Rupprecht        output = outf.getvalue()
409*99451b44SJordan Rupprecht        self.assertIn('Show a list of all debugger commands', output)
410*99451b44SJordan Rupprecht        self.assertIn('0xfff', output)
411*99451b44SJordan Rupprecht
412*99451b44SJordan Rupprecht
413*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
414*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
415*99451b44SJordan Rupprecht    def test_bytes_inout(self):
416*99451b44SJordan Rupprecht        inf = io.BytesIO(b"help help\nhelp b\n")
417*99451b44SJordan Rupprecht        outf = io.BytesIO()
418*99451b44SJordan Rupprecht        status = self.debugger.SetOutputFile(lldb.SBFile(outf))
419*99451b44SJordan Rupprecht        self.assertTrue(status.Success())
420*99451b44SJordan Rupprecht        status = self.debugger.SetInputFile(lldb.SBFile(inf))
421*99451b44SJordan Rupprecht        self.assertTrue(status.Success())
422*99451b44SJordan Rupprecht        opts = lldb.SBCommandInterpreterRunOptions()
423*99451b44SJordan Rupprecht        self.debugger.RunCommandInterpreter(True, False, opts, 0, False, False)
424*99451b44SJordan Rupprecht        self.debugger.GetOutputFile().Flush()
425*99451b44SJordan Rupprecht        output = outf.getvalue()
426*99451b44SJordan Rupprecht        self.assertIn(b'Show a list of all debugger commands', output)
427*99451b44SJordan Rupprecht        self.assertIn(b'Set a breakpoint', output)
428*99451b44SJordan Rupprecht
429*99451b44SJordan Rupprecht
430*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
431*99451b44SJordan Rupprecht    def test_fileno_error(self):
432*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
433*99451b44SJordan Rupprecht
434*99451b44SJordan Rupprecht            sbf = lldb.SBFile(f.fileno(), 'w', False)
435*99451b44SJordan Rupprecht            status = self.debugger.SetErrorFile(sbf)
436*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
437*99451b44SJordan Rupprecht
438*99451b44SJordan Rupprecht            self.handleCmd('lolwut', check=False, collect_result=False)
439*99451b44SJordan Rupprecht
440*99451b44SJordan Rupprecht            self.debugger.GetErrorFile().Write(b'\nzork\n')
441*99451b44SJordan Rupprecht
442*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
443*99451b44SJordan Rupprecht            errors = f.read()
444*99451b44SJordan Rupprecht            self.assertTrue(re.search(r'error:.*lolwut', errors))
445*99451b44SJordan Rupprecht            self.assertTrue(re.search(r'zork', errors))
446*99451b44SJordan Rupprecht
447*99451b44SJordan Rupprecht
448*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
449*99451b44SJordan Rupprecht    def test_replace_stdout(self):
450*99451b44SJordan Rupprecht        f = io.StringIO()
451*99451b44SJordan Rupprecht        with replace_stdout(f):
452*99451b44SJordan Rupprecht            self.assertEqual(sys.stdout, f)
453*99451b44SJordan Rupprecht            self.handleCmd('script sys.stdout.write("lol")',
454*99451b44SJordan Rupprecht                collect_result=False, check=False)
455*99451b44SJordan Rupprecht            self.assertEqual(sys.stdout, f)
456*99451b44SJordan Rupprecht
457*99451b44SJordan Rupprecht
458*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
459*99451b44SJordan Rupprecht    def test_replace_stdout_with_nonfile(self):
460*99451b44SJordan Rupprecht        debugger = self.debugger
461*99451b44SJordan Rupprecht        f = io.StringIO()
462*99451b44SJordan Rupprecht        with replace_stdout(f):
463*99451b44SJordan Rupprecht            class Nothing():
464*99451b44SJordan Rupprecht                pass
465*99451b44SJordan Rupprecht            with replace_stdout(Nothing):
466*99451b44SJordan Rupprecht                self.assertEqual(sys.stdout, Nothing)
467*99451b44SJordan Rupprecht                self.handleCmd('script sys.stdout.write("lol")',
468*99451b44SJordan Rupprecht                    check=False, collect_result=False)
469*99451b44SJordan Rupprecht                self.assertEqual(sys.stdout, Nothing)
470*99451b44SJordan Rupprecht            sys.stdout.write(u"FOO")
471*99451b44SJordan Rupprecht        self.assertEqual(f.getvalue(), "FOO")
472*99451b44SJordan Rupprecht
473*99451b44SJordan Rupprecht
474*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
475*99451b44SJordan Rupprecht    def test_sbfile_write_borrowed(self):
476*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
477*99451b44SJordan Rupprecht            sbf = lldb.SBFile.Create(f, borrow=True)
478*99451b44SJordan Rupprecht            e, n = sbf.Write(b'FOO')
479*99451b44SJordan Rupprecht            self.assertTrue(e.Success())
480*99451b44SJordan Rupprecht            self.assertEqual(n, 3)
481*99451b44SJordan Rupprecht            sbf.Close()
482*99451b44SJordan Rupprecht            self.assertFalse(f.closed)
483*99451b44SJordan Rupprecht            f.write('BAR\n')
484*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
485*99451b44SJordan Rupprecht            self.assertEqual(f.read().strip(), 'FOOBAR')
486*99451b44SJordan Rupprecht
487*99451b44SJordan Rupprecht
488*99451b44SJordan Rupprecht
489*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
490*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
491*99451b44SJordan Rupprecht    def test_sbfile_write_forced(self):
492*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
493*99451b44SJordan Rupprecht            written = MutableBool(False)
494*99451b44SJordan Rupprecht            orig_write = f.write
495*99451b44SJordan Rupprecht            def mywrite(x):
496*99451b44SJordan Rupprecht                written.set(True)
497*99451b44SJordan Rupprecht                return orig_write(x)
498*99451b44SJordan Rupprecht            f.write = mywrite
499*99451b44SJordan Rupprecht            sbf = lldb.SBFile.Create(f, force_io_methods=True)
500*99451b44SJordan Rupprecht            e, n = sbf.Write(b'FOO')
501*99451b44SJordan Rupprecht            self.assertTrue(written)
502*99451b44SJordan Rupprecht            self.assertTrue(e.Success())
503*99451b44SJordan Rupprecht            self.assertEqual(n, 3)
504*99451b44SJordan Rupprecht            sbf.Close()
505*99451b44SJordan Rupprecht            self.assertTrue(f.closed)
506*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
507*99451b44SJordan Rupprecht            self.assertEqual(f.read().strip(), 'FOO')
508*99451b44SJordan Rupprecht
509*99451b44SJordan Rupprecht
510*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
511*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
512*99451b44SJordan Rupprecht    def test_sbfile_write_forced_borrowed(self):
513*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
514*99451b44SJordan Rupprecht            written = MutableBool(False)
515*99451b44SJordan Rupprecht            orig_write = f.write
516*99451b44SJordan Rupprecht            def mywrite(x):
517*99451b44SJordan Rupprecht                written.set(True)
518*99451b44SJordan Rupprecht                return orig_write(x)
519*99451b44SJordan Rupprecht            f.write = mywrite
520*99451b44SJordan Rupprecht            sbf = lldb.SBFile.Create(f, borrow=True, force_io_methods=True)
521*99451b44SJordan Rupprecht            e, n = sbf.Write(b'FOO')
522*99451b44SJordan Rupprecht            self.assertTrue(written)
523*99451b44SJordan Rupprecht            self.assertTrue(e.Success())
524*99451b44SJordan Rupprecht            self.assertEqual(n, 3)
525*99451b44SJordan Rupprecht            sbf.Close()
526*99451b44SJordan Rupprecht            self.assertFalse(f.closed)
527*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
528*99451b44SJordan Rupprecht            self.assertEqual(f.read().strip(), 'FOO')
529*99451b44SJordan Rupprecht
530*99451b44SJordan Rupprecht
531*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
532*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
533*99451b44SJordan Rupprecht    def test_sbfile_write_string(self):
534*99451b44SJordan Rupprecht        f = io.StringIO()
535*99451b44SJordan Rupprecht        sbf = lldb.SBFile(f)
536*99451b44SJordan Rupprecht        e, n = sbf.Write(b'FOO')
537*99451b44SJordan Rupprecht        self.assertEqual(f.getvalue().strip(), "FOO")
538*99451b44SJordan Rupprecht        self.assertTrue(e.Success())
539*99451b44SJordan Rupprecht        self.assertEqual(n, 3)
540*99451b44SJordan Rupprecht        sbf.Close()
541*99451b44SJordan Rupprecht        self.assertTrue(f.closed)
542*99451b44SJordan Rupprecht
543*99451b44SJordan Rupprecht
544*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
545*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
546*99451b44SJordan Rupprecht    def test_string_out(self):
547*99451b44SJordan Rupprecht        f = io.StringIO()
548*99451b44SJordan Rupprecht        status = self.debugger.SetOutputFile(f)
549*99451b44SJordan Rupprecht        self.assertTrue(status.Success())
550*99451b44SJordan Rupprecht        self.handleCmd("script 'foobar'")
551*99451b44SJordan Rupprecht        self.assertEqual(f.getvalue().strip(), "'foobar'")
552*99451b44SJordan Rupprecht
553*99451b44SJordan Rupprecht
554*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
555*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
556*99451b44SJordan Rupprecht    def test_string_error(self):
557*99451b44SJordan Rupprecht        f = io.StringIO()
558*99451b44SJordan Rupprecht        debugger = self.debugger
559*99451b44SJordan Rupprecht        status = debugger.SetErrorFile(f)
560*99451b44SJordan Rupprecht        self.assertTrue(status.Success())
561*99451b44SJordan Rupprecht        self.handleCmd('lolwut', check=False, collect_result=False)
562*99451b44SJordan Rupprecht        errors = f.getvalue()
563*99451b44SJordan Rupprecht        self.assertTrue(re.search(r'error:.*lolwut', errors))
564*99451b44SJordan Rupprecht
565*99451b44SJordan Rupprecht
566*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
567*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
568*99451b44SJordan Rupprecht    def test_sbfile_write_bytes(self):
569*99451b44SJordan Rupprecht        f = io.BytesIO()
570*99451b44SJordan Rupprecht        sbf = lldb.SBFile(f)
571*99451b44SJordan Rupprecht        e, n = sbf.Write(b'FOO')
572*99451b44SJordan Rupprecht        self.assertEqual(f.getvalue().strip(), b"FOO")
573*99451b44SJordan Rupprecht        self.assertTrue(e.Success())
574*99451b44SJordan Rupprecht        self.assertEqual(n, 3)
575*99451b44SJordan Rupprecht        sbf.Close()
576*99451b44SJordan Rupprecht        self.assertTrue(f.closed)
577*99451b44SJordan Rupprecht
578*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
579*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
580*99451b44SJordan Rupprecht    def test_sbfile_read_string(self):
581*99451b44SJordan Rupprecht        f = io.StringIO('zork')
582*99451b44SJordan Rupprecht        sbf = lldb.SBFile(f)
583*99451b44SJordan Rupprecht        buf = bytearray(100)
584*99451b44SJordan Rupprecht        e, n = sbf.Read(buf)
585*99451b44SJordan Rupprecht        self.assertTrue(e.Success())
586*99451b44SJordan Rupprecht        self.assertEqual(buf[:n], b'zork')
587*99451b44SJordan Rupprecht
588*99451b44SJordan Rupprecht
589*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
590*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
591*99451b44SJordan Rupprecht    def test_sbfile_read_string_one_byte(self):
592*99451b44SJordan Rupprecht        f = io.StringIO('z')
593*99451b44SJordan Rupprecht        sbf = lldb.SBFile(f)
594*99451b44SJordan Rupprecht        buf = bytearray(1)
595*99451b44SJordan Rupprecht        e, n = sbf.Read(buf)
596*99451b44SJordan Rupprecht        self.assertTrue(e.Fail())
597*99451b44SJordan Rupprecht        self.assertEqual(n, 0)
598*99451b44SJordan Rupprecht        self.assertEqual(e.GetCString(), "can't read less than 6 bytes from a utf8 text stream")
599*99451b44SJordan Rupprecht
600*99451b44SJordan Rupprecht
601*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
602*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
603*99451b44SJordan Rupprecht    def test_sbfile_read_bytes(self):
604*99451b44SJordan Rupprecht        f = io.BytesIO(b'zork')
605*99451b44SJordan Rupprecht        sbf = lldb.SBFile(f)
606*99451b44SJordan Rupprecht        buf = bytearray(100)
607*99451b44SJordan Rupprecht        e, n = sbf.Read(buf)
608*99451b44SJordan Rupprecht        self.assertTrue(e.Success())
609*99451b44SJordan Rupprecht        self.assertEqual(buf[:n], b'zork')
610*99451b44SJordan Rupprecht
611*99451b44SJordan Rupprecht
612*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
613*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
614*99451b44SJordan Rupprecht    def test_sbfile_out(self):
615*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
616*99451b44SJordan Rupprecht            sbf = lldb.SBFile(f)
617*99451b44SJordan Rupprecht            status = self.debugger.SetOutputFile(sbf)
618*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
619*99451b44SJordan Rupprecht            self.handleCmd('script 2+2')
620*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
621*99451b44SJordan Rupprecht            self.assertEqual(f.read().strip(), '4')
622*99451b44SJordan Rupprecht
623*99451b44SJordan Rupprecht
624*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
625*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
626*99451b44SJordan Rupprecht    def test_file_out(self):
627*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
628*99451b44SJordan Rupprecht            status = self.debugger.SetOutputFile(f)
629*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
630*99451b44SJordan Rupprecht            self.handleCmd('script 2+2')
631*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
632*99451b44SJordan Rupprecht            self.assertEqual(f.read().strip(), '4')
633*99451b44SJordan Rupprecht
634*99451b44SJordan Rupprecht
635*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
636*99451b44SJordan Rupprecht    def test_sbfile_error(self):
637*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
638*99451b44SJordan Rupprecht            sbf = lldb.SBFile(f)
639*99451b44SJordan Rupprecht            status = self.debugger.SetErrorFile(sbf)
640*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
641*99451b44SJordan Rupprecht            self.handleCmd('lolwut', check=False, collect_result=False)
642*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
643*99451b44SJordan Rupprecht            errors = f.read()
644*99451b44SJordan Rupprecht            self.assertTrue(re.search(r'error:.*lolwut', errors))
645*99451b44SJordan Rupprecht
646*99451b44SJordan Rupprecht
647*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
648*99451b44SJordan Rupprecht    def test_file_error(self):
649*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
650*99451b44SJordan Rupprecht            status = self.debugger.SetErrorFile(f)
651*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
652*99451b44SJordan Rupprecht            self.handleCmd('lolwut', check=False, collect_result=False)
653*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
654*99451b44SJordan Rupprecht            errors = f.read()
655*99451b44SJordan Rupprecht            self.assertTrue(re.search(r'error:.*lolwut', errors))
656*99451b44SJordan Rupprecht
657*99451b44SJordan Rupprecht
658*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
659*99451b44SJordan Rupprecht    def test_exceptions(self):
660*99451b44SJordan Rupprecht        self.assertRaises(Exception, lldb.SBFile, None)
661*99451b44SJordan Rupprecht        self.assertRaises(Exception, lldb.SBFile, "ham sandwich")
662*99451b44SJordan Rupprecht        if sys.version_info[0] < 3:
663*99451b44SJordan Rupprecht            self.assertRaises(Exception, lldb.SBFile, ReallyBadIO())
664*99451b44SJordan Rupprecht        else:
665*99451b44SJordan Rupprecht            self.assertRaises(OhNoe, lldb.SBFile, ReallyBadIO())
666*99451b44SJordan Rupprecht            error, n = lldb.SBFile(BadIO()).Write(b"FOO")
667*99451b44SJordan Rupprecht            self.assertEqual(n, 0)
668*99451b44SJordan Rupprecht            self.assertTrue(error.Fail())
669*99451b44SJordan Rupprecht            self.assertIn('OH NOE', error.GetCString())
670*99451b44SJordan Rupprecht            error, n = lldb.SBFile(BadIO()).Read(bytearray(100))
671*99451b44SJordan Rupprecht            self.assertEqual(n, 0)
672*99451b44SJordan Rupprecht            self.assertTrue(error.Fail())
673*99451b44SJordan Rupprecht            self.assertIn('OH NOE', error.GetCString())
674*99451b44SJordan Rupprecht
675*99451b44SJordan Rupprecht
676*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
677*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
678*99451b44SJordan Rupprecht    def test_exceptions_logged(self):
679*99451b44SJordan Rupprecht        messages = list()
680*99451b44SJordan Rupprecht        self.debugger.SetLoggingCallback(messages.append)
681*99451b44SJordan Rupprecht        self.handleCmd('log enable lldb script')
682*99451b44SJordan Rupprecht        self.debugger.SetOutputFile(lldb.SBFile(BadIO()))
683*99451b44SJordan Rupprecht        self.handleCmd('script 1+1')
684*99451b44SJordan Rupprecht        self.assertTrue(any('OH NOE' in msg for msg in messages))
685*99451b44SJordan Rupprecht
686*99451b44SJordan Rupprecht
687*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
688*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
689*99451b44SJordan Rupprecht    def test_flush(self):
690*99451b44SJordan Rupprecht        flushed = MutableBool(False)
691*99451b44SJordan Rupprecht        closed = MutableBool(False)
692*99451b44SJordan Rupprecht        f = FlushTestIO(flushed, closed)
693*99451b44SJordan Rupprecht        self.assertFalse(flushed)
694*99451b44SJordan Rupprecht        self.assertFalse(closed)
695*99451b44SJordan Rupprecht        sbf = lldb.SBFile(f)
696*99451b44SJordan Rupprecht        self.assertFalse(flushed)
697*99451b44SJordan Rupprecht        self.assertFalse(closed)
698*99451b44SJordan Rupprecht        sbf = None
699*99451b44SJordan Rupprecht        self.assertFalse(flushed)
700*99451b44SJordan Rupprecht        self.assertTrue(closed)
701*99451b44SJordan Rupprecht        self.assertTrue(f.closed)
702*99451b44SJordan Rupprecht
703*99451b44SJordan Rupprecht        flushed = MutableBool(False)
704*99451b44SJordan Rupprecht        closed = MutableBool(False)
705*99451b44SJordan Rupprecht        f = FlushTestIO(flushed, closed)
706*99451b44SJordan Rupprecht        self.assertFalse(flushed)
707*99451b44SJordan Rupprecht        self.assertFalse(closed)
708*99451b44SJordan Rupprecht        sbf = lldb.SBFile.Create(f, borrow=True)
709*99451b44SJordan Rupprecht        self.assertFalse(flushed)
710*99451b44SJordan Rupprecht        self.assertFalse(closed)
711*99451b44SJordan Rupprecht        sbf = None
712*99451b44SJordan Rupprecht        self.assertTrue(flushed)
713*99451b44SJordan Rupprecht        self.assertFalse(closed)
714*99451b44SJordan Rupprecht        self.assertFalse(f.closed)
715*99451b44SJordan Rupprecht
716*99451b44SJordan Rupprecht
717*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
718*99451b44SJordan Rupprecht    def test_fileno_flush(self):
719*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
720*99451b44SJordan Rupprecht            f.write("foo")
721*99451b44SJordan Rupprecht            sbf = lldb.SBFile(f)
722*99451b44SJordan Rupprecht            sbf.Write(b'bar')
723*99451b44SJordan Rupprecht            sbf = None
724*99451b44SJordan Rupprecht            self.assertTrue(f.closed)
725*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
726*99451b44SJordan Rupprecht            self.assertEqual(f.read(), 'foobar')
727*99451b44SJordan Rupprecht
728*99451b44SJordan Rupprecht        with open(self.out_filename, 'w+') as f:
729*99451b44SJordan Rupprecht            f.write("foo")
730*99451b44SJordan Rupprecht            sbf = lldb.SBFile.Create(f, borrow=True)
731*99451b44SJordan Rupprecht            sbf.Write(b'bar')
732*99451b44SJordan Rupprecht            sbf = None
733*99451b44SJordan Rupprecht            self.assertFalse(f.closed)
734*99451b44SJordan Rupprecht            f.seek(0)
735*99451b44SJordan Rupprecht            self.assertEqual(f.read(), 'foobar')
736*99451b44SJordan Rupprecht
737*99451b44SJordan Rupprecht
738*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
739*99451b44SJordan Rupprecht    def test_close(self):
740*99451b44SJordan Rupprecht        debugger = self.debugger
741*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
742*99451b44SJordan Rupprecht            status = debugger.SetOutputFile(f)
743*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
744*99451b44SJordan Rupprecht            self.handleCmd("help help", check=False, collect_result=False)
745*99451b44SJordan Rupprecht            # make sure the file wasn't closed early.
746*99451b44SJordan Rupprecht            f.write("\nZAP\n")
747*99451b44SJordan Rupprecht            lldb.SBDebugger.Destroy(debugger)
748*99451b44SJordan Rupprecht            # check that output file was closed when debugger was destroyed.
749*99451b44SJordan Rupprecht            with self.assertRaises(ValueError):
750*99451b44SJordan Rupprecht                f.write("\nQUUX\n")
751*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
752*99451b44SJordan Rupprecht            output = f.read()
753*99451b44SJordan Rupprecht            self.assertTrue(re.search(r'Show a list of all debugger commands', output))
754*99451b44SJordan Rupprecht            self.assertTrue(re.search(r'ZAP', output))
755*99451b44SJordan Rupprecht
756*99451b44SJordan Rupprecht
757*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
758*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
759*99451b44SJordan Rupprecht    def test_stdout(self):
760*99451b44SJordan Rupprecht        f = io.StringIO()
761*99451b44SJordan Rupprecht        status = self.debugger.SetOutputFile(f)
762*99451b44SJordan Rupprecht        self.assertTrue(status.Success())
763*99451b44SJordan Rupprecht        self.handleCmd(r"script sys.stdout.write('foobar\n')")
764*99451b44SJordan Rupprecht        self.assertEqual(f.getvalue().strip().split(), ["foobar", "7"])
765*99451b44SJordan Rupprecht
766*99451b44SJordan Rupprecht
767*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
768*99451b44SJordan Rupprecht    def test_stdout_file(self):
769*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
770*99451b44SJordan Rupprecht            status = self.debugger.SetOutputFile(f)
771*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
772*99451b44SJordan Rupprecht            self.handleCmd(r"script sys.stdout.write('foobar\n')")
773*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
774*99451b44SJordan Rupprecht            # In python2 sys.stdout.write() returns None, which
775*99451b44SJordan Rupprecht            # the REPL will ignore, but in python3 it will
776*99451b44SJordan Rupprecht            # return the number of bytes written, which the REPL
777*99451b44SJordan Rupprecht            # will print out.
778*99451b44SJordan Rupprecht            lines = [x for x in f.read().strip().split() if x != "7"]
779*99451b44SJordan Rupprecht            self.assertEqual(lines, ["foobar"])
780*99451b44SJordan Rupprecht
781*99451b44SJordan Rupprecht
782*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
783*99451b44SJordan Rupprecht    @skipIf(py_version=['<', (3,)])
784*99451b44SJordan Rupprecht    def test_identity(self):
785*99451b44SJordan Rupprecht
786*99451b44SJordan Rupprecht        f = io.StringIO()
787*99451b44SJordan Rupprecht        sbf = lldb.SBFile(f)
788*99451b44SJordan Rupprecht        self.assertTrue(f is sbf.GetFile())
789*99451b44SJordan Rupprecht        sbf.Close()
790*99451b44SJordan Rupprecht        self.assertTrue(f.closed)
791*99451b44SJordan Rupprecht
792*99451b44SJordan Rupprecht        f = io.StringIO()
793*99451b44SJordan Rupprecht        sbf = lldb.SBFile.Create(f, borrow=True)
794*99451b44SJordan Rupprecht        self.assertTrue(f is sbf.GetFile())
795*99451b44SJordan Rupprecht        sbf.Close()
796*99451b44SJordan Rupprecht        self.assertFalse(f.closed)
797*99451b44SJordan Rupprecht
798*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
799*99451b44SJordan Rupprecht            sbf = lldb.SBFile(f)
800*99451b44SJordan Rupprecht            self.assertTrue(f is sbf.GetFile())
801*99451b44SJordan Rupprecht            sbf.Close()
802*99451b44SJordan Rupprecht            self.assertTrue(f.closed)
803*99451b44SJordan Rupprecht
804*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
805*99451b44SJordan Rupprecht            sbf = lldb.SBFile.Create(f, borrow=True)
806*99451b44SJordan Rupprecht            self.assertFalse(f is sbf.GetFile())
807*99451b44SJordan Rupprecht            sbf.Write(b"foobar\n")
808*99451b44SJordan Rupprecht            self.assertEqual(f.fileno(), sbf.GetFile().fileno())
809*99451b44SJordan Rupprecht            sbf.Close()
810*99451b44SJordan Rupprecht            self.assertFalse(f.closed)
811*99451b44SJordan Rupprecht
812*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
813*99451b44SJordan Rupprecht            self.assertEqual("foobar", f.read().strip())
814*99451b44SJordan Rupprecht
815*99451b44SJordan Rupprecht        with open(self.out_filename, 'wb') as f:
816*99451b44SJordan Rupprecht            sbf = lldb.SBFile.Create(f, borrow=True, force_io_methods=True)
817*99451b44SJordan Rupprecht            self.assertTrue(f is sbf.GetFile())
818*99451b44SJordan Rupprecht            sbf.Write(b"foobar\n")
819*99451b44SJordan Rupprecht            self.assertEqual(f.fileno(), sbf.GetFile().fileno())
820*99451b44SJordan Rupprecht            sbf.Close()
821*99451b44SJordan Rupprecht            self.assertFalse(f.closed)
822*99451b44SJordan Rupprecht
823*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
824*99451b44SJordan Rupprecht            self.assertEqual("foobar", f.read().strip())
825*99451b44SJordan Rupprecht
826*99451b44SJordan Rupprecht        with open(self.out_filename, 'wb') as f:
827*99451b44SJordan Rupprecht            sbf = lldb.SBFile.Create(f, force_io_methods=True)
828*99451b44SJordan Rupprecht            self.assertTrue(f is sbf.GetFile())
829*99451b44SJordan Rupprecht            sbf.Write(b"foobar\n")
830*99451b44SJordan Rupprecht            self.assertEqual(f.fileno(), sbf.GetFile().fileno())
831*99451b44SJordan Rupprecht            sbf.Close()
832*99451b44SJordan Rupprecht            self.assertTrue(f.closed)
833*99451b44SJordan Rupprecht
834*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
835*99451b44SJordan Rupprecht            self.assertEqual("foobar", f.read().strip())
836*99451b44SJordan Rupprecht
837*99451b44SJordan Rupprecht
838*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
839*99451b44SJordan Rupprecht    def test_back_and_forth(self):
840*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
841*99451b44SJordan Rupprecht            # at each step here we're borrowing the file, so we have to keep
842*99451b44SJordan Rupprecht            # them all alive until the end.
843*99451b44SJordan Rupprecht            sbf = lldb.SBFile.Create(f, borrow=True)
844*99451b44SJordan Rupprecht            def i(sbf):
845*99451b44SJordan Rupprecht                for i in range(10):
846*99451b44SJordan Rupprecht                    f = sbf.GetFile()
847*99451b44SJordan Rupprecht                    self.assertEqual(f.mode, "w")
848*99451b44SJordan Rupprecht                    yield f
849*99451b44SJordan Rupprecht                    sbf = lldb.SBFile.Create(f, borrow=True)
850*99451b44SJordan Rupprecht                    yield sbf
851*99451b44SJordan Rupprecht                    sbf.Write(str(i).encode('ascii') + b"\n")
852*99451b44SJordan Rupprecht            files = list(i(sbf))
853*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
854*99451b44SJordan Rupprecht            self.assertEqual(list(range(10)), list(map(int, f.read().strip().split())))
855*99451b44SJordan Rupprecht
856*99451b44SJordan Rupprecht
857*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
858*99451b44SJordan Rupprecht    def test_set_filehandle_none(self):
859*99451b44SJordan Rupprecht        self.assertRaises(Exception, self.debugger.SetOutputFile, None)
860*99451b44SJordan Rupprecht        self.assertRaises(Exception, self.debugger.SetOutputFile, "ham sandwich")
861*99451b44SJordan Rupprecht        self.assertRaises(Exception, self.debugger.SetOutputFileHandle, "ham sandwich")
862*99451b44SJordan Rupprecht        self.assertRaises(Exception, self.debugger.SetInputFile, None)
863*99451b44SJordan Rupprecht        self.assertRaises(Exception, self.debugger.SetInputFile, "ham sandwich")
864*99451b44SJordan Rupprecht        self.assertRaises(Exception, self.debugger.SetInputFileHandle, "ham sandwich")
865*99451b44SJordan Rupprecht        self.assertRaises(Exception, self.debugger.SetErrorFile, None)
866*99451b44SJordan Rupprecht        self.assertRaises(Exception, self.debugger.SetErrorFile, "ham sandwich")
867*99451b44SJordan Rupprecht        self.assertRaises(Exception, self.debugger.SetErrorFileHandle, "ham sandwich")
868*99451b44SJordan Rupprecht
869*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
870*99451b44SJordan Rupprecht            status = self.debugger.SetOutputFile(f)
871*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
872*99451b44SJordan Rupprecht            status = self.debugger.SetErrorFile(f)
873*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
874*99451b44SJordan Rupprecht            self.debugger.SetOutputFileHandle(None, False)
875*99451b44SJordan Rupprecht            self.debugger.SetErrorFileHandle(None, False)
876*99451b44SJordan Rupprecht            sbf = self.debugger.GetOutputFile()
877*99451b44SJordan Rupprecht            if sys.version_info.major >= 3:
878*99451b44SJordan Rupprecht                # python 2 lacks PyFile_FromFd, so GetFile() will
879*99451b44SJordan Rupprecht                # have to duplicate the file descriptor and make a FILE*
880*99451b44SJordan Rupprecht                # in order to convert a NativeFile it back to a python
881*99451b44SJordan Rupprecht                # file.
882*99451b44SJordan Rupprecht                self.assertEqual(sbf.GetFile().fileno(), 1)
883*99451b44SJordan Rupprecht            sbf = self.debugger.GetErrorFile()
884*99451b44SJordan Rupprecht            if sys.version_info.major >= 3:
885*99451b44SJordan Rupprecht                self.assertEqual(sbf.GetFile().fileno(), 2)
886*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
887*99451b44SJordan Rupprecht            status = self.debugger.SetInputFile(f)
888*99451b44SJordan Rupprecht            self.assertTrue(status.Success())
889*99451b44SJordan Rupprecht            self.debugger.SetInputFileHandle(None, False)
890*99451b44SJordan Rupprecht            sbf = self.debugger.GetInputFile()
891*99451b44SJordan Rupprecht            if sys.version_info.major >= 3:
892*99451b44SJordan Rupprecht                self.assertEqual(sbf.GetFile().fileno(), 0)
893*99451b44SJordan Rupprecht
894*99451b44SJordan Rupprecht
895*99451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
896*99451b44SJordan Rupprecht    def test_sbstream(self):
897*99451b44SJordan Rupprecht
898*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
899*99451b44SJordan Rupprecht            stream = lldb.SBStream()
900*99451b44SJordan Rupprecht            stream.RedirectToFile(f)
901*99451b44SJordan Rupprecht            stream.Print("zork")
902*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
903*99451b44SJordan Rupprecht            self.assertEqual(f.read().strip(), "zork")
904*99451b44SJordan Rupprecht
905*99451b44SJordan Rupprecht        with open(self.out_filename, 'w') as f:
906*99451b44SJordan Rupprecht            stream = lldb.SBStream()
907*99451b44SJordan Rupprecht            stream.RedirectToFileHandle(f, True)
908*99451b44SJordan Rupprecht            stream.Print("Yendor")
909*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
910*99451b44SJordan Rupprecht            self.assertEqual(f.read().strip(), "Yendor")
911*99451b44SJordan Rupprecht
912*99451b44SJordan Rupprecht        stream = lldb.SBStream()
913*99451b44SJordan Rupprecht        f = open(self.out_filename,  'w')
914*99451b44SJordan Rupprecht        stream.RedirectToFile(lldb.SBFile.Create(f, borrow=False))
915*99451b44SJordan Rupprecht        stream.Print("Frobozz")
916*99451b44SJordan Rupprecht        stream = None
917*99451b44SJordan Rupprecht        self.assertTrue(f.closed)
918*99451b44SJordan Rupprecht        with open(self.out_filename, 'r') as f:
919*99451b44SJordan Rupprecht            self.assertEqual(f.read().strip(), "Frobozz")
920