|
| 1 | +import sys |
| 2 | +import subprocess |
| 3 | +import fnmatch |
| 4 | +import tempfile |
| 5 | + |
| 6 | +install_dir = "../../install" |
| 7 | +temp_dir = None |
| 8 | +selected_testcase = "*" # The user might specify a pattern in order to run only a subset of all bit-trick tests. |
| 9 | +no_external_dependencies = False # suppress testcases that require external dependencies |
| 10 | +for arg in sys.argv[1:]: |
| 11 | + if arg.startswith("--prefix="): |
| 12 | + install_dir = arg[len("--prefix="):] |
| 13 | + elif arg.startswith('--tempdir='): |
| 14 | + temp_dir = arg[len('--tempdir='):] |
| 15 | + elif arg.startswith('--no-external-dependencies'): |
| 16 | + no_external_dependencies = True |
| 17 | + elif arg in ['-h', '--help']: |
| 18 | + print( |
| 19 | +"""Test script to run testcases of the "tricky program" under Derivgrind's |
| 20 | +forward-mode and bit-trick-finder instrumentation. |
| 21 | +Arguments: |
| 22 | + --prefix=path .. Path of Derivgrind installation. |
| 23 | + --tempdir=path .. Temporary directory used by this script. |
| 24 | + --no-external-dependencies |
| 25 | + .. If certain libraries required for some testcases (libgcrypt,libz) are |
| 26 | + missing, do not run these. |
| 27 | + testcase_name .. Run only a single or few testcases; "*" is a wildcard. |
| 28 | +""") |
| 29 | + exit(0) |
| 30 | + |
| 31 | + |
| 32 | + else: |
| 33 | + selected_testcase = arg |
| 34 | +if temp_dir == None: |
| 35 | + t = tempfile.TemporaryDirectory() |
| 36 | + temp_dir = t.name |
| 37 | + |
| 38 | +subprocess.run(["g++"] + (["-DTRICKTEST_NO_EXTERNAL_DEPENDENCIES"] if no_external_dependencies else []) +["tricky-program.cpp", "-o", temp_dir+"/tricky-program", "-O0", "-mfpmath=sse", "-g", "-I"+install_dir+"/include"] + ([] if no_external_dependencies else ["-lgcrypt","-lz"]) ) |
| 39 | + |
| 40 | +# Map testcase name to a tuple of booleans. |
| 41 | +# The first element indicates whether external dependencies are required. |
| 42 | +# The secomd element indicates whether a wrong derivative is reported as an error. |
| 43 | +# As we mostly test unsupported bit-tricks here, this will usually be False. |
| 44 | +# The third element indicates whether a wrong derivative without bit-trick finder |
| 45 | +# warning is reported as an error. This is usually True, except for known false negatives. |
| 46 | +tests = { |
| 47 | + "integer_addition_to_exponent_double": (False,False,True), |
| 48 | + "integer_addition_to_exponent_float": (False,False,True), |
| 49 | + "incomplete_masking_to_perform_frexp_double": (False,False,True), |
| 50 | + "incomplete_masking_to_perform_frexp_float": (False,False,True), |
| 51 | + "exploiting_imprecisions_for_rounding_double": (False,False,False), |
| 52 | + "exploiting_imprecisions_for_rounding_float": (False,False,False), |
| 53 | + "encrypt_decrypt": (True,False,True), |
| 54 | + "compress_inflate": (True,False,False), |
| 55 | + "multiple_mmap": (True,False,False), |
| 56 | +} |
| 57 | +fail = False |
| 58 | +for test in tests: |
| 59 | + if fnmatch.fnmatchcase(test,selected_testcase): |
| 60 | + print(test+":") |
| 61 | + # If test requires external dependencies but they are disabled, skip. |
| 62 | + if tests[test][0] and no_external_dependencies: |
| 63 | + print(" ext deps disabled - SKIP") |
| 64 | + continue |
| 65 | + |
| 66 | + # Test correctness of forward-mode derivatives. |
| 67 | + forwardrun = subprocess.run([install_dir+"/bin/valgrind", "--tool=derivgrind", temp_dir+"/tricky-program", test], capture_output=True) |
| 68 | + forward_correct = (forwardrun.stdout.decode("utf-8").find("WRONG FORWARD-MODE DERIVATIVE")==-1) |
| 69 | + if forward_correct: |
| 70 | + forward_output = "correct derivative - OK " |
| 71 | + elif not tests[test][1]: |
| 72 | + forward_output = "wrong derivative - OK " |
| 73 | + else: |
| 74 | + forward_output = "wrong derivative - FAIL" |
| 75 | + fail = True |
| 76 | + print(" "+forward_output) |
| 77 | + |
| 78 | + # Test whether the bit-trick finding instrumentation produces a warning. |
| 79 | + trickrun = subprocess.run([install_dir+"/bin/valgrind", "--tool=derivgrind", "--trick=yes", temp_dir+"/tricky-program", test], capture_output=True) |
| 80 | + trick_found = (trickrun.stderr.decode("utf-8").find("Active discrete data used as floating-point operand.")!=-1) |
| 81 | + if trick_found: |
| 82 | + trick_output = "trick found - OK " |
| 83 | + elif not tests[test][2]: |
| 84 | + trick_output = "trick not found - OK " |
| 85 | + else: |
| 86 | + trick_output = "trick not found - FAIL" |
| 87 | + fail = True |
| 88 | + print(" "+trick_output) |
| 89 | + |
| 90 | +exit(fail) |
| 91 | + |
| 92 | + |
| 93 | + |
0 commit comments