blob: 480deb822a2eb94f4b00b33181fd1e5c2b127f4c [file] [log] [blame]
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from recipe_engine import recipe_api
class LegionApi(recipe_api.RecipeApi):
"""Provides a recipes interface for the Legion framework."""
@property
def legion_path(self):
"""Returns the path to legion.py."""
return self.m.path['checkout'].join('testing', 'legion', 'tools',
'legion.py')
def create_controller(self, name, path, os, config_vars=None,
controller_vars=None, dimensions=None):
"""Returns a controller config dictionary.
Args:
name: The name of the controller.
path: The path to the .isolate or .isolated file for the controller.
os: The os to run the controller on.
config_vars: A dictionary of config vars to pass when isolating the
controller .isolate file. This is ignored if passing a .isolated file.
controller_vars: A dictionary of command line vars passed to the
controller.
dimensions: A dictionary of dimensions to pass when isolating the
controller .isolate file. This is ignored if passing a .isolated file.
"""
return {
'name': name,
'path': path,
'os': os,
'config_vars': config_vars or {},
'controller_vars': controller_vars or {},
'dimensions': dimensions or {},
'tasks': []
}
def add_task_to_controller(self, controller, name, path, config_vars=None):
"""Adds a task config to a controller config.
Args:
controller: A controller config returnd by create_controller.
name: The name of the task. This corresponds to the command line flag
defined in the controller code.
path: The path to the .isolate or .isolated file for the task.
config_vars: Config variables passed when isolating a task .isolate file.
This is ignored if passing a .isolated file.
"""
controller['tasks'].append({
'name': name,
'path': path,
'config_vars': config_vars or {}
})
def _archive_if_needed(self, config):
"""Archives an isolate file if needed.
This method is a no-op if the path is already an .isolated file. If not the
file is archived and the path is set to the .isolated file.
"""
for item in [config] + config['tasks']:
if self.m.path.splitext(item['path'])[-1] == '.isolated':
continue
isolated_path = str(item['path']) + 'd'
cmd = [
'archive',
'--isolate', item['path'],
'--isolated', isolated_path,
'--isolate-server', self.m.isolate.isolate_server,
]
for name, value in item['config_vars'].iteritems():
cmd.extend(['--config-variable', name, value])
self.m.python(
'archive for %s' % self.m.path.split(str(item['path']))[-1],
self.m.swarming_client.path.join('isolate.py'),
cmd)
item['path'] = isolated_path
def execute(self, config):
"""Executes a Legion-based swarming test.
config: The configuration returned by create_controller.
"""
self._archive_if_needed(config)
cmd = [
'run',
'--controller-isolated', config['path'],
'--task-name', config['name'],
'--isolate-server', self.m.isolate.isolate_server,
'--swarming-server', self.m.chromium_swarming.swarming_server,
'--dimension', 'os', config['os']
]
for name, value in config['dimensions'].iteritems():
cmd.extend(['--dimension', name, value])
for name, value in config['controller_vars'].iteritems():
cmd.extend(['--controller-var', name, value])
for task in config['tasks']:
cmd.extend(['--task', task['name'], task['path']])
step_result = self.m.python(
'Running test for %s' % config['name'],
self.legion_path,
cmd,
stdout=self.m.raw_io.output_text())
return step_result.stdout