7
from argparse import ArgumentParser
19
if not os.path.isfile(args.input_log_filename):
20
sys.stderr.write('Log file {0!r} not found\n'
21
.format(args.input_log_filename))
24
LoggingConfiguration.set(args.log_level,
25
args.output_log_filename)
26
parser = Parser(args.input_log_filename)
27
results = parser.parse()
29
if not compare_results(results):
37
Reboot test log file parser
39
is_logging_line = (re.compile('^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}')
41
is_getting_info_line = (re.compile('Gathering hardware information...$')
43
is_executing_line = (re.compile("Executing: '(?P<command>.*)'...$")
45
is_output_line = re.compile('Output:$').search
46
is_field_line = (re.compile('^- (?P<field>returncode|stdout|stderr):$')
48
is_test_complete_line = re.compile('test complete$').search
50
def __init__(self, filename):
51
self.filename = filename
55
Parse log file and return results
57
with open(self.filename) as f:
58
results = self._parse_file(LineIterator(f))
61
def _parse_file(self, iterator):
63
Parse all lines in iterator and return results
69
if self.is_getting_info_line(line):
71
# Add last result to list of results
72
results.append(result)
74
# Initialize for a new iteration results
77
match = self.is_executing_line(line)
79
command = match.group('command')
80
command_output = self._parse_command_output(iterator)
82
if command_output is not None:
83
result[command] = command_output
86
# Add last result to list of results
87
results.append(result)
89
if not self.is_test_complete_line(line):
90
sys.stderr.write("Test didn't finish properly according to logs\n")
91
sys.exit(NOT_FINISHED)
95
def _parse_command_output(self, iterator):
97
Parse one command output
101
# Skip all lines until command output is found
102
for line in iterator:
103
if self.is_output_line(line):
106
if (self.is_executing_line(line)
107
or self.is_getting_info_line(line)):
108
# Skip commands with no output
109
iterator.unnext(line)
112
# Parse command output message
113
for line in iterator:
114
match = self.is_field_line(line)
116
field = match.group('field')
117
value = self._parse_command_output_field(iterator)
118
command_output[field] = value
119
# Exit when all command output fields
122
iterator.unnext(line)
125
return command_output
127
def _parse_command_output_field(self, iterator):
129
Parse one command output field
131
# Accummulate as many lines as needed
132
# for the field value
134
for line in iterator:
135
if (self.is_logging_line(line)
136
or self.is_field_line(line)):
137
iterator.unnext(line)
142
value = ''.join(value)
148
Iterator wrapper to make it possible
149
to push back lines that shouldn't have been consumed
152
def __init__(self, iterator):
153
self.iterator = iterator
161
return self.buffer.pop()
163
return next(self.iterator)
165
def unnext(self, line):
166
self.buffer.append(line)
169
class LoggingConfiguration(object):
171
def set(cls, log_level, log_filename):
173
Configure a rotating file logger
175
logger = logging.getLogger()
176
logger.setLevel(logging.DEBUG)
178
# Log to sys.stderr using log level passed through command line
179
if log_level != logging.NOTSET:
180
log_handler = logging.StreamHandler()
181
formatter = logging.Formatter('%(levelname)-8s %(message)s')
182
log_handler.setFormatter(formatter)
183
log_handler.setLevel(log_level)
184
logger.addHandler(log_handler)
186
# Log to rotating file using DEBUG log level
187
log_handler = logging.FileHandler(log_filename, mode='w')
188
formatter = logging.Formatter('%(asctime)s %(levelname)-8s '
190
log_handler.setFormatter(formatter)
191
log_handler.setLevel(logging.DEBUG)
192
logger.addHandler(log_handler)
195
def compare_results(results):
197
Compare results using first one as a baseline
199
baseline = results[0]
202
for index, result in enumerate(results[1:]):
203
for command in baseline.keys():
204
baseline_output = baseline[command]
205
result_output = result[command]
208
fields = (set(baseline_output.keys())
209
| set(result_output.keys()))
211
baseline_field = baseline_output.get(field, '')
212
result_field = result_output.get(field, '')
214
if baseline_field != result_field:
215
differ = difflib.Differ()
217
message = ["** {field!r} field doesn't match:"
218
.format(field=field)]
219
comparison = differ.compare(baseline_field.splitlines(),
220
result_field.splitlines())
221
message.extend(list(comparison))
222
error_messages.append('\n'.join(message))
224
if not error_messages:
225
logging.debug('[Iteration {0}] {1}...\t[OK]'
226
.format(index + 1, command))
229
if command.startswith('fwts'):
230
logging.error('[Iteration {0}] {1}...\t[FAIL]'
231
.format(index + 1, command))
233
logging.error('[Iteration {0}] {1}...\t[FAIL]\n'
234
.format(index + 1, command))
235
for message in error_messages:
236
logging.error(message)
243
Parse command-line arguments
245
parser = ArgumentParser(description=('Check power management '
246
'test case results'))
247
parser.add_argument('input_log_filename', metavar='log_filename',
248
help=('Path to the input log file '
249
'on which to perform the check'))
250
parser.add_argument('output_log_filename', metavar='log_filename',
251
help=('Path to the output log file '
252
'for the results of the check'))
253
log_levels = ['notset', 'debug', 'info', 'warning', 'error', 'critical']
254
parser.add_argument('--log-level', dest='log_level', default='info',
257
'One of {0} or {1} (%(default)s by default)'
258
.format(', '.join(log_levels[:-1]),
260
args = parser.parse_args()
261
args.log_level = getattr(logging, args.log_level.upper())
266
if __name__ == '__main__':