@@ -3175,25 +3175,31 @@ async def test_a_request_after_the_child_died_still_names_the_exit_and_the_reaso
31753175 await client .request ("initialize" , acp_protocol .initialize_params (), timeout = 10 )
31763176
31773177
3178- def _without_killpg (monkeypatch : pytest .MonkeyPatch ) -> list [list [str ]]:
3178+ def _without_killpg (monkeypatch : pytest .MonkeyPatch ) -> list [tuple [ list [str ], int ]]:
31793179 """Windows as ``close`` sees it: no ``os.killpg``, and a ``taskkill`` on PATH.
31803180
3181- The ``taskkill`` runs are recorded rather than made .
3181+ Record real ``taskkill`` runs on Windows and simulate them on POSIX .
31823182 """
31833183 import shutil
31843184 import subprocess
31853185
31863186 real_which = shutil .which
3187- ran : list [list [str ]] = []
3188-
3189- def run (argv : list [str ], ** _kw : Any ) -> subprocess .CompletedProcess :
3190- ran .append (list (argv ))
3191- return subprocess .CompletedProcess (argv , 0 )
3192-
3193- monkeypatch .delattr (os , "killpg" )
3194- monkeypatch .setattr (
3195- shutil , "which" , lambda name : r"C:\Windows\System32\taskkill.exe" if name == "taskkill" else real_which (name )
3196- )
3187+ real_run = subprocess .run
3188+ native = not hasattr (os , "killpg" )
3189+ taskkill = real_which ("taskkill" ) if native else r"C:\Windows\System32\taskkill.exe"
3190+ if taskkill is None :
3191+ pytest .skip ("taskkill is unavailable" )
3192+ ran : list [tuple [list [str ], int ]] = []
3193+
3194+ def run (argv : list [str ], ** kw : Any ) -> subprocess .CompletedProcess :
3195+ if argv [0 ] != taskkill :
3196+ return real_run (argv , ** kw )
3197+ result = real_run (argv , ** kw ) if native else subprocess .CompletedProcess (argv , 0 )
3198+ ran .append ((list (argv [1 :]), result .returncode ))
3199+ return result
3200+
3201+ monkeypatch .delattr (os , "killpg" , raising = False )
3202+ monkeypatch .setattr (shutil , "which" , lambda name : taskkill if name == "taskkill" else real_which (name ))
31973203 monkeypatch .setattr (subprocess , "run" , run )
31983204 return ran
31993205
@@ -3205,18 +3211,23 @@ async def test_close_without_killpg_ends_the_tree_through_taskkill(monkeypatch:
32053211 its transport all still there. ``taskkill /T`` reaches what the launcher
32063212 started, which a bare ``Process.kill`` does not.
32073213 """
3214+ from raven .acp_client import protocol
32083215 from raven .acp_client .client import AcpClient
32093216
32103217 cfg = stub_config ("windows-close" )
32113218 client = await AcpClient .launch (name = "windows-close" , command = cfg .command , env = dict (cfg .env ))
3212- proc = client ._proc
3213- ran = _without_killpg (monkeypatch )
3219+ try :
3220+ await client .request ("initialize" , protocol .initialize_params (), timeout = 15 )
3221+ proc = client ._proc
3222+ ran = _without_killpg (monkeypatch )
32143223
3215- await client .close ()
3224+ await client .close ()
32163225
3217- assert ran == [[r"C:\Windows\System32\taskkill.exe" , "/T" , "/F" , "/PID" , str (proc .pid )]]
3218- assert proc .returncode is not None , "the Process.kill after it must still stop the launcher"
3219- assert client .closed and not client .alive
3226+ assert ran == [(["/T" , "/F" , "/PID" , str (proc .pid )], 0 )]
3227+ assert proc .returncode is not None , "close must stop the launcher"
3228+ assert client .closed and not client .alive
3229+ finally :
3230+ await client .close ()
32203231
32213232
32223233async def test_close_without_killpg_kills_nothing_by_the_pid_of_an_exited_launcher (
@@ -3227,17 +3238,20 @@ async def test_close_without_killpg_kills_nothing_by_the_pid_of_an_exited_launch
32273238
32283239 cfg = stub_config ("abort" , mode = "abort" )
32293240 client = await AcpClient .launch (name = "abort" , command = cfg .command , env = dict (cfg .env ))
3230- for _ in range (200 ):
3231- if client ._proc .returncode is not None :
3232- break
3233- await asyncio .sleep (0.025 )
3234- assert client ._proc .returncode is not None , "the stub must be gone before the close, or this tests nothing"
3235- ran = _without_killpg (monkeypatch )
3241+ try :
3242+ for _ in range (200 ):
3243+ if client ._proc .returncode is not None :
3244+ break
3245+ await asyncio .sleep (0.025 )
3246+ assert client ._proc .returncode is not None , "the stub must be gone before the close, or this tests nothing"
3247+ ran = _without_killpg (monkeypatch )
32363248
3237- await client .close ()
3249+ await client .close ()
32383250
3239- assert ran == []
3240- assert client .closed
3251+ assert ran == []
3252+ assert client .closed
3253+ finally :
3254+ await client .close ()
32413255
32423256
32433257@pytest .mark .skipif (not hasattr (os , "killpg" ), reason = "process groups are POSIX" )
0 commit comments