Skip to content

Commit 31a63ac

Browse files
committed
tests: Add Ctrl-C interrupt tests for REPL and execution.
Tests paste mode Ctrl-C cancellation and Ctrl-C interruption during code execution to validate terminal mode switching behavior. Signed-off-by: Andrew Leech <[email protected]>
1 parent c83fccf commit 31a63ac

File tree

5 files changed

+99
-0
lines changed

5 files changed

+99
-0
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ exclude = [ # Ruff finds Python SyntaxError in these files
3434
"tests/cmdline/repl_autoindent.py",
3535
"tests/cmdline/repl_basic.py",
3636
"tests/cmdline/repl_cont.py",
37+
"tests/cmdline/repl_ctrl_c_interrupt.py",
3738
"tests/cmdline/repl_emacs_keys.py",
3839
"tests/cmdline/repl_paste.py",
3940
"tests/cmdline/repl_words_move.py",
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Test that Ctrl-C interrupts running code
2+
3+
# Test paste mode Ctrl-C cancel
4+
{\x05}
5+
print('paste mode')
6+
{\x03}
7+
8+
# Verify REPL works
9+
print('REPL works')
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
MicroPython \.\+ version
2+
Type "help()" for more information.
3+
>>> # Test that Ctrl-C interrupts running code
4+
>>>
5+
>>> # Test paste mode Ctrl-C cancel
6+
>>>
7+
paste mode; Ctrl-C to cancel, Ctrl-D to finish
8+
===
9+
=== print('paste mode')
10+
===
11+
>>>
12+
>>>
13+
>>> # Verify REPL works
14+
>>> print('REPL works')
15+
REPL works
16+
>>>
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"""
2+
Test that Ctrl-C interrupts running code in the REPL.
3+
4+
This test is run by run-tests.py which sets up a PTY with ISIG enabled
5+
and spawns MicroPython with the PTY as its controlling terminal.
6+
The global 'master' variable (PTY master fd) is provided by run-tests.py.
7+
"""
8+
9+
import os
10+
import select
11+
import time
12+
13+
14+
def read_until_quiet(master, timeout=0.05):
15+
"""Read from PTY until no data for timeout seconds."""
16+
output = b""
17+
while True:
18+
ready = select.select([master], [], [], timeout)
19+
if ready[0]:
20+
data = os.read(master, 1024)
21+
if not data:
22+
break
23+
output += data
24+
else:
25+
break
26+
return output
27+
28+
29+
# Wait for banner
30+
time.sleep(0.2)
31+
banner = read_until_quiet(master)
32+
33+
if b"MicroPython" not in banner:
34+
print("SKIP")
35+
raise SystemExit
36+
37+
# Check if time module is available
38+
os.write(master, b"import time\n")
39+
time.sleep(0.05)
40+
check_output = read_until_quiet(master, timeout=0.05)
41+
if b"ImportError" in check_output:
42+
print("SKIP")
43+
raise SystemExit
44+
45+
# Start a long-running operation
46+
os.write(master, b"time.sleep(30)\n")
47+
time.sleep(0.1) # Give it time to start sleeping
48+
49+
# Send Ctrl-C byte (0x03) through the terminal
50+
# This tests that the terminal mode allows SIGINT generation
51+
os.write(master, b"\x03")
52+
53+
# Read output
54+
time.sleep(0.2)
55+
output = read_until_quiet(master, timeout=0.1)
56+
57+
# Check for KeyboardInterrupt
58+
if b"KeyboardInterrupt" in output:
59+
print("PASS: Ctrl-C interrupted execution")
60+
else:
61+
print("FAIL: No KeyboardInterrupt found")
62+
63+
# Verify REPL still works
64+
os.write(master, b"print('OK')\n")
65+
time.sleep(0.1)
66+
output = read_until_quiet(master)
67+
68+
if b"OK" in output:
69+
print("PASS: REPL functional after interrupt")
70+
else:
71+
print("FAIL: REPL not functional")
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
PASS: Ctrl-C interrupted execution
2+
PASS: REPL functional after interrupt

0 commit comments

Comments
 (0)