• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2016 gRPC authors.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""Tests clean exit of server/client on Python Interpreter exit/sigint.
15
16The tests in this module spawn a subprocess for each test case, the
17test is considered successful if it doesn't hang/timeout.
18"""
19
20import atexit
21import os
22import signal
23import six
24import subprocess
25import sys
26import threading
27import time
28import unittest
29
30from tests.unit import _exit_scenarios
31
32SCENARIO_FILE = os.path.abspath(
33    os.path.join(
34        os.path.dirname(os.path.realpath(__file__)), '_exit_scenarios.py'))
35INTERPRETER = sys.executable
36BASE_COMMAND = [INTERPRETER, SCENARIO_FILE]
37BASE_SIGTERM_COMMAND = BASE_COMMAND + ['--wait_for_interrupt']
38
39INIT_TIME = 1.0
40
41processes = []
42process_lock = threading.Lock()
43
44
45# Make sure we attempt to clean up any
46# processes we may have left running
47def cleanup_processes():
48    with process_lock:
49        for process in processes:
50            try:
51                process.kill()
52            except Exception:  # pylint: disable=broad-except
53                pass
54
55
56atexit.register(cleanup_processes)
57
58
59def interrupt_and_wait(process):
60    with process_lock:
61        processes.append(process)
62    time.sleep(INIT_TIME)
63    os.kill(process.pid, signal.SIGINT)
64    process.wait()
65
66
67def wait(process):
68    with process_lock:
69        processes.append(process)
70    process.wait()
71
72
73@unittest.skip('https://github.com/grpc/grpc/issues/7311')
74class ExitTest(unittest.TestCase):
75
76    def test_unstarted_server(self):
77        process = subprocess.Popen(
78            BASE_COMMAND + [_exit_scenarios.UNSTARTED_SERVER],
79            stdout=sys.stdout,
80            stderr=sys.stderr)
81        wait(process)
82
83    def test_unstarted_server_terminate(self):
84        process = subprocess.Popen(
85            BASE_SIGTERM_COMMAND + [_exit_scenarios.UNSTARTED_SERVER],
86            stdout=sys.stdout)
87        interrupt_and_wait(process)
88
89    def test_running_server(self):
90        process = subprocess.Popen(
91            BASE_COMMAND + [_exit_scenarios.RUNNING_SERVER],
92            stdout=sys.stdout,
93            stderr=sys.stderr)
94        wait(process)
95
96    def test_running_server_terminate(self):
97        process = subprocess.Popen(
98            BASE_SIGTERM_COMMAND + [_exit_scenarios.RUNNING_SERVER],
99            stdout=sys.stdout,
100            stderr=sys.stderr)
101        interrupt_and_wait(process)
102
103    def test_poll_connectivity_no_server(self):
104        process = subprocess.Popen(
105            BASE_COMMAND + [_exit_scenarios.POLL_CONNECTIVITY_NO_SERVER],
106            stdout=sys.stdout,
107            stderr=sys.stderr)
108        wait(process)
109
110    def test_poll_connectivity_no_server_terminate(self):
111        process = subprocess.Popen(
112            BASE_SIGTERM_COMMAND +
113            [_exit_scenarios.POLL_CONNECTIVITY_NO_SERVER],
114            stdout=sys.stdout,
115            stderr=sys.stderr)
116        interrupt_and_wait(process)
117
118    def test_poll_connectivity(self):
119        process = subprocess.Popen(
120            BASE_COMMAND + [_exit_scenarios.POLL_CONNECTIVITY],
121            stdout=sys.stdout,
122            stderr=sys.stderr)
123        wait(process)
124
125    def test_poll_connectivity_terminate(self):
126        process = subprocess.Popen(
127            BASE_SIGTERM_COMMAND + [_exit_scenarios.POLL_CONNECTIVITY],
128            stdout=sys.stdout,
129            stderr=sys.stderr)
130        interrupt_and_wait(process)
131
132    def test_in_flight_unary_unary_call(self):
133        process = subprocess.Popen(
134            BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_UNARY_UNARY_CALL],
135            stdout=sys.stdout,
136            stderr=sys.stderr)
137        interrupt_and_wait(process)
138
139    @unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999')
140    def test_in_flight_unary_stream_call(self):
141        process = subprocess.Popen(
142            BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_UNARY_STREAM_CALL],
143            stdout=sys.stdout,
144            stderr=sys.stderr)
145        interrupt_and_wait(process)
146
147    def test_in_flight_stream_unary_call(self):
148        process = subprocess.Popen(
149            BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_STREAM_UNARY_CALL],
150            stdout=sys.stdout,
151            stderr=sys.stderr)
152        interrupt_and_wait(process)
153
154    @unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999')
155    def test_in_flight_stream_stream_call(self):
156        process = subprocess.Popen(
157            BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_STREAM_STREAM_CALL],
158            stdout=sys.stdout,
159            stderr=sys.stderr)
160        interrupt_and_wait(process)
161
162    @unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999')
163    def test_in_flight_partial_unary_stream_call(self):
164        process = subprocess.Popen(
165            BASE_COMMAND +
166            [_exit_scenarios.IN_FLIGHT_PARTIAL_UNARY_STREAM_CALL],
167            stdout=sys.stdout,
168            stderr=sys.stderr)
169        interrupt_and_wait(process)
170
171    def test_in_flight_partial_stream_unary_call(self):
172        process = subprocess.Popen(
173            BASE_COMMAND +
174            [_exit_scenarios.IN_FLIGHT_PARTIAL_STREAM_UNARY_CALL],
175            stdout=sys.stdout,
176            stderr=sys.stderr)
177        interrupt_and_wait(process)
178
179    @unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999')
180    def test_in_flight_partial_stream_stream_call(self):
181        process = subprocess.Popen(
182            BASE_COMMAND +
183            [_exit_scenarios.IN_FLIGHT_PARTIAL_STREAM_STREAM_CALL],
184            stdout=sys.stdout,
185            stderr=sys.stderr)
186        interrupt_and_wait(process)
187
188
189if __name__ == '__main__':
190    unittest.main(verbosity=2)
191