1*9c5db199SXin Li# Lint as: python2, python3 2*9c5db199SXin Li# Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 3*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be 4*9c5db199SXin Li# found in the LICENSE file. 5*9c5db199SXin Li 6*9c5db199SXin Li"""Utility classes used by server_job.distribute_across_machines(). 7*9c5db199SXin Li 8*9c5db199SXin Litest_item: extends the basic test tuple to add include/exclude attributes and 9*9c5db199SXin Li pre/post actions. 10*9c5db199SXin Li""" 11*9c5db199SXin Li 12*9c5db199SXin Li 13*9c5db199SXin Liimport logging, os, six.moves.queue 14*9c5db199SXin Lifrom autotest_lib.client.common_lib import error, utils 15*9c5db199SXin Lifrom autotest_lib.server import autotest, hosts, host_attributes 16*9c5db199SXin Li 17*9c5db199SXin Li 18*9c5db199SXin Liclass test_item(object): 19*9c5db199SXin Li """Adds machine verification logic to the basic test tuple. 20*9c5db199SXin Li 21*9c5db199SXin Li Tests can either be tuples of the existing form ('testName', {args}) or the 22*9c5db199SXin Li extended form ('testname', {args}, {'include': [], 'exclude': [], 23*9c5db199SXin Li 'attributes': []}) where include and exclude are lists of host attribute 24*9c5db199SXin Li labels and attributes is a list of strings. A machine must have all the 25*9c5db199SXin Li labels in include and must not have any of the labels in exclude to be valid 26*9c5db199SXin Li for the test. Attributes strings can include reboot_before, reboot_after, 27*9c5db199SXin Li and server_job. 28*9c5db199SXin Li """ 29*9c5db199SXin Li 30*9c5db199SXin Li def __init__(self, test_name, test_args, test_attribs=None): 31*9c5db199SXin Li """Creates an instance of test_item. 32*9c5db199SXin Li 33*9c5db199SXin Li Args: 34*9c5db199SXin Li test_name: string, name of test to execute. 35*9c5db199SXin Li test_args: dictionary, arguments to pass into test. 36*9c5db199SXin Li test_attribs: Dictionary of test attributes. Valid keys are: 37*9c5db199SXin Li include - labels a machine must have to run a test. 38*9c5db199SXin Li exclude - labels preventing a machine from running a test. 39*9c5db199SXin Li attributes - reboot before/after test, run test as server job. 40*9c5db199SXin Li """ 41*9c5db199SXin Li self.test_name = test_name 42*9c5db199SXin Li self.test_args = test_args 43*9c5db199SXin Li self.tagged_test_name = test_name 44*9c5db199SXin Li if test_args.get('tag'): 45*9c5db199SXin Li self.tagged_test_name = test_name + '.' + test_args.get('tag') 46*9c5db199SXin Li 47*9c5db199SXin Li if test_attribs is None: 48*9c5db199SXin Li test_attribs = {} 49*9c5db199SXin Li self.inc_set = set(test_attribs.get('include', [])) 50*9c5db199SXin Li self.exc_set = set(test_attribs.get('exclude', [])) 51*9c5db199SXin Li self.attributes = test_attribs.get('attributes', []) 52*9c5db199SXin Li 53*9c5db199SXin Li def __str__(self): 54*9c5db199SXin Li """Return an info string of this test.""" 55*9c5db199SXin Li params = ['%s=%s' % (k, v) for k, v in self.test_args.items()] 56*9c5db199SXin Li msg = '%s(%s)' % (self.test_name, params) 57*9c5db199SXin Li if self.inc_set: 58*9c5db199SXin Li msg += ' include=%s' % [s for s in self.inc_set] 59*9c5db199SXin Li if self.exc_set: 60*9c5db199SXin Li msg += ' exclude=%s' % [s for s in self.exc_set] 61*9c5db199SXin Li if self.attributes: 62*9c5db199SXin Li msg += ' attributes=%s' % self.attributes 63*9c5db199SXin Li return msg 64*9c5db199SXin Li 65*9c5db199SXin Li def validate(self, machine_attributes): 66*9c5db199SXin Li """Check if this test can run on machine with machine_attributes. 67*9c5db199SXin Li 68*9c5db199SXin Li If the test has include attributes, a candidate machine must have all 69*9c5db199SXin Li the attributes to be valid. 70*9c5db199SXin Li 71*9c5db199SXin Li If the test has exclude attributes, a candidate machine cannot have any 72*9c5db199SXin Li of the attributes to be valid. 73*9c5db199SXin Li 74*9c5db199SXin Li Args: 75*9c5db199SXin Li machine_attributes: set, True attributes of candidate machine. 76*9c5db199SXin Li 77*9c5db199SXin Li Returns: 78*9c5db199SXin Li True/False if the machine is valid for this test. 79*9c5db199SXin Li """ 80*9c5db199SXin Li if self.inc_set is not None: 81*9c5db199SXin Li if not self.inc_set <= machine_attributes: 82*9c5db199SXin Li return False 83*9c5db199SXin Li if self.exc_set is not None: 84*9c5db199SXin Li if self.exc_set & machine_attributes: 85*9c5db199SXin Li return False 86*9c5db199SXin Li return True 87*9c5db199SXin Li 88*9c5db199SXin Li def run_test(self, client_at, work_dir='.', server_job=None): 89*9c5db199SXin Li """Runs the test on the client using autotest. 90*9c5db199SXin Li 91*9c5db199SXin Li Args: 92*9c5db199SXin Li client_at: Autotest instance for this host. 93*9c5db199SXin Li work_dir: Directory to use for results and log files. 94*9c5db199SXin Li server_job: Server_Job instance to use to runs server tests. 95*9c5db199SXin Li """ 96*9c5db199SXin Li if 'reboot_before' in self.attributes: 97*9c5db199SXin Li client_at.host.reboot() 98*9c5db199SXin Li 99*9c5db199SXin Li try: 100*9c5db199SXin Li if 'server_job' in self.attributes: 101*9c5db199SXin Li if 'host' in self.test_args: 102*9c5db199SXin Li self.test_args['host'] = client_at.host 103*9c5db199SXin Li if server_job is not None: 104*9c5db199SXin Li logging.info('Running Server_Job=%s', self.test_name) 105*9c5db199SXin Li server_job.run_test(self.test_name, **self.test_args) 106*9c5db199SXin Li else: 107*9c5db199SXin Li logging.error('No Server_Job instance provided for test ' 108*9c5db199SXin Li '%s.', self.test_name) 109*9c5db199SXin Li else: 110*9c5db199SXin Li client_at.run_test(self.test_name, results_dir=work_dir, 111*9c5db199SXin Li **self.test_args) 112*9c5db199SXin Li finally: 113*9c5db199SXin Li if 'reboot_after' in self.attributes: 114*9c5db199SXin Li client_at.host.reboot() 115