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=["sixgill-tree", "suppression", "hazards", "exceptions", "virtual"], 55 help="tests to run", 56) 57 58cfg = parser.parse_args() 59 60if not cfg.js: 61 exit("Must specify JS binary through environment variable or --js option") 62if not cfg.cc: 63 if cfg.gccdir: 64 cfg.cc = os.path.join(cfg.gccdir, "bin", "gcc") 65 else: 66 cfg.cc = "gcc" 67if not cfg.cxx: 68 if cfg.gccdir: 69 cfg.cxx = os.path.join(cfg.gccdir, "bin", "g++") 70 else: 71 cfg.cxx = "g++" 72if not cfg.sixgill_bin: 73 cfg.sixgill_bin = os.path.join(cfg.sixgill, "usr", "bin") 74if not cfg.sixgill_plugin: 75 cfg.sixgill_plugin = os.path.join( 76 cfg.sixgill, "usr", "libexec", "sixgill", "gcc", "xgill.so" 77 ) 78 79subprocess.check_call( 80 [cfg.js, "-e", 'if (!getBuildConfiguration()["has-ctypes"]) quit(1)'] 81) 82 83 84def binpath(prog): 85 return os.path.join(cfg.sixgill_bin, prog) 86 87 88def make_dir(dirname, exist_ok=True): 89 try: 90 os.mkdir(dirname) 91 except OSError as e: 92 if exist_ok and e.strerror == "File exists": 93 pass 94 else: 95 raise 96 97 98outroot = os.path.join(testdir, "out") 99make_dir(outroot) 100 101failed = set() 102for name in cfg.tests: 103 name = os.path.basename(name) 104 indir = os.path.join(testdir, name) 105 outdir = os.path.join(outroot, name) 106 make_dir(outdir) 107 108 test = Test(indir, outdir, cfg, verbose=cfg.verbose) 109 110 os.chdir(outdir) 111 for xdb in glob("*.xdb"): 112 os.unlink(xdb) 113 print("START TEST {}".format(name), flush=True) 114 testpath = os.path.join(indir, "test.py") 115 testscript = open(testpath).read() 116 testcode = compile(testscript, testpath, "exec") 117 try: 118 exec(testcode, {"test": test, "equal": equal}) 119 except subprocess.CalledProcessError: 120 print("TEST-FAILED: %s" % name) 121 failed.add(name) 122 except AssertionError: 123 print("TEST-FAILED: %s" % name) 124 failed.add(name) 125 raise 126 else: 127 print("TEST-PASSED: %s" % name) 128 129if failed: 130 raise Exception("Failed tests: " + " ".join(failed)) 131