diff -U2 -r /var/lib/copr-rpmbuild/results/openmw-git/upstream-unpacked/Source0/openmw-master/CI/run_integration_tests.sh /var/lib/copr-rpmbuild/results/openmw-git/srpm-unpacked/openmw-master.tar.bz2-extract/openmw-master/CI/run_integration_tests.sh --- /var/lib/copr-rpmbuild/results/openmw-git/upstream-unpacked/Source0/openmw-master/CI/run_integration_tests.sh 2026-08-25 23:35:46.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/openmw-git/srpm-unpacked/openmw-master.tar.bz2-extract/openmw-master/CI/run_integration_tests.sh 2026-08-25 22:10:48.000000000 +0000 @@ -10,15 +10,5 @@ xvfb-run --auto-servernum --server-args='-screen 0 640x480x24x60' \ - scripts/integration_tests.py \ - --verbose \ - --omw build/install/bin/openmw \ - --workdir integration_tests_output \ - --config example-suite \ - --data example-suite/game_template/data \ - --data example-suite/example_animated_creature/data \ - --data example-suite/the_hub/data \ - --data example-suite/integration_tests/data \ - --data example-suite/example_static_props/data \ - scripts/data/integration_tests + scripts/integration_tests.py --verbose --omw build/install/bin/openmw --workdir integration_tests_output example-suite/ ls integration_tests_output/*.osg_stats.log | while read v; do diff -U2 -r /var/lib/copr-rpmbuild/results/openmw-git/upstream-unpacked/Source0/openmw-master/scripts/data/integration_tests/test_lua_api/openmw.cfg /var/lib/copr-rpmbuild/results/openmw-git/srpm-unpacked/openmw-master.tar.bz2-extract/openmw-master/scripts/data/integration_tests/test_lua_api/openmw.cfg --- /var/lib/copr-rpmbuild/results/openmw-git/upstream-unpacked/Source0/openmw-master/scripts/data/integration_tests/test_lua_api/openmw.cfg 2026-08-25 23:35:46.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/openmw-git/srpm-unpacked/openmw-master.tar.bz2-extract/openmw-master/scripts/data/integration_tests/test_lua_api/openmw.cfg 2026-08-25 22:10:48.000000000 +0000 @@ -1,13 +1,2 @@ -replace=config -no-grab=1 -config=test_workdir -user-data=test_workdir -data-local=test_workdir -data=../testing_util -data=. -content=template.omwgame -content=landracer.omwaddon -content=the_hub.omwaddon -content=mwscript.omwaddon content=test_lua_api.omwscripts diff -U2 -r /var/lib/copr-rpmbuild/results/openmw-git/upstream-unpacked/Source0/openmw-master/scripts/data/morrowind_tests/README.md /var/lib/copr-rpmbuild/results/openmw-git/srpm-unpacked/openmw-master.tar.bz2-extract/openmw-master/scripts/data/morrowind_tests/README.md --- /var/lib/copr-rpmbuild/results/openmw-git/upstream-unpacked/Source0/openmw-master/scripts/data/morrowind_tests/README.md 2026-08-25 23:35:46.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/openmw-git/srpm-unpacked/openmw-master.tar.bz2-extract/openmw-master/scripts/data/morrowind_tests/README.md 2026-08-25 22:10:48.000000000 +0000 @@ -3,6 +3,5 @@ A set of scripts to provide integration tests based on Morrowind content. -Simple usage using default user configuration: - +Simple usage: ```bash "${OPENMW_BINARY_DIR:?}/openmw" \ @@ -10,12 +9,2 @@ --data "${MORROWIND_DATA_DIR:?}" ``` - -Or using dedicated configuration based on Morrowind.ini: - -```bash -scripts/integration_tests.py \ - --omw "${OPENMW_BINARY_DIR:?}/openmw" \ - --data "${MORROWIND_DIR:?}/Data Files" \ - --ini "${MORROWIND_DIR:?}/Morrowind.ini" \ - scripts/data/morrowind_tests -``` diff -U2 -r /var/lib/copr-rpmbuild/results/openmw-git/upstream-unpacked/Source0/openmw-master/scripts/integration_tests.py /var/lib/copr-rpmbuild/results/openmw-git/srpm-unpacked/openmw-master.tar.bz2-extract/openmw-master/scripts/integration_tests.py --- /var/lib/copr-rpmbuild/results/openmw-git/upstream-unpacked/Source0/openmw-master/scripts/integration_tests.py 2026-08-25 23:35:46.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/openmw-git/srpm-unpacked/openmw-master.tar.bz2-extract/openmw-master/scripts/integration_tests.py 2026-08-25 22:10:48.000000000 +0000 @@ -11,39 +11,53 @@ from pathlib import Path -def parse_args(): - parser = argparse.ArgumentParser(description="OpenMW integration tests.") - parser.add_argument( - "suites", - nargs='*', - type=str, - default=None, - help="suites to run: a directory with suites or subdirectories containing them", - ) - 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") - parser.add_argument( - "--test_filter", type=str, default=None, - help="test cases to run (e.g. 'player.*running')", - ) - parser.add_argument( - "--list_tests", action='store_true', - help="print test names instead of running them", - ) - parser.add_argument( - "--config", type=str, default=None, - help="extra directory with custom settings.cfg", - ) - parser.add_argument( - "--data", action='append', default=[], - help="extra data directories with content files", - ) - parser.add_argument( - "--ini", type=str, default=None, - help="INI file to import fallback values from via openmw-iniimporter (found next to --omw)", - ) - return parser.parse_args() +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") +parser.add_argument( + "--tests", nargs='+', default=None, + help="tests to run (directory names under scripts/data/integration_tests)", +) +parser.add_argument( + "--test_filter", type=str, default=None, + help="test cases to run (e.g. 'player.*running')", +) +parser.add_argument( + "--list_tests", action='store_true', + help="print test names instead of running them", +) +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" +test_config_dir = work_dir / "test_config" +time_str = datetime.datetime.now().strftime("%Y-%m-%d-%H.%M.%S") @@ -53,27 +67,11 @@ -def discover_suites(suite_roots): - all_suites = dict() - for root in suite_roots: - if not root.is_dir(): - sys.exit(f"{root} is not a directory") - if (root / "openmw.cfg").is_file(): - all_suites[root.name] = root - else: - for entry in sorted(root.glob("test_*")): - if entry.is_dir() and (entry / "openmw.cfg").is_file(): - all_suites[entry.name] = entry - if not all_suites: - sys.exit(f"No suites found in: {', '.join(str(v) for v in suite_roots)}") - return all_suites - - -def write_test_config_module(test_config_dir, test_filter, list_tests): +def write_test_config_module(): shutil.rmtree(test_config_dir, ignore_errors=True) test_config_dir.mkdir(parents=True) fields = [] - if test_filter: - fields.append(f"filter = {lua_string_literal(test_filter)}") - if list_tests: + if args.test_filter: + fields.append(f"filter = {lua_string_literal(args.test_filter)}") + if args.list_tests: fields.append("list = true") with open(test_config_dir / "test_config.lua", "w", encoding="utf-8") as stream: @@ -85,29 +83,29 @@ -def write_generated_config( - config_dir, userdata_dir, data_local_dir, test_config_dir, config_source_dir, args, iniimporter_binary, ini_path -): +def run_test(test_name): + start = time.time() + if not args.list_tests: + print(f'[----------] Running tests from {test_name}') shutil.rmtree(config_dir, ignore_errors=True) - config_dir.mkdir(parents=True) - base_cfg_path = config_dir / ("openmw.base.cfg" if args.ini else "openmw.cfg") - with open(base_cfg_path, "w", encoding="utf-8") as omw_cfg: - omw_cfg.write(f'user-data="{userdata_dir}"\n') - omw_cfg.write(f'data-local="{data_local_dir}"\n') - omw_cfg.write(f'data="{test_config_dir}"\n') - if args.ini: - subprocess.run( - [ - iniimporter_binary, - "--ini", ini_path, - "--cfg", base_cfg_path, - "--output", config_dir / "openmw.cfg", - ], - check=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', + ) ) - with open(config_dir / "settings.cfg", "w", encoding="utf-8") as settings_cfg: - if config_source_dir is not None: - source_settings = config_source_dir / "settings.cfg" - if source_settings.is_file(): - settings_cfg.write(source_settings.read_text(encoding="utf-8")) + omw_cfg.write(f'data="{test_config_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" @@ -121,22 +119,14 @@ "lua profiler = true\n" ) - - -def run_test(suite_name, suite_dir, config_dir, log_dir, time_str, data_dirs, args, openmw_binary): - start = time.time() - if not args.list_tests: - print(f'[----------] Running tests from {suite_name}') - command = [openmw_binary, "--replace=config", "--config", suite_dir, "--config", config_dir, "--no-grab"] - for path in data_dirs: - command += ["--data", path] stdout_lines = list() + test_success = True fatal_errors = list() with subprocess.Popen( - command, + [openmw_binary, "--replace=config", "--config", config_dir, "--no-grab"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding="utf-8", env={ - "OPENMW_OSG_STATS_FILE": str(log_dir / f"{suite_name}.{time_str}.osg_stats.log"), + "OPENMW_OSG_STATS_FILE": str(work_dir / f"{test_name}.{time_str}.osg_stats.log"), "OPENMW_OSG_STATS_LIST": "times", **os.environ, @@ -188,10 +178,10 @@ fatal_errors.append(f"openmw exited with code {process.returncode}") if os.path.exists(config_dir / "openmw.log"): - shutil.copyfile(config_dir / "openmw.log", log_dir / f"{suite_name}.{time_str}.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) if not args.list_tests: total_duration = (time.time() - start) * 1000 - print(f'\n[----------] {count} tests from {suite_name} ({total_duration:.3f} ms total)') + print(f'\n[----------] {count} tests from {test_name} ({total_duration:.3f} ms total)') print(f"[ PASSED ] {count - len(failed_tests)} tests.") if fatal_errors: @@ -204,67 +194,28 @@ -def main(): - args = parse_args() - - openmw_binary = Path(args.omw).resolve() - if not openmw_binary.is_file(): - sys.exit(f"{openmw_binary} not found") - - iniimporter_binary = None - ini_path = None - if args.ini: - ini_path = Path(args.ini).resolve() - if not ini_path.is_file(): - sys.exit(f"{ini_path} not found") - iniimporter_binary = openmw_binary.parent / f"openmw-iniimporter{openmw_binary.suffix}" - if not iniimporter_binary.is_file(): - sys.exit(f"{iniimporter_binary} not found") - - config_source_dir = Path(args.config).resolve() if args.config is not None else None - data_dirs = [Path(v).resolve() for v in args.data] - - work_dir = Path(args.workdir).resolve() - work_dir.mkdir(parents=True, exist_ok=True) - test_config_dir = work_dir / "test_config" - time_str = datetime.datetime.now().strftime("%Y-%m-%d-%H.%M.%S") - - suite_roots = [Path(v).resolve() for v in args.suites] - all_suites = discover_suites(suite_roots) - - write_test_config_module(test_config_dir=test_config_dir, test_filter=args.test_filter, list_tests=args.list_tests) - - status = 0 - total_count = 0 - for name in sorted(all_suites): - suite_work_dir = work_dir / name - write_generated_config( - config_dir=suite_work_dir, - userdata_dir=suite_work_dir / "userdata", - data_local_dir=suite_work_dir / "data-local", - test_config_dir=test_config_dir, - config_source_dir=config_source_dir, - args=args, - iniimporter_binary=iniimporter_binary, - ini_path=ini_path, - ) - result, count = run_test( - suite_name=name, - suite_dir=all_suites[name], - config_dir=suite_work_dir, - log_dir=work_dir, - time_str=time_str, - data_dirs=data_dirs, - args=args, - openmw_binary=openmw_binary, - ) - total_count += count - if not result: - status = -1 - if args.test_filter and total_count == 0: - print(f"[ WARNING ] no tests matched --test_filter {args.test_filter!r}") +all_suites = sorted(entry.name for entry in tests_dir.glob("test_*") if entry.is_dir()) +if args.tests: + unknown = [name for name in args.tests if name not in all_suites] + if unknown: + sys.exit(f"Unknown test suite(s): {', '.join(unknown)}") + suites_to_run = args.tests +else: + suites_to_run = all_suites + +write_test_config_module() + +status = 0 +total_count = 0 +for name in suites_to_run: + result, count = run_test(name) + total_count += count + if not result: status = -1 - exit(status) - - -if __name__ == "__main__": - main() +if args.test_filter and total_count == 0: + print(f"[ WARNING ] no tests matched --test_filter {args.test_filter!r}") + status = -1 +if status == 0: + shutil.rmtree(config_dir, ignore_errors=True) + shutil.rmtree(userdata_dir, ignore_errors=True) + shutil.rmtree(test_config_dir, ignore_errors=True) +exit(status)