1049ae930SJonas Devlieghere"""
2049ae930SJonas DevlieghereTest sending SIGINT to the embedded Python REPL.
3049ae930SJonas Devlieghere"""
4049ae930SJonas Devlieghere
5049ae930SJonas Devlieghereimport os
6049ae930SJonas Devlieghere
7049ae930SJonas Devlieghereimport lldb
8049ae930SJonas Devliegherefrom lldbsuite.test.decorators import *
9049ae930SJonas Devliegherefrom lldbsuite.test.lldbtest import *
10049ae930SJonas Devliegherefrom lldbsuite.test.lldbpexpect import PExpectTest
11049ae930SJonas Devlieghere
12049ae930SJonas Devlieghereclass TestCase(PExpectTest):
13049ae930SJonas Devlieghere
14049ae930SJonas Devlieghere    def start_python_repl(self):
15049ae930SJonas Devlieghere        """ Starts up the embedded Python REPL."""
16049ae930SJonas Devlieghere        self.launch()
17049ae930SJonas Devlieghere        # Start the embedded Python REPL via the 'script' command.
18049ae930SJonas Devlieghere        self.child.send("script -l python --\n")
19049ae930SJonas Devlieghere        # Wait for the Python REPL prompt.
20049ae930SJonas Devlieghere        self.child.expect(">>>")
21049ae930SJonas Devlieghere
22049ae930SJonas Devlieghere    # PExpect uses many timeouts internally and doesn't play well
23049ae930SJonas Devlieghere    # under ASAN on a loaded machine..
24049ae930SJonas Devlieghere    @skipIfAsan
25049ae930SJonas Devlieghere    @skipIfWindows
26df13239cSMuhammad Omair Javaid    @skipIf(oslist=["linux"], archs=["arm", "aarch64"])
27049ae930SJonas Devlieghere    def test_while_evaluating_code(self):
28049ae930SJonas Devlieghere        """ Tests SIGINT handling while Python code is being evaluated."""
29049ae930SJonas Devlieghere        self.start_python_repl()
30049ae930SJonas Devlieghere
31049ae930SJonas Devlieghere        # Start a long-running command that we try to abort with SIGINT.
32049ae930SJonas Devlieghere        # Note that we dont actually wait 10000s in this code as pexpect or
33049ae930SJonas Devlieghere        # lit will kill the test way before that.
34049ae930SJonas Devlieghere        self.child.send("import time; print('running' + 'now'); time.sleep(10000);\n")
35049ae930SJonas Devlieghere
36049ae930SJonas Devlieghere        # Make sure the command is actually being evaluated at the moment by
37049ae930SJonas Devlieghere        # looking at the string that the command is printing.
38049ae930SJonas Devlieghere        # Don't check for a needle that also occurs in the program itself to
39049ae930SJonas Devlieghere        # prevent that echoing will make this check pass unintentionally.
40049ae930SJonas Devlieghere        self.child.expect("runningnow")
41049ae930SJonas Devlieghere
42049ae930SJonas Devlieghere        # Send SIGINT to the LLDB process.
43049ae930SJonas Devlieghere        self.child.sendintr()
44049ae930SJonas Devlieghere
45049ae930SJonas Devlieghere        # This should get transformed to a KeyboardInterrupt which is the same
46049ae930SJonas Devlieghere        # behaviour as the standalone Python REPL. It should also interrupt
47049ae930SJonas Devlieghere        # the evaluation of our sleep statement.
48049ae930SJonas Devlieghere        self.child.expect("KeyboardInterrupt")
49049ae930SJonas Devlieghere        # Send EOF to quit the Python REPL.
50049ae930SJonas Devlieghere        self.child.sendeof()
51049ae930SJonas Devlieghere
52049ae930SJonas Devlieghere        self.quit()
53049ae930SJonas Devlieghere
54049ae930SJonas Devlieghere    # PExpect uses many timeouts internally and doesn't play well
55049ae930SJonas Devlieghere    # under ASAN on a loaded machine..
56049ae930SJonas Devlieghere    @skipIfAsan
57049ae930SJonas Devlieghere    # FIXME: On Linux the Python code that reads from stdin seems to block until
58049ae930SJonas Devlieghere    # it has finished reading a line before handling any queued signals.
59*27166e95SJonas Devlieghere    @skipIf(hostoslist=['linux'])
60049ae930SJonas Devlieghere    @skipIfWindows
61049ae930SJonas Devlieghere    def test_while_waiting_on_input(self):
62049ae930SJonas Devlieghere        """ Tests SIGINT handling while the REPL is waiting on input from
63049ae930SJonas Devlieghere        stdin."""
64049ae930SJonas Devlieghere        self.start_python_repl()
65049ae930SJonas Devlieghere
66049ae930SJonas Devlieghere        # Send SIGINT to the LLDB process.
67049ae930SJonas Devlieghere        self.child.sendintr()
68049ae930SJonas Devlieghere        # This should get transformed to a KeyboardInterrupt which is the same
69049ae930SJonas Devlieghere        # behaviour as the standalone Python REPL.
70049ae930SJonas Devlieghere        self.child.expect("KeyboardInterrupt")
71049ae930SJonas Devlieghere        # Send EOF to quit the Python REPL.
72049ae930SJonas Devlieghere        self.child.sendeof()
73049ae930SJonas Devlieghere
74049ae930SJonas Devlieghere        self.quit()
75