diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/jaegertracing/thrift/test/py/RunClientServer.py | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rwxr-xr-x | src/jaegertracing/thrift/test/py/RunClientServer.py | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/src/jaegertracing/thrift/test/py/RunClientServer.py b/src/jaegertracing/thrift/test/py/RunClientServer.py new file mode 100755 index 000000000..56a408e60 --- /dev/null +++ b/src/jaegertracing/thrift/test/py/RunClientServer.py @@ -0,0 +1,323 @@ +#!/usr/bin/env python + +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +from __future__ import division +from __future__ import print_function +import platform +import copy +import os +import signal +import socket +import subprocess +import sys +import time +from optparse import OptionParser + +from util import local_libpath + +SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) + +SCRIPTS = [ + 'FastbinaryTest.py', + 'TestFrozen.py', + 'TestRenderedDoubleConstants.py', + 'TSimpleJSONProtocolTest.py', + 'SerializationTest.py', + 'TestEof.py', + 'TestSyntax.py', + 'TestSocket.py', +] +FRAMED = ["TNonblockingServer"] +SKIP_ZLIB = ['TNonblockingServer', 'THttpServer'] +SKIP_SSL = ['THttpServer'] +EXTRA_DELAY = dict(TProcessPoolServer=5.5) + +PROTOS = [ + 'accel', + 'accelc', + 'binary', + 'compact', + 'json', + 'header', +] + + +def default_servers(): + servers = [ + 'TSimpleServer', + 'TThreadedServer', + 'TThreadPoolServer', + 'TNonblockingServer', + 'THttpServer', + ] + if platform.system() != 'Windows': + servers.append('TProcessPoolServer') + servers.append('TForkingServer') + return servers + + +def relfile(fname): + return os.path.join(SCRIPT_DIR, fname) + + +def setup_pypath(libdir, gendir): + dirs = [libdir, gendir] + env = copy.deepcopy(os.environ) + pypath = env.get('PYTHONPATH', None) + if pypath: + dirs.append(pypath) + env['PYTHONPATH'] = os.pathsep.join(dirs) + if gendir.endswith('gen-py-no_utf8strings'): + env['THRIFT_TEST_PY_NO_UTF8STRINGS'] = '1' + return env + + +def runScriptTest(libdir, genbase, genpydir, script): + env = setup_pypath(libdir, os.path.join(genbase, genpydir)) + script_args = [sys.executable, relfile(script)] + print('\nTesting script: %s\n----' % (' '.join(script_args))) + ret = subprocess.call(script_args, env=env) + if ret != 0: + print('*** FAILED ***', file=sys.stderr) + print('LIBDIR: %s' % libdir, file=sys.stderr) + print('PY_GEN: %s' % genpydir, file=sys.stderr) + print('SCRIPT: %s' % script, file=sys.stderr) + raise Exception("Script subprocess failed, retcode=%d, args: %s" % (ret, ' '.join(script_args))) + + +def runServiceTest(libdir, genbase, genpydir, server_class, proto, port, use_zlib, use_ssl, verbose): + env = setup_pypath(libdir, os.path.join(genbase, genpydir)) + # Build command line arguments + server_args = [sys.executable, relfile('TestServer.py')] + cli_args = [sys.executable, relfile('TestClient.py')] + for which in (server_args, cli_args): + which.append('--protocol=%s' % proto) # accel, binary, compact or json + which.append('--port=%d' % port) # default to 9090 + if use_zlib: + which.append('--zlib') + if use_ssl: + which.append('--ssl') + if verbose == 0: + which.append('-q') + if verbose == 2: + which.append('-v') + # server-specific option to select server class + server_args.append(server_class) + # client-specific cmdline options + if server_class in FRAMED: + cli_args.append('--transport=framed') + else: + cli_args.append('--transport=buffered') + if server_class == 'THttpServer': + cli_args.append('--http=/') + if verbose > 0: + print('Testing server %s: %s' % (server_class, ' '.join(server_args))) + serverproc = subprocess.Popen(server_args, env=env) + + def ensureServerAlive(): + if serverproc.poll() is not None: + print(('FAIL: Server process (%s) failed with retcode %d') + % (' '.join(server_args), serverproc.returncode)) + raise Exception('Server subprocess %s died, args: %s' + % (server_class, ' '.join(server_args))) + + # Wait for the server to start accepting connections on the given port. + sleep_time = 0.1 # Seconds + max_attempts = 100 + attempt = 0 + while True: + sock4 = socket.socket() + sock6 = socket.socket(socket.AF_INET6) + try: + if sock4.connect_ex(('127.0.0.1', port)) == 0 \ + or sock6.connect_ex(('::1', port)) == 0: + break + attempt += 1 + if attempt >= max_attempts: + raise Exception("TestServer not ready on port %d after %.2f seconds" + % (port, sleep_time * attempt)) + ensureServerAlive() + time.sleep(sleep_time) + finally: + sock4.close() + sock6.close() + + try: + if verbose > 0: + print('Testing client: %s' % (' '.join(cli_args))) + ret = subprocess.call(cli_args, env=env) + if ret != 0: + print('*** FAILED ***', file=sys.stderr) + print('LIBDIR: %s' % libdir, file=sys.stderr) + print('PY_GEN: %s' % genpydir, file=sys.stderr) + raise Exception("Client subprocess failed, retcode=%d, args: %s" % (ret, ' '.join(cli_args))) + finally: + # check that server didn't die + ensureServerAlive() + extra_sleep = EXTRA_DELAY.get(server_class, 0) + if extra_sleep > 0 and verbose > 0: + print('Giving %s (proto=%s,zlib=%s,ssl=%s) an extra %d seconds for child' + 'processes to terminate via alarm' + % (server_class, proto, use_zlib, use_ssl, extra_sleep)) + time.sleep(extra_sleep) + sig = signal.SIGKILL if platform.system() != 'Windows' else signal.SIGABRT + os.kill(serverproc.pid, sig) + serverproc.wait() + + +class TestCases(object): + def __init__(self, genbase, libdir, port, gendirs, servers, verbose): + self.genbase = genbase + self.libdir = libdir + self.port = port + self.verbose = verbose + self.gendirs = gendirs + self.servers = servers + + def default_conf(self): + return { + 'gendir': self.gendirs[0], + 'server': self.servers[0], + 'proto': PROTOS[0], + 'zlib': False, + 'ssl': False, + } + + def run(self, conf, test_count): + with_zlib = conf['zlib'] + with_ssl = conf['ssl'] + try_server = conf['server'] + try_proto = conf['proto'] + genpydir = conf['gendir'] + # skip any servers that don't work with the Zlib transport + if with_zlib and try_server in SKIP_ZLIB: + return False + # skip any servers that don't work with SSL + if with_ssl and try_server in SKIP_SSL: + return False + if self.verbose > 0: + print('\nTest run #%d: (includes %s) Server=%s, Proto=%s, zlib=%s, SSL=%s' + % (test_count, genpydir, try_server, try_proto, with_zlib, with_ssl)) + runServiceTest(self.libdir, self.genbase, genpydir, try_server, try_proto, self.port, with_zlib, with_ssl, self.verbose) + if self.verbose > 0: + print('OK: Finished (includes %s) %s / %s proto / zlib=%s / SSL=%s. %d combinations tested.' + % (genpydir, try_server, try_proto, with_zlib, with_ssl, test_count)) + return True + + def test_feature(self, name, values): + test_count = 0 + conf = self.default_conf() + for try_server in values: + conf[name] = try_server + if self.run(conf, test_count): + test_count += 1 + return test_count + + def run_all_tests(self): + test_count = 0 + for try_server in self.servers: + for genpydir in self.gendirs: + for try_proto in PROTOS: + for with_zlib in (False, True): + # skip any servers that don't work with the Zlib transport + if with_zlib and try_server in SKIP_ZLIB: + continue + for with_ssl in (False, True): + # skip any servers that don't work with SSL + if with_ssl and try_server in SKIP_SSL: + continue + test_count += 1 + if self.verbose > 0: + print('\nTest run #%d: (includes %s) Server=%s, Proto=%s, zlib=%s, SSL=%s' + % (test_count, genpydir, try_server, try_proto, with_zlib, with_ssl)) + runServiceTest(self.libdir, self.genbase, genpydir, try_server, try_proto, self.port, with_zlib, with_ssl) + if self.verbose > 0: + print('OK: Finished (includes %s) %s / %s proto / zlib=%s / SSL=%s. %d combinations tested.' + % (genpydir, try_server, try_proto, with_zlib, with_ssl, test_count)) + return test_count + + +def main(): + parser = OptionParser() + parser.add_option('--all', action="store_true", dest='all') + parser.add_option('--genpydirs', type='string', dest='genpydirs', + default='default,slots,oldstyle,no_utf8strings,dynamic,dynamicslots', + help='directory extensions for generated code, used as suffixes for \"gen-py-*\" added sys.path for individual tests') + parser.add_option("--port", type="int", dest="port", default=9090, + help="port number for server to listen on") + parser.add_option('-v', '--verbose', action="store_const", + dest="verbose", const=2, + help="verbose output") + parser.add_option('-q', '--quiet', action="store_const", + dest="verbose", const=0, + help="minimal output") + parser.add_option('-L', '--libdir', dest="libdir", default=local_libpath(), + help="directory path that contains Thrift Python library") + parser.add_option('--gen-base', dest="gen_base", default=SCRIPT_DIR, + help="directory path that contains Thrift Python library") + parser.set_defaults(verbose=1) + options, args = parser.parse_args() + + generated_dirs = [] + for gp_dir in options.genpydirs.split(','): + generated_dirs.append('gen-py-%s' % (gp_dir)) + + # commandline permits a single class name to be specified to override SERVERS=[...] + servers = default_servers() + if len(args) == 1: + if args[0] in servers: + servers = args + else: + print('Unavailable server type "%s", please choose one of: %s' % (args[0], servers)) + sys.exit(0) + + tests = TestCases(options.gen_base, options.libdir, options.port, generated_dirs, servers, options.verbose) + + # run tests without a client/server first + print('----------------') + print(' Executing individual test scripts with various generated code directories') + print(' Directories to be tested: ' + ', '.join(generated_dirs)) + print(' Scripts to be tested: ' + ', '.join(SCRIPTS)) + print('----------------') + for genpydir in generated_dirs: + for script in SCRIPTS: + runScriptTest(options.libdir, options.gen_base, genpydir, script) + + print('----------------') + print(' Executing Client/Server tests with various generated code directories') + print(' Servers to be tested: ' + ', '.join(servers)) + print(' Directories to be tested: ' + ', '.join(generated_dirs)) + print(' Protocols to be tested: ' + ', '.join(PROTOS)) + print(' Options to be tested: ZLIB(yes/no), SSL(yes/no)') + print('----------------') + + if options.all: + tests.run_all_tests() + else: + tests.test_feature('gendir', generated_dirs) + tests.test_feature('server', servers) + tests.test_feature('proto', PROTOS) + tests.test_feature('zlib', [False, True]) + tests.test_feature('ssl', [False, True]) + + +if __name__ == '__main__': + sys.exit(main()) |