Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Unified Diff: verification/try_job_on_rietveld.py

Issue 10907197: Differentiate between tests that needs to be run or need to wait for completion. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/commit-queue
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tests/try_job_on_rietveld_test.py ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: verification/try_job_on_rietveld.py
diff --git a/verification/try_job_on_rietveld.py b/verification/try_job_on_rietveld.py
index 704d443c7a15fb7b727af31d01749b59e5cf5f57..b6c66e6fcb8d6c5d1b1f81662ae9d6865ac4dafd 100644
--- a/verification/try_job_on_rietveld.py
+++ b/verification/try_job_on_rietveld.py
@@ -30,13 +30,28 @@ def is_job_expired(revision, timestamp, checkout):
return False
+class RietveldTryJobPending(model.PersistentMixIn):
+ """Represents a pending try job for a pending commit that we care about.
+ """
+ persistent = [
+ 'builder', 'revision', 'requested_steps',
+ 'clobber', 'tries',
+ ]
+ def __init__(self, builder, revision, requested_steps, clobber, tries):
+ super(RietveldTryJobPending, self).__init__()
+ self.builder = builder
+ self.revision = revision
+ self.requested_steps = requested_steps
+ self.clobber = clobber
+ # Number of retries for this configuration. Initial try is 1.
+ self.tries = tries
+
+
class RietveldTryJob(model.PersistentMixIn):
"""Represents a try job for a pending commit that we care about.
This data can be regenerated by parsing all the try job names but it is a bit
hard on the try server.
-
- TODO(maruel): Should use __getstate__(), __setstate__() and __reduce__().
"""
persistent = [
'builder', 'build', 'revision', 'requested_steps', 'started',
@@ -51,6 +66,7 @@ class RietveldTryJob(model.PersistentMixIn):
self.build = build
self.revision = revision
self.requested_steps = requested_steps
+ # The timestamp when the build started.
self.started = started
self.steps_passed = passed
self.steps_failed = failed
@@ -102,11 +118,12 @@ class RietveldTryJobs(base.IVerifierStatus):
self.skipped = False
self.builders_and_tests = {}
# Jobs that have been sent but are not found yet. Likely a builder is fully
- # utilized or the try server hasn't polled Rietveld yet.
+ # utilized or the try server hasn't polled Rietveld yet. list of
+ # RietveldTryJobPending() instances.
self.pendings = []
def get_state(self):
- if self.skipped or (not self.remaining() and not self.pendings):
+ if self.skipped or not self.tests_waiting_for_result():
return base.SUCCEEDED
if (self.pendings or
not all(t.completed for t in self.try_jobs.itervalues())):
@@ -114,33 +131,50 @@ class RietveldTryJobs(base.IVerifierStatus):
logging.debug('Not pending, all %d jobs completed' % len(self.try_jobs))
return base.FAILED
- def remaining(self):
- """Returns what remains to be tested.
+ def tests_need_to_be_run(self):
+ """Returns which tests need to be run.
- This excludes tests from any pending build so they are not retried
- unnecessarily.
+ These are the tests that are not pending on any try job, either running or
+ in the pending list.
"""
# What needs to be run.
all_tests = dict(
(builder, set(tests))
for builder, tests in self.builders_and_tests.iteritems())
- def clean(job):
- if job.builder in all_tests:
- all_tests[job.builder] -= set(job.steps_passed)
+ # Removes what was run and almost to be run, e.g. the build is running.
+ for try_job in self.try_jobs.itervalues():
+ if try_job.builder in all_tests:
+ all_tests[try_job.builder] -= set(try_job.steps_passed)
# If it was requested but still not run, do not add it either. Only do
# that if the job hasn't completed yet to catch issues like: a test was
# requested on a builder but the test was not run because it is not in
# the BuildFactory for the Builder.
- if not job.completed:
- to_be_run = set(job.requested_steps) - set(job.steps_failed)
- all_tests[job.builder] -= to_be_run
+ if not try_job.completed:
+ to_be_run = set(try_job.requested_steps) - set(try_job.steps_failed)
+ all_tests[try_job.builder] -= to_be_run
+
+ # Removes what is queued to be run but hasn't started yet.
+ for try_job in self.pendings:
+ if try_job.builder in all_tests:
+ all_tests[try_job.builder] -= set(try_job.requested_steps)
+
+ return dict(
+ (builder, list(tests)) for builder, tests in all_tests.iteritems()
+ if tests)
+
+ def tests_waiting_for_result(self):
+ """Returns the tests that we are waiting for results on pending or running
+ builds.
+ """
+ all_tests = dict(
+ (builder, set(tests))
+ for builder, tests in self.builders_and_tests.iteritems())
# Removes what was run.
for try_job in self.try_jobs.itervalues():
- clean(try_job)
- for try_job in self.pendings:
- clean(try_job)
+ if try_job.builder in all_tests:
+ all_tests[try_job.builder] -= set(try_job.steps_passed)
return dict(
(builder, list(tests)) for builder, tests in all_tests.iteritems()
@@ -215,6 +249,7 @@ class RietveldTryJobs(base.IVerifierStatus):
passed = [s.name for s in build.steps if s.simplified_result]
failed = [s.name for s in build.steps if s.simplified_result is False]
+ # The steps in neither passed or failed were skipped.
logging.info(
'Found Job success: %s/%d: %s',
builder, buildnumber, ','.join(passed))
@@ -253,8 +288,9 @@ class TryRunnerRietveld(base.VerifierCheckout):
1. Fetch result from try server.
2. If try job was generated from rietveld;
1. If not is_job_expired();
- 1. Strips from jobs to run for each succeeded steps
- 2. If no step remaining, mark job as succeeded.
+ 1. Skip any scheduled test that succeeded on this builder.
+ 2. For each builder with tests scheduled;
+ 1. If no step waiting to be triggered, skip this builder completely.
2. For each non succeeded job;
1. Send try jobs to rietveld.
@@ -330,7 +366,7 @@ class TryRunnerRietveld(base.VerifierCheckout):
if jobs.error_message:
# Too late.
return
- remaining = jobs.remaining()
+ remaining = jobs.tests_need_to_be_run()
if not remaining:
return
# Send them in order to simplify testing.
@@ -367,9 +403,7 @@ class TryRunnerRietveld(base.VerifierCheckout):
pending.issue, pending.patchset, 'CQ', clobber, None,
{builder: tests})
jobs.pendings.append(
- RietveldTryJob(
- builder, None, None, tests, time.time(), [], [],
- clobber, False, tries + 1))
+ RietveldTryJobPending(builder, None, tests, clobber, tries + 1))
# Update the status on the AppEngine status to signal a new try job was
# sent.
info = {
@@ -405,7 +439,7 @@ class TryRunnerRietveld(base.VerifierCheckout):
}
self.send_status(pending, info)
- remaining = jobs.remaining()
+ remaining = jobs.tests_need_to_be_run()
retry = [
step for step in job.steps_failed
if step in remaining.get(job.builder, [])
« no previous file with comments | « tests/try_job_on_rietveld_test.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698