File: integration_tests.py

package info (click to toggle)
openmw 0.50.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 37,076 kB
  • sloc: cpp: 380,958; xml: 2,192; sh: 1,449; python: 911; makefile: 26; javascript: 5
file content (159 lines) | stat: -rwxr-xr-x 6,328 bytes parent folder | download
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/usr/bin/env python3

import argparse
import datetime
import os
import shutil
import subprocess
import sys
import time

from pathlib import Path

parser = argparse.ArgumentParser(description="OpenMW integration tests.")
parser.add_argument(
    "example_suite",
    type=str,
    help="path to openmw example suite (use 'git clone https://gitlab.com/OpenMW/example-suite/' to get it)",
)
parser.add_argument("--omw", type=str, default="openmw", help="path to openmw binary")
parser.add_argument(
    "--workdir", type=str, default="integration_tests_output", help="directory for temporary files and logs"
)
parser.add_argument("--verbose", action='store_true', help="print all openmw output")
args = parser.parse_args()

example_suite_dir = Path(args.example_suite).resolve()

content_paths = (
    example_suite_dir / "game_template" / "data" / "template.omwgame",
    example_suite_dir / "example_animated_creature" / "data" / "landracer.omwaddon",
    example_suite_dir / "the_hub" / "data" / "the_hub.omwaddon",
    example_suite_dir / "integration_tests" / "data" / "mwscript.omwaddon",
)
for path in content_paths:
    if not path.is_file():
        sys.exit(f"{path} is not found, use 'git clone https://gitlab.com/OpenMW/example-suite/' to get it")

openmw_binary = Path(args.omw).resolve()
if not openmw_binary.is_file():
    sys.exit(f"{openmw_binary} not found")

work_dir = Path(args.workdir).resolve()
work_dir.mkdir(parents=True, exist_ok=True)
config_dir = work_dir / "config"
userdata_dir = work_dir / "userdata"
tests_dir = Path(__file__).resolve().parent / "data" / "integration_tests"
testing_util_dir = tests_dir / "testing_util"
time_str = datetime.datetime.now().strftime("%Y-%m-%d-%H.%M.%S")


def run_test(test_name):
    start = time.time()
    print(f'[----------] Running tests from {test_name}')
    shutil.rmtree(config_dir, ignore_errors=True)
    config_dir.mkdir()
    shutil.copyfile(example_suite_dir / "settings.cfg", config_dir / "settings.cfg")
    test_dir = tests_dir / test_name
    with open(config_dir / "openmw.cfg", "w", encoding="utf-8") as omw_cfg:
        for path in content_paths:
            omw_cfg.write(f'data="{path.parent}"\n')
        omw_cfg.writelines(
            (
                f'data="{testing_util_dir}"\n',
                f'data="{example_suite_dir / "example_static_props" / "data"}"\n',
                f'data-local="{test_dir}"\n',
                f'user-data="{userdata_dir}"\n',
            )
        )
        for path in content_paths:
            omw_cfg.write(f'content={path.name}\n')
        with open(test_dir / "openmw.cfg") as stream:
            omw_cfg.write(stream.read())
    with open(config_dir / "settings.cfg", "a", encoding="utf-8") as settings_cfg:
        settings_cfg.write(
            "[Video]\n"
            "resolution x = 640\n"
            "resolution y = 480\n"
            "framerate limit = 60\n"
            "[Game]\n"
            "smooth animation transitions = true\n"
            "[Lua]\n"
            f"memory limit = {1024 * 1024 * 256}\n"
        )
    stdout_lines = list()
    test_success = True
    fatal_errors = list()
    with subprocess.Popen(
        [openmw_binary, "--replace=config", "--config", config_dir, "--no-grab"],
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        encoding="utf-8",
        env={
            "OPENMW_OSG_STATS_FILE": str(work_dir / f"{test_name}.{time_str}.osg_stats.log"),
            "OPENMW_OSG_STATS_LIST": "times",
            **os.environ,
        },
    ) as process:
        quit_requested = False
        running_test_number = None
        running_test_name = None
        count = 0
        failed_tests = list()
        test_start = None
        for line in process.stdout:
            if args.verbose:
                sys.stdout.write(line)
            else:
                stdout_lines.append(line)
            if "Quit requested by a Lua script" in line:
                quit_requested = True
            elif "TEST_START" in line:
                test_start = time.time()
                number, name = line.split("TEST_START")[1].strip().split("\t", maxsplit=1)
                running_test_number = int(number)
                running_test_name = name
                count += 1
                print(f"[ RUN      ] {running_test_name}")
            elif "TEST_OK" in line:
                duration = (time.time() - test_start) * 1000
                number, name = line.split("TEST_OK")[1].strip().split("\t", maxsplit=1)
                assert running_test_number == int(number)
                print(f"[       OK ] {running_test_name} ({duration:.3f} ms)")
            elif "TEST_FAILED" in line:
                duration = (time.time() - test_start) * 1000
                number, name, error = line.split("TEST_FAILED")[1].strip().split("\t", maxsplit=2)
                assert running_test_number == int(number)
                print(error)
                print(f"[  FAILED  ] {running_test_name} ({duration:.3f} ms)")
                failed_tests.append(running_test_name)
        process.wait(5)
        if not quit_requested:
            fatal_errors.append("unexpected termination")
        if process.returncode != 0:
            fatal_errors.append(f"openmw exited with code {process.returncode}")
    if os.path.exists(config_dir / "openmw.log"):
        shutil.copyfile(config_dir / "openmw.log", work_dir / f"{test_name}.{time_str}.log")
    if fatal_errors and not args.verbose:
        sys.stdout.writelines(stdout_lines)
    total_duration = (time.time() - start) * 1000
    print(f'\n[----------] {count} tests from {test_name} ({total_duration:.3f} ms total)')
    print(f"[  PASSED  ] {count - len(failed_tests)} tests.")
    if fatal_errors:
        print(f"[  FAILED  ] fatal error: {'; '.join(fatal_errors)}")
    if failed_tests:
        print(f"[  FAILED  ] {len(failed_tests)} tests, listed below:")
        for failed_test in failed_tests:
            print(f"[  FAILED  ] {failed_test}")
    return len(failed_tests) == 0 and not fatal_errors


status = 0
for entry in tests_dir.glob("test_*"):
    if entry.is_dir():
        if not run_test(entry.name):
            status = -1
if status == 0:
    shutil.rmtree(config_dir, ignore_errors=True)
    shutil.rmtree(userdata_dir, ignore_errors=True)
exit(status)