From 49f0a5b3ffbb7d67eded14e0a94a2364f2930e3a Mon Sep 17 00:00:00 2001 From: Celso Providelo Date: Mon, 2 Feb 2015 17:04:24 -0500 Subject: [PATCH] Wraps 'boottest-britney' script for checking status or submitting new jobs. --- boottest.py | 68 ++++++++++++++++++++++++++++++------------ tests/test_boottest.py | 41 +++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 19 deletions(-) diff --git a/boottest.py b/boottest.py index 3c1b951..0815061 100644 --- a/boottest.py +++ b/boottest.py @@ -14,6 +14,7 @@ from __future__ import print_function import os +import subprocess import time import urllib @@ -86,10 +87,52 @@ class TouchManifest(object): return key in self._manifest +class BootTestJenkinsJob(object): + """Boottest - Jenkins **glue**. + + Wraps 'boottest/jenkins/boottest-britney' script for: + + * 'check' existing boottest job status ('check ') + * 'submit' new boottest jobs ('submit ') + + """ + + script_path = "boottest/jenkins/boottest-britney" + + def __init__(self, distribution, series): + self.distribution = distribution + self.series = series + + def _run(self, *args): + if not os.path.exists(self.script_path): + print("E: [%s] - Boottest/Jenking glue script missing: %s" % ( + time.asctime(), self.script_path)) + return '-' + command = [ + self.script_path, + "-d", self.distribution, "-s", self.series, + ] + command.extend(args) + return subprocess.check_output(command).strip() + + def get_status(self, name, version): + """Return the current boottest jenkins job status. + + Request a boottest attempt if it's new. + """ + try: + status = self._run('check', name, version) + except subprocess.CalledProcessError as err: + status = self._run('submit', name, version) + return status + + class BootTest(object): """Boottest criteria for Britney. - TBD! + Process (update) excuses for the 'boottest' criteria. Request and monitor + boottest attempts (see `BootTestJenkinsJob`) for binaries present in the + phone image manifest (see `TouchManifest`). """ VALID_STATUSES = ('PASS', 'SKIPPED') @@ -109,26 +152,13 @@ class BootTest(object): self.britney.options, "boottest_fetch", "no") == "yes" self.phone_manifest = TouchManifest( self.distribution, self.series, fetch=manifest_fetch) - - def _get_status(self, name, version): - """Return the current boottest status. - - Request a boottest attempt if it's new. - """ - # XXX cprov 20150120: replace with the test history latest - # record label, or a new job request if it was not found. - if name == 'pyqt5': - if version == '1.1~beta': - return 'PASS' - return 'FAIL' - - return 'RUNNING' + self.dispatcher = BootTestJenkinsJob(self.distribution, self.series) def update(self, excuse): """Update given 'excuse' and yields testing status. Yields (status, binary_name) for each binary considered for the - given excuse. See `_get_status()`. + given excuse. See `BootTestJenkinsJob.get_status`. Binaries are considered for boottesting if they are part of the phone image manifest. See `TouchManifest`. @@ -138,8 +168,8 @@ class BootTest(object): # Dismiss if source is not yet recognized (??). if excuse.name not in unstable_sources: raise StopIteration - # XXX cprov 20150120: binaries are a seq of "/" and, - # practically, boottest is only concerned about armhf+all binaries. + # Binaries are a seq of "/" and, practically, boottest + # is only concerned about armhf+all binaries. # Anything else should be skipped. binary_names = [ b.split('/')[0] @@ -150,7 +180,7 @@ class BootTest(object): # Process (request or update) boottest attempts for each binary. for name in binary_names: if name in self.phone_manifest: - status = self._get_status(name, excuse.ver[1]) + status = self.dispatcher.get_status(name, excuse.ver[1]) else: status = 'SKIPPED' yield name, status diff --git a/tests/test_boottest.py b/tests/test_boottest.py index 0442f3c..e9f7af8 100644 --- a/tests/test_boottest.py +++ b/tests/test_boottest.py @@ -20,6 +20,7 @@ sys.path.insert(0, PROJECT_DIR) from tests import TestBase from boottest import ( BootTest, + BootTestJenkinsJob, TouchManifest, ) @@ -157,10 +158,50 @@ class TestBoottestEnd2End(TestBase): 'boottest/images/ubuntu/{}'.format(self.data.series)) create_manifest(path, lines) + def make_boottest(self): + """Create a stub version of boottest-britney script.""" + script_path = os.path.join( + self.data.path, 'boottest/jenkins/boottest-britney') + os.makedirs(os.path.dirname(script_path)) + with open(script_path, 'w') as f: + f.write('''#!%(py)s +import argparse +import sys + +def submit(): + print 'RUNNING' + +def check(): + if args.name != 'pyqt5': + sys.exit(100) + if args.version == '1.1~beta': + print 'PASS' + else: + print 'FAIL' + +p = argparse.ArgumentParser() +p.add_argument('-d') +p.add_argument('-s') +sp = p.add_subparsers() +psubmit = sp.add_parser('submit') +psubmit.add_argument('name') +psubmit.add_argument('version') +psubmit.set_defaults(func=submit) +pcheck = sp.add_parser('check') +pcheck.add_argument('name') +pcheck.add_argument('version') +pcheck.set_defaults(func=check) + +args = p.parse_args() +args.func() + ''' % {'py': sys.executable}) + os.chmod(script_path, 0o755) + def do_test(self, context, expect=None, no_expect=None): """Process the given package context and assert britney results.""" for (pkg, fields) in context: self.data.add(pkg, True, fields) + self.make_boottest() (excuses, out) = self.run_britney() #print('-------\nexcuses: %s\n-----' % excuses) if expect: