run-test.py (3975B)
1 #!/usr/bin/env python3 2 # This Source Code Form is subject to the terms of the Mozilla Public 3 # License, v. 2.0. If a copy of the MPL was not distributed with this 4 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 5 6 import argparse 7 import os 8 import site 9 import subprocess 10 import sys 11 from glob import glob 12 13 scriptdir = os.path.abspath(os.path.dirname(__file__)) 14 testdir = os.path.join(scriptdir, "t") 15 16 site.addsitedir(testdir) 17 from testlib import Test, equal 18 19 parser = argparse.ArgumentParser(description="run hazard analysis tests") 20 parser.add_argument( 21 "--js", default=os.environ.get("JS"), help="JS binary to run the tests with" 22 ) 23 parser.add_argument( 24 "--sixgill", 25 default=os.environ.get("SIXGILL", os.path.join(testdir, "sixgill")), 26 help="Path to root of sixgill installation", 27 ) 28 parser.add_argument( 29 "--sixgill-bin", 30 default=os.environ.get("SIXGILL_BIN"), 31 help="Path to sixgill binary dir", 32 ) 33 parser.add_argument( 34 "--sixgill-plugin", 35 default=os.environ.get("SIXGILL_PLUGIN"), 36 help="Full path to sixgill gcc plugin", 37 ) 38 parser.add_argument( 39 "--gccdir", default=os.environ.get("GCCDIR"), help="Path to GCC installation dir" 40 ) 41 parser.add_argument("--cc", default=os.environ.get("CC"), help="Path to gcc") 42 parser.add_argument("--cxx", default=os.environ.get("CXX"), help="Path to g++") 43 parser.add_argument( 44 "--verbose", 45 "-v", 46 default=0, 47 action="count", 48 help="Display verbose output, including commands executed", 49 ) 50 ALL_TESTS = [ 51 "sixgill-tree", 52 "suppression", 53 "hazards", 54 "exceptions", 55 "virtual", 56 "graph", 57 "types", 58 ] 59 parser.add_argument( 60 "tests", 61 nargs="*", 62 default=ALL_TESTS, 63 help="tests to run", 64 ) 65 66 cfg = parser.parse_args() 67 68 if not cfg.js: 69 sys.exit("Must specify JS binary through environment variable or --js option") 70 if not cfg.cc: 71 if cfg.gccdir: 72 cfg.cc = os.path.join(cfg.gccdir, "bin", "gcc") 73 else: 74 cfg.cc = "gcc" 75 if not cfg.cxx: 76 if cfg.gccdir: 77 cfg.cxx = os.path.join(cfg.gccdir, "bin", "g++") 78 else: 79 cfg.cxx = "g++" 80 if not cfg.sixgill_bin: 81 cfg.sixgill_bin = os.path.join(cfg.sixgill, "usr", "bin") 82 if not cfg.sixgill_plugin: 83 cfg.sixgill_plugin = os.path.join( 84 cfg.sixgill, "usr", "libexec", "sixgill", "gcc", "xgill.so" 85 ) 86 87 subprocess.check_call([ 88 cfg.js, 89 "-e", 90 'if (!getBuildConfiguration("has-ctypes")) quit(1)', 91 ]) 92 93 94 def binpath(prog): 95 return os.path.join(cfg.sixgill_bin, prog) 96 97 98 def make_dir(dirname, exist_ok=True): 99 try: 100 os.mkdir(dirname) 101 except OSError as e: 102 if exist_ok and e.strerror == "File exists": 103 pass 104 else: 105 raise 106 107 108 outroot = os.path.join(testdir, "out") 109 make_dir(outroot) 110 111 os.environ["HAZARD_RUN_INTERNAL_TESTS"] = "1" 112 113 exclude = [] 114 tests = [] 115 for t in cfg.tests: 116 if t.startswith("!"): 117 exclude.append(t[1:]) 118 else: 119 tests.append(t) 120 if len(tests) == 0: 121 tests = filter(lambda t: t not in exclude, ALL_TESTS) 122 123 failed = set() 124 passed = set() 125 for path in tests: 126 name = os.path.basename(path) 127 indir = os.path.join(testdir, name) 128 outdir = os.path.join(outroot, name) 129 make_dir(outdir) 130 131 test = Test(indir, outdir, cfg, verbose=cfg.verbose) 132 133 os.chdir(outdir) 134 for xdb in glob("*.xdb"): 135 os.unlink(xdb) 136 print(f"START TEST {name}", flush=True) 137 testpath = os.path.join(indir, "test.py") 138 testscript = open(testpath).read() 139 testcode = compile(testscript, testpath, "exec") 140 try: 141 exec(testcode, {"test": test, "equal": equal}) 142 except subprocess.CalledProcessError: 143 print("TEST-FAILED: %s" % name) 144 failed.add(name) 145 except AssertionError: 146 print("TEST-FAILED: %s" % name) 147 failed.add(name) 148 raise 149 else: 150 print("TEST-PASSED: %s" % name) 151 passed.add(name) 152 153 if failed: 154 raise Exception("Failed tests: " + " ".join(failed)) 155 156 print(f"All {len(passed)} tests passed.")