diff --git a/cpu/em_cpufreq.py b/cpu/em_cpufreq.py index 2a6521de1..f27dda842 100755 --- a/cpu/em_cpufreq.py +++ b/cpu/em_cpufreq.py @@ -13,6 +13,7 @@ # # Copyright: 2017 IBM # Author: Shriya Kulkarni + import random import platform from avocado import Test @@ -20,15 +21,18 @@ 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() @@ -36,80 +40,113 @@ def setUp(self): 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) diff --git a/cpu/em_cpufreq.py.data/em_cpufreq.yaml b/cpu/em_cpufreq.py.data/em_cpufreq.yaml new file mode 100644 index 000000000..33202b7c1 --- /dev/null +++ b/cpu/em_cpufreq.py.data/em_cpufreq.yaml @@ -0,0 +1,2 @@ +test_loop : 10 +cpufreq_diff_threshold : 10000