xref: /aosp_15_r20/external/grpc-grpc/bazel/_gevent_test_main.py (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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