Skip to content

Commit 1880d21

Browse files
committed
Odin: post processing hook to flip expected failures to success
1 parent ac0f405 commit 1880d21

File tree

2 files changed

+101
-43
lines changed

2 files changed

+101
-43
lines changed

ODIN_II/regression_test/parse_result/conf/hooks.py

Lines changed: 86 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,58 +2,105 @@
22
import pwd
33
import re
44
import sys
5+
from collections import OrderedDict
6+
import json
57

6-
HOOKS = [
7-
'strip_paths',
8-
'anonymize',
9-
'make_expected_failures_pass',
10-
'patch_logs'
8+
PRE_HOOKS = [
9+
# nothing
1110
]
1211

13-
def strip_paths(line):
12+
POST_HOOKS = [
13+
'drop_entries_on_failure',
14+
'patch_logs',
15+
'inverse_result_from_expectation'
16+
]
17+
18+
def do_something_on_the_raw_log(line: str):
1419
"""
15-
strip all path from known file extensions
16-
this can prevent broken test do to mismatch in path
20+
this is an example preprocessing hook.
1721
"""
18-
# its a bit limiting, maybe a better regex would do
19-
# but it seems to work fine for now
20-
path_regex = r"[\/]?[a-zA-Z_.\-0-9]*\/"
21-
file_regex = r"[^\/\s]*(_input|_output|\.xml|\.v|\.vh|\.blif|\.log|\.do|\.dot|_vectors|_activity)"
22-
return re.sub(r"(" + path_regex + r")+(?=" + file_regex + r"[\s\n]+)", "", line)
22+
return line
2323

24-
def anonymize(line):
24+
def do_something_on_the_parsed_log(values: OrderedDict):
2525
"""
26-
strip all occurance of this user in the log file
26+
this is an example post-processing hook.
2727
"""
28-
user_name = pwd.getpwuid(os.getuid()).pw_name
29-
return re.sub(r"(" + user_name + r")", "",line)
30-
28+
# if 'exit' in values:
29+
# # do
3130

32-
def patch_logs(line):
31+
return values
32+
33+
34+
def drop_entries_on_failure(values):
3335
"""
34-
Some librairies and tools Odin uses can have different display messages
35-
we do replacements for possible mismatch to stop false positives
36-
we don't use regex
36+
if we failed we drop the folowing sections
37+
Failure may happen late in the log, so we may still end up parsing them
3738
"""
38-
for old_str, new_string in {
39+
if 'exit' in values:
40+
if values['exit'] != 0:
41+
for sections in [
42+
# all the statistical values are not relevant if we failed
43+
'max_rss(MiB)',
44+
'exec_time(ms)',
45+
'synthesis_time(ms)',
46+
'simulation_time(ms)',
47+
'Latch Drivers',
48+
'Pi',
49+
'Po',
50+
'logic element',
51+
'latch',
52+
'Adder',
53+
'Multiplier',
54+
'Memory',
55+
'Hard Ip',
56+
'generic logic size',
57+
'Longest Path',
58+
'Average Path',
59+
'Estimated LUTs',
60+
'Total Node',
61+
]:
62+
if sections in values:
63+
del values[sections]
64+
return values
65+
66+
def patch_logs(values):
67+
"""
68+
patch the string logs
69+
"""
70+
sub_re = {
71+
# strip username from the logs
72+
r"(" + pwd.getpwuid(os.getuid()).pw_name + r")": "",
73+
# strip path from known file extensions
74+
r"([\/]?[a-zA-Z_.\-0-9]*\/)(?=[^\/\s]*(_input|_output|\.xml|\.v|\.vh|\.blif|\.log|\.do|\.dot|_vectors|_activity)[\s\n]+)": "",
3975
# bison used to call EOF $end, but switched to end of file since
40-
r"syntax error, unexpected \$end": r"syntax error, unexpected end of file",
41-
}.items():
42-
line = re.sub(old_str, new_string,line)
76+
r"syntax error, unexpected \$end": r"syntax error, unexpected end of file"
77+
}
4378

44-
return line
79+
if isinstance(values, str):
80+
for old_str, new_string in sub_re.items():
81+
values = re.sub(old_str, new_string, values)
82+
elif isinstance(values, list):
83+
values = [ patch_logs(log_entry) for log_entry in values ]
84+
elif isinstance(values, ( OrderedDict, dict )):
85+
for section in values:
86+
values[section] = patch_logs(values[section])
4587

88+
return values
4689

47-
IS_EXPECTED_TO_FAIL = False
48-
def make_expected_failures_pass(line):
49-
# figure out if we expected this to fail
50-
global IS_EXPECTED_TO_FAIL
51-
if re.search(r"^EXPECT:: failure$",line) is not None:
52-
IS_EXPECTED_TO_FAIL = True
90+
def inverse_result_from_expectation(values):
5391

54-
# if this was expected to fail
55-
if IS_EXPECTED_TO_FAIL:
56-
# make it pass
57-
line = re.sub(r"(?!Odin exited with code: )(\d+)", "0",line)
58-
59-
return line
92+
should_fail = False
93+
if 'expectation' in values:
94+
for log in values['expectation']:
95+
if log == "failure":
96+
should_fail = True
97+
break
98+
99+
if 'exit' in values:
100+
if values['exit'] == 0 and should_fail:
101+
values['exit'] = 51
102+
elif values['exit'] != 0 and should_fail:
103+
values['exit'] = 0
104+
values['expectation'].append("Failure caught and flipped to success by the post processor")
105+
106+
return values

ODIN_II/regression_test/parse_result/parse_result.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -400,12 +400,18 @@ def load_log_into_tbl(toml_dict, log_file_name):
400400

401401
# load the hooks if there are any
402402
# run.py
403-
hooks = []
403+
pre_hooks = []
404+
post_hooks = []
404405
for hook_file in HOOK_FILES:
405406
module = __import__(hook_file)
406-
module_hook_list = getattr(module, _HOOK_HDR)
407+
module_hook_list = getattr(module, "PRE_HOOKS")
407408
for runtime_hook in module_hook_list:
408-
hooks.append(getattr(module, runtime_hook))
409+
pre_hooks.append(getattr(module, runtime_hook))
410+
411+
module_hook_list = getattr(module, "POST_HOOKS")
412+
for runtime_hook in module_hook_list:
413+
post_hooks.append(getattr(module, runtime_hook))
414+
409415

410416
# setup our output dict, print as csv expects a hashed table
411417
parsed_dict = OrderedDict()
@@ -418,7 +424,7 @@ def load_log_into_tbl(toml_dict, log_file_name):
418424
for line in log:
419425

420426
# boostrap the preprocessor here
421-
for fn in hooks:
427+
for fn in pre_hooks:
422428
line = fn(line)
423429

424430
line = " ".join(line.split())
@@ -438,10 +444,15 @@ def load_log_into_tbl(toml_dict, log_file_name):
438444
if input_values is None:
439445
input_values[header] = toml_dict[header][_K_DFLT]
440446

447+
# boostrap the post-processor here
448+
for fn in post_hooks:
449+
input_values = fn(input_values)
450+
441451
# make a key from the user desired key items
442452
key = hash_item(toml_dict, input_values)
443453
parsed_dict[key] = input_values
444454

455+
445456
return parsed_dict
446457

447458
def load_into_tbl(toml_dict, file_name):

0 commit comments

Comments
 (0)