1# Copyright 2019 the 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"""Test for cancellation example.""" 15 16import contextlib 17import os 18import signal 19import socket 20import subprocess 21import unittest 22 23_BINARY_DIR = os.path.realpath( 24 os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')) 25_SERVER_PATH = os.path.join(_BINARY_DIR, 'server') 26_CLIENT_PATH = os.path.join(_BINARY_DIR, 'client') 27 28 29@contextlib.contextmanager 30def _get_port(): 31 sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) 32 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) 33 if sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT) == 0: 34 raise RuntimeError("Failed to set SO_REUSEPORT.") 35 sock.bind(('', 0)) 36 try: 37 yield sock.getsockname()[1] 38 finally: 39 sock.close() 40 41 42def _start_client(server_port, 43 desired_string, 44 ideal_distance, 45 interesting_distance=None): 46 interesting_distance_args = () if interesting_distance is None else ( 47 '--show-inferior', interesting_distance) 48 return subprocess.Popen((_CLIENT_PATH, desired_string, '--server', 49 'localhost:{}'.format(server_port), 50 '--ideal-distance', str(ideal_distance)) + 51 interesting_distance_args) 52 53 54class CancellationExampleTest(unittest.TestCase): 55 56 def test_successful_run(self): 57 with _get_port() as test_port: 58 server_process = subprocess.Popen( 59 (_SERVER_PATH, '--port', str(test_port))) 60 try: 61 client_process = _start_client(test_port, 'aa', 0) 62 client_return_code = client_process.wait() 63 self.assertEqual(0, client_return_code) 64 self.assertIsNone(server_process.poll()) 65 finally: 66 server_process.kill() 67 server_process.wait() 68 69 def test_graceful_sigint(self): 70 with _get_port() as test_port: 71 server_process = subprocess.Popen( 72 (_SERVER_PATH, '--port', str(test_port))) 73 try: 74 client_process1 = _start_client(test_port, 'aaaaaaaaaa', 0) 75 client_process1.send_signal(signal.SIGINT) 76 client_process1.wait() 77 client_process2 = _start_client(test_port, 'aa', 0) 78 client_return_code = client_process2.wait() 79 self.assertEqual(0, client_return_code) 80 self.assertIsNone(server_process.poll()) 81 finally: 82 server_process.kill() 83 server_process.wait() 84 85 86if __name__ == '__main__': 87 unittest.main(verbosity=2) 88