@@ -51,6 +51,7 @@ def run_repl(
5151 cwd : str | None = None ,
5252 skip : bool = False ,
5353 timeout : float = SHORT_TIMEOUT ,
54+ exit_on_output : str | None = None ,
5455 ) -> tuple [str , int ]:
5556 temp_dir = None
5657 if cwd is None :
@@ -64,6 +65,7 @@ def run_repl(
6465 cwd = cwd ,
6566 skip = skip ,
6667 timeout = timeout ,
68+ exit_on_output = exit_on_output ,
6769 )
6870 finally :
6971 if temp_dir is not None :
@@ -78,6 +80,7 @@ def _run_repl(
7880 cwd : str ,
7981 skip : bool ,
8082 timeout : float ,
83+ exit_on_output : str | None ,
8184 ) -> tuple [str , int ]:
8285 assert pty
8386 master_fd , slave_fd = pty .openpty ()
@@ -123,6 +126,11 @@ def _run_repl(
123126 except OSError :
124127 break
125128 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
126134 else :
127135 os .close (master_fd )
128136 process .kill ()
@@ -1718,18 +1726,24 @@ def test_history_survive_crash(self):
17181726
17191727 commands = "1\n 2\n 3\n exit()\n "
17201728 output , exit_code = self .run_repl (commands , env = env , skip = True )
1729+ self .assertEqual (exit_code , 0 )
17211730
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 )
17271738
17281739 history = pathlib .Path (hfile .name ).read_text ()
17291740 self .assertIn ("2" , history )
17301741 self .assertIn ("exit()" , history )
17311742 self .assertIn ("spam" , history )
17321743 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.
17331747 self .assertNotIn ("sleep" , history )
17341748 self .assertNotIn ("quit" , history )
17351749
0 commit comments