run_regression_tests.py (3383B)
1 import argparse 2 import glob 3 import sys 4 import os 5 import subprocess 6 import multiprocessing 7 from functools import partial 8 9 def is_game_path(path): 10 idx = path.rfind('.') 11 if idx < 0: 12 return False 13 14 extension = path[idx + 1:].strip().lower() 15 return extension in ["cue", "chd"] 16 17 18 def run_regression_test(runner, destdir, dump_interval, frames, renderer, cargs, gamepath): 19 args = [runner, 20 "-log", "error", 21 "-dumpdir", destdir, 22 "-dumpinterval", str(dump_interval), 23 "-frames", str(frames), 24 "-renderer", ("Software" if renderer is None else renderer), 25 ] 26 args += cargs 27 args += ["--", gamepath] 28 29 print("Running '%s'" % (" ".join(args))) 30 subprocess.run(args) 31 32 33 def run_regression_tests(runner, gamedir, destdir, dump_interval, frames, parallel, renderer, cargs): 34 paths = glob.glob(gamedir + "/*.*", recursive=True) 35 gamepaths = list(filter(is_game_path, paths)) 36 37 try: 38 if not os.path.isdir(destdir): 39 os.mkdir(destdir) 40 except OSError: 41 print("Failed to create directory") 42 return False 43 44 print("Found %u games" % len(gamepaths)) 45 46 if parallel <= 1: 47 for game in gamepaths: 48 run_regression_test(runner, destdir, dump_interval, frames, renderer, cargs, game) 49 else: 50 print("Processing %u games on %u processors" % (len(gamepaths), parallel)) 51 func = partial(run_regression_test, runner, destdir, dump_interval, frames, renderer, cargs) 52 pool = multiprocessing.Pool(parallel) 53 pool.map(func, gamepaths, chunksize=1) 54 pool.close() 55 56 57 return True 58 59 60 if __name__ == "__main__": 61 parser = argparse.ArgumentParser(description="Generate frame dump images for regression tests") 62 parser.add_argument("-runner", action="store", required=True, help="Path to DuckStation regression test runner") 63 parser.add_argument("-gamedir", action="store", required=True, help="Directory containing game images") 64 parser.add_argument("-destdir", action="store", required=True, help="Base directory to dump frames to") 65 parser.add_argument("-dumpinterval", action="store", type=int, default=600, help="Interval to dump frames at") 66 parser.add_argument("-frames", action="store", type=int, default=36000, help="Number of frames to run") 67 parser.add_argument("-parallel", action="store", type=int, default=1, help="Number of processes to run") 68 parser.add_argument("-renderer", action="store", type=str, help="Renderer to use") 69 parser.add_argument("-upscale", action="store", type=int, help="Upscale multiplier") 70 parser.add_argument("-pgxp", action="store_true", help="Enable PGXP") 71 parser.add_argument("-pgxpcpu", action="store_true", help="Enable PGXP CPU mode") 72 parser.add_argument("-cpu", action="store", help="CPU execution mode") 73 74 args = parser.parse_args() 75 cargs = [] 76 if (args.upscale is not None): 77 cargs += ["-upscale", str(args.upscale)] 78 if (args.pgxp): 79 cargs += ["-pgxp"] 80 if (args.pgxpcpu): 81 cargs += ["-pgxp-cpu"] 82 if (args.cpu is not None): 83 cargs += ["-cpu", args.cpu] 84 85 if not run_regression_tests(args.runner, os.path.realpath(args.gamedir), os.path.realpath(args.destdir), args.dumpinterval, args.frames, args.parallel, args.renderer, cargs): 86 sys.exit(1) 87 else: 88 sys.exit(0) 89