1#!/usr/bin/env python2 2# -*- coding: utf-8 -*- 3# 4# Copyright 2020 The Chromium OS Authors. All rights reserved. 5# Use of this source code is governed by a BSD-style license that can be 6# found in the LICENSE file. 7""" 8Unittest for device_setup_utils. 9 10""" 11 12from __future__ import print_function 13 14import logging 15import time 16import unittest 17import mock 18 19import common 20from autotest_lib.server import hosts 21from autotest_lib.server.cros.crosperf import device_setup_utils 22 23BIG_LITTLE_CPUINFO = """processor : 0 24model name : ARMv8 Processor rev 4 (v8l) 25BogoMIPS : 48.00 26Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 27CPU implementer : 0x41 28CPU architecture: 8 29CPU variant : 0x0 30CPU part : 0xd03 31CPU revision : 4 32 33processor : 1 34model name : ARMv8 Processor rev 4 (v8l) 35BogoMIPS : 48.00 36Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 37CPU implementer : 0x41 38CPU architecture: 8 39CPU variant : 0x0 40CPU part : 0xd03 41CPU revision : 4 42 43processor : 2 44model name : ARMv8 Processor rev 2 (v8l) 45BogoMIPS : 48.00 46Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 47CPU implementer : 0x41 48CPU architecture: 8 49CPU variant : 0x0 50CPU part : 0xd08 51CPU revision : 2 52""" 53LITTLE_ONLY_CPUINFO = """processor : 0 54model name : ARMv8 Processor rev 4 (v8l) 55BogoMIPS : 48.00 56Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 57CPU implementer : 0x41 58CPU architecture: 8 59CPU variant : 0x0 60CPU part : 0xd03 61CPU revision : 4 62 63processor : 1 64model name : ARMv8 Processor rev 4 (v8l) 65BogoMIPS : 48.00 66Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 67CPU implementer : 0x41 68CPU architecture: 8 69CPU variant : 0x0 70CPU part : 0xd03 71CPU revision : 4 72""" 73 74NOT_BIG_LITTLE_CPUINFO = """processor : 0 75model name : ARMv7 Processor rev 1 (v7l) 76Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpv4 77CPU implementer : 0x41 78CPU architecture: 7 79CPU variant : 0x0 80CPU part : 0xc0d 81CPU revision : 1 82 83processor : 1 84model name : ARMv7 Processor rev 1 (v7l) 85Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpv4 86CPU implementer : 0x41 87CPU architecture: 7 88CPU variant : 0x0 89CPU part : 0xc0d 90CPU revision : 1 91 92Hardware : Rockchip (Device Tree) 93Revision : 0000 94Serial : 0000000000000000 95""" 96 97 98class device_setup_utilsTest(unittest.TestCase): 99 """ 100 Class of device setup utils test. 101 """ 102 103 def __init__(self, *args, **kwargs): 104 super(device_setup_utilsTest, self).__init__(*args, **kwargs) 105 106 self.dut = mock.Mock(spec=hosts.create_host) 107 self.dut.hostname = 'lumpy.cros2' 108 self.dut.run = mock.Mock() 109 110 logging.error = mock.Mock() 111 logging.warning = mock.Mock() 112 113 114 def test_run_command_on_dut(self): 115 self.dut.run.return_value.exit_status = 0 116 self.dut.run.return_value.stdout = '' 117 self.dut.run.return_value.stderr = '' 118 119 self.dut.run.assert_not_called() 120 device_setup_utils.run_command_on_dut(self.dut, 'run command;') 121 self.dut.run.assert_called_once_with( 122 'run command;', ignore_status=False) 123 124 125 def test_run_command_on_dut_fatal_error(self): 126 # Command returns error 1. 127 self.dut.run.return_value.exit_status = 1 128 self.dut.run.return_value.stdout = '' 129 self.dut.run.return_value.stderr = 'Error!' 130 131 self.dut.run.assert_not_called() 132 device_setup_utils.run_command_on_dut(self.dut, 'run command;') 133 self.dut.run.assert_called_once_with( 134 'run command;', ignore_status=False) 135 # Error status causes log fatal. 136 logging.error.assert_called_once_with( 137 'Command execution on DUT lumpy.cros2 failed.\n' 138 'Failing command: run command;\nreturned 1\n' 139 'Error message: Error!') 140 141 142 def test_run_command_on_dut_ignore_error(self): 143 # Command returns error 1. 144 self.dut.run.return_value.exit_status = 1 145 self.dut.run.return_value.stdout = '' 146 self.dut.run.return_value.stderr = 'Error!' 147 148 self.dut.run.assert_not_called() 149 device_setup_utils.run_command_on_dut( 150 self.dut, 'run command;', ignore_status=True) 151 self.dut.run.assert_called_once_with( 152 'run command;', ignore_status=True) 153 # Error status causes log fatal. 154 logging.warning.assert_called_once_with( 155 'Command execution on DUT lumpy.cros2 failed.\n' 156 'Failing command: run command;\nreturned 1\n' 157 'Error message: Error!\n' 158 '(Failure is considered non-fatal. Continue.)') 159 160 161 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 162 def test_disable_aslr(self, mock_run_command): 163 mock_run_command.return_value = (0, '', '') 164 device_setup_utils.disable_aslr(self.dut) 165 # pyformat: disable 166 set_cpu_cmd = ('set -e; ' 167 'if [[ -e /proc/sys/kernel/randomize_va_space ]]; then ' 168 ' echo 0 > /proc/sys/kernel/randomize_va_space; ' 169 'fi') 170 mock_run_command.assert_called_once_with(self.dut, set_cpu_cmd) 171 172 173 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 174 def test_set_cpu_governor(self, mock_run_command): 175 mock_run_command.return_value = (0, '', '') 176 device_setup_utils.set_cpu_governor( 177 self.dut, 'new_governor', ignore_status=False) 178 set_cpu_cmd = ( 179 'for f in `ls -d /sys/devices/system/cpu/cpu*/cpufreq 2>/dev/null`; do' 180 # Skip writing scaling_governor if cpu is offline. 181 ' [[ -e ${f/cpufreq/online} ]] && grep -q 0 ${f/cpufreq/online} ' 182 ' && continue; ' 183 ' cd $f; ' 184 ' if [[ -e scaling_governor ]]; then ' 185 ' echo %s > scaling_governor; fi; ' 186 'done; ') 187 mock_run_command.assert_called_once_with( 188 self.dut, set_cpu_cmd % 'new_governor', ignore_status=False) 189 190 191 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 192 def test_set_cpu_governor_propagate_error(self, mock_run_command): 193 mock_run_command.return_value = (1, '', 'Error.') 194 device_setup_utils.set_cpu_governor(self.dut, 'non-exist_governor') 195 set_cpu_cmd = ( 196 'for f in `ls -d /sys/devices/system/cpu/cpu*/cpufreq 2>/dev/null`; do' 197 # Skip writing scaling_governor if cpu is not online. 198 ' [[ -e ${f/cpufreq/online} ]] && grep -q 0 ${f/cpufreq/online} ' 199 ' && continue; ' 200 ' cd $f; ' 201 ' if [[ -e scaling_governor ]]; then ' 202 ' echo %s > scaling_governor; fi; ' 203 'done; ') 204 # By default error status is fatal. 205 mock_run_command.assert_called_once_with( 206 self.dut, 207 set_cpu_cmd % 'non-exist_governor', 208 ignore_status=False) 209 210 211 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 212 def test_set_cpu_governor_ignore_status(self, mock_run_command): 213 mock_run_command.return_value = (1, '', 'Error.') 214 ret_code = device_setup_utils.set_cpu_governor( 215 self.dut, 'non-exist_governor', ignore_status=True) 216 set_cpu_cmd = ( 217 'for f in `ls -d /sys/devices/system/cpu/cpu*/cpufreq 2>/dev/null`; do' 218 # Skip writing scaling_governor if cpu is not online. 219 ' [[ -e ${f/cpufreq/online} ]] && grep -q 0 ${f/cpufreq/online} ' 220 ' && continue; ' 221 ' cd $f; ' 222 ' if [[ -e scaling_governor ]]; then ' 223 ' echo %s > scaling_governor; fi; ' 224 'done; ') 225 mock_run_command.assert_called_once_with( 226 self.dut, 227 set_cpu_cmd % 'non-exist_governor', 228 ignore_status=True) 229 self.assertEqual(ret_code, 1) 230 231 232 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 233 def test_disable_turbo(self, mock_run_command): 234 mock_run_command.return_value = (0, '', '') 235 device_setup_utils.disable_turbo(self.dut) 236 set_cpu_cmd = ( 237 # Disable Turbo the in Intel pstate driver. 238 'if [[ -e /sys/devices/system/cpu/intel_pstate/no_turbo ]]; then ' 239 ' if grep -q 0 /sys/devices/system/cpu/intel_pstate/no_turbo; then ' 240 ' echo -n 1 > /sys/devices/system/cpu/intel_pstate/no_turbo; ' 241 ' fi; ' 242 'fi; ' 243 # Disable Boost on AMD. 244 'if [[ -e /sys/devices/system/cpu/cpufreq/boost ]]; then ' 245 ' if grep -q 1 /sys/devices/system/cpu/cpufreq/boost; then ' 246 ' echo -n 0 > /sys/devices/system/cpu/cpufreq/boost; ' 247 ' fi; ' 248 'fi; ' 249 ) 250 mock_run_command.assert_called_once_with(self.dut, set_cpu_cmd) 251 252 253 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 254 def test_get_cpu_online_two(self, mock_run_command): 255 """Test one digit CPU #.""" 256 mock_run_command.return_value = ( 257 0, '/sys/devices/system/cpu/cpu0/online 0\n' 258 '/sys/devices/system/cpu/cpu1/online 1\n', '') 259 cpu_online = device_setup_utils.get_cpu_online(self.dut) 260 self.assertEqual(cpu_online, {0: 0, 1: 1}) 261 262 263 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 264 def test_get_cpu_online_twelve(self, mock_run_command): 265 """Test two digit CPU #.""" 266 mock_run_command.return_value = ( 267 0, '/sys/devices/system/cpu/cpu0/online 1\n' 268 '/sys/devices/system/cpu/cpu1/online 0\n' 269 '/sys/devices/system/cpu/cpu10/online 1\n' 270 '/sys/devices/system/cpu/cpu11/online 1\n' 271 '/sys/devices/system/cpu/cpu2/online 1\n' 272 '/sys/devices/system/cpu/cpu3/online 0\n' 273 '/sys/devices/system/cpu/cpu4/online 1\n' 274 '/sys/devices/system/cpu/cpu5/online 0\n' 275 '/sys/devices/system/cpu/cpu6/online 1\n' 276 '/sys/devices/system/cpu/cpu7/online 0\n' 277 '/sys/devices/system/cpu/cpu8/online 1\n' 278 '/sys/devices/system/cpu/cpu9/online 0\n', '') 279 cpu_online = device_setup_utils.get_cpu_online(self.dut) 280 self.assertEqual( 281 cpu_online, { 282 0: 1, 283 1: 0, 284 2: 1, 285 3: 0, 286 4: 1, 287 5: 0, 288 6: 1, 289 7: 0, 290 8: 1, 291 9: 0, 292 10: 1, 293 11: 1 294 }) 295 296 297 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 298 def test_get_cpu_online_core0_not_exposed(self, mock_run_command): 299 """Test that not exposed cpu0/online will still be in the list.""" 300 301 def run_command(dut, cmd): 302 """Helper function.""" 303 if '/sys/devices/system/cpu/cpu' in cmd: 304 # Cpu0 online is not exposed. 305 return (0, '/sys/devices/system/cpu/cpu1/online 1\n', '') 306 elif '/sys/devices/system/cpu/online' in cmd: 307 # All online cores shows cpu0. 308 return (0, '0-1', '') 309 else: 310 return (1, '', '') 311 312 mock_run_command.side_effect = run_command 313 cpu_online = device_setup_utils.get_cpu_online(self.dut) 314 # Make sure core0 in the online list. 315 self.assertEqual(cpu_online, {0: 1, 1: 1}) 316 317 318 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 319 def test_get_cpu_online_no_output(self, mock_run_command): 320 """Test error case, no output.""" 321 mock_run_command.return_value = (0, '', '') 322 with self.assertRaises(AssertionError): 323 device_setup_utils.get_cpu_online(self.dut) 324 325 326 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 327 def test_get_cpu_online_command_error(self, mock_run_command): 328 """Test error case, command error.""" 329 mock_run_command.side_effect = AssertionError 330 with self.assertRaises(AssertionError): 331 device_setup_utils.get_cpu_online(self.dut) 332 333 334 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 335 @mock.patch.object(device_setup_utils, 'setup_arm_cores') 336 def test_setup_cpu_usage_little_on_arm(self, mock_setup_arm, 337 mock_run_command): 338 device_setup_utils.setup_arm_cores = mock_setup_arm 339 mock_run_command.return_value = (0, 'armv7l', '') 340 cpu_usage = 'little_only' 341 device_setup_utils.setup_cpu_usage(self.dut, cpu_usage) 342 mock_setup_arm.assert_called_once() 343 344 345 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 346 @mock.patch.object(device_setup_utils, 'setup_arm_cores') 347 def test_setup_cpu_usage_big_on_aarch64(self, mock_setup_arm, 348 mock_run_command): 349 device_setup_utils.setup_arm_cores = mock_setup_arm 350 mock_run_command.return_value = (0, 'aarch64', '') 351 cpu_usage = 'big_only' 352 device_setup_utils.setup_cpu_usage(self.dut, cpu_usage) 353 mock_setup_arm.assert_called_once() 354 355 356 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 357 @mock.patch.object(device_setup_utils, 'setup_arm_cores') 358 def test_setup_cpu_usage_big_on_intel(self, mock_setup_arm, 359 mock_run_command): 360 device_setup_utils.setup_arm_cores = mock_setup_arm 361 mock_run_command.return_value = (0, 'x86_64', '') 362 cpu_usage = 'big_only' 363 device_setup_utils.setup_cpu_usage(self.dut, cpu_usage) 364 # Check that setup_arm_cores not called with invalid setup. 365 mock_setup_arm.assert_not_called() 366 367 368 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 369 @mock.patch.object(device_setup_utils, 'setup_arm_cores') 370 def test_setup_cpu_usage_all_on_intel(self, mock_setup_arm, 371 mock_run_command): 372 device_setup_utils.setup_arm_cores = mock_setup_arm 373 mock_run_command.return_value = (0, 'x86_64', '') 374 cpu_usage = 'all' 375 device_setup_utils.setup_cpu_usage(self.dut, cpu_usage) 376 # Check that setup_arm_cores not called in general case. 377 mock_setup_arm.assert_not_called() 378 379 380 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 381 def test_setup_arm_cores_big_on_big_little(self, mock_run_command): 382 mock_run_command.side_effect = [ 383 (0, BIG_LITTLE_CPUINFO, ''), 384 (0, '', ''), 385 ] 386 cpu_usage = 'big_only' 387 device_setup_utils.setup_arm_cores(self.dut, cpu_usage) 388 mock_run_command.assert_called_with( 389 self.dut, 390 'echo 1 | tee /sys/devices/system/cpu/cpu{2}/online; ' 391 'echo 0 | tee /sys/devices/system/cpu/cpu{0,1}/online') 392 393 394 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 395 def test_setup_arm_cores_little_on_big_little(self, mock_run_command): 396 mock_run_command.side_effect = [ 397 (0, BIG_LITTLE_CPUINFO, ''), 398 (0, '', ''), 399 ] 400 cpu_usage = 'little_only' 401 device_setup_utils.setup_arm_cores(self.dut, cpu_usage) 402 mock_run_command.assert_called_with( 403 self.dut, 404 'echo 1 | tee /sys/devices/system/cpu/cpu{0,1}/online; ' 405 'echo 0 | tee /sys/devices/system/cpu/cpu{2}/online') 406 407 408 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 409 def test_setup_arm_cores_invalid_config(self, mock_run_command): 410 mock_run_command.side_effect = [ 411 (0, LITTLE_ONLY_CPUINFO, ''), 412 (0, '', ''), 413 ] 414 cpu_usage = 'big_only' 415 device_setup_utils.setup_arm_cores(self.dut, cpu_usage) 416 # Check that setup command is not sent when trying 417 # to use 'big_only' on a platform with all little cores. 418 mock_run_command.assert_called_once_with(self.dut, 'cat /proc/cpuinfo') 419 420 421 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 422 def test_setup_arm_cores_not_big_little(self, mock_run_command): 423 mock_run_command.side_effect = [ 424 (0, NOT_BIG_LITTLE_CPUINFO, ''), 425 (0, '', ''), 426 ] 427 cpu_usage = 'big_only' 428 device_setup_utils.setup_arm_cores(self.dut, cpu_usage) 429 # Check that setup command is not sent when trying 430 # to use 'big_only' on a platform w/o support of big/little. 431 mock_run_command.assert_called_once_with(self.dut, 'cat /proc/cpuinfo') 432 433 434 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 435 def test_setup_arm_cores_unsupported_cpu_usage(self, mock_run_command): 436 mock_run_command.side_effect = [ 437 (0, BIG_LITTLE_CPUINFO, ''), 438 (0, '', ''), 439 ] 440 cpu_usage = 'exclusive_cores' 441 device_setup_utils.setup_arm_cores(self.dut, cpu_usage) 442 # Check that setup command is not sent when trying to use 443 # 'exclusive_cores' on ARM CPU setup. 444 mock_run_command.assert_called_once_with(self.dut, 'cat /proc/cpuinfo') 445 446 447 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 448 def test_setup_cpu_freq_single_full(self, mock_run_command): 449 online = [0] 450 mock_run_command.side_effect = [ 451 (0, 452 '/sys/devices/system/cpu/cpu0/cpufreq/' 453 'scaling_available_frequencies\n', 454 ''), 455 (0, '1 2 3 4 5 6 7 8 9 10', ''), 456 (0, '', ''), 457 ] 458 cpu_frq_pct = 100 459 device_setup_utils.setup_cpu_freq(self.dut, cpu_frq_pct, online) 460 self.assertGreaterEqual(mock_run_command.call_count, 3) 461 self.assertIn( 462 mock.call( 463 self.dut, 'echo 10 | tee ' 464 '/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq ' 465 '/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq' 466 ), 467 mock_run_command.call_args_list) 468 # Check the fix of single core online. 469 # We expect to see cpu0 instead of cpu{0}. 470 self.assertIn( 471 mock.call(self.dut, 472 'ls /sys/devices/system/cpu/cpu0/cpufreq/' 473 'scaling_available_frequencies', 474 ignore_status=True), 475 mock_run_command.call_args_list) 476 477 478 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 479 def test_setup_cpu_freq_middle(self, mock_run_command): 480 online = [0] 481 mock_run_command.side_effect = [ 482 (0, 483 '/sys/devices/system/cpu/cpu0/cpufreq/' 484 'scaling_available_frequencies\n', 485 ''), 486 (0, '1 2 3 4 5 6 7 8 9 10', ''), 487 (0, '', ''), 488 ] 489 cpu_frq_pct = 60 490 device_setup_utils.setup_cpu_freq(self.dut, cpu_frq_pct, online) 491 self.assertGreaterEqual(mock_run_command.call_count, 2) 492 self.assertEqual( 493 mock_run_command.call_args, 494 mock.call( 495 self.dut, 'echo 6 | tee ' 496 '/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq ' 497 '/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq' 498 )) 499 500 501 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 502 def test_setup_cpu_freq_lowest(self, mock_run_command): 503 online = [0] 504 mock_run_command.side_effect = [ 505 (0, 506 '/sys/devices/system/cpu/cpu0/cpufreq/' 507 'scaling_available_frequencies\n', 508 ''), 509 (0, '1 2 3 4 5 6 7 8 9 10', ''), 510 (0, '', ''), 511 ] 512 cpu_frq_pct = 0 513 device_setup_utils.setup_cpu_freq(self.dut, cpu_frq_pct, online) 514 self.assertGreaterEqual(mock_run_command.call_count, 2) 515 self.assertEqual( 516 mock_run_command.call_args, 517 mock.call( 518 self.dut, 'echo 1 | tee ' 519 '/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq ' 520 '/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq' 521 )) 522 523 524 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 525 def test_setup_cpu_freq_multiple_middle(self, mock_run_command): 526 online = [0, 1] 527 mock_run_command.side_effect = [ 528 (0, 529 '/sys/devices/system/cpu/cpu0/cpufreq/' 530 'scaling_available_frequencies\n' 531 '/sys/devices/system/cpu/cpu1/cpufreq/' 532 'scaling_available_frequencies\n', 533 ''), 534 (0, '1 2 3 4 5 6 7 8 9 10', ''), 535 (0, '', ''), 536 (0, '1 4 6 8 10 12 14 16 18 20', ''), 537 (0, '', ''), 538 ] 539 cpu_frq_pct = 70 540 device_setup_utils.setup_cpu_freq(self.dut, cpu_frq_pct, online) 541 self.assertEqual(mock_run_command.call_count, 5) 542 self.assertIn( 543 mock.call( 544 self.dut, 'echo 7 | tee ' 545 '/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq ' 546 '/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq' 547 ), 548 mock_run_command.call_args_list) 549 self.assertIn( 550 mock.call( 551 self.dut, 'echo 14 | tee ' 552 '/sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq ' 553 '/sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq' 554 ), 555 mock_run_command.call_args_list) 556 # Check that setup_cpu_freq queries all online cores. 557 self.assertIn( 558 mock.call(self.dut, 559 'ls /sys/devices/system/cpu/cpu{0,1}/cpufreq/' 560 'scaling_available_frequencies', 561 ignore_status=True), 562 mock_run_command.call_args_list) 563 564 565 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 566 def test_setup_cpu_freq_no_scaling_available(self, mock_run_command): 567 online = [0, 1] 568 mock_run_command.return_value = (2, '', 'No such file or directory') 569 cpu_frq_pct = 50 570 device_setup_utils.setup_cpu_freq(self.dut, cpu_frq_pct, online) 571 mock_run_command.assert_called_once() 572 self.assertNotRegexpMatches(mock_run_command.call_args_list[0][0][1], 573 '^echo.*scaling_max_freq$') 574 575 576 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 577 def test_setup_cpu_freq_multiple_no_access(self, mock_run_command): 578 online = [0, 1] 579 mock_run_command.side_effect = [ 580 (0, 581 '/sys/devices/system/cpu/cpu0/cpufreq/' 582 'scaling_available_frequencies\n' 583 '/sys/devices/system/cpu/cpu1/cpufreq/' 584 'scaling_available_frequencies\n', 585 ''), 586 (0, '1 4 6 8 10 12 14 16 18 20', ''), 587 AssertionError(), 588 ] 589 cpu_frq_pct = 30 590 # Error status causes log fatal. 591 with self.assertRaises(AssertionError): 592 device_setup_utils.setup_cpu_freq(self.dut, cpu_frq_pct, online) 593 594 595 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 596 @mock.patch.object(time, 'sleep') 597 def test_wait_cooldown_nowait(self, mock_sleep, mock_run_command): 598 mock_sleep.return_value = 0 599 mock_run_command.return_value = (0, '39000', '') 600 cooldown_time = 10 601 cooldown_temp = 40 602 wait_time = device_setup_utils.wait_cooldown(self.dut, cooldown_time, 603 cooldown_temp) 604 # Send command to DUT only once to check temperature 605 # and make sure it does not exceed the threshold. 606 mock_run_command.assert_called_once() 607 mock_sleep.assert_not_called() 608 self.assertEqual(wait_time, 0) 609 610 611 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 612 @mock.patch.object(time, 'sleep') 613 def test_wait_cooldown_needwait_once(self, mock_sleep, mock_run_command): 614 """ 615 Wait one iteration for cooldown. 616 617 Set large enough timeout and changing temperature 618 output. Make sure it exits when expected value 619 received. 620 Expect that WaitCooldown check temp twice. 621 622 """ 623 mock_sleep.return_value = 0 624 mock_run_command.side_effect = [(0, '41000', ''), (0, '39999', '')] 625 cooldown_time = 100 626 cooldown_temp = 40 627 wait_time = device_setup_utils.wait_cooldown(self.dut, cooldown_time, 628 cooldown_temp) 629 mock_run_command.assert_called() 630 self.assertEqual(mock_run_command.call_count, 2) 631 mock_sleep.assert_called() 632 self.assertGreater(wait_time, 0) 633 634 635 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 636 @mock.patch.object(time, 'sleep') 637 def test_wait_cooldown_needwait(self, mock_sleep, mock_run_command): 638 """ 639 Test exit by timeout. 640 641 Send command to DUT checking the temperature and 642 check repeatedly until timeout goes off. 643 Output from temperature sensor never changes. 644 645 """ 646 mock_sleep.return_value = 0 647 mock_run_command.return_value = (0, '41000', '') 648 cooldown_time = 60 649 cooldown_temp = 40 650 wait_time = device_setup_utils.wait_cooldown(self.dut, cooldown_time, 651 cooldown_temp) 652 mock_run_command.assert_called() 653 self.assertGreater(mock_run_command.call_count, 2) 654 mock_sleep.assert_called() 655 self.assertGreater(wait_time, 0) 656 657 658 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 659 @mock.patch.object(time, 'sleep') 660 def test_wait_cooldown_needwait_multtemp(self, mock_sleep, 661 mock_run_command): 662 """ 663 Wait until all temps go down. 664 665 Set large enough timeout and changing temperature 666 output. Make sure it exits when expected value 667 for all temperatures received. 668 Expect 3 checks. 669 670 """ 671 mock_sleep.return_value = 0 672 mock_run_command.side_effect = [ 673 (0, '41000\n20000\n30000\n45000', ''), 674 (0, '39000\n20000\n30000\n41000', ''), 675 (0, '39000\n20000\n30000\n31000', ''), 676 ] 677 cooldown_time = 100 678 cooldown_temp = 40 679 wait_time = device_setup_utils.wait_cooldown(self.dut, cooldown_time, 680 cooldown_temp) 681 mock_run_command.assert_called() 682 self.assertEqual(mock_run_command.call_count, 3) 683 mock_sleep.assert_called() 684 self.assertGreater(wait_time, 0) 685 686 687 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 688 @mock.patch.object(time, 'sleep') 689 def test_wait_cooldown_thermal_error(self, mock_sleep, mock_run_command): 690 """ 691 Handle error status. 692 693 Any error should be considered non-fatal. 694 695 """ 696 mock_sleep.return_value = 0 697 mock_run_command.side_effect = [ 698 (1, '39000\n20000\n30000\n41000', 'Thermal error'), 699 (1, '39000\n20000\n30000\n31000', 'Thermal error'), 700 ] 701 cooldown_time = 10 702 cooldown_temp = 40 703 wait_time = device_setup_utils.wait_cooldown(self.dut, cooldown_time, 704 cooldown_temp) 705 # Check that errors are ignored. 706 mock_run_command.assert_called_with( 707 self.dut, 708 'cat /sys/class/thermal/thermal_zone*/temp', 709 ignore_status=True) 710 self.assertEqual(mock_run_command.call_count, 2) 711 # Check that we are waiting even when an error is returned 712 # as soon as data is coming. 713 mock_sleep.assert_called() 714 self.assertGreater(wait_time, 0) 715 716 717 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 718 @mock.patch.object(time, 'sleep') 719 def test_wait_cooldown_thermal_no_output(self, mock_sleep, 720 mock_run_command): 721 """ 722 Handle no output. 723 724 Check handling of empty stdout. 725 726 """ 727 mock_sleep.return_value = 0 728 mock_run_command.side_effect = [(1, '', 'Thermal error')] 729 cooldown_time = 10 730 cooldown_temp = 40 731 wait_time = device_setup_utils.wait_cooldown(self.dut, cooldown_time, 732 cooldown_temp) 733 # Check that errors are ignored. 734 mock_run_command.assert_called_once_with( 735 self.dut, 736 'cat /sys/class/thermal/thermal_zone*/temp', 737 ignore_status=True) 738 # No wait. 739 mock_sleep.assert_not_called() 740 self.assertEqual(wait_time, 0) 741 742 743 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 744 @mock.patch.object(time, 'sleep') 745 def test_wait_cooldown_thermal_ws_output(self, mock_sleep, 746 mock_run_command): 747 """ 748 Handle whitespace output. 749 750 Check handling of whitespace only. 751 752 """ 753 mock_sleep.return_value = 0 754 mock_run_command.side_effect = [(1, '\n', 'Thermal error')] 755 cooldown_time = 10 756 cooldown_temp = 40 757 wait_time = device_setup_utils.wait_cooldown(self.dut, cooldown_time, 758 cooldown_temp) 759 # Check that errors are ignored. 760 mock_run_command.assert_called_once_with( 761 self.dut, 762 'cat /sys/class/thermal/thermal_zone*/temp', 763 ignore_status=True) 764 # No wait. 765 mock_sleep.assert_not_called() 766 self.assertEqual(wait_time, 0) 767 768 769 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 770 def test_stop_ui(self, mock_run_command): 771 mock_run_command.return_value = (0, '', '') 772 device_setup_utils.stop_ui(self.dut) 773 mock_run_command.assert_called_once_with(self.dut, 'stop ui') 774 775 776 @mock.patch.object(device_setup_utils, 'run_command_on_dut') 777 def test_start_ui(self, mock_run_command): 778 mock_run_command.return_value = (0, '', '') 779 device_setup_utils.start_ui(self.dut) 780 mock_run_command.assert_called_once_with(self.dut, 'start ui') 781 782 783 @mock.patch.object(device_setup_utils, 'kern_cmd_update_needed') 784 @mock.patch.object(device_setup_utils, 'update_kern_cmd_intel_pstate') 785 @mock.patch.object(device_setup_utils, 'disable_aslr') 786 @mock.patch.object(device_setup_utils, 'setup_cpu_usage') 787 @mock.patch.object(device_setup_utils, 'setup_cpu_freq') 788 @mock.patch.object(device_setup_utils, 'get_cpu_online') 789 @mock.patch.object(device_setup_utils, 'set_cpu_governor') 790 @mock.patch.object(device_setup_utils, 'disable_turbo') 791 @mock.patch.object(device_setup_utils, 'stop_ui') 792 @mock.patch.object(device_setup_utils, 'start_ui') 793 @mock.patch.object(device_setup_utils, 'wait_cooldown') 794 @mock.patch.object(device_setup_utils, 'decrease_wait_time') 795 def test_setup_device(self, mock_decrease_wait_time, mock_wait_cooldown, 796 mock_start_ui, mock_stop_ui, mock_disable_turbo, 797 mock_set_cpu_governor, mock_get_cpu_online, 798 mock_setup_cpu_freq, mock_setup_cpu_usage, 799 mock_disable_aslr, mock_update_kern_cmd_intel_pstate, 800 mock_kern_cmd_update_needed): 801 802 def setup_mock_functions(): 803 """ 804 Reset mock functions. 805 """ 806 mock_kern_cmd_update_needed.reset_mock() 807 mock_update_kern_cmd_intel_pstate.reset_mock() 808 mock_disable_aslr.reset_mock() 809 mock_setup_cpu_usage.reset_mock() 810 mock_setup_cpu_freq.reset_mock() 811 mock_get_cpu_online.reset_mock() 812 mock_set_cpu_governor.reset_mock() 813 mock_disable_turbo.reset_mock() 814 mock_stop_ui.reset_mock() 815 mock_start_ui.reset_mock() 816 mock_wait_cooldown.reset_mock() 817 mock_decrease_wait_time.reset_mock() 818 819 mock_kern_cmd_update_needed.return_value = True 820 mock_update_kern_cmd_intel_pstate.return_value = 0 821 mock_disable_aslr.return_value = 0 822 mock_setup_cpu_usage.return_value = 0 823 mock_setup_cpu_freq.return_value = 0 824 mock_get_cpu_online.return_value = {0: 1, 1: 1, 2: 0} 825 mock_set_cpu_governor.return_value = 0 826 mock_disable_turbo.return_value = 0 827 mock_stop_ui.return_value = 0 828 mock_start_ui.return_value = 0 829 mock_wait_cooldown.return_value = 0 830 mock_decrease_wait_time.return_value = 0 831 832 dut_config = { 833 'enable_aslr': False, 834 'cooldown_time': 0, 835 'cooldown_temp': 40, 836 'governor': 'fake_governor', 837 'cpu_freq_pct': 65, 838 'intel_pstate': 'no_hwp', 839 } 840 841 setup_mock_functions() 842 device_setup_utils.setup_device(self.dut, dut_config) 843 844 mock_kern_cmd_update_needed.assert_called_once() 845 mock_update_kern_cmd_intel_pstate.assert_called_once() 846 mock_disable_aslr.assert_called_once() 847 mock_setup_cpu_usage.assert_called_once() 848 mock_setup_cpu_freq.assert_called_once_with( 849 self.dut, dut_config['cpu_freq_pct'], [0, 1]) 850 mock_get_cpu_online.assert_called_once() 851 mock_set_cpu_governor.assert_called_once_with(self.dut, 852 'fake_governor') 853 mock_disable_turbo.assert_called_once() 854 mock_decrease_wait_time.assert_called_once() 855 mock_stop_ui.assert_called_once() 856 mock_start_ui.assert_called_once() 857 mock_wait_cooldown.assert_not_called() 858 859 # Test SetupDevice with cooldown 860 dut_config['cooldown_time'] = 10 861 862 setup_mock_functions() 863 mock_get_cpu_online.return_value = {0: 0, 1: 1} 864 865 device_setup_utils.setup_device(self.dut, dut_config) 866 867 mock_wait_cooldown.assert_called_once() 868 mock_disable_aslr.assert_called_once() 869 mock_disable_turbo.assert_called_once() 870 mock_setup_cpu_usage.assert_called_once() 871 mock_setup_cpu_freq.assert_called_once_with( 872 self.dut, dut_config['cpu_freq_pct'], [1]) 873 mock_set_cpu_governor.assert_called() 874 mock_get_cpu_online.assert_called_once() 875 mock_stop_ui.assert_called_once() 876 mock_start_ui.assert_called_once() 877 self.assertGreater(mock_set_cpu_governor.call_count, 1) 878 self.assertEqual(mock_set_cpu_governor.call_args, 879 mock.call(self.dut, 'fake_governor')) 880 881 # Test SetupDevice with cooldown 882 setup_mock_functions() 883 mock_setup_cpu_usage.side_effect = RuntimeError() 884 885 with self.assertRaises(RuntimeError): 886 device_setup_utils.setup_device(self.dut, dut_config) 887 888 # This call injected an exception. 889 mock_setup_cpu_usage.assert_called_once() 890 # Calls following the exception are skipped. 891 mock_wait_cooldown.assert_not_called() 892 mock_disable_turbo.assert_not_called() 893 mock_setup_cpu_freq.assert_not_called() 894 mock_set_cpu_governor.assert_not_called() 895 mock_get_cpu_online.assert_not_called() 896 # Check that Stop/Start UI are always called. 897 mock_stop_ui.assert_called_once() 898 mock_start_ui.assert_called_once() 899 900 901if __name__ == '__main__': 902 unittest.main() 903