7 # Make sure to have unique matches in different lines
8 # Order the list in alphabetical order based on the "issue" key
11 "issue": "https://jira.opendaylight.org/browse/OPNFLWPLUG-917",
12 "id": "IllegalStateException",
14 "java.lang.IllegalStateException: Deserializer for key: msgVersion: 4 objectClass: "
15 + "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry "
16 + "msgType: 1 oxm_field: 33 experimenterID: null was not found "
17 + "- please verify that all needed deserializers ale loaded correctly"
22 _re_ts = re.compile(r"^[0-9]{4}(-[0-9]{2}){2}T([0-9]{2}:){2}[0-9]{2},[0-9]{3}")
23 _re_ts_we = re.compile(
24 r"^[0-9]{4}(-[0-9]{2}){2}T([0-9]{2}:){2}[0-9]{2},[0-9]{3}( \| ERROR \| | \| WARN \| )"
26 _re_ex = re.compile(r"(?i)exception")
27 _ex_map = collections.OrderedDict()
32 def get_exceptions(lines):
34 Create a map of exceptions that also has a list of warnings and errors preceeding
35 the exception to use as context.
37 The lines are parsed to create a list where all lines related to a timestamp
38 are aggregated. Timestamped lines with exception (case insensitive) are copied
39 to the exception map keyed to the index of the timestamp line. Each exception value
40 also has a list containing WARN and ERROR lines proceeding the exception.
43 :return OrderedDict _ex_map: map of exceptions
46 _ex_map = collections.OrderedDict()
50 warnerr_deq = collections.deque(maxlen=5)
53 ts = _re_ts.search(line)
55 # Check if this is the start or continuation of a timestamp line
58 _ts_list.append(cur_list)
59 ts_we = _re_ts_we.search(line)
60 # Track WARN and ERROR lines
62 warn_err_index = len(_ts_list) - 1
63 warnerr_deq.append(warn_err_index)
64 # Append to current timestamp line since this is not a timestamp line
68 # Add the timestamp line to the exception map if it has an exception
69 ex = _re_ex.search(line)
71 index = len(_ts_list) - 1
72 if index not in _ex_map:
73 _ex_map[index] = {"warnerr_list": list(warnerr_deq), "lines": cur_list}
74 warnerr_deq.clear() # reset the deque to only track new ERROR and WARN lines
79 def check_exceptions():
81 Return a list of exceptions that were not in the whitelist.
83 Each exception found is compared against all the patterns
86 :return list _fail: list of exceptions not in the whitelist
91 for ex_idx, ex in _ex_map.items():
92 ex_str = "__".join(ex.get("lines"))
93 for whitelist in _whitelist:
94 # skip the current whitelist exception if not in the current exception
95 if whitelist.get("id") not in ex_str:
97 whitelist_contexts = whitelist.get("context")
98 num_context_matches = 0
99 for whitelist_context in whitelist_contexts:
100 for exwe_index in reversed(ex.get("warnerr_list")):
101 exwe_str = "__".join(_ts_list[exwe_index])
102 if whitelist_context in exwe_str:
103 num_context_matches += 1
104 # Mark this exception as a known issue if all the context's matched
105 if num_context_matches >= len(whitelist_contexts):
106 ex["issue"] = whitelist.get("issue")
108 logging.info("known exception was seen: {}".format(ex["issue"]))
110 # A new exception when it isn't marked with a known issue.
111 if "issue" not in ex:
116 def verify_exceptions(lines):
118 Return a list of exceptions not in the whitelist for the given lines.
120 :param list lines: list of lines from a log
121 :return list, list: one list of exceptions not in the whitelist, and a second with matching issues
125 get_exceptions(lines)
126 return check_exceptions()
129 def write_exceptions_map_to_file(testname, filename, mode="a+"):
131 Write the exceptions map to a file under the testname header. The output
132 will include all lines in the exception itself as well as any previous
133 contextual warning or error lines. The output will be appended or overwritten
134 depending on the mode parameter. It is assumed that the caller has called
135 verify_exceptions() earlier to populate the exceptions map, otherwise only
136 the testname and header will be printed to the file.
138 :param str testname: The name of the test
139 :param str filename: The file to open for writing
140 :param str mode: Append (a+) or overwrite (w+)
143 os.makedirs(os.path.dirname(filename))
144 except OSError as exception:
145 if exception.errno != errno.EEXIST:
148 with open(filename, mode) as fp:
149 fp.write("{}\n".format("=" * 60))
150 fp.write("Starting test: {}\n".format(testname))
151 for ex_idx, ex in _ex_map.items():
152 fp.write("{}\n".format("-" * 40))
154 fp.write("Exception was matched to: {}\n".format(ex.get("issue")))
156 fp.write("Exception is new\n")
157 for exwe_index in ex.get("warnerr_list")[:-1]:
158 for line in _ts_list[exwe_index]:
159 fp.write("{}\n".format(line))
160 fp.writelines(ex.get("lines"))