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