14 """Tests clean exit of server/client on Python Interpreter exit/sigint.
16 The tests in this module spawn a subprocess for each test case, the
17 test is considered successful if it doesn't freeze/timeout.
35 SCENARIO_FILE = os.path.abspath(
36 os.path.join(os.path.dirname(os.path.realpath(__file__)),
37 '_exit_scenarios.py'))
38 INTERPRETER = sys.executable
39 BASE_COMMAND = [INTERPRETER, SCENARIO_FILE]
40 BASE_SIGTERM_COMMAND = BASE_COMMAND + [
'--wait_for_interrupt']
42 INIT_TIME = datetime.timedelta(seconds=1)
43 WAIT_CHECK_INTERVAL = datetime.timedelta(milliseconds=100)
44 WAIT_CHECK_DEFAULT_TIMEOUT = datetime.timedelta(seconds=5)
47 process_lock = threading.Lock()
54 for process
in processes:
61 atexit.register(cleanup_processes)
65 """A funciton to mimic 3.3+ only timeout argument in process.wait."""
66 deadline = datetime.datetime.now() + timeout
67 while (process.poll()
is None)
and (datetime.datetime.now() < deadline):
68 time.sleep(WAIT_CHECK_INTERVAL.total_seconds())
69 if process.returncode
is None:
70 raise RuntimeError(
'Process failed to exit within %s' % timeout)
75 processes.append(process)
76 time.sleep(INIT_TIME.total_seconds())
77 os.kill(process.pid, signal.SIGINT)
83 processes.append(process)
88 @unittest.skip(
'https://github.com/grpc/grpc/issues/23982')
89 @unittest.skip(
'https://github.com/grpc/grpc/issues/23028')
93 process = subprocess.Popen(BASE_COMMAND +
94 [_exit_scenarios.UNSTARTED_SERVER],
100 process = subprocess.Popen(BASE_SIGTERM_COMMAND +
101 [_exit_scenarios.UNSTARTED_SERVER],
106 process = subprocess.Popen(BASE_COMMAND +
107 [_exit_scenarios.RUNNING_SERVER],
113 process = subprocess.Popen(BASE_SIGTERM_COMMAND +
114 [_exit_scenarios.RUNNING_SERVER],
120 process = subprocess.Popen(
121 BASE_COMMAND + [_exit_scenarios.POLL_CONNECTIVITY_NO_SERVER],
127 process = subprocess.Popen(
128 BASE_SIGTERM_COMMAND +
129 [_exit_scenarios.POLL_CONNECTIVITY_NO_SERVER],
135 process = subprocess.Popen(BASE_COMMAND +
136 [_exit_scenarios.POLL_CONNECTIVITY],
142 process = subprocess.Popen(BASE_SIGTERM_COMMAND +
143 [_exit_scenarios.POLL_CONNECTIVITY],
148 @unittest.skipIf(os.name ==
'nt',
149 'os.kill does not have required permission on Windows')
151 process = subprocess.Popen(BASE_COMMAND +
152 [_exit_scenarios.IN_FLIGHT_UNARY_UNARY_CALL],
157 @unittest.skipIf(os.name ==
'nt',
158 'os.kill does not have required permission on Windows')
160 process = subprocess.Popen(
161 BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_UNARY_STREAM_CALL],
166 @unittest.skipIf(os.name ==
'nt',
167 'os.kill does not have required permission on Windows')
169 process = subprocess.Popen(
170 BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_STREAM_UNARY_CALL],
175 @unittest.skipIf(os.name ==
'nt',
176 'os.kill does not have required permission on Windows')
178 process = subprocess.Popen(
179 BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_STREAM_STREAM_CALL],
184 @unittest.skipIf(os.name ==
'nt',
185 'os.kill does not have required permission on Windows')
187 process = subprocess.Popen(
189 [_exit_scenarios.IN_FLIGHT_PARTIAL_UNARY_STREAM_CALL],
194 @unittest.skipIf(os.name ==
'nt',
195 'os.kill does not have required permission on Windows')
197 process = subprocess.Popen(
199 [_exit_scenarios.IN_FLIGHT_PARTIAL_STREAM_UNARY_CALL],
204 @unittest.skipIf(os.name ==
'nt',
205 'os.kill does not have required permission on Windows')
207 process = subprocess.Popen(
209 [_exit_scenarios.IN_FLIGHT_PARTIAL_STREAM_STREAM_CALL],
215 if __name__ ==
'__main__':
216 logging.basicConfig(level=logging.DEBUG)
217 unittest.main(verbosity=2)