|
| 1 | +#!/usr/bin/env python3 |
| 2 | +""" |
| 3 | +""" |
| 4 | + |
| 5 | +import argparse, tempfile, subprocess, re, sys, os, webbrowser |
| 6 | +from os.path import exists, isdir, isfile |
| 7 | + |
| 8 | +_ERR_PREFIX = "\033[31mcode-coverage-test-gap.py: error: " |
| 9 | +_INFO_PREFIX = "\033[40;38;5;82m" |
| 10 | + |
| 11 | +_PARSER = argparse.ArgumentParser( |
| 12 | + prog="code-coverage-test-gap.py", usage="%(prog)s [options]" |
| 13 | +) |
| 14 | +_PARSER.add_argument( |
| 15 | + "tstfiles", |
| 16 | + nargs="+", |
| 17 | + type=str, |
| 18 | + help="the test files you want to check code coverage for" |
| 19 | + + "(must be at least one)", |
| 20 | +) |
| 21 | +_PARSER.add_argument( |
| 22 | + "--gap-root", |
| 23 | + nargs="?", |
| 24 | + type=str, |
| 25 | + help="the gap root directory (default: ~/gap)", |
| 26 | + default="~/gap/", |
| 27 | +) |
| 28 | +_PARSER.add_argument( |
| 29 | + "--open", |
| 30 | + nargs="?", |
| 31 | + type=str, |
| 32 | + help=("open the html page for this file " + "(default: None)"), |
| 33 | + default=None, |
| 34 | +) |
| 35 | + |
| 36 | +_ARGS = _PARSER.parse_args() |
| 37 | +if not _ARGS.gap_root[-1] == "/": |
| 38 | + _ARGS.gap_root += "/" |
| 39 | + |
| 40 | +if exists("gap") and isdir("gap"): |
| 41 | + _PROFILE_DIR = "/gap/" |
| 42 | +elif exists("lib") and isdir("lib"): |
| 43 | + _PROFILE_DIR = "/lib/" |
| 44 | +else: |
| 45 | + sys.exit(_ERR_PREFIX + "no directory gap or lib to profile!\033[0m") |
| 46 | + |
| 47 | +_ARGS.gap_root = os.path.expanduser(_ARGS.gap_root) |
| 48 | +if not (exists(_ARGS.gap_root) and isdir(_ARGS.gap_root)): |
| 49 | + sys.exit(_ERR_PREFIX + "can't find GAP root directory!\033[0m") |
| 50 | + |
| 51 | +for f in _ARGS.tstfiles: |
| 52 | + if not (exists(f) and isfile(f)): |
| 53 | + sys.exit(_ERR_PREFIX + f + " does not exist!\033[0m") |
| 54 | + |
| 55 | +_DIR = tempfile.mkdtemp() |
| 56 | +print(f"{_INFO_PREFIX}Using temporary directory: {_DIR}\033[0m") |
| 57 | + |
| 58 | +_COMMANDS = 'echo "' |
| 59 | +for f in _ARGS.tstfiles: |
| 60 | + _COMMANDS += f'Test(\\"{f}\\");;\n' |
| 61 | +_COMMANDS += ( |
| 62 | + '''UncoverageLineByLine();; |
| 63 | +LoadPackage(\\"profiling\\", false);; |
| 64 | +filesdir := \\"''' |
| 65 | + + os.getcwd() |
| 66 | + + _PROFILE_DIR |
| 67 | + + """\\";;\n""" |
| 68 | +) |
| 69 | +_COMMANDS += 'outdir := \\"' + _DIR + '\\";;\n' |
| 70 | +_COMMANDS += 'x := ReadLineByLineProfile(\\"' + _DIR + '/profile.gz\\");;\n' |
| 71 | +_COMMANDS += 'OutputAnnotatedCodeCoverageFiles(x, filesdir, outdir);"' |
| 72 | + |
| 73 | +pro1 = subprocess.Popen(_COMMANDS, stdout=subprocess.PIPE, shell=True) |
| 74 | +_RUN_GAP = _ARGS.gap_root + "gap -A -m 1g -T --cover " + _DIR + "/profile.gz" |
| 75 | + |
| 76 | +try: |
| 77 | + pro2 = subprocess.Popen(_RUN_GAP, stdin=pro1.stdout, shell=True) |
| 78 | + pro2.wait() |
| 79 | +except KeyboardInterrupt: |
| 80 | + pro1.terminate() |
| 81 | + pro1.wait() |
| 82 | + pro2.terminate() |
| 83 | + pro2.wait() |
| 84 | + sys.exit("\033[31mKilled!\033[0m") |
| 85 | +except (subprocess.CalledProcessError, IOError, OSError): |
| 86 | + sys.exit(_ERR_PREFIX + "Something went wrong calling GAP!\033[0m") |
| 87 | + |
| 88 | +suffix = "" |
| 89 | +if _ARGS.open: |
| 90 | + filename = ( |
| 91 | + _DIR |
| 92 | + + "/" |
| 93 | + + os.getcwd().replace("/", "_") |
| 94 | + + "_" |
| 95 | + + _ARGS.open.replace("/", "_") |
| 96 | + + ".html" |
| 97 | + ) |
| 98 | + p = re.compile(r"<tr class='missed'><td><a name=\"line(\d+)\">") |
| 99 | + with open(filename, "r") as f: |
| 100 | + m = p.search(f.read()) |
| 101 | + if m: |
| 102 | + suffix += f"#line{m.group(1)}" |
| 103 | +else: |
| 104 | + filename = _DIR + "/index.html" |
| 105 | + |
| 106 | +if exists(filename) and isfile(filename): |
| 107 | + if _ARGS.open: |
| 108 | + filename += suffix |
| 109 | + try: |
| 110 | + webbrowser.get("safari").open(f"file://{filename}", new=2) |
| 111 | + except Exception: |
| 112 | + webbrowser.open(f"file://{filename}", new=2) |
| 113 | +else: |
| 114 | + sys.exit(f"\n{_ERR_PREFIX}Failed to open file://{filename}\033[0m") |
| 115 | + |
| 116 | +print(f"\n{_INFO_PREFIX}SUCCESS!\033[0m") |
| 117 | +sys.exit(0) |
0 commit comments