File: demo_checker.py

package info (click to toggle)
seqan2 2.4.0%2Bdfsg-16
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 224,180 kB
  • sloc: cpp: 256,886; ansic: 91,672; python: 8,330; sh: 995; xml: 570; makefile: 252; awk: 51; javascript: 21
file content (121 lines) | stat: -rwxr-xr-x 4,776 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/usr/bin/env python3
"""Demo checker script.

Given a demo .cpp file PATH.cpp we can make it a small test if there is a file
PATH.cpp.stdout and/or PATH.cpp.stderr.  The test is implemented using this
script.

The script is called with the options --binary-path and one or both of
--stdout-path and --stderr-path.  The demo is executed and the test succeeds
if the exit code is 0 and the standard/error output is the same as in the
.stdout/.stderr file.  If there is output and the file is missing then this is
a failure as well.
"""

__author__ = """Manuel Holtgrewe <manuel.holtgrewe@fu-berlin.de>
                Temesgen H. Dadi <temesgen.dadi@fu-berlin.de>
            """


import argparse
import difflib
import subprocess
import sys
import re

def t(s):
    """Force Windows line endings to Unix line endings."""
    return s.replace("\r\n", "\n")

def fuzzyEqual(pattern, text):
    """checks if the expected output is eqal to the actualoutput using a reqex
        use the literal [VAR] if the part of the output is not expected to be the same all the time.
    """
    if len(pattern) != len(text):
        print('Number of lines differ. Expected output has %s lines whereas actual has %s lines.' % (len(pattern), len(text)), file=sys.stderr)
        return False
    for i in range(len(pattern)):
        T = text[i]
        P = pattern[i]
        if T == P :
            continue
        else :
            if '[VAR]' not in P:
                print('Line %s is different between expected and actual outputs.' % (i), file=sys.stderr)
                return False
            else:
                P = (re.escape(P)).replace('\\[VAR\\]', "[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?")
                r = re.compile(P)
                if re.match(r, T) == None:
                    print('Line %s is different (REGEX) between expected and actual outputs.' % (i), file=sys.stderr)
                    return False
    return True

def loadExpected(args):
    """Load the expected file contents."""
    out, err = b'', b''
    if args.stdout_path:
        with open(args.stdout_path, 'rb') as f:
            out = f.read()
    if args.stderr_path:
        with open(args.stderr_path, 'rb') as f:
            err = f.read()
    return t(out.decode('utf8').strip()).split('\n'), t(err.decode('utf8').strip()).split('\n')


def runDemo(args):
    cmd = [args.binary_path]
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdoutbuff, stderrbuff = p.communicate()
    return t(stdoutbuff.decode('utf8').strip()).split('\n'), t(stderrbuff.decode('utf8').strip()).split('\n'), p.returncode


def main():
    """Program entry point."""
    parser = argparse.ArgumentParser(description='Run SeqAn demos as apps.')
    parser.add_argument('--binary-path', dest='binary_path', required='True',
                        help='Path to the demo binary to execute.')
    parser.add_argument('--stdout-path', dest='stdout_path',
                        help='Path to standard out file to compare to.',
                        default=None)
    parser.add_argument('--stderr-path', dest='stderr_path',
                        help='Path to standard error file to compare to.',
                        default=None)
    args = parser.parse_args()

    print('Running %s.' % args.binary_path, file=sys.stderr)
    actual_out, actual_err, ret = runDemo(args)

    if ret != 0:
        print('ERROR: Return code of %s was %s.' % (args.binary_path, ret), file=sys.stderr)
        return 1
    else:
        print('Return code was %s.' % ret, file=sys.stderr)

    print('Loading files "%s", "%s".' % (args.stdout_path, args.stderr_path), file=sys.stderr)
    expected_out, expected_err = loadExpected(args)
    is_stdout_as_expected = fuzzyEqual(expected_out, actual_out)
    is_stderr_as_expected = fuzzyEqual(expected_err, actual_err)

    if not is_stdout_as_expected:
        print('The standard output was not as expected!', file=sys.stderr)
        l = difflib.context_diff(expected_out, actual_out,
                                 fromfile='expected', tofile='actual')
        print('\n'.join(l), file=sys.stderr)
    else:
        print('Standard output was as expected.', file=sys.stderr)

    if not is_stderr_as_expected:
        print('The standard error was not as expected!', file=sys.stderr)
        l = difflib.context_diff(expected_err, actual_err,
                                 fromfile='expected', tofile='actual')
        print('\n'.join(l), file=sys.stderr)
    else:
        print('Standard error was as expected.', file=sys.stderr)

    # here we used not because we need return-code 0 (False) if test is successful 
    return not (is_stdout_as_expected and is_stderr_as_expected)


if __name__ == '__main__':
    sys.exit(main())