Let go tests run without blocking on stdio
This commit is contained in:
parent
d6187b5bfc
commit
1347d1ad47
1 changed files with 53 additions and 18 deletions
|
|
@ -8,10 +8,12 @@
|
|||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import unittest
|
||||
from contextlib import contextmanager
|
||||
from functools import lru_cache
|
||||
from tempfile import TemporaryDirectory
|
||||
from threading import Thread
|
||||
from typing import (
|
||||
Any,
|
||||
Callable,
|
||||
|
|
@ -141,18 +143,52 @@ def go_exe() -> str:
|
|||
return shutil.which('go') or ''
|
||||
|
||||
|
||||
def run_go(packages: Set[str], names: str) -> 'subprocess.Popen[bytes]':
|
||||
class GoProc(Thread):
|
||||
|
||||
def __init__(self, cmd: List[str]):
|
||||
super().__init__(name='GoProc')
|
||||
from kitty.constants import kitty_exe
|
||||
env = os.environ.copy()
|
||||
env['KITTY_PATH_TO_KITTY_EXE'] = kitty_exe()
|
||||
self.stdout = b''
|
||||
self.start_time = time.monotonic()
|
||||
self.proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)
|
||||
self.start()
|
||||
|
||||
@property
|
||||
def runtime(self):
|
||||
return self.end_time - self.start_time
|
||||
|
||||
@property
|
||||
def returncode(self):
|
||||
return self.proc.returncode
|
||||
|
||||
def run(self) -> None:
|
||||
self.stdout, _ = self.proc.communicate()
|
||||
self.proc.stdout.close()
|
||||
|
||||
def wait(self, timeout=None) -> None:
|
||||
try:
|
||||
self.join(timeout)
|
||||
except KeyboardInterrupt:
|
||||
self.proc.terminate()
|
||||
if self.proc.wait(0.1) is None:
|
||||
self.proc.kill()
|
||||
self.join()
|
||||
self.end_time = time.monotonic()
|
||||
return self.stdout.decode('utf-8', 'replace'), self.proc.returncode
|
||||
|
||||
|
||||
def run_go(packages: Set[str], names: str) -> GoProc:
|
||||
go = go_exe()
|
||||
go_pkg_args = [f'kitty/{x}' for x in packages]
|
||||
cmd = [go, 'test', '-v']
|
||||
for name in names:
|
||||
cmd.extend(('-run', name))
|
||||
cmd += go_pkg_args
|
||||
env = os.environ.copy()
|
||||
from kitty.constants import kitty_exe
|
||||
env['KITTY_PATH_TO_KITTY_EXE'] = kitty_exe()
|
||||
print(shlex.join(cmd), flush=True)
|
||||
return subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)
|
||||
return GoProc(cmd)
|
||||
|
||||
|
||||
|
||||
def reduce_go_pkgs(module: str, names: Sequence[str]) -> Set[str]:
|
||||
|
|
@ -169,22 +205,18 @@ def reduce_go_pkgs(module: str, names: Sequence[str]) -> Set[str]:
|
|||
return go_packages
|
||||
|
||||
|
||||
def run_python_tests(args: Any, go_proc: 'Optional[subprocess.Popen[bytes]]' = None) -> None:
|
||||
def run_python_tests(args: Any, go_proc: 'Optional[GoProc]' = None) -> None:
|
||||
tests = find_all_tests()
|
||||
|
||||
def print_go() -> None:
|
||||
try:
|
||||
go_proc.wait()
|
||||
except KeyboardInterrupt:
|
||||
go_proc.terminate()
|
||||
if go_proc.wait(0.1) is None:
|
||||
go_proc.kill()
|
||||
|
||||
stdout, rc = go_proc.wait()
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
print(go_proc.stdout.read().decode('utf-8', 'replace'), end='', flush=True)
|
||||
go_proc.stdout.close()
|
||||
return go_proc.wait()
|
||||
if go_proc.returncode == 0 and tests._tests:
|
||||
print(f'All Go tests succeeded, ran in {go_proc.runtime:.1f} seconds', flush=True)
|
||||
else:
|
||||
print(stdout, end='', flush=True)
|
||||
return rc
|
||||
|
||||
if args.module:
|
||||
tests = filter_tests_by_module(tests, args.module)
|
||||
|
|
@ -197,7 +229,10 @@ def print_go() -> None:
|
|||
tests = filter_tests_by_name(tests, *args.name)
|
||||
if not tests._tests and not go_proc:
|
||||
raise SystemExit('No test named %s found' % args.name)
|
||||
python_tests_ok = run_cli(tests, args.verbosity)
|
||||
if tests._tests:
|
||||
python_tests_ok = run_cli(tests, args.verbosity)
|
||||
else:
|
||||
python_tests_ok = True
|
||||
exit_code = 0 if python_tests_ok else 1
|
||||
if go_proc:
|
||||
print_go()
|
||||
|
|
@ -230,7 +265,7 @@ def run_tests(report_env: bool = False) -> None:
|
|||
type_check()
|
||||
go_pkgs = reduce_go_pkgs(args.module, args.name)
|
||||
if go_pkgs:
|
||||
go_proc: 'Optional[subprocess.Popen[bytes]]' = run_go(go_pkgs, args.name)
|
||||
go_proc: 'Optional[GoProc]' = run_go(go_pkgs, args.name)
|
||||
else:
|
||||
go_proc = None
|
||||
with env_for_python_tests(report_env):
|
||||
|
|
|
|||
Loading…
Reference in a new issue