-
Notifications
You must be signed in to change notification settings - Fork 123
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cpu/em_cpufreq: fix and refactor cpufreq test
- Ensure validation of cpufreq setting in `cpuinfo_cur_freq`. - Validate cpufreq with absolute difference to ensure and detect both positive and negative discrepancies. - Add a configuration file to make a few attributes configurable. Signed-off-by: Aboorva Devarajan <[email protected]>
- Loading branch information
1 parent
d9692a7
commit 0ad7a9f
Showing
2 changed files
with
100 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,103 +13,140 @@ | |
# | ||
# Copyright: 2017 IBM | ||
# Author: Shriya Kulkarni <[email protected]> | ||
|
||
import random | ||
import platform | ||
from avocado import Test | ||
from avocado import skipIf | ||
from avocado.utils import process, distro, cpu | ||
from avocado.utils.software_manager.manager import SoftwareManager | ||
|
||
# Check if the platform is PowerNV | ||
IS_POWER_NV = 'PowerNV' in open('/proc/cpuinfo', 'r').read() | ||
|
||
|
||
class Cpufreq(Test): | ||
""" | ||
Test to validate the frequency transition. | ||
Test to validate the frequency transition on PowerNV. | ||
:avocado: tags=cpu,power | ||
""" | ||
|
||
# Skip this test if the platform is not PowerNV | ||
@skipIf(not IS_POWER_NV, "This test is not supported on PowerVM platform") | ||
def setUp(self): | ||
smm = SoftwareManager() | ||
self.detected_distro = distro.detect() | ||
self.distro_name = self.detected_distro.name | ||
self.distro_ver = self.detected_distro.version | ||
self.distro_rel = self.detected_distro.release | ||
# Get the configured attributes | ||
self.num_loop = int(self.params.get('test_loop', default=10)) | ||
self.cpufreq_diff_threshold = int( | ||
self.params.get('cpufreq_diff_threshold', default=10000)) | ||
self.cpu = 0 | ||
if 'Ubuntu' in self.distro_name: | ||
deps = ['linux-tools-common', 'linux-tools-%s' | ||
% platform.uname()[2]] | ||
deps = [ | ||
'linux-tools-common', | ||
'linux-tools-%s' % platform.uname()[2] | ||
] | ||
else: | ||
deps = ['kernel-tools'] | ||
for package in deps: | ||
if not smm.check_installed(package) and not smm.install(package): | ||
self.cancel('%s is needed for the test to be run' % package) | ||
self.log.info('Checking if %s is installed' % package) | ||
|
||
# Pick a random CPU from the list of online CPUs | ||
def get_random_cpu(self): | ||
self.log.info('Getting a random CPU') | ||
return random.choice(cpu.cpu_online_list()) | ||
|
||
# Get the CPU frequency attribute | ||
def get_cpufreq_attribute(self, file): | ||
self.log.info('Getting CPU frequency path for file %s' % file) | ||
f_name = "/sys/devices/system/cpu/cpu%s/cpufreq/%s" % (self.cpu, file) | ||
return open(f_name, 'r').readline().strip('\n').strip(' ') | ||
|
||
# Get the ppc64 CPU frequency | ||
def get_ppc64_cpu_frequency(self, new_format): | ||
self.log.info('Getting ppc64 CPU frequency') | ||
if new_format: | ||
freq_read = process.system_output( | ||
"ppc64_cpu --frequency -t 5 | grep 'avg' | awk '{print $3}'", | ||
shell=True) | ||
else: | ||
freq_read = process.system_output( | ||
"ppc64_cpu --frequency -t 5 | grep 'avg:' | awk '{print $2}'", | ||
shell=True) | ||
|
||
return float(freq_read) * (10**6) | ||
|
||
# Get a random frequency | ||
def get_random_freq(self): | ||
self.log.info('Getting a random frequency') | ||
cmd = "scaling_available_frequencies" | ||
return random.choice(self.get_cpufreq_attribute(cmd).split(' ')) | ||
|
||
# Check if the distro uses the new format | ||
def check_new_format(self): | ||
new_format = False | ||
if self.distro_name == "rhel": | ||
if (self.distro_ver == "9" and self.distro_rel > "1") or \ | ||
(self.distro_ver == "8" and self.distro_rel > "7"): | ||
new_format = True | ||
elif self.distro_name == "SuSE": | ||
if self.distro_ver == "15" and self.distro_rel > "4": | ||
new_format = True | ||
return new_format | ||
|
||
# Compare two frequencies and check if they are within the threshold | ||
def compare_frequencies(self, loop, freq1, freq2): | ||
diff = float(freq1) - float(freq2) | ||
if abs(diff) > self.cpufreq_diff_threshold: | ||
self.fail("Frequency set and frequency read differs : %s %s" % | ||
(freq2, freq1)) | ||
else: | ||
self.log.info( | ||
"Frequency set and frequency read are within the threshold : %s %s" | ||
% (freq1, freq2)) | ||
self.log.info("Difference between the two frequencies is %s" % | ||
diff) | ||
self.log.info("Test %s passed" % loop) | ||
|
||
# Set the CPU frequency | ||
def set_cpu_frequency(self, rand_freq): | ||
self.log.info("cpupower frequency-set -f %s" % rand_freq) | ||
process.run("cpupower frequency-set -f %s" % rand_freq) | ||
|
||
# Perform the test | ||
def test(self): | ||
""" | ||
Set the governor to userspace | ||
choose random frequency and cpu | ||
validate the frequency is set using ppc64_cpu tool. | ||
This method performs a series of tests on the CPU frequency settings. | ||
It sets the CPU governor to 'userspace' and verifies if the governor is set | ||
successfully. Then, it performs a number of iterations, each time setting a | ||
random CPU frequency and comparing it with the actual frequency. | ||
""" | ||
self.cpu = 0 | ||
threshold = 10000 | ||
self.log.info('Starting the test') | ||
output = process.run("cpupower frequency-set -g userspace", shell=True) | ||
cur_governor = self.cpu_freq_path('scaling_governor') | ||
cur_governor = self.get_cpufreq_attribute('scaling_governor') | ||
|
||
if 'userspace' == cur_governor and output.exit_status == 0: | ||
self.log.info("%s governor set successfully" % cur_governor) | ||
else: | ||
self.cancel("Unable to set the userspace governor") | ||
for var in range(1, 10): | ||
self.cpu = self.__get_random_cpu() | ||
self.log.info(" cpu is %s" % self.cpu) | ||
self.log.info("---------------Iteration %s-----------------" % var) | ||
process.run("cpupower frequency-set -f %s" | ||
% self.get_random_freq()) | ||
freq_set = self.cpu_freq_path("cpuinfo_cur_freq") | ||
new_format = False | ||
if self.distro_name == "rhel": | ||
if (self.distro_ver == "9" and self.distro_rel > "1") or \ | ||
(self.distro_ver == "8" and self.distro_rel > "7"): | ||
new_format = True | ||
if self.distro_name == "SuSE": | ||
if self.distro_ver == "15" and self.distro_rel > "4": | ||
new_format = True | ||
if new_format: | ||
freq_read = process.system_output("ppc64_cpu --frequency -t 5" | ||
"| grep 'avg' | awk " | ||
"'{print $3}'", shell=True) | ||
else: | ||
freq_read = process.system_output("ppc64_cpu --frequency -t 5" | ||
"| grep 'avg:' | awk " | ||
"'{print $2}'", shell=True) | ||
freq_read = float(freq_read) * (10 ** 6) | ||
diff = float(freq_read) - float(freq_set) | ||
self.log.info(" Difference is %s" % diff) | ||
if diff > threshold: | ||
self.log.info("Frequency set and frequency read differs :" | ||
"%s %s " % (freq_set, freq_read)) | ||
else: | ||
self.log.info("Works as expected for iteration %s " % var) | ||
|
||
def get_random_freq(self): | ||
""" | ||
Get random frequency from list | ||
""" | ||
cmd = "scaling_available_frequencies" | ||
return random.choice(self.cpu_freq_path(cmd).split(' ')) | ||
|
||
@staticmethod | ||
def __get_random_cpu(): | ||
""" | ||
Get random online cpu | ||
""" | ||
return random.choice(cpu.cpu_online_list()) | ||
for loop in range(self.num_loop): | ||
self.cpu = self.get_random_cpu() | ||
self.log.info("---------------CPU %s-----------------" % self.cpu) | ||
self.log.info("---------------Iteration %s-----------------" % | ||
loop) | ||
rand_freq = self.get_random_freq() | ||
self.set_cpu_frequency(rand_freq) | ||
freq_set = self.get_cpufreq_attribute("cpuinfo_cur_freq") | ||
self.compare_frequencies(loop, rand_freq, freq_set) | ||
|
||
def cpu_freq_path(self, file): | ||
""" | ||
get cpu_freq values | ||
:param: file: is filename which data needs to be fetched | ||
:param: cpu_num is value for cpu | ||
""" | ||
f_name = "/sys/devices/system/cpu/cpu%s/cpufreq/%s" % (self.cpu, file) | ||
return open(f_name, 'r').readline().strip('\n').strip(' ') | ||
new_format = self.check_new_format() | ||
freq_read = self.get_ppc64_cpu_frequency(new_format) | ||
self.compare_frequencies(loop, freq_set, freq_read) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
test_loop : 10 | ||
cpufreq_diff_threshold : 10000 |