File: check_test_times.py

package info (click to toggle)
quantlib 1.40-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 41,768 kB
  • sloc: cpp: 398,987; makefile: 6,574; python: 214; sh: 150; lisp: 86
file content (102 lines) | stat: -rw-r--r-- 2,706 bytes parent folder | download | duplicates (3)
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
import re
import sys
import xml.etree.ElementTree as ET
from collections import namedtuple, defaultdict

regex1 = re.compile(".*test_case\(&(.*?)__(.*?)\)")
regex2 = re.compile(".*ext__bind\(&(.*?)__(.*?)__.*\)\)")
regex3 = re.compile(".*{_?([a-zA-Z]*Test)__([a-zA-Z]*?)\(")
regex4 = re.compile("([^.]+)\.(.+)")

def parse_simple(t):
    # test names get mangled - here we extract class and method name
    m = regex1.match(t.attrib["name"])
    if m:
        return m.groups()


def parse_bound(t):
    # same, for cases inside a bind
    m = regex2.match(t.attrib["name"])
    if m:
        return m.groups()


def parse_lambda(t):
    # same, for cases inside a lambda
    m = regex3.match(t.attrib["name"])
    if m:
        return m.groups()

def parse_simple_auto_generated(t):
    # used for classname generated by automated registration using boost test
    m = regex4.match(t.attrib["classname"])
    if m:
        return m.groups()[1], t.attrib["name"]

def extract_test_info(filename):
    root = ET.parse(filename).getroot()
    tests = root.findall("testcase")
    for t in tests:
        if t.findall("skipped"):
            continue
        cls, method = parse_simple(t) or parse_bound(t) or parse_lambda(t) or parse_simple_auto_generated(t)
        time = float(t.attrib["time"])
        yield (cls, method, time)


Case = namedtuple("Case", ["files", "times"])


def collect():
    data = defaultdict(lambda: Case([], []))
    for filename in ["faster.xml", "fast.xml", "all.xml"]:
        for cls, method, time in extract_test_info(filename):
            c = data[(cls, method)]
            c.files.append(filename)
            c.times.append(time)
    return data


def check(data, condition, action):
    errors = False
    for cls, method in data:
        c = data[(cls, method)]
        if condition(c):
            print(
                f"{cls}.{method} ({min(c.times):.2f} s / {max(c.times):.2f} s) {action}"
            )
            errors = True
    return errors


data = collect()

errors = check(
    data,
    lambda c: "faster.xml" in c.files and min(c.times) > 3.0,
    "should be moved out of the 'Faster' section",
)
errors |= check(
    data,
    lambda c: "fast.xml" in c.files and min(c.times) > 8.0,
    "should be moved out of the 'Fast' section",
)
errors |= check(
    data, lambda c: max(c.times) > 30.0, "should be kept reliably under 30 seconds"
)

errors |= check(
    data,
    lambda c: "faster.xml" not in c.files and max(c.times) < 1.0,
    "could be moved into the 'Faster' section",
)
errors |= check(
    data,
    lambda c: "fast.xml" not in c.files and max(c.times) < 3.0,
    "could be moved into the 'Fast' section",
)


if errors:
    sys.exit(1)