aboutsummaryrefslogtreecommitdiffstats
path: root/build/scripts/run_junit.py
blob: 380d25e6a7f7292d399bcbda63c2ff09b1d9235e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import json
import os
import sys

SHUTDOWN_SIGNAL = 'SIGUSR1'


class SignalInterruptionError(Exception):
    pass


def on_shutdown(s, f):
    raise SignalInterruptionError()


def mkdir_p(directory):
    if not os.path.exists(directory):
        os.makedirs(directory)


def _resolve_tmpdir_to_ram_drive_path(args):
    java_io_tmpdir_arg = '-Djava.io.tmpdir='
    for i, arg in enumerate(args):
        if arg.startswith(java_io_tmpdir_arg) and arg.split('=')[-1] == "${YA_TEST_JAVA_TMP_DIR}":
            try:
                with open(os.environ['YA_TEST_CONTEXT_FILE']) as afile:
                    context = json.load(afile)
                ram_tmpdir = context['runtime']['ram_drive_path']
            except Exception as e:
                ram_tmpdir = os.path.join(os.getcwd(), 'tests_tmp_dir')
                msg = "Warning: temp dir on ram drive was requested but ram drive path couldn't be obtained "
                msg += 'from context file due to error {!r}. '.format(e)
                msg += 'Temp dir in cwd will be used instead: {}\n'.format(ram_tmpdir)
                sys.stderr.write(msg)
                mkdir_p(ram_tmpdir)
            args[i] = java_io_tmpdir_arg + ram_tmpdir
            return


def main():
    args = sys.argv[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.exe' if sys.platform == 'win32' else 'jstack')

    _resolve_tmpdir_to_ram_drive_path(args)

    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())