def test_size_always_at_least_zero(self): stack = status_lib.status_stack() self.assertEquals(stack.size(), 0) stack.start() stack.end() self.assertEquals(stack.size(), 0) stack.end() self.assertEquals(stack.size(), 0)
def test_better_never_overrides_better(self): for i in xrange(len(self.statuses)): better_status = self.statuses[i] for j in xrange(i): stack = status_lib.status_stack() worse_status = self.statuses[j] stack.update(worse_status) stack.update(better_status) self.assertEquals(stack.current_status(), worse_status)
def test_stack_is_lifo(self): stack = status_lib.status_stack() stack.update("GOOD") stack.start() stack.update("FAIL") stack.start() stack.update("WARN") self.assertEquals(stack.end(), "WARN") self.assertEquals(stack.end(), "FAIL") self.assertEquals(stack.end(), "GOOD") self.assertEquals(stack.end(), "NOSTATUS")
def state_iterator(self, buffer): new_tests = [] boot_count = 0 group_subdir = None sought_level = 0 stack = status_lib.status_stack() current_kernel = kernel(self.job) boot_in_progress = False alert_pending = None started_time = None while not self.finished or buffer.size(): # stop processing once the buffer is empty if buffer.size() == 0: yield new_tests new_tests = [] continue # parse the next line line = buffer.get() tko_utils.dprint('\nSTATUS: ' + line.strip()) line = status_line.parse_line(line) if line is None: tko_utils.dprint('non-status line, ignoring') continue # ignore non-status lines # have we hit the job start line? if (line.type == "START" and not line.subdir and not line.testname): sought_level = 1 tko_utils.dprint("found job level start " "marker, looking for level " "1 groups now") continue # have we hit the job end line? if (line.type == "END" and not line.subdir and not line.testname): tko_utils.dprint("found job level end " "marker, looking for level " "0 lines now") sought_level = 0 # START line, just push another layer on to the stack # and grab the start time if this is at the job level # we're currently seeking if line.type == "START": group_subdir = None stack.start() if line.indent == sought_level: started_time = \ tko_utils.get_timestamp( line.optional_fields, "timestamp") tko_utils.dprint("start line, ignoring") continue # otherwise, update the status on the stack else: tko_utils.dprint("GROPE_STATUS: %s" % [stack.current_status(), line.status, line.subdir, line.testname, line.reason]) stack.update(line.status) if line.status == "ALERT": tko_utils.dprint("job level alert, recording") alert_pending = line.reason continue # ignore Autotest.install => GOOD lines if (line.testname == "Autotest.install" and line.status == "GOOD"): tko_utils.dprint("Successful Autotest " "install, ignoring") continue # ignore END lines for a reboot group if (line.testname == "reboot" and line.type == "END"): tko_utils.dprint("reboot group, ignoring") continue # convert job-level ABORTs into a 'CLIENT_JOB' test, and # ignore other job-level events if line.testname is None: if (line.status == "ABORT" and line.type != "END"): line.testname = "CLIENT_JOB" else: tko_utils.dprint("job level event, " "ignoring") continue # use the group subdir for END lines if line.type == "END": line.subdir = group_subdir # are we inside a block group? if (line.indent != sought_level and line.status != "ABORT" and not line.testname.startswith('reboot.')): if line.subdir: tko_utils.dprint("set group_subdir: " + line.subdir) group_subdir = line.subdir tko_utils.dprint("ignoring incorrect indent " "level %d != %d," % (line.indent, sought_level)) continue # use the subdir as the testname, except for # boot.* and kernel.* tests if (line.testname is None or not re.search(r"^(boot(\.\d+)?$|kernel\.)", line.testname)): if line.subdir and '.' in line.subdir: line.testname = line.subdir # has a reboot started? if line.testname == "reboot.start": started_time = tko_utils.get_timestamp( line.optional_fields, "timestamp") tko_utils.dprint("reboot start event, " "ignoring") boot_in_progress = True continue # has a reboot finished? if line.testname == "reboot.verify": line.testname = "boot.%d" % boot_count tko_utils.dprint("reboot verified") boot_in_progress = False verify_ident = line.reason.strip() current_kernel = kernel(self.job, verify_ident) boot_count += 1 if alert_pending: line.status = "ALERT" line.reason = alert_pending alert_pending = None # create the actual test object finished_time = tko_utils.get_timestamp( line.optional_fields, "timestamp") final_status = stack.end() tko_utils.dprint("Adding: " "%s\nSubdir:%s\nTestname:%s\n%s" % (final_status, line.subdir, line.testname, line.reason)) new_test = test.parse_test(self.job, line.subdir, line.testname, final_status, line.reason, current_kernel, started_time, finished_time) started_time = None new_tests.append(new_test) # the job is finished, but we never came back from reboot if boot_in_progress: testname = "boot.%d" % boot_count reason = "machine did not return from reboot" tko_utils.dprint(("Adding: ABORT\nSubdir:----\n" "Testname:%s\n%s") % (testname, reason)) new_test = test.parse_test(self.job, None, testname, "ABORT", reason, current_kernel, None, None) new_tests.append(new_test) yield new_tests
def test_anything_overrides_nostatus(self): for status in self.statuses: stack = status_lib.status_stack() stack.update(status) self.assertEquals(stack.current_status(), status)
def test_default_on_start_to_nostatus(self): stack = status_lib.status_stack() stack.update("FAIL") stack.start() self.assertEquals(stack.current_status(), "NOSTATUS")
def test_default_to_nostatus(self): stack = status_lib.status_stack() self.assertEquals(stack.current_status(), "NOSTATUS")
def state_iterator(self, buffer): new_tests = [] boot_count = 0 group_subdir = None sought_level = 0 stack = status_lib.status_stack() current_kernel = kernel(self.job) boot_in_progress = False alert_pending = None started_time = None while not self.finished or buffer.size(): # stop processing once the buffer is empty if buffer.size() == 0: yield new_tests new_tests = [] continue # parse the next line line = buffer.get() tko_utils.dprint('\nSTATUS: ' + line.strip()) line = status_line.parse_line(line) if line is None: tko_utils.dprint('non-status line, ignoring') continue # ignore non-status lines # have we hit the job start line? if (line.type == "START" and not line.subdir and not line.testname): sought_level = 1 tko_utils.dprint("found job level start " "marker, looking for level " "1 groups now") continue # have we hit the job end line? if (line.type == "END" and not line.subdir and not line.testname): tko_utils.dprint("found job level end " "marker, looking for level " "0 lines now") sought_level = 0 # START line, just push another layer on to the stack # and grab the start time if this is at the job level # we're currently seeking if line.type == "START": group_subdir = None stack.start() if line.indent == sought_level: started_time = \ tko_utils.get_timestamp( line.optional_fields, "timestamp") tko_utils.dprint("start line, ignoring") continue # otherwise, update the status on the stack else: tko_utils.dprint("GROPE_STATUS: %s" % [ stack.current_status(), line.status, line.subdir, line.testname, line.reason ]) stack.update(line.status) if line.status == "ALERT": tko_utils.dprint("job level alert, recording") alert_pending = line.reason continue # ignore Autotest.install => GOOD lines if (line.testname == "Autotest.install" and line.status == "GOOD"): tko_utils.dprint("Successful Autotest " "install, ignoring") continue # ignore END lines for a reboot group if (line.testname == "reboot" and line.type == "END"): tko_utils.dprint("reboot group, ignoring") continue # convert job-level ABORTs into a 'CLIENT_JOB' test, and # ignore other job-level events if line.testname is None: if (line.status == "ABORT" and line.type != "END"): line.testname = "CLIENT_JOB" else: tko_utils.dprint("job level event, " "ignoring") continue # use the group subdir for END lines if line.type == "END": line.subdir = group_subdir # are we inside a block group? if (line.indent != sought_level and line.status != "ABORT" and not line.testname.startswith('reboot.')): if line.subdir: tko_utils.dprint("set group_subdir: " + line.subdir) group_subdir = line.subdir tko_utils.dprint("ignoring incorrect indent " "level %d != %d," % (line.indent, sought_level)) continue # use the subdir as the testname, except for # boot.* and kernel.* tests if (line.testname is None or not re.search( r"^(boot(\.\d+)?$|kernel\.)", line.testname)): if line.subdir and '.' in line.subdir: line.testname = line.subdir # has a reboot started? if line.testname == "reboot.start": started_time = tko_utils.get_timestamp(line.optional_fields, "timestamp") tko_utils.dprint("reboot start event, " "ignoring") boot_in_progress = True continue # has a reboot finished? if line.testname == "reboot.verify": line.testname = "boot.%d" % boot_count tko_utils.dprint("reboot verified") boot_in_progress = False verify_ident = line.reason.strip() current_kernel = kernel(self.job, verify_ident) boot_count += 1 if alert_pending: line.status = "ALERT" line.reason = alert_pending alert_pending = None # create the actual test object finished_time = tko_utils.get_timestamp(line.optional_fields, "timestamp") final_status = stack.end() tko_utils.dprint( "Adding: " "%s\nSubdir:%s\nTestname:%s\n%s" % (final_status, line.subdir, line.testname, line.reason)) new_test = test.parse_test(self.job, line.subdir, line.testname, final_status, line.reason, current_kernel, started_time, finished_time) started_time = None new_tests.append(new_test) # the job is finished, but we never came back from reboot if boot_in_progress: testname = "boot.%d" % boot_count reason = "machine did not return from reboot" tko_utils.dprint(("Adding: ABORT\nSubdir:----\n" "Testname:%s\n%s") % (testname, reason)) new_test = test.parse_test(self.job, None, testname, "ABORT", reason, current_kernel, None, None) new_tests.append(new_test) yield new_tests
def state_iterator(self, buffer): line = None new_tests = [] job_count, boot_count = 0, 0 min_stack_size = 0 stack = status_lib.status_stack() current_kernel = kernel("", []) # UNKNOWN current_status = status_lib.statuses[-1] current_reason = None started_time_stack = [None] subdir_stack = [None] running_test = None running_reasons = set() yield [] # we're ready to start running # create a RUNNING SERVER_JOB entry to represent the entire test running_job = test.parse_partial_test(self.job, "----", "SERVER_JOB", "", current_kernel, self.job.started_time) new_tests.append(running_job) while True: # are we finished with parsing? if buffer.size() == 0 and self.finished: if stack.size() == 0: break # we have status lines left on the stack, # we need to implicitly abort them first tko_utils.dprint('\nUnexpected end of job, aborting') abort_subdir_stack = list(subdir_stack) if self.job.aborted_by: reason = "Job aborted by %s" % self.job.aborted_by reason += self.job.aborted_on.strftime( " at %b %d %H:%M:%S") else: reason = "Job aborted unexpectedly" timestamp = line.optional_fields.get('timestamp') for i in reversed(xrange(stack.size())): if abort_subdir_stack: subdir = abort_subdir_stack.pop() else: subdir = None abort = self.make_dummy_abort( i, subdir, subdir, timestamp, reason) buffer.put(abort) # stop processing once the buffer is empty if buffer.size() == 0: yield new_tests new_tests = [] continue # reinitialize the per-iteration state started_time = None finished_time = None # get the next line raw_line = status_lib.clean_raw_line(buffer.get()) tko_utils.dprint('\nSTATUS: ' + raw_line.strip()) line = status_line.parse_line(raw_line) if line is None: tko_utils.dprint('non-status line, ignoring') continue # do an initial sanity check of the indentation expected_indent = stack.size() if line.type == "END": expected_indent -= 1 if line.indent < expected_indent: # ABORT the current level if indentation was unexpectedly low self.put_back_line_and_abort( buffer, raw_line, stack.size() - 1, subdir_stack[-1], line.optional_fields.get("timestamp"), line.reason) continue elif line.indent > expected_indent: # ignore the log if the indent was unexpectedly high tko_utils.dprint("unexpected extra indentation, ignoring") continue # initial line processing if line.type == "START": stack.start() started_time = line.get_timestamp() if (line.testname is None and line.subdir is None and not running_test): # we just started a client, all tests are relative to here min_stack_size = stack.size() elif stack.size() == min_stack_size + 1 and not running_test: # we just started a new test, insert a running record running_reasons = set() if line.reason: running_reasons.add(line.reason) running_test = test.parse_partial_test(self.job, line.subdir, line.testname, line.reason, current_kernel, started_time) msg = "RUNNING: %s\nSubdir: %s\nTestname: %s\n%s" msg %= (running_test.status, running_test.subdir, running_test.testname, running_test.reason) tko_utils.dprint(msg) new_tests.append(running_test) started_time_stack.append(started_time) subdir_stack.append(line.subdir) continue elif line.type == "INFO": # update the current kernel if one is defined in the info if "kernel" in line.optional_fields: current_kernel = line.get_kernel() continue elif line.type == "STATUS": # update the stacks if line.subdir and stack.size() > min_stack_size: subdir_stack[-1] = line.subdir # update the status, start and finished times stack.update(line.status) if status_lib.is_worse_than_or_equal_to(line.status, current_status): if line.reason: # update the status of a currently running test if running_test: running_reasons.add(line.reason) running_reasons = tko_utils.drop_redundant_messages( running_reasons) sorted_reasons = sorted(running_reasons) running_test.reason = ", ".join(sorted_reasons) current_reason = running_test.reason new_tests.append(running_test) msg = "update RUNNING reason: %s" % line.reason tko_utils.dprint(msg) else: current_reason = line.reason current_status = stack.current_status() started_time = None finished_time = line.get_timestamp() # if this is a non-test entry there's nothing else to do if line.testname is None and line.subdir is None: continue elif line.type == "END": # grab the current subdir off of the subdir stack, or, if this # is the end of a job, just pop it off if (line.testname is None and line.subdir is None and not running_test): min_stack_size = stack.size() - 1 subdir_stack.pop() else: line.subdir = subdir_stack.pop() if not subdir_stack[-1] and stack.size() > min_stack_size: subdir_stack[-1] = line.subdir # update the status, start and finished times stack.update(line.status) current_status = stack.end() if stack.size() > min_stack_size: stack.update(current_status) current_status = stack.current_status() started_time = started_time_stack.pop() finished_time = line.get_timestamp() # update the current kernel if line.is_successful_reboot(current_status): current_kernel = line.get_kernel() # adjust the testname if this is a reboot if line.testname == "reboot" and line.subdir is None: line.testname = "boot.%d" % boot_count else: assert False # have we just finished a test? if stack.size() <= min_stack_size: # if there was no testname, just use the subdir if line.testname is None: line.testname = line.subdir # if there was no testname or subdir, use 'CLIENT_JOB' if line.testname is None: line.testname = "CLIENT_JOB.%d" % job_count job_count += 1 if not status_lib.is_worse_than_or_equal_to( current_status, "ABORT"): # a job hasn't really failed just because some of the # tests it ran have current_status = "GOOD" if not current_reason: current_reason = line.reason new_test = test.parse_test(self.job, line.subdir, line.testname, current_status, current_reason, current_kernel, started_time, finished_time, running_test) running_test = None current_status = status_lib.statuses[-1] current_reason = None if new_test.testname == ("boot.%d" % boot_count): boot_count += 1 msg = "ADD: %s\nSubdir: %s\nTestname: %s\n%s" msg %= (new_test.status, new_test.subdir, new_test.testname, new_test.reason) tko_utils.dprint(msg) new_tests.append(new_test) # the job is finished, produce the final SERVER_JOB entry and exit final_job = test.parse_test(self.job, "----", "SERVER_JOB", self.job.exit_status(), "", current_kernel, self.job.started_time, self.job.finished_time, running_job) new_tests.append(final_job) yield new_tests
def state_iterator(self, buffer): line = None new_tests = [] job_count, boot_count = 0, 0 min_stack_size = 0 stack = status_lib.status_stack() current_kernel = kernel("", []) # UNKNOWN current_status = status_lib.statuses[-1] current_reason = None started_time_stack = [None] subdir_stack = [None] running_test = None running_reasons = set() yield [] # We're ready to start running. # Create a RUNNING SERVER_JOB entry to represent the entire test. running_job = test.parse_partial_test(self.job, '----', 'SERVER_JOB', '', current_kernel, self.job.started_time) new_tests.append(running_job) while True: # Are we finished with parsing? if buffer.size() == 0 and self.finished: if stack.size() == 0: break # We have status lines left on the stack; # we need to implicitly abort them first. tko_utils.dprint('\nUnexpected end of job, aborting') abort_subdir_stack = list(subdir_stack) if self.job.aborted_by: reason = 'Job aborted by %s' % self.job.aborted_by reason += self.job.aborted_on.strftime( ' at %b %d %H:%M:%S') else: reason = 'Job aborted unexpectedly' timestamp = line.optional_fields.get('timestamp') for i in reversed(xrange(stack.size())): if abort_subdir_stack: subdir = abort_subdir_stack.pop() else: subdir = None abort = self.make_dummy_abort(i, subdir, subdir, timestamp, reason) buffer.put(abort) # Stop processing once the buffer is empty. if buffer.size() == 0: yield new_tests new_tests = [] continue # Reinitialize the per-iteration state. started_time = None finished_time = None # Get the next line. raw_line = status_lib.clean_raw_line(buffer.get()) tko_utils.dprint('\nSTATUS: ' + raw_line.strip()) line = status_line.parse_line(raw_line) if line is None: tko_utils.dprint('non-status line, ignoring') continue # Do an initial sanity check of the indentation. expected_indent = stack.size() if line.type == 'END': expected_indent -= 1 if line.indent < expected_indent: # ABORT the current level if indentation was unexpectedly low. self.put_back_line_and_abort( buffer, raw_line, stack.size() - 1, subdir_stack[-1], line.optional_fields.get('timestamp'), line.reason) continue elif line.indent > expected_indent: # Ignore the log if the indent was unexpectedly high. tko_utils.dprint('unexpected extra indentation, ignoring') continue # Initial line processing. if line.type == 'START': stack.start() started_time = line.get_timestamp() if (line.testname is None and line.subdir is None and not running_test): # We just started a client; all tests are relative to here. min_stack_size = stack.size() # Start a "RUNNING" CLIENT_JOB entry. job_name = 'CLIENT_JOB.%d' % job_count running_client = test.parse_partial_test( self.job, None, job_name, '', current_kernel, started_time) msg = 'RUNNING: %s\n%s\n' msg %= (running_client.status, running_client.testname) tko_utils.dprint(msg) new_tests.append(running_client) elif stack.size() == min_stack_size + 1 and not running_test: # We just started a new test; insert a running record. running_reasons = set() if line.reason: running_reasons.add(line.reason) running_test = test.parse_partial_test( self.job, line.subdir, line.testname, line.reason, current_kernel, started_time) msg = 'RUNNING: %s\nSubdir: %s\nTestname: %s\n%s' msg %= (running_test.status, running_test.subdir, running_test.testname, running_test.reason) tko_utils.dprint(msg) new_tests.append(running_test) started_time_stack.append(started_time) subdir_stack.append(line.subdir) continue elif line.type == 'INFO': fields = line.optional_fields # Update the current kernel if one is defined in the info. if 'kernel' in fields: current_kernel = line.get_kernel() # Update the SERVER_JOB reason if one was logged for an abort. if 'job_abort_reason' in fields: running_job.reason = fields['job_abort_reason'] new_tests.append(running_job) continue elif line.type == 'STATUS': # Update the stacks. if line.subdir and stack.size() > min_stack_size: subdir_stack[-1] = line.subdir # Update the status, start and finished times. stack.update(line.status) if status_lib.is_worse_than_or_equal_to( line.status, current_status): if line.reason: # Update the status of a currently running test. if running_test: running_reasons.add(line.reason) running_reasons = tko_utils.drop_redundant_messages( running_reasons) sorted_reasons = sorted(running_reasons) running_test.reason = ', '.join(sorted_reasons) current_reason = running_test.reason new_tests.append(running_test) msg = 'update RUNNING reason: %s' % line.reason tko_utils.dprint(msg) else: current_reason = line.reason current_status = stack.current_status() started_time = None finished_time = line.get_timestamp() # If this is a non-test entry there's nothing else to do. if line.testname is None and line.subdir is None: continue elif line.type == 'END': # Grab the current subdir off of the subdir stack, or, if this # is the end of a job, just pop it off. if (line.testname is None and line.subdir is None and not running_test): min_stack_size = stack.size() - 1 subdir_stack.pop() else: line.subdir = subdir_stack.pop() if not subdir_stack[-1] and stack.size() > min_stack_size: subdir_stack[-1] = line.subdir # Update the status, start and finished times. stack.update(line.status) current_status = stack.end() if stack.size() > min_stack_size: stack.update(current_status) current_status = stack.current_status() started_time = started_time_stack.pop() finished_time = line.get_timestamp() # Update the current kernel. if line.is_successful_reboot(current_status): current_kernel = line.get_kernel() # Adjust the testname if this is a reboot. if line.testname == 'reboot' and line.subdir is None: line.testname = 'boot.%d' % boot_count else: assert False # Have we just finished a test? if stack.size() <= min_stack_size: # If there was no testname, just use the subdir. if line.testname is None: line.testname = line.subdir # If there was no testname or subdir, use 'CLIENT_JOB'. if line.testname is None: line.testname = 'CLIENT_JOB.%d' % job_count running_test = running_client job_count += 1 if not status_lib.is_worse_than_or_equal_to( current_status, 'ABORT'): # A job hasn't really failed just because some of the # tests it ran have. current_status = 'GOOD' if not current_reason: current_reason = line.reason new_test = test.parse_test(self.job, line.subdir, line.testname, current_status, current_reason, current_kernel, started_time, finished_time, running_test) running_test = None current_status = status_lib.statuses[-1] current_reason = None if new_test.testname == ('boot.%d' % boot_count): boot_count += 1 msg = 'ADD: %s\nSubdir: %s\nTestname: %s\n%s' msg %= (new_test.status, new_test.subdir, new_test.testname, new_test.reason) tko_utils.dprint(msg) new_tests.append(new_test) # The job is finished; produce the final SERVER_JOB entry and exit. final_job = test.parse_test(self.job, '----', 'SERVER_JOB', self.job.exit_status(), running_job.reason, current_kernel, self.job.started_time, self.job.finished_time, running_job) new_tests.append(final_job) yield new_tests
def state_iterator(self, buffer): line = None new_tests = [] job_count, boot_count = 0, 0 min_stack_size = 0 stack = status_lib.status_stack() current_kernel = kernel("", []) # UNKNOWN current_status = status_lib.statuses[-1] current_reason = None started_time_stack = [None] subdir_stack = [None] running_test = None running_reasons = set() yield [] # we're ready to start running # create a RUNNING SERVER_JOB entry to represent the entire test running_job = test.parse_partial_test(self.job, "----", "SERVER_JOB", "", current_kernel, self.job.started_time) new_tests.append(running_job) while True: # are we finished with parsing? if buffer.size() == 0 and self.finished: if stack.size() == 0: break # we have status lines left on the stack, # we need to implicitly abort them first tko_utils.dprint('\nUnexpected end of job, aborting') abort_subdir_stack = list(subdir_stack) if self.job.aborted_by: reason = "Job aborted by %s" % self.job.aborted_by reason += self.job.aborted_on.strftime( " at %b %d %H:%M:%S") else: reason = "Job aborted unexpectedly" timestamp = line.optional_fields.get('timestamp') for i in reversed(xrange(stack.size())): if abort_subdir_stack: subdir = abort_subdir_stack.pop() else: subdir = None abort = self.make_dummy_abort( i, subdir, subdir, timestamp, reason) buffer.put(abort) # stop processing once the buffer is empty if buffer.size() == 0: yield new_tests new_tests = [] continue # reinitialize the per-iteration state started_time = None finished_time = None # get the next line raw_line = status_lib.clean_raw_line(buffer.get()) tko_utils.dprint('\nSTATUS: ' + raw_line.strip()) line = status_line.parse_line(raw_line) if line is None: tko_utils.dprint('non-status line, ignoring') continue # do an initial sanity check of the indentation expected_indent = stack.size() if line.type == "END": expected_indent -= 1 if line.indent < expected_indent: # ABORT the current level if indentation was unexpectedly low self.put_back_line_and_abort( buffer, raw_line, stack.size() - 1, subdir_stack[-1], line.optional_fields.get("timestamp"), line.reason) continue elif line.indent > expected_indent: # ignore the log if the indent was unexpectedly high tko_utils.dprint("unexpected extra indentation, ignoring") continue # initial line processing if line.type == "START": stack.start() started_time = line.get_timestamp() if (line.testname is None and line.subdir is None and not running_test): # we just started a client, all tests are relative to here min_stack_size = stack.size() # start a "RUNNING" CLIENT_JOB entry job_name = "CLIENT_JOB.%d" % job_count running_client = test.parse_partial_test(self.job, None, job_name, "", current_kernel, started_time) msg = "RUNNING: %s\n%s\n" msg %= (running_client.status, running_client.testname) tko_utils.dprint(msg) new_tests.append(running_client) elif stack.size() == min_stack_size + 1 and not running_test: # we just started a new test, insert a running record running_reasons = set() if line.reason: running_reasons.add(line.reason) running_test = test.parse_partial_test(self.job, line.subdir, line.testname, line.reason, current_kernel, started_time) msg = "RUNNING: %s\nSubdir: %s\nTestname: %s\n%s" msg %= (running_test.status, running_test.subdir, running_test.testname, running_test.reason) tko_utils.dprint(msg) new_tests.append(running_test) started_time_stack.append(started_time) subdir_stack.append(line.subdir) continue elif line.type == "INFO": fields = line.optional_fields # update the current kernel if one is defined in the info if "kernel" in fields: current_kernel = line.get_kernel() # update the SERVER_JOB reason if one was logged for an abort if "job_abort_reason" in fields: running_job.reason = fields["job_abort_reason"] new_tests.append(running_job) continue elif line.type == "STATUS": # update the stacks if line.subdir and stack.size() > min_stack_size: subdir_stack[-1] = line.subdir # update the status, start and finished times stack.update(line.status) if status_lib.is_worse_than_or_equal_to(line.status, current_status): if line.reason: # update the status of a currently running test if running_test: running_reasons.add(line.reason) running_reasons = tko_utils.drop_redundant_messages( running_reasons) sorted_reasons = sorted(running_reasons) running_test.reason = ", ".join(sorted_reasons) current_reason = running_test.reason new_tests.append(running_test) msg = "update RUNNING reason: %s" % line.reason tko_utils.dprint(msg) else: current_reason = line.reason current_status = stack.current_status() started_time = None finished_time = line.get_timestamp() # if this is a non-test entry there's nothing else to do if line.testname is None and line.subdir is None: continue elif line.type == "END": # grab the current subdir off of the subdir stack, or, if this # is the end of a job, just pop it off if (line.testname is None and line.subdir is None and not running_test): min_stack_size = stack.size() - 1 subdir_stack.pop() else: line.subdir = subdir_stack.pop() if not subdir_stack[-1] and stack.size() > min_stack_size: subdir_stack[-1] = line.subdir # update the status, start and finished times stack.update(line.status) current_status = stack.end() if stack.size() > min_stack_size: stack.update(current_status) current_status = stack.current_status() started_time = started_time_stack.pop() finished_time = line.get_timestamp() # update the current kernel if line.is_successful_reboot(current_status): current_kernel = line.get_kernel() # adjust the testname if this is a reboot if line.testname == "reboot" and line.subdir is None: line.testname = "boot.%d" % boot_count else: assert False # have we just finished a test? if stack.size() <= min_stack_size: # if there was no testname, just use the subdir if line.testname is None: line.testname = line.subdir # if there was no testname or subdir, use 'CLIENT_JOB' if line.testname is None: line.testname = "CLIENT_JOB.%d" % job_count running_test = running_client job_count += 1 if not status_lib.is_worse_than_or_equal_to( current_status, "ABORT"): # a job hasn't really failed just because some of the # tests it ran have current_status = "GOOD" if not current_reason: current_reason = line.reason new_test = test.parse_test(self.job, line.subdir, line.testname, current_status, current_reason, current_kernel, started_time, finished_time, running_test) running_test = None current_status = status_lib.statuses[-1] current_reason = None if new_test.testname == ("boot.%d" % boot_count): boot_count += 1 msg = "ADD: %s\nSubdir: %s\nTestname: %s\n%s" msg %= (new_test.status, new_test.subdir, new_test.testname, new_test.reason) tko_utils.dprint(msg) new_tests.append(new_test) # the job is finished, produce the final SERVER_JOB entry and exit final_job = test.parse_test(self.job, "----", "SERVER_JOB", self.job.exit_status(), running_job.reason, current_kernel, self.job.started_time, self.job.finished_time, running_job) new_tests.append(final_job) yield new_tests