aboutsummaryrefslogtreecommitdiff
path: root/crosperf
diff options
context:
space:
mode:
authorDenis Nikitin <denik@google.com>2019-09-13 12:25:57 -0700
committerDenis Nikitin <denik@chromium.org>2019-09-16 20:32:03 +0000
commit1b3c925ab0a395fdc256672b47abf7427a4498d0 (patch)
tree16a7356591c2eb5383ffa1b3fe353240fdc9b94b /crosperf
parent67a3a585354c03993cb5b5458f123844670f01dc (diff)
downloadtoolchain-utils-1b3c925ab0a395fdc256672b47abf7427a4498d0.tar.gz
crosperf: Setup CPU frequency
Added "cpu_freq_pct" in global settings specifying percent of the max frequency which will be set on DUT during benchmark run. The actual value will be chosen from available frequencies less than or equal to the calculated number. Feature requires scaling_available_frequencies. On the platforms not supporting scaling_available_frequencies "cpu_freq_pct" will be ignored. BUG=chromium:966514 TEST=Unittest and local HW tests on veyron, scarlet and kevin64 passed. Change-Id: I175e2836ecf02fcf6b93d196926c7801d7f016c0 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/1803780 Reviewed-by: George Burgess <gbiv@chromium.org> Tested-by: Denis Nikitin <denik@chromium.org> Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
Diffstat (limited to 'crosperf')
-rwxr-xr-xcrosperf/benchmark_run_unittest.py1
-rwxr-xr-xcrosperf/crosperf_unittest.py2
-rw-r--r--crosperf/experiment_factory.py1
-rwxr-xr-xcrosperf/experiment_file_unittest.py2
-rw-r--r--crosperf/experiment_files/dut_config.exp3
-rw-r--r--crosperf/settings_factory.py9
-rwxr-xr-xcrosperf/settings_factory_unittest.py5
-rw-r--r--crosperf/suite_runner.py100
-rwxr-xr-xcrosperf/suite_runner_unittest.py174
9 files changed, 288 insertions, 9 deletions
diff --git a/crosperf/benchmark_run_unittest.py b/crosperf/benchmark_run_unittest.py
index 4c2a7e60..59d701b8 100755
--- a/crosperf/benchmark_run_unittest.py
+++ b/crosperf/benchmark_run_unittest.py
@@ -105,6 +105,7 @@ class BenchmarkRunTest(unittest.TestCase):
'cooldown_temp': 45,
'governor': 'powersave',
'cpu_usage': 'big_only',
+ 'cpu_freq_pct': 80,
}
b = benchmark_run.MockBenchmarkRun('test run', bench, my_label, 1, [], m,
logger.GetLogger(), logging_level, '',
diff --git a/crosperf/crosperf_unittest.py b/crosperf/crosperf_unittest.py
index 8d5569e0..84f646a6 100755
--- a/crosperf/crosperf_unittest.py
+++ b/crosperf/crosperf_unittest.py
@@ -67,7 +67,7 @@ class CrosperfTest(unittest.TestCase):
settings = crosperf.ConvertOptionsToSettings(options)
self.assertIsNotNone(settings)
self.assertIsInstance(settings, settings_factory.GlobalSettings)
- self.assertEqual(len(settings.fields), 35)
+ self.assertEqual(len(settings.fields), 36)
self.assertTrue(settings.GetField('rerun'))
argv = ['crosperf/crosperf.py', 'temp.exp']
options, _ = parser.parse_known_args(argv)
diff --git a/crosperf/experiment_factory.py b/crosperf/experiment_factory.py
index 28755c80..9bf42d4f 100644
--- a/crosperf/experiment_factory.py
+++ b/crosperf/experiment_factory.py
@@ -165,6 +165,7 @@ class ExperimentFactory(object):
'cooldown_temp': global_settings.GetField('cooldown_temp'),
'governor': global_settings.GetField('governor'),
'cpu_usage': global_settings.GetField('cpu_usage'),
+ 'cpu_freq_pct': global_settings.GetField('cpu_freq_pct'),
}
# Default cache hit conditions. The image checksum in the cache and the
diff --git a/crosperf/experiment_file_unittest.py b/crosperf/experiment_file_unittest.py
index 861e2549..f0d5178b 100755
--- a/crosperf/experiment_file_unittest.py
+++ b/crosperf/experiment_file_unittest.py
@@ -93,6 +93,7 @@ DUT_CONFIG_EXPERIMENT_FILE_GOOD = """
cooldown_time: 5
governor: powersave
cpu_usage: exclusive_cores
+ cpu_freq_pct: 50
benchmark: speedometer {
iterations: 3
@@ -217,6 +218,7 @@ class ExperimentFileTest(unittest.TestCase):
self.assertEqual(global_settings.GetField('intel_pstate'), 'no_hwp')
self.assertEqual(global_settings.GetField('governor'), 'powersave')
self.assertEqual(global_settings.GetField('cpu_usage'), 'exclusive_cores')
+ self.assertEqual(global_settings.GetField('cpu_freq_pct'), 50)
self.assertEqual(global_settings.GetField('cooldown_time'), 5)
self.assertEqual(global_settings.GetField('cooldown_temp'), 38)
diff --git a/crosperf/experiment_files/dut_config.exp b/crosperf/experiment_files/dut_config.exp
index f96242ff..fe8f8f77 100644
--- a/crosperf/experiment_files/dut_config.exp
+++ b/crosperf/experiment_files/dut_config.exp
@@ -34,6 +34,9 @@ governor: <one-of-scaling_available_governors-values>
# Restrict CPU usage to predefined "models":
# all, big_only, little_only, exclusive_cores.
cpu_usage: <usage-model>
+# Setup CPU frequency as percent of max_freq.
+# Default: 100
+cpu_freq_pct: <0-100>
# The example below will run Telemetry toolchain performance benchmarks.
# The exact list of benchmarks that will be run can be seen in
diff --git a/crosperf/settings_factory.py b/crosperf/settings_factory.py
index b96ad342..1fbc8e14 100644
--- a/crosperf/settings_factory.py
+++ b/crosperf/settings_factory.py
@@ -360,7 +360,7 @@ class GlobalSettings(Settings):
required=False,
default=0,
description='Wait specified time in minutes allowing'
- ' CPU to cool down. Zero value disables cooldown,'))
+ ' CPU to cool down. Zero value disables cooldown.'))
self.AddField(
EnumField(
'governor',
@@ -396,6 +396,13 @@ class GlobalSettings(Settings):
' applicable only on ARM;\n'
'exclusive-cores - (for future use)'
' isolate cores for exclusive use of benchmark processes.'))
+ self.AddField(
+ IntegerField(
+ 'cpu_freq_pct',
+ required=False,
+ default=100,
+ description='Setup CPU frequency to a supported value less than'
+ ' or equal to a percent of max_freq.'))
class SettingsFactory(object):
diff --git a/crosperf/settings_factory_unittest.py b/crosperf/settings_factory_unittest.py
index 6dfb0bff..633f2e5f 100755
--- a/crosperf/settings_factory_unittest.py
+++ b/crosperf/settings_factory_unittest.py
@@ -50,7 +50,7 @@ class GlobalSettingsTest(unittest.TestCase):
def test_init(self):
res = settings_factory.GlobalSettings('g_settings')
self.assertIsNotNone(res)
- self.assertEqual(len(res.fields), 35)
+ self.assertEqual(len(res.fields), 36)
self.assertEqual(res.GetField('name'), '')
self.assertEqual(res.GetField('board'), '')
self.assertEqual(res.GetField('skylab'), False)
@@ -82,6 +82,7 @@ class GlobalSettingsTest(unittest.TestCase):
self.assertEqual(res.GetField('cooldown_temp'), 40)
self.assertEqual(res.GetField('governor'), 'performance')
self.assertEqual(res.GetField('cpu_usage'), 'all')
+ self.assertEqual(res.GetField('cpu_freq_pct'), 100)
class SettingsFactoryTest(unittest.TestCase):
@@ -104,7 +105,7 @@ class SettingsFactoryTest(unittest.TestCase):
g_settings = settings_factory.SettingsFactory().GetSettings(
'global', 'global')
self.assertIsInstance(g_settings, settings_factory.GlobalSettings)
- self.assertEqual(len(g_settings.fields), 35)
+ self.assertEqual(len(g_settings.fields), 36)
if __name__ == '__main__':
diff --git a/crosperf/suite_runner.py b/crosperf/suite_runner.py
index 5b677949..faf40b52 100644
--- a/crosperf/suite_runner.py
+++ b/crosperf/suite_runner.py
@@ -119,6 +119,13 @@ class SuiteRunner(object):
if not self.enable_aslr:
self.DisableASLR(run_on_dut)
+ # CPU usage setup comes first where we enable/disable cores.
+ self.SetupCpuUsage(run_on_dut)
+ cpu_online_status = self.GetCpuOnline(run_on_dut)
+ # List of online cores of type int (core number).
+ online_cores = [
+ core for core, status in cpu_online_status.items() if status
+ ]
if self.dut_config['cooldown_time']:
# Setup power conservative mode for effective cool down.
# Set ignore status since powersave may no be available
@@ -138,13 +145,20 @@ class SuiteRunner(object):
# Setup CPU governor for the benchmark run.
# It overwrites the previous governor settings.
governor = self.dut_config['governor']
+ # FIXME(denik): Pass online cores to governor setup.
self.SetCpuGovernor(governor, run_on_dut, ignore_status=False)
+
+ # Disable Turbo and Setup CPU freq should ALWAYS proceed governor setup
+ # since governor may change:
+ # - frequency;
+ # - turbo/boost.
self.DisableTurbo(run_on_dut)
- self.SetupCpuUsage(run_on_dut)
+ self.SetupCpuFreq(run_on_dut, online_cores)
# FIXME(denik): Currently we are not recovering the previous cpufreq
# settings since we do reboot/setup every time anyway.
# But it may change in the future and then we have to recover the
# settings.
+
if benchmark.suite == 'telemetry_Crosperf':
self.DecreaseWaitTime(run_on_dut)
ret_tup = self.Telemetry_Crosperf_Run(machine, label, benchmark,
@@ -231,8 +245,7 @@ class SuiteRunner(object):
# 'cooldown_temp'. Exit the loop.
break
- self.logger.LogOutput(
- 'Cooldown wait time: %.1f min' % (float(waittime) / 60))
+ self.logger.LogOutput('Cooldown wait time: %.1f min' % (waittime / 60))
return waittime
def SetupCpuUsage(self, run_on_dut):
@@ -344,6 +357,87 @@ class SuiteRunner(object):
'Ignore ARM CPU setup and continue.' % (self.dut_config['cpu_usage'],
dut_big_cores, dut_lit_cores))
+ def GetCpuOnline(self, run_on_dut):
+ """Get online status of CPU cores.
+
+ Return dict of {int(cpu_num): <0|1>}.
+ """
+ get_cpu_online_cmd = ('paste -d" "'
+ ' <(ls /sys/devices/system/cpu/cpu*/online)'
+ ' <(cat /sys/devices/system/cpu/cpu*/online)')
+ _, online_output_str, _ = run_on_dut(get_cpu_online_cmd)
+
+ # Here is the output we expect to see:
+ # -----------------
+ # /sys/devices/system/cpu/cpu0/online 0
+ # /sys/devices/system/cpu/cpu1/online 1
+
+ cpu_online = {}
+ cpu_online_match = re.compile(r'^[/\S]+/cpu(\d+)/[/\S]+\s+(\d+)$')
+ for line in online_output_str.splitlines():
+ match = cpu_online_match.match(line)
+ if match:
+ cpu = int(match.group(1))
+ status = int(match.group(2))
+ cpu_online[cpu] = status
+ # At least one CPU has to be online.
+ assert cpu_online
+
+ return cpu_online
+
+ def SetupCpuFreq(self, run_on_dut, online_cores):
+ """Setup CPU frequency.
+
+ Based on self.dut_config['cpu_freq_pct'] setup frequency of online CPU cores
+ to a supported value which is less or equal to (freq_pct * max_freq / 100)
+ limited by min_freq.
+
+ NOTE: scaling_available_frequencies support is required.
+ Otherwise the function has no effect.
+ """
+ freq_percent = self.dut_config['cpu_freq_pct']
+ list_all_avail_freq_cmd = (
+ 'ls /sys/devices/system/cpu/cpu{%s}/cpufreq/'
+ 'scaling_available_frequencies'
+ )
+ # Ignore error to support general usage of frequency setup.
+ # Not all platforms support scaling_available_frequencies.
+ ret, all_avail_freq_str, _ = run_on_dut(
+ list_all_avail_freq_cmd % ','.join(str(core) for core in online_cores),
+ ignore_status=True)
+ if ret or not all_avail_freq_str:
+ # No scalable frequencies available for the core.
+ return ret
+ for avail_freq_path in all_avail_freq_str.split():
+ # Get available freq from every scaling_available_frequency path.
+ # Error is considered fatal in run_on_dut().
+ _, avail_freq_str, _ = run_on_dut('cat ' + avail_freq_path)
+ assert avail_freq_str
+
+ all_avail_freq = sorted(
+ int(freq_str) for freq_str in avail_freq_str.split())
+ min_freq = all_avail_freq[0]
+ max_freq = all_avail_freq[-1]
+ # Calculate the frequency we are targeting.
+ target_freq = round(max_freq * freq_percent / 100)
+ # More likely it's not in the list of supported frequencies
+ # and our goal is to find the one which is less or equal.
+ # Default is min and we will try to maximize it.
+ avail_ngt_target = min_freq
+ # Find the largest not greater than the target.
+ for next_largest in reversed(all_avail_freq):
+ if next_largest <= target_freq:
+ avail_ngt_target = next_largest
+ break
+
+ max_freq_path = avail_freq_path.replace('scaling_available_frequencies',
+ 'scaling_max_freq')
+ min_freq_path = avail_freq_path.replace('scaling_available_frequencies',
+ 'scaling_min_freq')
+ # With default ignore_status=False we expect 0 status or Fatal error.
+ run_on_dut('echo %s | tee %s %s' % (avail_ngt_target, max_freq_path,
+ min_freq_path))
+
def DecreaseWaitTime(self, run_on_dut):
"""Change the ten seconds wait time for pagecycler to two seconds."""
FILE = '/usr/local/telemetry/src/tools/perf/page_sets/page_cycler_story.py'
diff --git a/crosperf/suite_runner_unittest.py b/crosperf/suite_runner_unittest.py
index 6be3865f..2bc299cd 100755
--- a/crosperf/suite_runner_unittest.py
+++ b/crosperf/suite_runner_unittest.py
@@ -153,7 +153,7 @@ class SuiteRunnerTest(unittest.TestCase):
{}, self.mock_logger, 'verbose', self.mock_cmd_exec, self.mock_cmd_term)
def test_get_profiler_args(self):
- input_str = ('--profiler=custom_perf --profiler_args=\'perf_options'
+ input_str = ("--profiler=custom_perf --profiler_args='perf_options"
'="record -a -e cycles,instructions"\'')
output_str = ("profiler=custom_perf profiler_args='record -a -e "
"cycles,instructions'")
@@ -173,6 +173,8 @@ class SuiteRunnerTest(unittest.TestCase):
self.telemetry_crosperf_args = []
def FakeDisableASLR(runner):
+ # pylint fix for unused variable.
+ del runner
self.call_disable_aslr = True
def FakeSkylabRun(test_label, benchmark, test_args, profiler_args):
@@ -197,6 +199,8 @@ class SuiteRunnerTest(unittest.TestCase):
return 'Ran FakeTestThatRun'
def FakeRunner(command, ignore_status=False):
+ # pylint fix for unused variable.
+ del command, ignore_status
return 0, '', ''
self.runner.DisableASLR = FakeDisableASLR
@@ -204,12 +208,15 @@ class SuiteRunnerTest(unittest.TestCase):
self.runner.Telemetry_Crosperf_Run = FakeTelemetryCrosperfRun
self.runner.Test_That_Run = FakeTestThatRun
self.runner.SetupCpuUsage = mock.Mock()
+ self.runner.SetupCpuFreq = mock.Mock()
self.runner.DutWrapper = mock.Mock(return_value=FakeRunner)
self.runner.DisableTurbo = mock.Mock()
self.runner.SetCpuGovernor = mock.Mock()
self.runner.WaitCooldown = mock.Mock(return_value=0)
+ self.runner.GetCpuOnline = mock.Mock(return_value={0: 1, 1: 1, 2: 0})
self.runner.dut_config['cooldown_time'] = 0
self.runner.dut_config['governor'] = 'fake_governor'
+ self.runner.dut_config['cpu_freq_pct'] = 65
machine = 'fake_machine'
test_args = ''
profiler_args = ''
@@ -225,6 +232,8 @@ class SuiteRunnerTest(unittest.TestCase):
self.assertEqual(self.skylab_run_args,
[self.mock_label, self.telemetry_bench, '', ''])
self.runner.SetupCpuUsage.assert_not_called()
+ self.runner.SetupCpuFreq.assert_not_called()
+ self.runner.GetCpuOnline.assert_not_called()
self.runner.DutWrapper.assert_not_called()
self.runner.SetCpuGovernor.assert_not_called()
self.runner.DisableTurbo.assert_not_called()
@@ -241,6 +250,8 @@ class SuiteRunnerTest(unittest.TestCase):
self.test_that_args,
['fake_machine', self.mock_label, self.test_that_bench, '', ''])
self.runner.SetupCpuUsage.assert_called_once_with(FakeRunner)
+ self.runner.SetupCpuFreq.assert_called_once_with(FakeRunner, [0, 1])
+ self.runner.GetCpuOnline.assert_called_once_with(FakeRunner)
self.runner.DutWrapper.assert_called_once_with(
machine, self.mock_label.chromeos_root)
self.runner.SetCpuGovernor.assert_called_once_with(
@@ -263,6 +274,8 @@ class SuiteRunnerTest(unittest.TestCase):
def test_run_with_cooldown(self):
def FakeRunner(command, ignore_status=False):
+ # pylint fix for unused variable.
+ del command, ignore_status
return 0, '', ''
self.runner.DisableASLR = mock.Mock()
@@ -270,10 +283,13 @@ class SuiteRunnerTest(unittest.TestCase):
self.runner.DisableTurbo = mock.Mock()
self.runner.SetCpuGovernor = mock.Mock()
self.runner.SetupCpuUsage = mock.Mock()
+ self.runner.SetupCpuFreq = mock.Mock()
self.runner.WaitCooldown = mock.Mock(return_value=0)
+ self.runner.GetCpuOnline = mock.Mock(return_value={0: 0, 1: 1})
self.runner.Telemetry_Crosperf_Run = mock.Mock(return_value=(0, '', ''))
self.runner.dut_config['cooldown_time'] = 10
self.runner.dut_config['governor'] = 'fake_governor'
+ self.runner.dut_config['cpu_freq_pct'] = 75
self.runner.Run('fake_machine', self.mock_label,
self.telemetry_crosperf_bench, '', '')
@@ -283,7 +299,9 @@ class SuiteRunnerTest(unittest.TestCase):
self.runner.Telemetry_Crosperf_Run.assert_called_once()
self.runner.DisableTurbo.assert_called_once_with(FakeRunner)
self.runner.SetupCpuUsage.assert_called_once_with(FakeRunner)
+ self.runner.SetupCpuFreq.assert_called_once_with(FakeRunner, [1])
self.runner.SetCpuGovernor.assert_called()
+ self.runner.GetCpuOnline.assert_called_once_with(FakeRunner)
self.assertGreater(self.runner.SetCpuGovernor.call_count, 1)
self.assertEqual(
self.runner.SetCpuGovernor.call_args,
@@ -390,6 +408,7 @@ class SuiteRunnerTest(unittest.TestCase):
'done; ')
dut_runner.assert_called_once_with(
set_cpu_cmd % 'non-exist_governor', ignore_status=True)
+ self.assertEqual(ret_code, 1)
def test_disable_turbo(self):
dut_runner = mock.Mock(return_value=(0, '', ''))
@@ -403,6 +422,57 @@ class SuiteRunnerTest(unittest.TestCase):
'fi; ')
dut_runner.assert_called_once_with(set_cpu_cmd)
+ def test_get_cpu_online_two(self):
+ """Test one digit CPU #."""
+ dut_runner = mock.Mock(
+ return_value=(0, '/sys/devices/system/cpu/cpu0/online 0\n'
+ '/sys/devices/system/cpu/cpu1/online 1\n', ''))
+ cpu_online = self.runner.GetCpuOnline(dut_runner)
+ self.assertEqual(cpu_online, {0: 0, 1: 1})
+
+ def test_get_cpu_online_twelve(self):
+ """Test two digit CPU #."""
+ dut_runner = mock.Mock(
+ return_value=(0, '/sys/devices/system/cpu/cpu0/online 1\n'
+ '/sys/devices/system/cpu/cpu1/online 0\n'
+ '/sys/devices/system/cpu/cpu10/online 1\n'
+ '/sys/devices/system/cpu/cpu11/online 1\n'
+ '/sys/devices/system/cpu/cpu2/online 1\n'
+ '/sys/devices/system/cpu/cpu3/online 0\n'
+ '/sys/devices/system/cpu/cpu4/online 1\n'
+ '/sys/devices/system/cpu/cpu5/online 0\n'
+ '/sys/devices/system/cpu/cpu6/online 1\n'
+ '/sys/devices/system/cpu/cpu7/online 0\n'
+ '/sys/devices/system/cpu/cpu8/online 1\n'
+ '/sys/devices/system/cpu/cpu9/online 0\n', ''))
+ cpu_online = self.runner.GetCpuOnline(dut_runner)
+ self.assertEqual(cpu_online, {
+ 0: 1,
+ 1: 0,
+ 2: 1,
+ 3: 0,
+ 4: 1,
+ 5: 0,
+ 6: 1,
+ 7: 0,
+ 8: 1,
+ 9: 0,
+ 10: 1,
+ 11: 1
+ })
+
+ def test_get_cpu_online_no_output(self):
+ """Test error case, no output."""
+ dut_runner = mock.Mock(return_value=(0, '', ''))
+ with self.assertRaises(AssertionError):
+ self.runner.GetCpuOnline(dut_runner)
+
+ def test_get_cpu_online_command_error(self):
+ """Test error case, command error."""
+ dut_runner = mock.Mock(side_effect=AssertionError)
+ with self.assertRaises(AssertionError):
+ self.runner.GetCpuOnline(dut_runner)
+
@mock.patch.object(suite_runner.SuiteRunner, 'SetupArmCores')
def test_setup_cpu_usage_little_on_arm(self, mock_setup_arm):
self.runner.SetupArmCores = mock_setup_arm
@@ -487,6 +557,106 @@ class SuiteRunnerTest(unittest.TestCase):
# 'exclusive_cores' on ARM CPU setup.
dut_runner.assert_called_once_with('cat /proc/cpuinfo')
+ def test_setup_cpu_freq_single_full(self):
+ online = [0]
+ dut_runner = mock.Mock(side_effect=[
+ (0,
+ '/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies\n',
+ ''),
+ (0, '1 2 3 4 5 6 7 8 9 10', ''),
+ (0, '', '')])
+ self.runner.dut_config['cpu_freq_pct'] = 100
+ self.runner.SetupCpuFreq(dut_runner, online)
+ self.assertGreaterEqual(dut_runner.call_count, 3)
+ self.assertEqual(
+ dut_runner.call_args,
+ mock.call('echo 10 | tee '
+ '/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq '
+ '/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq'))
+
+ def test_setup_cpu_freq_middle(self):
+ online = [0]
+ dut_runner = mock.Mock(side_effect=[
+ (0,
+ '/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies\n',
+ ''),
+ (0, '1 2 3 4 5 6 7 8 9 10', ''),
+ (0, '', '')])
+ self.runner.dut_config['cpu_freq_pct'] = 60
+ self.runner.SetupCpuFreq(dut_runner, online)
+ self.assertGreaterEqual(dut_runner.call_count, 2)
+ self.assertEqual(
+ dut_runner.call_args,
+ mock.call('echo 6 | tee '
+ '/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq '
+ '/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq'))
+
+ def test_setup_cpu_freq_lowest(self):
+ online = [0]
+ dut_runner = mock.Mock(side_effect=[
+ (0,
+ '/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies\n',
+ ''),
+ (0, '1 2 3 4 5 6 7 8 9 10', ''),
+ (0, '', '')])
+ self.runner.dut_config['cpu_freq_pct'] = 0
+ self.runner.SetupCpuFreq(dut_runner, online)
+ self.assertGreaterEqual(dut_runner.call_count, 2)
+ self.assertEqual(
+ dut_runner.call_args,
+ mock.call('echo 1 | tee '
+ '/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq '
+ '/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq'))
+
+ def test_setup_cpu_freq_multiple_middle(self):
+ online = [0, 1]
+ dut_runner = mock.Mock(side_effect=[
+ (0,
+ '/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies\n'
+ '/sys/devices/system/cpu/cpu1/cpufreq/scaling_available_frequencies\n',
+ ''),
+ (0, '1 2 3 4 5 6 7 8 9 10', ''),
+ (0, '', ''),
+ (0, '1 4 6 8 10 12 14 16 18 20', ''),
+ (0, '', '')])
+ self.runner.dut_config['cpu_freq_pct'] = 70
+ self.runner.SetupCpuFreq(dut_runner, online)
+ self.assertEqual(dut_runner.call_count, 5)
+ self.assertEqual(
+ dut_runner.call_args_list[2],
+ mock.call('echo 7 | tee '
+ '/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq '
+ '/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq'))
+ self.assertEqual(
+ dut_runner.call_args_list[4],
+ mock.call('echo 14 | tee '
+ '/sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq '
+ '/sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq'))
+
+ def test_setup_cpu_freq_no_scaling_available(self):
+ online = [0, 1]
+ dut_runner = mock.Mock(return_value=(2, '', 'No such file or directory'))
+ self.runner.dut_config['cpu_freq_pct'] = 50
+ self.runner.SetupCpuFreq(dut_runner, online)
+ dut_runner.assert_called_once()
+ self.assertNotRegexpMatches(dut_runner.call_args_list[0][0][0],
+ '^echo.*scaling_max_freq$')
+
+ def test_setup_cpu_freq_multiple_no_access(self):
+ online = [0, 1]
+ dut_runner = mock.Mock(side_effect=[
+ (0,
+ '/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies\n'
+ '/sys/devices/system/cpu/cpu1/cpufreq/scaling_available_frequencies\n',
+ ''),
+ (0, '1 4 6 8 10 12 14 16 18 20', ''),
+ AssertionError(),
+ ])
+ self.runner.dut_config['cpu_freq_pct'] = 30
+ # Error status causes log fatal.
+ with self.assertRaises(AssertionError):
+ self.runner.SetupCpuFreq(dut_runner, online)
+
def test_wait_cooldown_nowait(self):
dut_runner = mock.Mock(return_value=(0, '39000', ''))
self.runner.dut_config['cooldown_time'] = 10
@@ -607,7 +777,7 @@ class SuiteRunnerTest(unittest.TestCase):
mock_isdir.return_value = True
mock_chroot_runcmd.return_value = 0
self.mock_cmd_exec.ChrootRunCommandWOutput = mock_chroot_runcmd
- profiler_args = ('--profiler=custom_perf --profiler_args=\'perf_options'
+ profiler_args = ("--profiler=custom_perf --profiler_args='perf_options"
'="record -a -e cycles,instructions"\'')
res = self.runner.Telemetry_Crosperf_Run('lumpy1.cros', self.mock_label,
self.telemetry_crosperf_bench, '',