434
434
self.result.status = 'PASS'
435
435
return fetch_success
437
def process_master_runlist(self, runlist=None, resume=False):
438
"""Parse a master runlist and build a list of suites from the data.
440
:param runlist: URL pointing to a runlist
442
:param resume: Continue previous execution
443
:type resume: boolean
447
runlist = runlist or self.master_runlist
449
# Download runlist using the URL passed through the commmand line to
450
# local filename if needed (it might be a local file already or cached)
438
def _fetch_and_parse(runlist):
452
440
local_filename = urllib.urlretrieve(runlist)[0]
454
raise exceptions.MissingFile(runlist)
455
except urllib.ContentTooShortError as err:
441
except IOError as err:
456
442
raise exceptions.MissingFile(
457
'Error when downloading {} (probably interrupted): {}'
458
.format(runlist, err))
443
'Error when downloading {}: {}'.format(runlist, err))
460
445
data = parse_yaml_file(local_filename)
461
validator = DefaultValidator(self.MASTER_RUNLIST_SCHEMA)
446
validator = DefaultValidator(Runner.MASTER_RUNLIST_SCHEMA)
463
448
validator.validate(data)
464
449
except jsonschema.ValidationError as exception:
466
451
'Master runlist failed to validate: {!r}\n'
467
452
'Detailed information: {}'
468
453
.format(local_filename, exception))
457
def _clean_suite(name):
458
# convert to absolute name to make troubleshooting a little easier
459
name = os.path.abspath(name)
463
raise exceptions.UTAHClientError(
464
'Error removing the testsuite {}: {}'.format(name, e))
466
def _add_suite(self, suite):
469
if name not in self.fetched_suites:
470
if self._fetch_suite(suite):
471
self.fetched_suites.append(name)
472
suite_runlist = suite.get('runlist', DEFAULT_TSLIST)
474
s = TestSuite(name=name,
475
runlist_file=suite_runlist,
476
includes=suite.get('include_tests', None),
477
excludes=suite.get('exclude_tests', None),
479
path=self.testsuitedir,
480
timeout=self.timeout,
481
battery_measurements=self.battery_measurements,
482
_save_state_callback=self.save_state,
483
_reboot_callback=self.reboot)
486
self.fetch_errors += 1
488
def process_master_runlist(self, runlist=None, resume=False):
489
"""Parse a master runlist and build a list of suites from the data.
491
:param runlist: URL pointing to a runlist
493
:param resume: Continue previous execution
494
:type resume: boolean
497
runlist = runlist or self.master_runlist
498
data = self._fetch_and_parse(runlist)
470
500
if 'timeout' in data:
471
501
self.timeout = int(data['timeout'])
474
self.name = data['name']
476
self.name = 'unnamed'
503
self.name = data.get('name', 'unnamed')
478
504
self.battery_measurements = data['battery_measurements']
479
505
self.repeat_count = data['repeat_count']
483
509
orig_dir = os.getcwd()
485
if 'testsuites' in data:
486
suites = data['testsuites']
487
elif isinstance(data, list):
490
raise exceptions.BadMasterRunlist(str(data))
511
suites = data['testsuites']
492
512
suites = data['testsuites'] if 'testsuites' in data else data
493
513
for suite in suites:
494
514
# Allow the inclusion of other master.run files
501
521
name = suite['name']
503
includes = suite.get('include_tests')
504
excludes = suite.get('exclude_tests')
506
suite_runlist = suite.get('runlist', DEFAULT_TSLIST)
509
524
raise exceptions.BadMasterRunlist(
510
525
"{} duplicated in runlist".format(name))
512
527
# Fetch the testsuite. On resume don't remove the testsuite
514
529
if not resume and os.path.exists(name):
515
# Using absolute name makes no difference
516
# except on failures where it's easier
517
# to find troubleshoot permission problems
518
absolute_name = os.path.abspath(name)
520
shutil.rmtree(absolute_name)
521
except OSError as err:
522
raise exceptions.UTAHClientError(
523
'Error removing the testsuite directory {}: {}'
524
.format(absolute_name, err))
530
self._clean_suite(name)
527
if name not in self.fetched_suites:
528
if not self._fetch_suite(suite):
529
# If fetch failed move on to the next testsuite.
530
self.fetch_errors += 1
533
self.fetched_suites.append(name)
536
s = TestSuite(name=name,
537
runlist_file=suite_runlist,
541
path=self.testsuitedir,
542
timeout=self.timeout,
543
battery_measurements=self.battery_measurements,
544
_save_state_callback=self.save_state,
545
_reboot_callback=self.reboot)
533
self._add_suite(suite)
548
535
def get_next_suite(self):
549
536
"""Return the next suite to be run.