1*cc02d7e2SAndroid Build Coastguard Worker# Copyright 2021 The gRPC Authors 2*cc02d7e2SAndroid Build Coastguard Worker# 3*cc02d7e2SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*cc02d7e2SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*cc02d7e2SAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*cc02d7e2SAndroid Build Coastguard Worker# 7*cc02d7e2SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*cc02d7e2SAndroid Build Coastguard Worker# 9*cc02d7e2SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*cc02d7e2SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*cc02d7e2SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*cc02d7e2SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*cc02d7e2SAndroid Build Coastguard Worker# limitations under the License. 14*cc02d7e2SAndroid Build Coastguard Worker 15*cc02d7e2SAndroid Build Coastguard Workerimport gevent 16*cc02d7e2SAndroid Build Coastguard Workerfrom gevent import monkey 17*cc02d7e2SAndroid Build Coastguard Worker 18*cc02d7e2SAndroid Build Coastguard Workermonkey.patch_all() 19*cc02d7e2SAndroid Build Coastguard Workerthreadpool = gevent.hub.get_hub().threadpool 20*cc02d7e2SAndroid Build Coastguard Worker 21*cc02d7e2SAndroid Build Coastguard Worker# Currently, each channel corresponds to a single native thread in the 22*cc02d7e2SAndroid Build Coastguard Worker# gevent threadpool. Thus, when the unit test suite spins up hundreds of 23*cc02d7e2SAndroid Build Coastguard Worker# channels concurrently, some will be starved out, causing the test to 24*cc02d7e2SAndroid Build Coastguard Worker# increase in duration. We increase the max size here so this does not 25*cc02d7e2SAndroid Build Coastguard Worker# happen. 26*cc02d7e2SAndroid Build Coastguard Workerthreadpool.maxsize = 1024 27*cc02d7e2SAndroid Build Coastguard Workerthreadpool.size = 32 28*cc02d7e2SAndroid Build Coastguard Worker 29*cc02d7e2SAndroid Build Coastguard Workerimport traceback, signal 30*cc02d7e2SAndroid Build Coastguard Workerfrom typing import Sequence 31*cc02d7e2SAndroid Build Coastguard Worker 32*cc02d7e2SAndroid Build Coastguard Worker 33*cc02d7e2SAndroid Build Coastguard Workerimport grpc.experimental.gevent 34*cc02d7e2SAndroid Build Coastguard Workergrpc.experimental.gevent.init_gevent() 35*cc02d7e2SAndroid Build Coastguard Worker 36*cc02d7e2SAndroid Build Coastguard Workerimport gevent 37*cc02d7e2SAndroid Build Coastguard Workerimport greenlet 38*cc02d7e2SAndroid Build Coastguard Workerimport datetime 39*cc02d7e2SAndroid Build Coastguard Worker 40*cc02d7e2SAndroid Build Coastguard Workerimport grpc 41*cc02d7e2SAndroid Build Coastguard Workerimport unittest 42*cc02d7e2SAndroid Build Coastguard Workerimport sys 43*cc02d7e2SAndroid Build Coastguard Workerimport os 44*cc02d7e2SAndroid Build Coastguard Workerimport pkgutil 45*cc02d7e2SAndroid Build Coastguard Workerimport importlib 46*cc02d7e2SAndroid Build Coastguard Worker 47*cc02d7e2SAndroid Build Coastguard Workerdef trace_callback(event, args): 48*cc02d7e2SAndroid Build Coastguard Worker if event in ("switch", "throw"): 49*cc02d7e2SAndroid Build Coastguard Worker origin, target = args 50*cc02d7e2SAndroid Build Coastguard Worker sys.stderr.write("{} Transfer from {} to {} with {}\n".format(datetime.datetime.now(), origin, target, event)) 51*cc02d7e2SAndroid Build Coastguard Worker else: 52*cc02d7e2SAndroid Build Coastguard Worker sys.stderr.write("Unknown event {}.\n".format(event)) 53*cc02d7e2SAndroid Build Coastguard Worker sys.stderr.flush() 54*cc02d7e2SAndroid Build Coastguard Worker 55*cc02d7e2SAndroid Build Coastguard Workerif os.getenv("GREENLET_TRACE") is not None: 56*cc02d7e2SAndroid Build Coastguard Worker greenlet.settrace(trace_callback) 57*cc02d7e2SAndroid Build Coastguard Worker 58*cc02d7e2SAndroid Build Coastguard Workerdef debug(sig, frame): 59*cc02d7e2SAndroid Build Coastguard Worker d={'_frame':frame} 60*cc02d7e2SAndroid Build Coastguard Worker d.update(frame.f_globals) 61*cc02d7e2SAndroid Build Coastguard Worker d.update(frame.f_locals) 62*cc02d7e2SAndroid Build Coastguard Worker 63*cc02d7e2SAndroid Build Coastguard Worker sys.stderr.write("Traceback:\n{}".format("\n".join(traceback.format_stack(frame)))) 64*cc02d7e2SAndroid Build Coastguard Worker import gevent.util; gevent.util.print_run_info() 65*cc02d7e2SAndroid Build Coastguard Worker sys.stderr.flush() 66*cc02d7e2SAndroid Build Coastguard Worker 67*cc02d7e2SAndroid Build Coastguard Workersignal.signal(signal.SIGTERM, debug) 68*cc02d7e2SAndroid Build Coastguard Worker 69*cc02d7e2SAndroid Build Coastguard Worker 70*cc02d7e2SAndroid Build Coastguard Workerclass SingleLoader(object): 71*cc02d7e2SAndroid Build Coastguard Worker def __init__(self, pattern: str): 72*cc02d7e2SAndroid Build Coastguard Worker loader = unittest.TestLoader() 73*cc02d7e2SAndroid Build Coastguard Worker self.suite = unittest.TestSuite() 74*cc02d7e2SAndroid Build Coastguard Worker tests = [] 75*cc02d7e2SAndroid Build Coastguard Worker for importer, module_name, is_package in pkgutil.walk_packages([os.path.dirname(os.path.relpath(__file__))]): 76*cc02d7e2SAndroid Build Coastguard Worker if pattern in module_name: 77*cc02d7e2SAndroid Build Coastguard Worker spec = importer.find_spec(module_name) 78*cc02d7e2SAndroid Build Coastguard Worker module = importlib.util.module_from_spec(spec) 79*cc02d7e2SAndroid Build Coastguard Worker spec.loader.exec_module(module) 80*cc02d7e2SAndroid Build Coastguard Worker tests.append(loader.loadTestsFromModule(module)) 81*cc02d7e2SAndroid Build Coastguard Worker if len(tests) != 1: 82*cc02d7e2SAndroid Build Coastguard Worker raise AssertionError("Expected only 1 test module. Found {}".format(tests)) 83*cc02d7e2SAndroid Build Coastguard Worker self.suite.addTest(tests[0]) 84*cc02d7e2SAndroid Build Coastguard Worker 85*cc02d7e2SAndroid Build Coastguard Worker 86*cc02d7e2SAndroid Build Coastguard Worker def loadTestsFromNames(self, names: Sequence[str], module: str = None) -> unittest.TestSuite: 87*cc02d7e2SAndroid Build Coastguard Worker return self.suite 88*cc02d7e2SAndroid Build Coastguard Worker 89*cc02d7e2SAndroid Build Coastguard Workerif __name__ == "__main__": 90*cc02d7e2SAndroid Build Coastguard Worker 91*cc02d7e2SAndroid Build Coastguard Worker if len(sys.argv) != 2: 92*cc02d7e2SAndroid Build Coastguard Worker print(f"USAGE: {sys.argv[0]} TARGET_MODULE", file=sys.stderr) 93*cc02d7e2SAndroid Build Coastguard Worker 94*cc02d7e2SAndroid Build Coastguard Worker target_module = sys.argv[1] 95*cc02d7e2SAndroid Build Coastguard Worker 96*cc02d7e2SAndroid Build Coastguard Worker loader = SingleLoader(target_module) 97*cc02d7e2SAndroid Build Coastguard Worker runner = unittest.TextTestRunner() 98*cc02d7e2SAndroid Build Coastguard Worker 99*cc02d7e2SAndroid Build Coastguard Worker result = gevent.spawn(runner.run, loader.suite) 100*cc02d7e2SAndroid Build Coastguard Worker result.join() 101*cc02d7e2SAndroid Build Coastguard Worker if not result.value.wasSuccessful(): 102*cc02d7e2SAndroid Build Coastguard Worker sys.exit("Test failure.") 103