|
|
|
@ -24,6 +24,7 @@ import six |
|
|
|
|
import subprocess |
|
|
|
|
import sys |
|
|
|
|
import threading |
|
|
|
|
import datetime |
|
|
|
|
import time |
|
|
|
|
import unittest |
|
|
|
|
import logging |
|
|
|
@ -37,7 +38,9 @@ INTERPRETER = sys.executable |
|
|
|
|
BASE_COMMAND = [INTERPRETER, SCENARIO_FILE] |
|
|
|
|
BASE_SIGTERM_COMMAND = BASE_COMMAND + ['--wait_for_interrupt'] |
|
|
|
|
|
|
|
|
|
INIT_TIME = 1.0 |
|
|
|
|
INIT_TIME = datetime.timedelta(seconds=1) |
|
|
|
|
WAIT_CHECK_INTERVAL = datetime.timedelta(milliseconds=100) |
|
|
|
|
WAIT_CHECK_DEFAULT_TIMEOUT = datetime.timedelta(seconds=5) |
|
|
|
|
|
|
|
|
|
processes = [] |
|
|
|
|
process_lock = threading.Lock() |
|
|
|
@ -57,18 +60,27 @@ def cleanup_processes(): |
|
|
|
|
atexit.register(cleanup_processes) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _process_wait_with_timeout(process, timeout=WAIT_CHECK_DEFAULT_TIMEOUT): |
|
|
|
|
"""A funciton to mimic 3.3+ only timeout argument in process.wait.""" |
|
|
|
|
deadline = datetime.datetime.now() + timeout |
|
|
|
|
while (process.poll() is None) and (datetime.datetime.now() < deadline): |
|
|
|
|
time.sleep(WAIT_CHECK_INTERVAL.total_seconds()) |
|
|
|
|
if process.returncode is None: |
|
|
|
|
raise RuntimeError('Process failed to exit within %s' % timeout) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def interrupt_and_wait(process): |
|
|
|
|
with process_lock: |
|
|
|
|
processes.append(process) |
|
|
|
|
time.sleep(INIT_TIME) |
|
|
|
|
time.sleep(INIT_TIME.total_seconds()) |
|
|
|
|
os.kill(process.pid, signal.SIGINT) |
|
|
|
|
process.wait() |
|
|
|
|
_process_wait_with_timeout(process) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def wait(process): |
|
|
|
|
with process_lock: |
|
|
|
|
processes.append(process) |
|
|
|
|
process.wait() |
|
|
|
|
_process_wait_with_timeout(process) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ExitTest(unittest.TestCase): |
|
|
|
@ -138,7 +150,6 @@ class ExitTest(unittest.TestCase): |
|
|
|
|
stderr=sys.stderr) |
|
|
|
|
interrupt_and_wait(process) |
|
|
|
|
|
|
|
|
|
@unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999') |
|
|
|
|
@unittest.skipIf(os.name == 'nt', |
|
|
|
|
'os.kill does not have required permission on Windows') |
|
|
|
|
def test_in_flight_unary_stream_call(self): |
|
|
|
@ -157,7 +168,6 @@ class ExitTest(unittest.TestCase): |
|
|
|
|
stderr=sys.stderr) |
|
|
|
|
interrupt_and_wait(process) |
|
|
|
|
|
|
|
|
|
@unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999') |
|
|
|
|
@unittest.skipIf(os.name == 'nt', |
|
|
|
|
'os.kill does not have required permission on Windows') |
|
|
|
|
def test_in_flight_stream_stream_call(self): |
|
|
|
@ -167,7 +177,6 @@ class ExitTest(unittest.TestCase): |
|
|
|
|
stderr=sys.stderr) |
|
|
|
|
interrupt_and_wait(process) |
|
|
|
|
|
|
|
|
|
@unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999') |
|
|
|
|
@unittest.skipIf(os.name == 'nt', |
|
|
|
|
'os.kill does not have required permission on Windows') |
|
|
|
|
def test_in_flight_partial_unary_stream_call(self): |
|
|
|
@ -188,7 +197,6 @@ class ExitTest(unittest.TestCase): |
|
|
|
|
stderr=sys.stderr) |
|
|
|
|
interrupt_and_wait(process) |
|
|
|
|
|
|
|
|
|
@unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999') |
|
|
|
|
@unittest.skipIf(os.name == 'nt', |
|
|
|
|
'os.kill does not have required permission on Windows') |
|
|
|
|
def test_in_flight_partial_stream_stream_call(self): |
|
|
|
@ -201,5 +209,5 @@ class ExitTest(unittest.TestCase): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
|
logging.basicConfig() |
|
|
|
|
logging.basicConfig(level=logging.DEBUG) |
|
|
|
|
unittest.main(verbosity=2) |
|
|
|
|