@@ -51,6 +51,7 @@ def run_repl(
51
51
cwd : str | None = None ,
52
52
skip : bool = False ,
53
53
timeout : float = SHORT_TIMEOUT ,
54
+ exit_on_output : str | None = None ,
54
55
) -> tuple [str , int ]:
55
56
temp_dir = None
56
57
if cwd is None :
@@ -64,6 +65,7 @@ def run_repl(
64
65
cwd = cwd ,
65
66
skip = skip ,
66
67
timeout = timeout ,
68
+ exit_on_output = exit_on_output ,
67
69
)
68
70
finally :
69
71
if temp_dir is not None :
@@ -78,6 +80,7 @@ def _run_repl(
78
80
cwd : str ,
79
81
skip : bool ,
80
82
timeout : float ,
83
+ exit_on_output : str | None ,
81
84
) -> tuple [str , int ]:
82
85
assert pty
83
86
master_fd , slave_fd = pty .openpty ()
@@ -123,6 +126,11 @@ def _run_repl(
123
126
except OSError :
124
127
break
125
128
output .append (data )
129
+ if exit_on_output is not None :
130
+ output = ["" .join (output )]
131
+ if exit_on_output in output [0 ]:
132
+ process .kill ()
133
+ break
126
134
else :
127
135
os .close (master_fd )
128
136
process .kill ()
@@ -1718,18 +1726,24 @@ def test_history_survive_crash(self):
1718
1726
1719
1727
commands = "1\n 2\n 3\n exit()\n "
1720
1728
output , exit_code = self .run_repl (commands , env = env , skip = True )
1729
+ self .assertEqual (exit_code , 0 )
1721
1730
1722
- commands = "spam\n import time\n time.sleep(1000)\n quit\n "
1723
- try :
1724
- self .run_repl (commands , env = env , timeout = 3 )
1725
- except AssertionError :
1726
- pass
1731
+ # Run until "0xcafe" is printed (as "51966") and then kill the
1732
+ # process to simulate a crash. Note that the output also includes
1733
+ # the echoed input commands.
1734
+ commands = "spam\n import time\n 0xcafe\n time.sleep(1000)\n quit\n "
1735
+ output , exit_code = self .run_repl (commands , env = env ,
1736
+ exit_on_output = "51966" )
1737
+ self .assertNotEqual (exit_code , 0 )
1727
1738
1728
1739
history = pathlib .Path (hfile .name ).read_text ()
1729
1740
self .assertIn ("2" , history )
1730
1741
self .assertIn ("exit()" , history )
1731
1742
self .assertIn ("spam" , history )
1732
1743
self .assertIn ("import time" , history )
1744
+ # History is written after each command's output is printed to the
1745
+ # console, so depending on how quickly the process is killed,
1746
+ # the last command may or may not be written to the history file.
1733
1747
self .assertNotIn ("sleep" , history )
1734
1748
self .assertNotIn ("quit" , history )
1735
1749
0 commit comments