aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crosperf/experiment.py3
-rw-r--r--crosperf/experiment_runner.py5
-rw-r--r--crosperf/suite_runner.py170
-rwxr-xr-xcrosperf/suite_runner_unittest.py141
4 files changed, 190 insertions, 129 deletions
diff --git a/crosperf/experiment.py b/crosperf/experiment.py
index 80674b4b..1ce9b5aa 100644
--- a/crosperf/experiment.py
+++ b/crosperf/experiment.py
@@ -105,6 +105,9 @@ class Experiment(object):
except BadChecksum:
# Force same image on all machines, then we do checksum again. No
# bailout if checksums still do not match.
+ # TODO: It's not a good idea to force flashing the image when we are
+ # running with skylab... Although for now it even helps us getting
+ # that machine...
self.machine_manager.ForceSameImageToAllMachines(label)
self.machine_manager.ComputeCommonCheckSum(label)
diff --git a/crosperf/experiment_runner.py b/crosperf/experiment_runner.py
index 9eff1fb5..159c86e4 100644
--- a/crosperf/experiment_runner.py
+++ b/crosperf/experiment_runner.py
@@ -2,6 +2,7 @@
# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+
"""The experiment runner module."""
from __future__ import print_function
@@ -166,7 +167,7 @@ class ExperimentRunner(object):
def _Run(self, experiment):
try:
- if not experiment.locks_dir:
+ if not experiment.locks_dir and not experiment.skylab:
self._LockAllMachines(experiment)
if self._using_schedv2:
schedv2 = Schedv2(experiment)
@@ -211,7 +212,7 @@ class ExperimentRunner(object):
experiment.Terminate()
raise
finally:
- if not experiment.locks_dir:
+ if not experiment.locks_dir and not experiment.skylab:
self._UnlockAllMachines(experiment)
def _PrintTable(self, experiment):
diff --git a/crosperf/suite_runner.py b/crosperf/suite_runner.py
index ba1c3fa7..f61a90bf 100644
--- a/crosperf/suite_runner.py
+++ b/crosperf/suite_runner.py
@@ -9,11 +9,14 @@ from __future__ import print_function
import os
import shlex
+import time
from cros_utils import command_executer
-import test_flag
TEST_THAT_PATH = '/usr/bin/test_that'
+# TODO: Need to check whether Skylab is installed and set up correctly.
+SKYLAB_PATH = '/usr/local/bin/skylab'
+GS_UTIL = 'chromium/tools/depot_tools/gsutil.py'
AUTOTEST_DIR = '~/trunk/src/third_party/autotest/files'
CHROME_MOUNT_DIR = '/tmp/chrome_root'
@@ -62,21 +65,26 @@ class SuiteRunner(object):
def Run(self, machine, label, benchmark, test_args, profiler_args):
for i in range(0, benchmark.retries + 1):
- # Unless the user turns on ASLR in the flag, we first disable ASLR
- # before running the benchmarks
- if not self.enable_aslr:
- self.DisableASLR(machine, label.chromeos_root)
- self.PinGovernorExecutionFrequencies(machine, label.chromeos_root)
- if benchmark.suite == 'telemetry':
- self.DecreaseWaitTime(machine, label.chromeos_root)
- ret_tup = self.Telemetry_Run(machine, label, benchmark, profiler_args)
- elif benchmark.suite == 'telemetry_Crosperf':
- self.DecreaseWaitTime(machine, label.chromeos_root)
- ret_tup = self.Telemetry_Crosperf_Run(machine, label, benchmark,
- test_args, profiler_args)
+ if label.skylab:
+ # TODO: need to migrate DisableASLR and PinGovernorExecutionFrequencies
+ # since in skylab mode, we may not know the DUT until one is assigned
+ # to the test. For telemetry_Crosperf run, we can move them into the
+ # server test script, for client runs, need to figure out wrapper to do
+ # it before running.
+ ret_tup = self.Skylab_Run(label, benchmark, test_args, profiler_args)
else:
- ret_tup = self.Test_That_Run(machine, label, benchmark, test_args,
- profiler_args)
+ # Unless the user turns on ASLR in the flag, we first disable ASLR
+ # before running the benchmarks
+ if not self.enable_aslr:
+ self.DisableASLR(machine, label.chromeos_root)
+ self.PinGovernorExecutionFrequencies(machine, label.chromeos_root)
+ if benchmark.suite == 'telemetry_Crosperf':
+ self.DecreaseWaitTime(machine, label.chromeos_root)
+ ret_tup = self.Telemetry_Crosperf_Run(machine, label, benchmark,
+ test_args, profiler_args)
+ else:
+ ret_tup = self.Test_That_Run(machine, label, benchmark, test_args,
+ profiler_args)
if ret_tup[0] != 0:
self.logger.LogOutput('benchmark %s failed. Retries left: %s' %
@@ -226,6 +234,103 @@ class SuiteRunner(object):
command_terminator=self._ct,
cros_sdk_options='--no-ns-pid')
+ def DownloadResult(self, label, task_id):
+ gsutil_cmd = os.path.join(label.chromeos_root, GS_UTIL)
+ result_dir = 'gs://chromeos-autotest-results/swarming-%s' % task_id
+ download_path = os.path.join(label.chromeos_root, 'chroot/tmp')
+ ls_command = '%s ls %s' % (gsutil_cmd,
+ os.path.join(result_dir, 'autoserv_test'))
+ cp_command = '%s -mq cp -r %s %s' % (gsutil_cmd, result_dir, download_path)
+
+ # Server sometimes will not be able to generate the result directory right
+ # after the test. Will try to access this gs location every 60s for 5 mins.
+ t = 0
+ RETRY_LIMIT = 5
+ while t < RETRY_LIMIT:
+ self.logger.LogOutput('Downloading test results.')
+ t += 1
+ status = self._ce.RunCommand(ls_command, print_to_console=False)
+ if status == 0:
+ break
+ if t < RETRY_LIMIT:
+ self.logger.LogOutput('Result directory not generated yet, '
+ 'retry (%d) in 60s.' % t)
+ time.sleep(60)
+ else:
+ self.logger.LogOutput('No result directory for task %s' % task_id)
+ return status
+
+ # Wait for 60s to make sure server finished writing to gs location.
+ time.sleep(60)
+
+ status = self._ce.RunCommand(cp_command)
+ if status != 0:
+ self.logger.LogOutput('Cannot download results from task %s' % task_id)
+ return status
+
+ def Skylab_Run(self, label, benchmark, test_args, profiler_args):
+ """Run the test via skylab.."""
+ options = ''
+ if benchmark.suite != 'telemetry_Crosperf':
+ options += '-client-test'
+ if label.board:
+ options += ' -board=%s' % label.board
+ if label.build:
+ options += ' -image=%s' % label.build
+ # TODO: now only put quota pool here, user need to be able to specify which
+ # pool to use. Need to request feature to not use this option at all.
+ options += ' -pool=DUT_POOL_QUOTA'
+ if benchmark.suite == 'telemetry_Crosperf':
+ if test_args:
+ # Strip double quotes off args (so we can wrap them in single
+ # quotes, to pass through to Telemetry).
+ if test_args[0] == '"' and test_args[-1] == '"':
+ test_args = test_args[1:-1]
+ if profiler_args:
+ test_args += GetProfilerArgs(profiler_args)
+ test_args += ' run_local={} test={}'.format(
+ benchmark.run_local,
+ benchmark.test_name,
+ )
+ else:
+ if profiler_args:
+ self.logger.LogFatal('Client tests do not support profiler.')
+ if test_args:
+ options += ' -test-args="%s"' % test_args
+
+ dimensions = ''
+ for dut in label.remote:
+ dimensions += ' dut_name:%s' % dut.rstrip('.cros')
+
+ command = (('%s create-test %s %s %s') % \
+ (SKYLAB_PATH, options, benchmark.test_name, dimensions))
+
+ if self.log_level != 'verbose':
+ self.logger.LogOutput('Starting skylab test.')
+ self.logger.LogOutput('CMD: %s' % command)
+ ret_tup = self._ce.RunCommandWOutput(command, command_terminator=self._ct)
+
+ if ret_tup[0] != 0:
+ self.logger.LogOutput('Skylab test not created successfully.')
+ return ret_tup
+
+ # Std output of the command will look like:
+ # Created Swarming task https://chromeos-swarming.appspot.com/task?id=12345
+ # We want to parse it and get the id number of the task.
+ task_id = ret_tup[1].strip().split('id=')[1]
+
+ command = ('skylab wait-task %s' % (task_id))
+ if self.log_level != 'verbose':
+ self.logger.LogOutput('Waiting for skylab test to finish.')
+ self.logger.LogOutput('CMD: %s' % command)
+
+ ret_tup = self._ce.RunCommandWOutput(command, command_terminator=self._ct)
+ if '"success":true' in ret_tup[1]:
+ if self.DownloadResult(label, task_id) == 0:
+ result_dir = '\nResults placed in tmp/swarming-%s\n' % task_id
+ return (ret_tup[0], result_dir, ret_tup[2])
+ return ret_tup
+
def RemoveTelemetryTempFile(self, machine, chromeos_root):
filename = 'telemetry@%s' % machine
fullname = os.path.join(chromeos_root, 'chroot', 'tmp', filename)
@@ -284,41 +389,6 @@ class SuiteRunner(object):
command_terminator=self._ct,
cros_sdk_options=chrome_root_options)
- def Telemetry_Run(self, machine, label, benchmark, profiler_args):
- telemetry_run_path = ''
- if not os.path.isdir(label.chrome_src):
- self.logger.LogFatal('Cannot find chrome src dir to' ' run telemetry.')
- else:
- telemetry_run_path = os.path.join(label.chrome_src, 'src/tools/perf')
- if not os.path.exists(telemetry_run_path):
- self.logger.LogFatal('Cannot find %s directory.' % telemetry_run_path)
-
- if profiler_args:
- self.logger.LogFatal('Telemetry does not support the perf profiler.')
-
- # Check for and remove temporary file that may have been left by
- # previous telemetry runs (and which might prevent this run from
- # working).
- if not test_flag.GetTestMode():
- self.RemoveTelemetryTempFile(machine, label.chromeos_root)
-
- rsa_key = os.path.join(
- label.chromeos_root,
- 'src/scripts/mod_for_test_scripts/ssh_keys/testing_rsa')
-
- cmd = ('cd {0} && '
- './run_measurement '
- '--browser=cros-chrome '
- '--output-format=csv '
- '--remote={1} '
- '--identity {2} '
- '{3} {4}'.format(telemetry_run_path, machine, rsa_key,
- benchmark.test_name, benchmark.test_args))
- if self.log_level != 'verbose':
- self.logger.LogOutput('Running test.')
- self.logger.LogOutput('CMD: %s' % cmd)
- return self._ce.RunCommandWOutput(cmd, print_to_console=False)
-
def CommandTerminator(self):
return self._ct
diff --git a/crosperf/suite_runner_unittest.py b/crosperf/suite_runner_unittest.py
index e3a34f1e..2fcb45ac 100755
--- a/crosperf/suite_runner_unittest.py
+++ b/crosperf/suite_runner_unittest.py
@@ -10,13 +10,13 @@
from __future__ import print_function
import os.path
+import time
import mock
import unittest
import suite_runner
import label
-import test_flag
from benchmark import Benchmark
@@ -68,13 +68,14 @@ class SuiteRunnerTest(unittest.TestCase):
self.call_test_that_run = False
self.disable_aslr_args = []
self.pin_governor_args = []
+ self.skylab_run_args = []
self.test_that_args = []
self.telemetry_run_args = []
self.telemetry_crosperf_args = []
+ self.call_skylab_run = False
self.call_telemetry_crosperf_run = False
self.call_disable_aslr = False
self.call_pin_governor = False
- self.call_telemetry_run = False
def setUp(self):
self.runner = suite_runner.SuiteRunner(
@@ -93,9 +94,10 @@ class SuiteRunnerTest(unittest.TestCase):
def reset():
self.call_pin_governor = False
self.call_test_that_run = False
- self.call_telemetry_run = False
+ self.call_skylab_run = False
self.call_telemetry_crosperf_run = False
self.pin_governor_args = []
+ self.skylab_run_args = []
self.test_that_args = []
self.telemetry_run_args = []
self.telemetry_crosperf_args = []
@@ -108,10 +110,10 @@ class SuiteRunnerTest(unittest.TestCase):
self.call_pin_governor = True
self.pin_governor_args = [machine, chroot]
- def FakeTelemetryRun(machine, test_label, benchmark, profiler_args):
- self.telemetry_run_args = [machine, test_label, benchmark, profiler_args]
- self.call_telemetry_run = True
- return 'Ran FakeTelemetryRun'
+ def FakeSkylabRun(test_label, benchmark, test_args, profiler_args):
+ self.skylab_run_args = [test_label, benchmark, test_args, profiler_args]
+ self.call_skylab_run = True
+ return 'Ran FakeSkylabRun'
def FakeTelemetryCrosperfRun(machine, test_label, benchmark, test_args,
profiler_args):
@@ -131,31 +133,31 @@ class SuiteRunnerTest(unittest.TestCase):
self.runner.DisableASLR = FakeDisableASLR
self.runner.PinGovernorExecutionFrequencies = FakePinGovernor
- self.runner.Telemetry_Run = FakeTelemetryRun
+ self.runner.Skylab_Run = FakeSkylabRun
self.runner.Telemetry_Crosperf_Run = FakeTelemetryCrosperfRun
self.runner.Test_That_Run = FakeTestThatRun
-
machine = 'fake_machine'
test_args = ''
profiler_args = ''
+
reset()
+ self.mock_label.skylab = True
self.runner.Run(machine, self.mock_label, self.telemetry_bench, test_args,
profiler_args)
- self.assertTrue(self.call_disable_aslr)
- self.assertTrue(self.call_pin_governor)
- self.assertTrue(self.call_telemetry_run)
+ self.assertFalse(self.call_disable_aslr)
+ self.assertFalse(self.call_pin_governor)
+ self.assertTrue(self.call_skylab_run)
self.assertFalse(self.call_test_that_run)
self.assertFalse(self.call_telemetry_crosperf_run)
- self.assertEqual(
- self.telemetry_run_args,
- ['fake_machine', self.mock_label, self.telemetry_bench, ''])
+ self.assertEqual(self.skylab_run_args,
+ [self.mock_label, self.telemetry_bench, '', ''])
+ self.mock_label.skylab = False
reset()
self.runner.Run(machine, self.mock_label, self.test_that_bench, test_args,
profiler_args)
self.assertTrue(self.call_disable_aslr)
self.assertTrue(self.call_pin_governor)
- self.assertFalse(self.call_telemetry_run)
self.assertTrue(self.call_test_that_run)
self.assertFalse(self.call_telemetry_crosperf_run)
self.assertEqual(
@@ -167,7 +169,6 @@ class SuiteRunnerTest(unittest.TestCase):
test_args, profiler_args)
self.assertTrue(self.call_disable_aslr)
self.assertTrue(self.call_pin_governor)
- self.assertFalse(self.call_telemetry_run)
self.assertFalse(self.call_test_that_run)
self.assertTrue(self.call_telemetry_crosperf_run)
self.assertEqual(self.telemetry_crosperf_args, [
@@ -235,10 +236,6 @@ class SuiteRunnerTest(unittest.TestCase):
'ChrootRunCommandWOutput')
def test_test_that_run(self, mock_chroot_runcmd, mock_cros_runcmd):
- def FakeRebootMachine(machine, chroot):
- if machine or chroot:
- pass
-
def FakeLogMsg(fd, termfd, msg, flush=True):
if fd or termfd or msg or flush:
pass
@@ -246,7 +243,6 @@ class SuiteRunnerTest(unittest.TestCase):
save_log_msg = self.real_logger.LogMsg
self.real_logger.LogMsg = FakeLogMsg
self.runner.logger = self.real_logger
- self.runner.RebootMachine = FakeRebootMachine
raised_exception = False
try:
@@ -307,67 +303,58 @@ class SuiteRunnerTest(unittest.TestCase):
self.assertEqual(args_dict['command_terminator'], self.mock_cmd_term)
self.assertEqual(len(args_dict), 2)
- @mock.patch.object(os.path, 'isdir')
- @mock.patch.object(os.path, 'exists')
@mock.patch.object(command_executer.CommandExecuter, 'RunCommandWOutput')
- def test_telemetry_run(self, mock_runcmd, mock_exists, mock_isdir):
-
- def FakeLogMsg(fd, termfd, msg, flush=True):
- if fd or termfd or msg or flush:
- pass
+ def test_skylab_run(self, mock_runcmd):
- save_log_msg = self.real_logger.LogMsg
- self.real_logger.LogMsg = FakeLogMsg
- mock_runcmd.return_value = 0
+ def FakeDownloadResult(l, task_id):
+ if l and task_id:
+ self.assertEqual(task_id, '12345')
+ return 0
+ mock_runcmd.return_value = \
+ (0,
+ '"success":true\nCreated Swarming task https://swarming/task?id=12345',
+ '')
self.mock_cmd_exec.RunCommandWOutput = mock_runcmd
- self.runner.logger = self.real_logger
-
- profiler_args = ('--profiler=custom_perf --profiler_args=\'perf_options'
- '="record -a -e cycles,instructions"\'')
-
- raises_exception = False
- mock_isdir.return_value = False
- try:
- self.runner.Telemetry_Run('lumpy1.cros', self.mock_label,
- self.telemetry_bench, '')
- except SystemExit:
- raises_exception = True
- self.assertTrue(raises_exception)
-
- raises_exception = False
- mock_isdir.return_value = True
- mock_exists.return_value = False
- try:
- self.runner.Telemetry_Run('lumpy1.cros', self.mock_label,
- self.telemetry_bench, '')
- except SystemExit:
- raises_exception = True
- self.assertTrue(raises_exception)
-
- raises_exception = False
- mock_isdir.return_value = True
- mock_exists.return_value = True
- try:
- self.runner.Telemetry_Run('lumpy1.cros', self.mock_label,
- self.telemetry_bench, profiler_args)
- except SystemExit:
- raises_exception = True
- self.assertTrue(raises_exception)
+ self.mock_label.skylab = True
+ self.runner.DownloadResult = FakeDownloadResult
+ res = self.runner.Skylab_Run(self.mock_label, self.test_that_bench, '', '')
+ ret_tup = (0, '\nResults placed in tmp/swarming-12345\n', '')
+ self.assertEqual(res, ret_tup)
+ self.assertEqual(mock_runcmd.call_count, 2)
+
+ args_list = mock_runcmd.call_args_list[0][0]
+ args_dict = mock_runcmd.call_args_list[0][1]
+ self.assertEqual(args_list[0],
+ ('/usr/local/bin/skylab create-test -client-test '
+ '-board=lumpy -image=build -pool=DUT_POOL_QUOTA '
+ 'octane dut_name:lumpy1 dut_name:lumpy.cros2'))
+ self.assertEqual(args_dict['command_terminator'], self.mock_cmd_term)
- test_flag.SetTestMode(True)
- res = self.runner.Telemetry_Run('lumpy1.cros', self.mock_label,
- self.telemetry_bench, '')
- self.assertEqual(res, 0)
- self.assertEqual(mock_runcmd.call_count, 1)
- self.assertEqual(
- mock_runcmd.call_args_list[0][0],
- (('cd src/tools/perf && ./run_measurement '
- '--browser=cros-chrome --output-format=csv '
- '--remote=lumpy1.cros --identity /tmp/chromeos/src/scripts'
- '/mod_for_test_scripts/ssh_keys/testing_rsa octane '),))
+ args_list = mock_runcmd.call_args_list[1][0]
+ self.assertEqual(args_list[0], ('skylab wait-task 12345'))
+ self.assertEqual(args_dict['command_terminator'], self.mock_cmd_term)
- self.real_logger.LogMsg = save_log_msg
+ @mock.patch.object(time, 'sleep')
+ @mock.patch.object(command_executer.CommandExecuter, 'RunCommand')
+ def test_download_result(self, mock_runcmd, mock_sleep):
+ mock_runcmd.return_value = 0
+ mock_sleep.return_value = 0
+ self.mock_cmd_exec.RunCommand = mock_runcmd
+
+ self.runner.DownloadResult(self.mock_label, '12345')
+
+ self.assertEqual(mock_runcmd.call_count, 2)
+ cmd = mock_runcmd.call_args_list[0][0][0]
+ self.assertEqual(cmd,
+ ('/tmp/chromeos/chromium/tools/depot_tools/gsutil.py ls '
+ 'gs://chromeos-autotest-results/swarming-12345/'
+ 'autoserv_test'))
+ cmd = mock_runcmd.call_args_list[1][0][0]
+ self.assertEqual(cmd,
+ ('/tmp/chromeos/chromium/tools/depot_tools/gsutil.py -mq '
+ 'cp -r gs://chromeos-autotest-results/swarming-12345 '
+ '/tmp/chromeos/chroot/tmp'))
if __name__ == '__main__':