1"""
2Test sending SIGINT to the embedded Python REPL.
3"""
4
5import os
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test.lldbpexpect import PExpectTest
11
12class TestCase(PExpectTest):
13
14    mydir = TestBase.compute_mydir(__file__)
15
16    def start_python_repl(self):
17        """ Starts up the embedded Python REPL."""
18        self.launch()
19        # Start the embedded Python REPL via the 'script' command.
20        self.child.send("script -l python --\n")
21        # Wait for the Python REPL prompt.
22        self.child.expect(">>>")
23
24    # PExpect uses many timeouts internally and doesn't play well
25    # under ASAN on a loaded machine..
26    @skipIfAsan
27    @skipIfWindows
28    @skipIf(oslist=["linux"], archs=["arm", "aarch64"])
29    def test_while_evaluating_code(self):
30        """ Tests SIGINT handling while Python code is being evaluated."""
31        self.start_python_repl()
32
33        # Start a long-running command that we try to abort with SIGINT.
34        # Note that we dont actually wait 10000s in this code as pexpect or
35        # lit will kill the test way before that.
36        self.child.send("import time; print('running' + 'now'); time.sleep(10000);\n")
37
38        # Make sure the command is actually being evaluated at the moment by
39        # looking at the string that the command is printing.
40        # Don't check for a needle that also occurs in the program itself to
41        # prevent that echoing will make this check pass unintentionally.
42        self.child.expect("runningnow")
43
44        # Send SIGINT to the LLDB process.
45        self.child.sendintr()
46
47        # This should get transformed to a KeyboardInterrupt which is the same
48        # behaviour as the standalone Python REPL. It should also interrupt
49        # the evaluation of our sleep statement.
50        self.child.expect("KeyboardInterrupt")
51        # Send EOF to quit the Python REPL.
52        self.child.sendeof()
53
54        self.quit()
55
56    # PExpect uses many timeouts internally and doesn't play well
57    # under ASAN on a loaded machine..
58    @skipIfAsan
59    # FIXME: On Linux the Python code that reads from stdin seems to block until
60    # it has finished reading a line before handling any queued signals.
61    @skipIf(hostoslist=['linux'])
62    @skipIfWindows
63    def test_while_waiting_on_input(self):
64        """ Tests SIGINT handling while the REPL is waiting on input from
65        stdin."""
66        self.start_python_repl()
67
68        # Send SIGINT to the LLDB process.
69        self.child.sendintr()
70        # This should get transformed to a KeyboardInterrupt which is the same
71        # behaviour as the standalone Python REPL.
72        self.child.expect("KeyboardInterrupt")
73        # Send EOF to quit the Python REPL.
74        self.child.sendeof()
75
76        self.quit()
77