summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/common_lib/logging.py2
-rw-r--r--tko/db.py31
-rw-r--r--tko/migrations/012_add_running_status.py6
-rw-r--r--tko/models.py27
-rw-r--r--tko/parsers/version_1.py25
5 files changed, 72 insertions, 19 deletions
diff --git a/client/common_lib/logging.py b/client/common_lib/logging.py
index 4f15a62e..5f6f6200 100644
--- a/client/common_lib/logging.py
+++ b/client/common_lib/logging.py
@@ -8,7 +8,7 @@ __author__ = 'jadmanski@google.com (John Admanski)'
job_statuses = ["TEST_NA", "ABORT", "ERROR", "FAIL", "WARN", "GOOD", "ALERT",
- "NOSTATUS"]
+ "RUNNING", "NOSTATUS"]
def is_valid_status(status):
if not re.match(r'(START|(END )?('+'|'.join(job_statuses)+'))$',
diff --git a/tko/db.py b/tko/db.py
index 4bac507c..df91103b 100644
--- a/tko/db.py
+++ b/tko/db.py
@@ -164,10 +164,14 @@ class db_sql(object):
values = []
if where and isinstance(where, types.DictionaryType):
- # key/value pairs (which should be equal)
- keys = [field + '=%s' for field in where.keys()]
- values = [where[field] for field in where.keys()]
-
+ # key/value pairs (which should be equal, or None for null)
+ keys, values = [], []
+ for field, value in where.iteritems():
+ if value is None:
+ keys.append(field + ' is null')
+ else:
+ keys.append(field + '=%s')
+ values.append(value)
cmd.append(' where ' + ' and '.join(keys))
elif where and isinstance(where, types.StringTypes):
# the exact string
@@ -282,14 +286,14 @@ class db_sql(object):
fields = data.keys()
data_refs = [field + '=%s' for field in fields]
data_values = [data[field] for field in fields]
- cmd += ' set ' + ' and '.join(data_refs)
+ cmd += ' set ' + ', '.join(data_refs)
where_keys = [field + '=%s' for field in where.keys()]
where_values = [where[field] for field in where.keys()]
cmd += ' where ' + ' and '.join(where_keys)
values = data_values + where_values
- print '%s %s' % (cmd, values)
+ self.dprint('%s %s' % (cmd, values))
self._exec_sql_with_commit(cmd, values, commit)
@@ -299,6 +303,7 @@ class db_sql(object):
for test_idx in self.find_tests(job_idx):
where = {'test_idx' : test_idx}
self.delete('iteration_result', where)
+ self.delete('iteration_attributes', where)
self.delete('test_attributes', where)
where = {'job_idx' : job_idx}
self.delete('tests', where)
@@ -331,9 +336,13 @@ class db_sql(object):
'reason':test.reason, 'machine_idx':job.machine_idx,
'started_time': test.started_time,
'finished_time':test.finished_time}
- self.insert('tests', data, commit=commit)
- test_idx = self.get_last_autonumber_value()
- data = { 'test_idx':test_idx }
+ if hasattr(test, "test_idx"):
+ test_idx = test.test_idx
+ self.update('tests', data, {'test_idx': test_idx}, commit=commit)
+ else:
+ self.insert('tests', data, commit=commit)
+ test_idx = test.test_idx = self.get_last_autonumber_value()
+ data = {'test_idx': test_idx}
for i in test.iterations:
data['iteration'] = i.index
@@ -441,8 +450,8 @@ class db_sql(object):
commit=commit)
- def find_test(self, job_idx, subdir):
- where = { 'job_idx':job_idx , 'subdir':subdir }
+ def find_test(self, job_idx, testname, subdir):
+ where = {'job_idx': job_idx , 'test': testname, 'subdir': subdir}
rows = self.select('test_idx', 'tests', where)
if rows:
return rows[0][0]
diff --git a/tko/migrations/012_add_running_status.py b/tko/migrations/012_add_running_status.py
new file mode 100644
index 00000000..db7db2ec
--- /dev/null
+++ b/tko/migrations/012_add_running_status.py
@@ -0,0 +1,6 @@
+def migrate_up(manager):
+ manager.execute("INSERT INTO status (word) values ('RUNNING')")
+
+
+def migrate_down(manager):
+ manager.execute("DELETE FROM status where word = 'RUNNING'")
diff --git a/tko/models.py b/tko/models.py
index a5e230b6..d754e9e7 100644
--- a/tko/models.py
+++ b/tko/models.py
@@ -56,7 +56,7 @@ class test(object):
@classmethod
def parse_test(cls, job, subdir, testname, status, reason, test_kernel,
- started_time, finished_time):
+ started_time, finished_time, existing_instance=None):
"""Given a job and the basic metadata about the test that
can be extracted from the status logs, parse the test
keyval files and use it to construct a complete test
@@ -76,9 +76,28 @@ class test(object):
iterations = []
attributes = {}
- return cls(subdir, testname, status, reason, test_kernel,
- job.machine, started_time, finished_time,
- iterations, attributes)
+ if existing_instance:
+ def constructor(*args, **dargs):
+ existing_instance.__init__(*args, **dargs)
+ return existing_instance
+ else:
+ constructor = cls
+ return constructor(subdir, testname, status, reason, test_kernel,
+ job.machine, started_time, finished_time,
+ iterations, attributes)
+
+
+ @classmethod
+ def parse_partial_test(cls, job, subdir, testname, reason, test_kernel,
+ started_time):
+ """Given a job and the basic metadata available when a test is
+ started, create a test instance representing the partial result.
+ Assume that since the test is not complete there are no results files
+ actually available for parsing."""
+ tko_utils.dprint("parsing partial test %s %s" % (subdir, testname))
+
+ return cls(subdir, testname, "RUNNING", reason, test_kernel,
+ job.machine, started_time, None, [], {})
@staticmethod
diff --git a/tko/parsers/version_1.py b/tko/parsers/version_1.py
index 317a082c..95f608db 100644
--- a/tko/parsers/version_1.py
+++ b/tko/parsers/version_1.py
@@ -110,6 +110,7 @@ class parser(base.parser):
current_kernel = kernel("", []) # UNKNOWN
started_time_stack = [None]
subdir_stack = [None]
+ running_test = None
while True:
# are we finished with parsing?
@@ -142,9 +143,25 @@ class parser(base.parser):
# initial line processing
if line.type == "START":
stack.start()
- if (line.testname, line.subdir) == (None,) * 2:
+ started_time = line.get_timestamp()
+ if (line.testname, line.subdir) == (None, None):
+ # we just started a client, all tests are relative to here
min_stack_size = stack.size()
- started_time_stack.append(line.get_timestamp())
+ elif stack.size() == min_stack_size + 1:
+ # we just started a new test, insert a running record
+ assert(running_test is None)
+ 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 == "STATUS":
@@ -212,7 +229,9 @@ class parser(base.parser):
line.reason,
current_kernel,
started_time,
- finished_time)
+ finished_time,
+ running_test)
+ running_test = None
msg = "ADD: %s\nSubdir: %s\nTestname: %s\n%s"
msg %= (new_test.status, new_test.subdir,
new_test.testname, new_test.reason)