diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /build/scripts/run_junit.py | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'build/scripts/run_junit.py')
-rw-r--r-- | build/scripts/run_junit.py | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/build/scripts/run_junit.py b/build/scripts/run_junit.py new file mode 100644 index 00000000000..5f56403bedf --- /dev/null +++ b/build/scripts/run_junit.py @@ -0,0 +1,125 @@ +import collections +import json +import time +import os +import sys + +SHUTDOWN_SIGNAL = 'SIGUSR1' + +PROVIDES = { + "devtools/junit-runner/devtools-junit-runner.jar": "junit-runner", + "devtools/junit5-runner/devtools-junit5-runner.jar": "junit-runner", +} + + +class SignalInterruptionError(Exception): + pass + + +def on_shutdown(s, f): + raise SignalInterruptionError() + + +def get_tracefile_path(args): + return args[args.index('--output') + 1] + + +def dump_chunk_error(tracefile, name, imps): + with open(tracefile, 'a') as afile: + msg = { + "timestamp": time.time(), + "name": "chunk-event", + "value": { + "errors": [ + [ + "fail", + "[[bad]]Test contains conflicting dependencies for [[imp]]{}[[bad]]: {}[[rst]]".format( + name, ', '.join(imps) + ), + ], + ], + }, + } + json.dump(msg, afile) + afile.write("\n") + + +def verify_classpath(args): + cpfile = args[args.index('-classpath') + 1] + assert cpfile.startswith('@'), cpfile + + cpfile = cpfile[1:] + assert os.path.exists(cpfile) + + with open(cpfile) as afile: + data = afile.read().splitlines() + + collisions = collections.defaultdict(set) + for cp in data: + if cp in PROVIDES: + collisions[PROVIDES[cp]].add(cp) + + for name, imps in collisions.items(): + if len(imps) > 1: + tracefile = get_tracefile_path(args) + dump_chunk_error(tracefile, name, imps) + return False + return True + + +def main(): + args = sys.argv[1:] + + # Emulates PROVIDES(X) for junit-runner and junit5-runner. + # For more info see DEVTOOLSSUPPORT-7454 + if not verify_classpath(args): + return 1 + + def execve(): + os.execve(args[0], args, os.environ) + + jar_binary = args[args.index('--jar-binary') + 1] + java_bin_dir = os.path.dirname(jar_binary) + jstack_binary = os.path.join(java_bin_dir, 'jstack') + + if not os.path.exists(jstack_binary): + sys.stderr.write("jstack is missing: {}\n".format(jstack_binary)) + execve() + + import signal + + signum = getattr(signal, SHUTDOWN_SIGNAL, None) + + if signum is None: + execve() + + import subprocess + + proc = subprocess.Popen(args) + signal.signal(signum, on_shutdown) + timeout = False + + try: + proc.wait() + except SignalInterruptionError: + sys.stderr.write("\nGot {} signal: going to shutdown junit\n".format(signum)) + # Dump stack traces + subprocess.call([jstack_binary, str(proc.pid)], stdout=sys.stderr) + # Kill junit - for more info see DEVTOOLS-7636 + os.kill(proc.pid, signal.SIGKILL) + proc.wait() + timeout = True + + if proc.returncode: + sys.stderr.write('java exit code: {}\n'.format(proc.returncode)) + if timeout: + # In case of timeout return specific exit code + # https://a.yandex-team.ru/arc/trunk/arcadia/devtools/ya/test/const/__init__.py?rev=r8578188#L301 + proc.returncode = 10 + sys.stderr.write('java exit code changed to {}\n'.format(proc.returncode)) + + return proc.returncode + + +if __name__ == '__main__': + exit(main()) |