jadmanski | f7fa2cc | 2008-10-01 14:13:23 +0000 | [diff] [blame] | 1 | import os, re, time |
jadmanski | cc54917 | 2008-05-21 18:11:51 +0000 | [diff] [blame] | 2 | |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 3 | from autotest_lib.tko import models, status_lib, utils as tko_utils |
| 4 | from autotest_lib.tko.parsers import base, version_0 |
| 5 | |
| 6 | |
jadmanski | 6f6299a | 2008-12-02 15:22:21 +0000 | [diff] [blame] | 7 | class job(version_0.job): |
| 8 | def exit_status(self): |
jadmanski | 165fe4c | 2009-01-07 17:06:00 +0000 | [diff] [blame] | 9 | # find the .autoserv_execute path |
| 10 | top_dir = tko_utils.find_toplevel_job_dir(self.dir) |
| 11 | if not top_dir: |
| 12 | return "ABORT" |
| 13 | execute_path = os.path.join(top_dir, ".autoserv_execute") |
| 14 | |
jadmanski | 6f6299a | 2008-12-02 15:22:21 +0000 | [diff] [blame] | 15 | # if for some reason we can't read the status code, assume disaster |
jadmanski | 6f6299a | 2008-12-02 15:22:21 +0000 | [diff] [blame] | 16 | if not os.path.exists(execute_path): |
| 17 | return "ABORT" |
| 18 | lines = open(execute_path).readlines() |
| 19 | if len(lines) < 2: |
| 20 | return "ABORT" |
| 21 | try: |
| 22 | status_code = int(lines[1]) |
| 23 | except ValueError: |
| 24 | return "ABORT" |
| 25 | |
| 26 | if not os.WIFEXITED(status_code): |
| 27 | # looks like a signal - an ABORT |
| 28 | return "ABORT" |
| 29 | elif os.WEXITSTATUS(status_code) != 0: |
| 30 | # looks like a non-zero exit - a failure |
| 31 | return "FAIL" |
| 32 | else: |
| 33 | # looks like exit code == 0 |
| 34 | return "GOOD" |
| 35 | |
| 36 | |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 37 | class kernel(models.kernel): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 38 | def __init__(self, base, patches): |
| 39 | if base: |
| 40 | patches = [patch(*p.split()) for p in patches] |
| 41 | hashes = [p.hash for p in patches] |
| 42 | kernel_hash = self.compute_hash(base, hashes) |
| 43 | else: |
| 44 | base = "UNKNOWN" |
| 45 | patches = [] |
| 46 | kernel_hash = "UNKNOWN" |
| 47 | super(kernel, self).__init__(base, patches, kernel_hash) |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 48 | |
| 49 | |
jadmanski | cc54917 | 2008-05-21 18:11:51 +0000 | [diff] [blame] | 50 | class test(models.test): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 51 | @staticmethod |
| 52 | def load_iterations(keyval_path): |
| 53 | return iteration.load_from_keyval(keyval_path) |
jadmanski | cc54917 | 2008-05-21 18:11:51 +0000 | [diff] [blame] | 54 | |
| 55 | |
| 56 | class iteration(models.iteration): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 57 | @staticmethod |
| 58 | def parse_line_into_dicts(line, attr_dict, perf_dict): |
jadmanski | d2e0f0c | 2009-07-20 17:52:57 +0000 | [diff] [blame] | 59 | key, val_type, value = "", "", "" |
| 60 | |
mbligh | 1ef218d | 2009-08-03 16:57:56 +0000 | [diff] [blame] | 61 | # figure out what the key, value and keyval type are |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 62 | typed_match = re.search("^([^=]*)\{(\w*)\}=(.*)$", line) |
| 63 | if typed_match: |
| 64 | key, val_type, value = typed_match.groups() |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 65 | else: |
| 66 | # old-fashioned untyped match, assume perf |
| 67 | untyped_match = re.search("^([^=]*)=(.*)$", line) |
jadmanski | d2e0f0c | 2009-07-20 17:52:57 +0000 | [diff] [blame] | 68 | if untyped_match: |
| 69 | key, value = untyped_match.groups() |
| 70 | val_type = "perf" |
| 71 | |
| 72 | # parse the actual value into a dict |
Eric Li | 861b2d5 | 2011-02-04 14:50:35 -0800 | [diff] [blame] | 73 | try: |
| 74 | if val_type == "attr": |
| 75 | attr_dict[key] = value |
| 76 | elif val_type == "perf": |
| 77 | perf_dict[key] = float(value) |
| 78 | else: |
| 79 | raise ValueError |
| 80 | except ValueError: |
jadmanski | d2e0f0c | 2009-07-20 17:52:57 +0000 | [diff] [blame] | 81 | msg = ("WARNING: line '%s' found in test " |
| 82 | "iteration keyval could not be parsed") |
| 83 | msg %= line |
| 84 | tko_utils.dprint(msg) |
jadmanski | cc54917 | 2008-05-21 18:11:51 +0000 | [diff] [blame] | 85 | |
| 86 | |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 87 | class status_line(version_0.status_line): |
jadmanski | 807490c | 2008-09-15 19:15:02 +0000 | [diff] [blame] | 88 | def __init__(self, indent, status, subdir, testname, reason, |
| 89 | optional_fields): |
| 90 | # handle INFO fields |
| 91 | if status == "INFO": |
| 92 | self.type = "INFO" |
| 93 | self.indent = indent |
| 94 | self.status = self.subdir = self.testname = self.reason = None |
| 95 | self.optional_fields = optional_fields |
| 96 | else: |
| 97 | # everything else is backwards compatible |
| 98 | super(status_line, self).__init__(indent, status, subdir, |
| 99 | testname, reason, |
| 100 | optional_fields) |
| 101 | |
| 102 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 103 | def is_successful_reboot(self, current_status): |
| 104 | # make sure this is a reboot line |
| 105 | if self.testname != "reboot": |
| 106 | return False |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 107 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 108 | # make sure this was not a failure |
jadmanski | ba1fa66 | 2008-07-11 21:18:30 +0000 | [diff] [blame] | 109 | if status_lib.is_worse_than_or_equal_to(current_status, "FAIL"): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 110 | return False |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 111 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 112 | # it must have been a successful reboot |
| 113 | return True |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 114 | |
| 115 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 116 | def get_kernel(self): |
| 117 | # get the base kernel version |
| 118 | fields = self.optional_fields |
mbligh | abe869a | 2009-03-25 22:09:59 +0000 | [diff] [blame] | 119 | base = re.sub("-autotest$", "", fields.get("kernel", "")) |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 120 | # get a list of patches |
| 121 | patches = [] |
| 122 | patch_index = 0 |
| 123 | while ("patch%d" % patch_index) in fields: |
| 124 | patches.append(fields["patch%d" % patch_index]) |
| 125 | patch_index += 1 |
| 126 | # create a new kernel instance |
| 127 | return kernel(base, patches) |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 128 | |
| 129 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 130 | def get_timestamp(self): |
| 131 | return tko_utils.get_timestamp(self.optional_fields, |
| 132 | "timestamp") |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 133 | |
| 134 | |
| 135 | # the default implementations from version 0 will do for now |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 136 | patch = version_0.patch |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 137 | |
| 138 | |
| 139 | class parser(base.parser): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 140 | @staticmethod |
| 141 | def make_job(dir): |
| 142 | return job(dir) |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 143 | |
| 144 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 145 | @staticmethod |
mbligh | b22c21f | 2008-11-27 00:40:38 +0000 | [diff] [blame] | 146 | def make_dummy_abort(indent, subdir, testname, timestamp, reason): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 147 | indent = "\t" * indent |
jadmanski | fd3ba2b | 2008-07-28 19:30:54 +0000 | [diff] [blame] | 148 | if not subdir: |
| 149 | subdir = "----" |
| 150 | if not testname: |
| 151 | testname = "----" |
mbligh | b22c21f | 2008-11-27 00:40:38 +0000 | [diff] [blame] | 152 | |
| 153 | # There is no guarantee that this will be set. |
| 154 | timestamp_field = '' |
| 155 | if timestamp: |
| 156 | timestamp_field = '\ttimestamp=%s' % timestamp |
| 157 | |
| 158 | msg = indent + "END ABORT\t%s\t%s%s\t%s" |
| 159 | return msg % (subdir, testname, timestamp_field, reason) |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 160 | |
| 161 | |
jadmanski | b69f250 | 2008-08-27 19:49:30 +0000 | [diff] [blame] | 162 | @staticmethod |
mbligh | b22c21f | 2008-11-27 00:40:38 +0000 | [diff] [blame] | 163 | def put_back_line_and_abort( |
| 164 | line_buffer, line, indent, subdir, timestamp, reason): |
jadmanski | b69f250 | 2008-08-27 19:49:30 +0000 | [diff] [blame] | 165 | tko_utils.dprint("Unexpected indent regression, aborting") |
| 166 | line_buffer.put_back(line) |
mbligh | b22c21f | 2008-11-27 00:40:38 +0000 | [diff] [blame] | 167 | abort = parser.make_dummy_abort( |
| 168 | indent, subdir, subdir, timestamp, reason) |
jadmanski | b69f250 | 2008-08-27 19:49:30 +0000 | [diff] [blame] | 169 | line_buffer.put_back(abort) |
| 170 | |
| 171 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 172 | def state_iterator(self, buffer): |
jadmanski | fd3ba2b | 2008-07-28 19:30:54 +0000 | [diff] [blame] | 173 | line = None |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 174 | new_tests = [] |
jadmanski | ba1fa66 | 2008-07-11 21:18:30 +0000 | [diff] [blame] | 175 | job_count, boot_count = 0, 0 |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 176 | min_stack_size = 0 |
| 177 | stack = status_lib.status_stack() |
| 178 | current_kernel = kernel("", []) # UNKNOWN |
jadmanski | c69138f | 2008-12-17 15:44:22 +0000 | [diff] [blame] | 179 | current_status = status_lib.statuses[-1] |
| 180 | current_reason = None |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 181 | started_time_stack = [None] |
| 182 | subdir_stack = [None] |
jadmanski | 74eebf3 | 2008-07-15 20:04:42 +0000 | [diff] [blame] | 183 | running_test = None |
jadmanski | aaac45e | 2009-05-06 20:25:46 +0000 | [diff] [blame] | 184 | running_reasons = set() |
jadmanski | 6f6299a | 2008-12-02 15:22:21 +0000 | [diff] [blame] | 185 | yield [] # we're ready to start running |
| 186 | |
| 187 | # create a RUNNING SERVER_JOB entry to represent the entire test |
| 188 | running_job = test.parse_partial_test(self.job, "----", "SERVER_JOB", |
| 189 | "", current_kernel, |
| 190 | self.job.started_time) |
| 191 | new_tests.append(running_job) |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 192 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 193 | while True: |
| 194 | # are we finished with parsing? |
| 195 | if buffer.size() == 0 and self.finished: |
| 196 | if stack.size() == 0: |
| 197 | break |
| 198 | # we have status lines left on the stack, |
| 199 | # we need to implicitly abort them first |
jadmanski | fd3ba2b | 2008-07-28 19:30:54 +0000 | [diff] [blame] | 200 | tko_utils.dprint('\nUnexpected end of job, aborting') |
| 201 | abort_subdir_stack = list(subdir_stack) |
jadmanski | f7fa2cc | 2008-10-01 14:13:23 +0000 | [diff] [blame] | 202 | if self.job.aborted_by: |
| 203 | reason = "Job aborted by %s" % self.job.aborted_by |
| 204 | reason += self.job.aborted_on.strftime( |
| 205 | " at %b %d %H:%M:%S") |
| 206 | else: |
| 207 | reason = "Job aborted unexpectedly" |
mbligh | b22c21f | 2008-11-27 00:40:38 +0000 | [diff] [blame] | 208 | |
| 209 | timestamp = line.optional_fields.get('timestamp') |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 210 | for i in reversed(xrange(stack.size())): |
jadmanski | fd3ba2b | 2008-07-28 19:30:54 +0000 | [diff] [blame] | 211 | if abort_subdir_stack: |
| 212 | subdir = abort_subdir_stack.pop() |
| 213 | else: |
| 214 | subdir = None |
mbligh | b22c21f | 2008-11-27 00:40:38 +0000 | [diff] [blame] | 215 | abort = self.make_dummy_abort( |
| 216 | i, subdir, subdir, timestamp, reason) |
jadmanski | fd3ba2b | 2008-07-28 19:30:54 +0000 | [diff] [blame] | 217 | buffer.put(abort) |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 218 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 219 | # stop processing once the buffer is empty |
| 220 | if buffer.size() == 0: |
| 221 | yield new_tests |
| 222 | new_tests = [] |
| 223 | continue |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 224 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 225 | # reinitialize the per-iteration state |
| 226 | started_time = None |
| 227 | finished_time = None |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 228 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 229 | # get the next line |
mbligh | 51ee7c7 | 2008-11-24 17:10:14 +0000 | [diff] [blame] | 230 | raw_line = status_lib.clean_raw_line(buffer.get()) |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 231 | tko_utils.dprint('\nSTATUS: ' + raw_line.strip()) |
| 232 | line = status_line.parse_line(raw_line) |
| 233 | if line is None: |
| 234 | tko_utils.dprint('non-status line, ignoring') |
| 235 | continue |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 236 | |
jadmanski | b82cb14 | 2009-02-04 18:33:08 +0000 | [diff] [blame] | 237 | # do an initial sanity check of the indentation |
| 238 | expected_indent = stack.size() |
| 239 | if line.type == "END": |
| 240 | expected_indent -= 1 |
| 241 | if line.indent < expected_indent: |
| 242 | # ABORT the current level if indentation was unexpectedly low |
| 243 | self.put_back_line_and_abort( |
| 244 | buffer, raw_line, stack.size() - 1, subdir_stack[-1], |
| 245 | line.optional_fields.get("timestamp"), line.reason) |
| 246 | continue |
| 247 | elif line.indent > expected_indent: |
| 248 | # ignore the log if the indent was unexpectedly high |
| 249 | tko_utils.dprint("unexpected extra indentation, ignoring") |
| 250 | continue |
| 251 | |
| 252 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 253 | # initial line processing |
| 254 | if line.type == "START": |
| 255 | stack.start() |
jadmanski | 74eebf3 | 2008-07-15 20:04:42 +0000 | [diff] [blame] | 256 | started_time = line.get_timestamp() |
jadmanski | 717bb99 | 2008-10-08 14:29:23 +0000 | [diff] [blame] | 257 | if (line.testname is None and line.subdir is None |
| 258 | and not running_test): |
jadmanski | 74eebf3 | 2008-07-15 20:04:42 +0000 | [diff] [blame] | 259 | # we just started a client, all tests are relative to here |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 260 | min_stack_size = stack.size() |
jadmanski | 43b7210 | 2010-04-30 21:22:28 +0000 | [diff] [blame] | 261 | # start a "RUNNING" CLIENT_JOB entry |
| 262 | job_name = "CLIENT_JOB.%d" % job_count |
jadmanski | d1b0a13 | 2010-05-04 19:50:30 +0000 | [diff] [blame] | 263 | running_client = test.parse_partial_test(self.job, None, |
| 264 | job_name, |
| 265 | "", current_kernel, |
| 266 | started_time) |
jadmanski | 43b7210 | 2010-04-30 21:22:28 +0000 | [diff] [blame] | 267 | msg = "RUNNING: %s\n%s\n" |
jadmanski | d1b0a13 | 2010-05-04 19:50:30 +0000 | [diff] [blame] | 268 | msg %= (running_client.status, running_client.testname) |
jadmanski | 43b7210 | 2010-04-30 21:22:28 +0000 | [diff] [blame] | 269 | tko_utils.dprint(msg) |
jadmanski | d1b0a13 | 2010-05-04 19:50:30 +0000 | [diff] [blame] | 270 | new_tests.append(running_client) |
jadmanski | 717bb99 | 2008-10-08 14:29:23 +0000 | [diff] [blame] | 271 | elif stack.size() == min_stack_size + 1 and not running_test: |
jadmanski | 74eebf3 | 2008-07-15 20:04:42 +0000 | [diff] [blame] | 272 | # we just started a new test, insert a running record |
jadmanski | aaac45e | 2009-05-06 20:25:46 +0000 | [diff] [blame] | 273 | running_reasons = set() |
jadmanski | 7839548 | 2009-03-10 04:21:03 +0000 | [diff] [blame] | 274 | if line.reason: |
jadmanski | aaac45e | 2009-05-06 20:25:46 +0000 | [diff] [blame] | 275 | running_reasons.add(line.reason) |
jadmanski | 74eebf3 | 2008-07-15 20:04:42 +0000 | [diff] [blame] | 276 | running_test = test.parse_partial_test(self.job, |
| 277 | line.subdir, |
| 278 | line.testname, |
| 279 | line.reason, |
| 280 | current_kernel, |
| 281 | started_time) |
| 282 | msg = "RUNNING: %s\nSubdir: %s\nTestname: %s\n%s" |
| 283 | msg %= (running_test.status, running_test.subdir, |
| 284 | running_test.testname, running_test.reason) |
| 285 | tko_utils.dprint(msg) |
| 286 | new_tests.append(running_test) |
| 287 | started_time_stack.append(started_time) |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 288 | subdir_stack.append(line.subdir) |
| 289 | continue |
jadmanski | 807490c | 2008-09-15 19:15:02 +0000 | [diff] [blame] | 290 | elif line.type == "INFO": |
Eric Li | 6f27d4f | 2010-09-29 10:55:17 -0700 | [diff] [blame] | 291 | fields = line.optional_fields |
jadmanski | 807490c | 2008-09-15 19:15:02 +0000 | [diff] [blame] | 292 | # update the current kernel if one is defined in the info |
Eric Li | 6f27d4f | 2010-09-29 10:55:17 -0700 | [diff] [blame] | 293 | if "kernel" in fields: |
jadmanski | 807490c | 2008-09-15 19:15:02 +0000 | [diff] [blame] | 294 | current_kernel = line.get_kernel() |
Eric Li | 6f27d4f | 2010-09-29 10:55:17 -0700 | [diff] [blame] | 295 | # update the SERVER_JOB reason if one was logged for an abort |
| 296 | if "job_abort_reason" in fields: |
| 297 | running_job.reason = fields["job_abort_reason"] |
| 298 | new_tests.append(running_job) |
jadmanski | 807490c | 2008-09-15 19:15:02 +0000 | [diff] [blame] | 299 | continue |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 300 | elif line.type == "STATUS": |
jadmanski | b69f250 | 2008-08-27 19:49:30 +0000 | [diff] [blame] | 301 | # update the stacks |
| 302 | if line.subdir and stack.size() > min_stack_size: |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 303 | subdir_stack[-1] = line.subdir |
jadmanski | c66e93c | 2008-07-29 21:25:22 +0000 | [diff] [blame] | 304 | # update the status, start and finished times |
| 305 | stack.update(line.status) |
jadmanski | b683796 | 2009-04-21 14:21:00 +0000 | [diff] [blame] | 306 | if status_lib.is_worse_than_or_equal_to(line.status, |
jadmanski | 262e1ab | 2009-04-01 18:27:38 +0000 | [diff] [blame] | 307 | current_status): |
jadmanski | c69138f | 2008-12-17 15:44:22 +0000 | [diff] [blame] | 308 | if line.reason: |
jadmanski | 7839548 | 2009-03-10 04:21:03 +0000 | [diff] [blame] | 309 | # update the status of a currently running test |
| 310 | if running_test: |
jadmanski | aaac45e | 2009-05-06 20:25:46 +0000 | [diff] [blame] | 311 | running_reasons.add(line.reason) |
jadmanski | 1f99f67 | 2009-07-01 16:23:09 +0000 | [diff] [blame] | 312 | running_reasons = tko_utils.drop_redundant_messages( |
| 313 | running_reasons) |
jadmanski | aaac45e | 2009-05-06 20:25:46 +0000 | [diff] [blame] | 314 | sorted_reasons = sorted(running_reasons) |
| 315 | running_test.reason = ", ".join(sorted_reasons) |
jadmanski | b683796 | 2009-04-21 14:21:00 +0000 | [diff] [blame] | 316 | current_reason = running_test.reason |
jadmanski | 7839548 | 2009-03-10 04:21:03 +0000 | [diff] [blame] | 317 | new_tests.append(running_test) |
| 318 | msg = "update RUNNING reason: %s" % line.reason |
| 319 | tko_utils.dprint(msg) |
jadmanski | b683796 | 2009-04-21 14:21:00 +0000 | [diff] [blame] | 320 | else: |
| 321 | current_reason = line.reason |
jadmanski | c69138f | 2008-12-17 15:44:22 +0000 | [diff] [blame] | 322 | current_status = stack.current_status() |
jadmanski | c66e93c | 2008-07-29 21:25:22 +0000 | [diff] [blame] | 323 | started_time = None |
| 324 | finished_time = line.get_timestamp() |
jadmanski | 0986b25 | 2009-04-01 18:26:59 +0000 | [diff] [blame] | 325 | # if this is a non-test entry there's nothing else to do |
| 326 | if line.testname is None and line.subdir is None: |
| 327 | continue |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 328 | elif line.type == "END": |
jadmanski | c66e93c | 2008-07-29 21:25:22 +0000 | [diff] [blame] | 329 | # grab the current subdir off of the subdir stack, or, if this |
| 330 | # is the end of a job, just pop it off |
jadmanski | 717bb99 | 2008-10-08 14:29:23 +0000 | [diff] [blame] | 331 | if (line.testname is None and line.subdir is None |
| 332 | and not running_test): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 333 | min_stack_size = stack.size() - 1 |
| 334 | subdir_stack.pop() |
| 335 | else: |
| 336 | line.subdir = subdir_stack.pop() |
jadmanski | 64e6345 | 2009-06-10 17:22:01 +0000 | [diff] [blame] | 337 | if not subdir_stack[-1] and stack.size() > min_stack_size: |
| 338 | subdir_stack[-1] = line.subdir |
jadmanski | c66e93c | 2008-07-29 21:25:22 +0000 | [diff] [blame] | 339 | # update the status, start and finished times |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 340 | stack.update(line.status) |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 341 | current_status = stack.end() |
jadmanski | 29e61ce | 2008-08-22 17:38:28 +0000 | [diff] [blame] | 342 | if stack.size() > min_stack_size: |
| 343 | stack.update(current_status) |
jadmanski | c69138f | 2008-12-17 15:44:22 +0000 | [diff] [blame] | 344 | current_status = stack.current_status() |
jadmanski | c66e93c | 2008-07-29 21:25:22 +0000 | [diff] [blame] | 345 | started_time = started_time_stack.pop() |
| 346 | finished_time = line.get_timestamp() |
| 347 | # update the current kernel |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 348 | if line.is_successful_reboot(current_status): |
| 349 | current_kernel = line.get_kernel() |
jadmanski | c66e93c | 2008-07-29 21:25:22 +0000 | [diff] [blame] | 350 | # adjust the testname if this is a reboot |
jadmanski | c8034f0 | 2008-07-14 19:10:47 +0000 | [diff] [blame] | 351 | if line.testname == "reboot" and line.subdir is None: |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 352 | line.testname = "boot.%d" % boot_count |
jadmanski | c66e93c | 2008-07-29 21:25:22 +0000 | [diff] [blame] | 353 | else: |
| 354 | assert False |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 355 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 356 | # have we just finished a test? |
| 357 | if stack.size() <= min_stack_size: |
| 358 | # if there was no testname, just use the subdir |
| 359 | if line.testname is None: |
| 360 | line.testname = line.subdir |
jadmanski | b14dc7a | 2008-07-11 23:14:01 +0000 | [diff] [blame] | 361 | # if there was no testname or subdir, use 'CLIENT_JOB' |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 362 | if line.testname is None: |
jadmanski | b14dc7a | 2008-07-11 23:14:01 +0000 | [diff] [blame] | 363 | line.testname = "CLIENT_JOB.%d" % job_count |
jadmanski | d1b0a13 | 2010-05-04 19:50:30 +0000 | [diff] [blame] | 364 | running_test = running_client |
jadmanski | ba1fa66 | 2008-07-11 21:18:30 +0000 | [diff] [blame] | 365 | job_count += 1 |
| 366 | if not status_lib.is_worse_than_or_equal_to( |
| 367 | current_status, "ABORT"): |
| 368 | # a job hasn't really failed just because some of the |
| 369 | # tests it ran have |
| 370 | current_status = "GOOD" |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 371 | |
jadmanski | c69138f | 2008-12-17 15:44:22 +0000 | [diff] [blame] | 372 | if not current_reason: |
| 373 | current_reason = line.reason |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 374 | new_test = test.parse_test(self.job, |
| 375 | line.subdir, |
| 376 | line.testname, |
| 377 | current_status, |
jadmanski | c69138f | 2008-12-17 15:44:22 +0000 | [diff] [blame] | 378 | current_reason, |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 379 | current_kernel, |
| 380 | started_time, |
jadmanski | 74eebf3 | 2008-07-15 20:04:42 +0000 | [diff] [blame] | 381 | finished_time, |
| 382 | running_test) |
| 383 | running_test = None |
jadmanski | d6f5c59 | 2009-01-10 00:26:21 +0000 | [diff] [blame] | 384 | current_status = status_lib.statuses[-1] |
jadmanski | c69138f | 2008-12-17 15:44:22 +0000 | [diff] [blame] | 385 | current_reason = None |
jadmanski | 1ce9fbb | 2008-10-21 16:25:05 +0000 | [diff] [blame] | 386 | if new_test.testname == ("boot.%d" % boot_count): |
| 387 | boot_count += 1 |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 388 | msg = "ADD: %s\nSubdir: %s\nTestname: %s\n%s" |
| 389 | msg %= (new_test.status, new_test.subdir, |
| 390 | new_test.testname, new_test.reason) |
| 391 | tko_utils.dprint(msg) |
| 392 | new_tests.append(new_test) |
jadmanski | 6e8bf75 | 2008-05-14 00:17:48 +0000 | [diff] [blame] | 393 | |
jadmanski | 6f6299a | 2008-12-02 15:22:21 +0000 | [diff] [blame] | 394 | # the job is finished, produce the final SERVER_JOB entry and exit |
| 395 | final_job = test.parse_test(self.job, "----", "SERVER_JOB", |
Eric Li | 6f27d4f | 2010-09-29 10:55:17 -0700 | [diff] [blame] | 396 | self.job.exit_status(), running_job.reason, |
jadmanski | 6f6299a | 2008-12-02 15:22:21 +0000 | [diff] [blame] | 397 | current_kernel, |
| 398 | self.job.started_time, |
| 399 | self.job.finished_time, |
| 400 | running_job) |
| 401 | new_tests.append(final_job) |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 402 | yield new_tests |