1*760c253cSXin Li#!/usr/bin/env python3 2*760c253cSXin Li# -*- coding: utf-8 -*- 3*760c253cSXin Li# 4*760c253cSXin Li# Copyright 2014 The ChromiumOS Authors 5*760c253cSXin Li# Use of this source code is governed by a BSD-style license that can be 6*760c253cSXin Li# found in the LICENSE file. 7*760c253cSXin Li 8*760c253cSXin Li"""Unittest for suite_runner.""" 9*760c253cSXin Li 10*760c253cSXin Li 11*760c253cSXin Liimport contextlib 12*760c253cSXin Liimport json 13*760c253cSXin Liimport unittest 14*760c253cSXin Liimport unittest.mock as mock 15*760c253cSXin Li 16*760c253cSXin Lifrom benchmark import Benchmark 17*760c253cSXin Lifrom cros_utils import command_executer 18*760c253cSXin Lifrom cros_utils import logger 19*760c253cSXin Liimport label 20*760c253cSXin Lifrom machine_manager import MockCrosMachine 21*760c253cSXin Liimport suite_runner 22*760c253cSXin Li 23*760c253cSXin Li 24*760c253cSXin Liclass SuiteRunnerTest(unittest.TestCase): 25*760c253cSXin Li """Class of SuiteRunner test.""" 26*760c253cSXin Li 27*760c253cSXin Li mock_json = mock.Mock(spec=json) 28*760c253cSXin Li mock_cmd_exec = mock.Mock(spec=command_executer.CommandExecuter) 29*760c253cSXin Li mock_cmd_term = mock.Mock(spec=command_executer.CommandTerminator) 30*760c253cSXin Li mock_logger = mock.Mock(spec=logger.Logger) 31*760c253cSXin Li mock_label = label.MockLabel( 32*760c253cSXin Li "lumpy", 33*760c253cSXin Li "build", 34*760c253cSXin Li "lumpy_chromeos_image", 35*760c253cSXin Li "", 36*760c253cSXin Li "", 37*760c253cSXin Li "/tmp/chromeos", 38*760c253cSXin Li "lumpy", 39*760c253cSXin Li ["lumpy1.cros", "lumpy.cros2"], 40*760c253cSXin Li "", 41*760c253cSXin Li "", 42*760c253cSXin Li False, 43*760c253cSXin Li "average", 44*760c253cSXin Li "gcc", 45*760c253cSXin Li False, 46*760c253cSXin Li "", 47*760c253cSXin Li ) 48*760c253cSXin Li telemetry_crosperf_bench = Benchmark( 49*760c253cSXin Li "b1_test", # name 50*760c253cSXin Li "octane", # test_name 51*760c253cSXin Li "", # test_args 52*760c253cSXin Li 3, # iterations 53*760c253cSXin Li False, # rm_chroot_tmp 54*760c253cSXin Li "record -e cycles", # perf_args 55*760c253cSXin Li "telemetry_Crosperf", # suite 56*760c253cSXin Li True, 57*760c253cSXin Li ) # show_all_results 58*760c253cSXin Li 59*760c253cSXin Li crosperf_wrapper_bench = Benchmark( 60*760c253cSXin Li "b2_test", # name 61*760c253cSXin Li "webgl", # test_name 62*760c253cSXin Li "", # test_args 63*760c253cSXin Li 3, # iterations 64*760c253cSXin Li False, # rm_chroot_tmp 65*760c253cSXin Li "", # perf_args 66*760c253cSXin Li "crosperf_Wrapper", 67*760c253cSXin Li ) # suite 68*760c253cSXin Li 69*760c253cSXin Li tast_bench = Benchmark( 70*760c253cSXin Li "b3_test", # name 71*760c253cSXin Li "platform.ReportDiskUsage", # test_name 72*760c253cSXin Li "", # test_args 73*760c253cSXin Li 1, # iterations 74*760c253cSXin Li False, # rm_chroot_tmp 75*760c253cSXin Li "", # perf_args 76*760c253cSXin Li "tast", 77*760c253cSXin Li ) # suite 78*760c253cSXin Li 79*760c253cSXin Li def __init__(self, *args, **kwargs): 80*760c253cSXin Li super(SuiteRunnerTest, self).__init__(*args, **kwargs) 81*760c253cSXin Li self.crosfleet_run_args = [] 82*760c253cSXin Li self.test_that_args = [] 83*760c253cSXin Li self.tast_args = [] 84*760c253cSXin Li self.call_crosfleet_run = False 85*760c253cSXin Li self.call_test_that_run = False 86*760c253cSXin Li self.call_tast_run = False 87*760c253cSXin Li 88*760c253cSXin Li def setUp(self): 89*760c253cSXin Li self.runner = suite_runner.SuiteRunner( 90*760c253cSXin Li {}, 91*760c253cSXin Li self.mock_logger, 92*760c253cSXin Li "verbose", 93*760c253cSXin Li self.mock_cmd_exec, 94*760c253cSXin Li self.mock_cmd_term, 95*760c253cSXin Li ) 96*760c253cSXin Li 97*760c253cSXin Li def test_get_profiler_args(self): 98*760c253cSXin Li input_str = ( 99*760c253cSXin Li "--profiler=custom_perf --profiler_args='perf_options" 100*760c253cSXin Li '="record -a -e cycles,instructions"\'' 101*760c253cSXin Li ) 102*760c253cSXin Li output_str = ( 103*760c253cSXin Li "profiler=custom_perf profiler_args='record -a -e " 104*760c253cSXin Li "cycles,instructions'" 105*760c253cSXin Li ) 106*760c253cSXin Li res = suite_runner.GetProfilerArgs(input_str) 107*760c253cSXin Li self.assertEqual(res, output_str) 108*760c253cSXin Li 109*760c253cSXin Li def test_get_dut_config_args(self): 110*760c253cSXin Li dut_config = {"enable_aslr": False, "top_interval": 1.0} 111*760c253cSXin Li output_str = ( 112*760c253cSXin Li "dut_config=" 113*760c253cSXin Li "'" 114*760c253cSXin Li '{"enable_aslr": ' 115*760c253cSXin Li 'false, "top_interval": 1.0}' 116*760c253cSXin Li "'" 117*760c253cSXin Li "" 118*760c253cSXin Li ) 119*760c253cSXin Li res = suite_runner.GetDutConfigArgs(dut_config) 120*760c253cSXin Li self.assertEqual(res, output_str) 121*760c253cSXin Li 122*760c253cSXin Li @mock.patch("suite_runner.ssh_tunnel") 123*760c253cSXin Li def test_run(self, ssh_tunnel): 124*760c253cSXin Li @contextlib.contextmanager 125*760c253cSXin Li def mock_ssh_tunnel(_watcher, _host): 126*760c253cSXin Li yield "fakelocalhost:1234" 127*760c253cSXin Li 128*760c253cSXin Li ssh_tunnel.side_effect = mock_ssh_tunnel 129*760c253cSXin Li 130*760c253cSXin Li def reset(): 131*760c253cSXin Li self.test_that_args = [] 132*760c253cSXin Li self.crosfleet_run_args = [] 133*760c253cSXin Li self.tast_args = [] 134*760c253cSXin Li self.call_test_that_run = False 135*760c253cSXin Li self.call_crosfleet_run = False 136*760c253cSXin Li self.call_tast_run = False 137*760c253cSXin Li 138*760c253cSXin Li def FakeCrosfleetRun(test_label, benchmark, test_args, profiler_args): 139*760c253cSXin Li self.crosfleet_run_args = [ 140*760c253cSXin Li test_label, 141*760c253cSXin Li benchmark, 142*760c253cSXin Li test_args, 143*760c253cSXin Li profiler_args, 144*760c253cSXin Li ] 145*760c253cSXin Li self.call_crosfleet_run = True 146*760c253cSXin Li return "Ran FakeCrosfleetRun" 147*760c253cSXin Li 148*760c253cSXin Li def FakeTestThatRun( 149*760c253cSXin Li machine, test_label, benchmark, test_args, profiler_args 150*760c253cSXin Li ): 151*760c253cSXin Li self.test_that_args = [ 152*760c253cSXin Li machine, 153*760c253cSXin Li test_label, 154*760c253cSXin Li benchmark, 155*760c253cSXin Li test_args, 156*760c253cSXin Li profiler_args, 157*760c253cSXin Li ] 158*760c253cSXin Li self.call_test_that_run = True 159*760c253cSXin Li return "Ran FakeTestThatRun" 160*760c253cSXin Li 161*760c253cSXin Li def FakeTastRun(machine, test_label, benchmark): 162*760c253cSXin Li self.tast_args = [machine, test_label, benchmark] 163*760c253cSXin Li self.call_tast_run = True 164*760c253cSXin Li return "Ran FakeTastRun" 165*760c253cSXin Li 166*760c253cSXin Li self.runner.Crosfleet_Run = FakeCrosfleetRun 167*760c253cSXin Li self.runner.Test_That_Run = FakeTestThatRun 168*760c253cSXin Li self.runner.Tast_Run = FakeTastRun 169*760c253cSXin Li 170*760c253cSXin Li self.runner.dut_config["enable_aslr"] = False 171*760c253cSXin Li self.runner.dut_config["cooldown_time"] = 0 172*760c253cSXin Li self.runner.dut_config["governor"] = "fake_governor" 173*760c253cSXin Li self.runner.dut_config["cpu_freq_pct"] = 65 174*760c253cSXin Li self.runner.dut_config["intel_pstate"] = "no_hwp" 175*760c253cSXin Li machine = "fake_machine" 176*760c253cSXin Li cros_machine = MockCrosMachine( 177*760c253cSXin Li machine, self.mock_label.chromeos_root, self.mock_logger 178*760c253cSXin Li ) 179*760c253cSXin Li test_args = "" 180*760c253cSXin Li profiler_args = "" 181*760c253cSXin Li 182*760c253cSXin Li # Test crosfleet run for telemetry_Crosperf and crosperf_Wrapper benchmarks. 183*760c253cSXin Li self.mock_label.crosfleet = True 184*760c253cSXin Li reset() 185*760c253cSXin Li self.runner.Run( 186*760c253cSXin Li cros_machine, 187*760c253cSXin Li self.mock_label, 188*760c253cSXin Li self.crosperf_wrapper_bench, 189*760c253cSXin Li test_args, 190*760c253cSXin Li profiler_args, 191*760c253cSXin Li ) 192*760c253cSXin Li self.assertTrue(self.call_crosfleet_run) 193*760c253cSXin Li self.assertFalse(self.call_test_that_run) 194*760c253cSXin Li self.assertEqual( 195*760c253cSXin Li self.crosfleet_run_args, 196*760c253cSXin Li [self.mock_label, self.crosperf_wrapper_bench, "", ""], 197*760c253cSXin Li ) 198*760c253cSXin Li 199*760c253cSXin Li reset() 200*760c253cSXin Li self.runner.Run( 201*760c253cSXin Li cros_machine, 202*760c253cSXin Li self.mock_label, 203*760c253cSXin Li self.telemetry_crosperf_bench, 204*760c253cSXin Li test_args, 205*760c253cSXin Li profiler_args, 206*760c253cSXin Li ) 207*760c253cSXin Li self.assertTrue(self.call_crosfleet_run) 208*760c253cSXin Li self.assertFalse(self.call_test_that_run) 209*760c253cSXin Li self.assertEqual( 210*760c253cSXin Li self.crosfleet_run_args, 211*760c253cSXin Li [self.mock_label, self.telemetry_crosperf_bench, "", ""], 212*760c253cSXin Li ) 213*760c253cSXin Li 214*760c253cSXin Li # Test test_that run for telemetry_Crosperf and crosperf_Wrapper benchmarks. 215*760c253cSXin Li self.mock_label.crosfleet = False 216*760c253cSXin Li reset() 217*760c253cSXin Li self.runner.Run( 218*760c253cSXin Li cros_machine, 219*760c253cSXin Li self.mock_label, 220*760c253cSXin Li self.crosperf_wrapper_bench, 221*760c253cSXin Li test_args, 222*760c253cSXin Li profiler_args, 223*760c253cSXin Li ) 224*760c253cSXin Li self.assertTrue(self.call_test_that_run) 225*760c253cSXin Li self.assertFalse(self.call_crosfleet_run) 226*760c253cSXin Li self.assertEqual( 227*760c253cSXin Li self.test_that_args, 228*760c253cSXin Li [ 229*760c253cSXin Li "fake_machine", 230*760c253cSXin Li self.mock_label, 231*760c253cSXin Li self.crosperf_wrapper_bench, 232*760c253cSXin Li "", 233*760c253cSXin Li "", 234*760c253cSXin Li ], 235*760c253cSXin Li ) 236*760c253cSXin Li 237*760c253cSXin Li reset() 238*760c253cSXin Li self.runner.Run( 239*760c253cSXin Li cros_machine, 240*760c253cSXin Li self.mock_label, 241*760c253cSXin Li self.telemetry_crosperf_bench, 242*760c253cSXin Li test_args, 243*760c253cSXin Li profiler_args, 244*760c253cSXin Li ) 245*760c253cSXin Li self.assertTrue(self.call_test_that_run) 246*760c253cSXin Li self.assertFalse(self.call_crosfleet_run) 247*760c253cSXin Li self.assertEqual( 248*760c253cSXin Li self.test_that_args, 249*760c253cSXin Li [ 250*760c253cSXin Li "fake_machine", 251*760c253cSXin Li self.mock_label, 252*760c253cSXin Li self.telemetry_crosperf_bench, 253*760c253cSXin Li "", 254*760c253cSXin Li "", 255*760c253cSXin Li ], 256*760c253cSXin Li ) 257*760c253cSXin Li 258*760c253cSXin Li # Test tast run for tast benchmarks. 259*760c253cSXin Li reset() 260*760c253cSXin Li self.runner.Run(cros_machine, self.mock_label, self.tast_bench, "", "") 261*760c253cSXin Li self.assertTrue(self.call_tast_run) 262*760c253cSXin Li self.assertFalse(self.call_test_that_run) 263*760c253cSXin Li self.assertFalse(self.call_crosfleet_run) 264*760c253cSXin Li self.assertEqual( 265*760c253cSXin Li self.tast_args, 266*760c253cSXin Li ["fakelocalhost:1234", self.mock_label, self.tast_bench], 267*760c253cSXin Li ) 268*760c253cSXin Li 269*760c253cSXin Li def test_gen_test_args(self): 270*760c253cSXin Li test_args = "--iterations=2" 271*760c253cSXin Li perf_args = "record -a -e cycles" 272*760c253cSXin Li 273*760c253cSXin Li # Test crosperf_Wrapper benchmarks arg list generation 274*760c253cSXin Li args_list = [ 275*760c253cSXin Li "test_args='--iterations=2'", 276*760c253cSXin Li "dut_config='{}'", 277*760c253cSXin Li "test=webgl", 278*760c253cSXin Li ] 279*760c253cSXin Li res = self.runner.GenTestArgs( 280*760c253cSXin Li self.crosperf_wrapper_bench, test_args, "" 281*760c253cSXin Li ) 282*760c253cSXin Li self.assertCountEqual(res, args_list) 283*760c253cSXin Li 284*760c253cSXin Li # Test telemetry_Crosperf benchmarks arg list generation 285*760c253cSXin Li args_list = [ 286*760c253cSXin Li "test_args='--iterations=2'", 287*760c253cSXin Li "dut_config='{}'", 288*760c253cSXin Li "test=octane", 289*760c253cSXin Li "run_local=False", 290*760c253cSXin Li ] 291*760c253cSXin Li args_list.append(suite_runner.GetProfilerArgs(perf_args)) 292*760c253cSXin Li res = self.runner.GenTestArgs( 293*760c253cSXin Li self.telemetry_crosperf_bench, test_args, perf_args 294*760c253cSXin Li ) 295*760c253cSXin Li self.assertCountEqual(res, args_list) 296*760c253cSXin Li 297*760c253cSXin Li @mock.patch.object(command_executer.CommandExecuter, "CrosRunCommand") 298*760c253cSXin Li @mock.patch.object( 299*760c253cSXin Li command_executer.CommandExecuter, "ChrootRunCommandWOutput" 300*760c253cSXin Li ) 301*760c253cSXin Li def test_tast_run(self, mock_chroot_runcmd, mock_cros_runcmd): 302*760c253cSXin Li mock_chroot_runcmd.return_value = 0 303*760c253cSXin Li self.mock_cmd_exec.ChrootRunCommandWOutput = mock_chroot_runcmd 304*760c253cSXin Li self.mock_cmd_exec.CrosRunCommand = mock_cros_runcmd 305*760c253cSXin Li res = self.runner.Tast_Run( 306*760c253cSXin Li "lumpy1.cros", self.mock_label, self.tast_bench 307*760c253cSXin Li ) 308*760c253cSXin Li self.assertEqual(mock_cros_runcmd.call_count, 1) 309*760c253cSXin Li self.assertEqual(mock_chroot_runcmd.call_count, 1) 310*760c253cSXin Li self.assertEqual(res, 0) 311*760c253cSXin Li self.assertEqual( 312*760c253cSXin Li mock_cros_runcmd.call_args_list[0][0], 313*760c253cSXin Li ("rm -rf /usr/local/autotest/results/*",), 314*760c253cSXin Li ) 315*760c253cSXin Li args_list = mock_chroot_runcmd.call_args_list[0][0] 316*760c253cSXin Li args_dict = mock_chroot_runcmd.call_args_list[0][1] 317*760c253cSXin Li self.assertEqual(len(args_list), 2) 318*760c253cSXin Li self.assertEqual(args_dict["command_terminator"], self.mock_cmd_term) 319*760c253cSXin Li 320*760c253cSXin Li @mock.patch.object(command_executer.CommandExecuter, "CrosRunCommand") 321*760c253cSXin Li @mock.patch.object( 322*760c253cSXin Li command_executer.CommandExecuter, "ChrootRunCommandWOutput" 323*760c253cSXin Li ) 324*760c253cSXin Li @mock.patch.object(logger.Logger, "LogFatal") 325*760c253cSXin Li def test_test_that_run( 326*760c253cSXin Li self, mock_log_fatal, mock_chroot_runcmd, mock_cros_runcmd 327*760c253cSXin Li ): 328*760c253cSXin Li mock_log_fatal.side_effect = SystemExit() 329*760c253cSXin Li self.runner.logger.LogFatal = mock_log_fatal 330*760c253cSXin Li # Test crosperf_Wrapper benchmarks cannot take perf_args 331*760c253cSXin Li raised_exception = False 332*760c253cSXin Li try: 333*760c253cSXin Li self.runner.Test_That_Run( 334*760c253cSXin Li "lumpy1.cros", 335*760c253cSXin Li self.mock_label, 336*760c253cSXin Li self.crosperf_wrapper_bench, 337*760c253cSXin Li "", 338*760c253cSXin Li "record -a -e cycles", 339*760c253cSXin Li ) 340*760c253cSXin Li except SystemExit: 341*760c253cSXin Li raised_exception = True 342*760c253cSXin Li self.assertTrue(raised_exception) 343*760c253cSXin Li 344*760c253cSXin Li mock_chroot_runcmd.return_value = 0 345*760c253cSXin Li self.mock_cmd_exec.ChrootRunCommandWOutput = mock_chroot_runcmd 346*760c253cSXin Li self.mock_cmd_exec.CrosRunCommand = mock_cros_runcmd 347*760c253cSXin Li res = self.runner.Test_That_Run( 348*760c253cSXin Li "lumpy1.cros", 349*760c253cSXin Li self.mock_label, 350*760c253cSXin Li self.crosperf_wrapper_bench, 351*760c253cSXin Li "--iterations=2", 352*760c253cSXin Li "", 353*760c253cSXin Li ) 354*760c253cSXin Li self.assertEqual(mock_cros_runcmd.call_count, 1) 355*760c253cSXin Li self.assertEqual(mock_chroot_runcmd.call_count, 1) 356*760c253cSXin Li self.assertEqual(res, 0) 357*760c253cSXin Li self.assertEqual( 358*760c253cSXin Li mock_cros_runcmd.call_args_list[0][0], 359*760c253cSXin Li ("rm -rf /usr/local/autotest/results/*",), 360*760c253cSXin Li ) 361*760c253cSXin Li args_list = mock_chroot_runcmd.call_args_list[0][0] 362*760c253cSXin Li args_dict = mock_chroot_runcmd.call_args_list[0][1] 363*760c253cSXin Li self.assertEqual(len(args_list), 2) 364*760c253cSXin Li self.assertEqual(args_dict["command_terminator"], self.mock_cmd_term) 365*760c253cSXin Li 366*760c253cSXin Li @mock.patch.object(command_executer.CommandExecuter, "RunCommandWOutput") 367*760c253cSXin Li @mock.patch.object(json, "loads") 368*760c253cSXin Li def test_crosfleet_run_client(self, mock_json_loads, mock_runcmd): 369*760c253cSXin Li def FakeDownloadResult(l, task_id): 370*760c253cSXin Li if l and task_id: 371*760c253cSXin Li self.assertEqual(task_id, "12345") 372*760c253cSXin Li return 0 373*760c253cSXin Li 374*760c253cSXin Li mock_runcmd.return_value = ( 375*760c253cSXin Li 0, 376*760c253cSXin Li "Created Swarming task https://swarming/task/b12345", 377*760c253cSXin Li "", 378*760c253cSXin Li ) 379*760c253cSXin Li self.mock_cmd_exec.RunCommandWOutput = mock_runcmd 380*760c253cSXin Li 381*760c253cSXin Li mock_json_loads.return_value = { 382*760c253cSXin Li "child-results": [ 383*760c253cSXin Li { 384*760c253cSXin Li "success": True, 385*760c253cSXin Li "task-run-url": "https://swarming/task?id=12345", 386*760c253cSXin Li } 387*760c253cSXin Li ] 388*760c253cSXin Li } 389*760c253cSXin Li self.mock_json.loads = mock_json_loads 390*760c253cSXin Li 391*760c253cSXin Li self.mock_label.crosfleet = True 392*760c253cSXin Li self.runner.DownloadResult = FakeDownloadResult 393*760c253cSXin Li res = self.runner.Crosfleet_Run( 394*760c253cSXin Li self.mock_label, self.crosperf_wrapper_bench, "", "" 395*760c253cSXin Li ) 396*760c253cSXin Li ret_tup = (0, "\nResults placed in tmp/swarming-12345\n", "") 397*760c253cSXin Li self.assertEqual(res, ret_tup) 398*760c253cSXin Li self.assertEqual(mock_runcmd.call_count, 2) 399*760c253cSXin Li 400*760c253cSXin Li args_list = mock_runcmd.call_args_list[0][0] 401*760c253cSXin Li args_dict = mock_runcmd.call_args_list[0][1] 402*760c253cSXin Li self.assertEqual(len(args_list), 1) 403*760c253cSXin Li self.assertEqual(args_dict["command_terminator"], self.mock_cmd_term) 404*760c253cSXin Li 405*760c253cSXin Li args_list = mock_runcmd.call_args_list[1][0] 406*760c253cSXin Li self.assertEqual(args_list[0], ("crosfleet wait-task 12345")) 407*760c253cSXin Li self.assertEqual(args_dict["command_terminator"], self.mock_cmd_term) 408*760c253cSXin Li 409*760c253cSXin Li 410*760c253cSXin Liif __name__ == "__main__": 411*760c253cSXin Li unittest.main() 412