From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 2B92AA0352; Thu, 16 Jan 2020 03:28:19 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 1E23C1C0D7; Thu, 16 Jan 2020 03:28:19 +0100 (CET) Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by dpdk.org (Postfix) with ESMTP id 765E51BFCC for ; Thu, 16 Jan 2020 03:28:17 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Jan 2020 18:28:16 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,324,1574150400"; d="scan'208";a="425313121" Received: from fmsmsx107.amr.corp.intel.com ([10.18.124.205]) by fmsmga006.fm.intel.com with ESMTP; 15 Jan 2020 18:28:16 -0800 Received: from shsmsx606.ccr.corp.intel.com (10.109.6.216) by fmsmsx107.amr.corp.intel.com (10.18.124.205) with Microsoft SMTP Server (TLS) id 14.3.439.0; Wed, 15 Jan 2020 18:28:00 -0800 Received: from shsmsx602.ccr.corp.intel.com (10.109.6.142) by SHSMSX606.ccr.corp.intel.com (10.109.6.216) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Thu, 16 Jan 2020 10:27:58 +0800 Received: from shsmsx602.ccr.corp.intel.com ([10.109.6.142]) by SHSMSX602.ccr.corp.intel.com ([10.109.6.142]) with mapi id 15.01.1713.004; Thu, 16 Jan 2020 10:27:58 +0800 From: "Yao, Lei A" To: "Mo, YufengX" , "dts@dpdk.org" Thread-Topic: [dts][PATCH V2 2/4] tests/power_bidirection_channel: upload automation script Thread-Index: AQHVzA/VmSxxtsfwQ0meSyd5GIXKJ6fskO7A Date: Thu, 16 Jan 2020 02:27:58 +0000 Message-ID: References: <20200116015630.21250-1-yufengx.mo@intel.com> <20200116015630.21250-3-yufengx.mo@intel.com> In-Reply-To: <20200116015630.21250-3-yufengx.mo@intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-version: 11.2.0.6 dlp-reaction: no-action dlp-product: dlpe-windows x-originating-ip: [10.239.127.36] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dts] [PATCH V2 2/4] tests/power_bidirection_channel: upload automation script X-BeenThere: dts@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: test suite reviews and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dts-bounces@dpdk.org Sender: "dts" > -----Original Message----- > From: Mo, YufengX > Sent: Thursday, January 16, 2020 9:56 AM > To: dts@dpdk.org; Yao, Lei A > Cc: Mo, YufengX > Subject: [dts][PATCH V2 2/4] tests/power_bidirection_channel: upload > automation script >=20 >=20 > upload automation script. >=20 > Signed-off-by: yufengmx Acked-by: Lei Yao > --- > tests/TestSuite_power_bidirection_channel.py | 590 > +++++++++++++++++++ > 1 file changed, 590 insertions(+) > create mode 100644 tests/TestSuite_power_bidirection_channel.py >=20 > diff --git a/tests/TestSuite_power_bidirection_channel.py > b/tests/TestSuite_power_bidirection_channel.py > new file mode 100644 > index 0000000..ed82fda > --- /dev/null > +++ b/tests/TestSuite_power_bidirection_channel.py > @@ -0,0 +1,590 @@ > +# BSD LICENSE > +# > +# Copyright(c) 2010-2020 Intel Corporation. All rights reserved. > +# All rights reserved. > +# > +# Redistribution and use in source and binary forms, with or without # > +modification, are permitted provided that the following conditions # > +are met: > +# > +# * Redistributions of source code must retain the above copyright > +# notice, this list of conditions and the following disclaimer. > +# * Redistributions in binary form must reproduce the above copyright > +# notice, this list of conditions and the following disclaimer in > +# the documentation and/or other materials provided with the > +# distribution. > +# * Neither the name of Intel Corporation nor the names of its > +# contributors may be used to endorse or promote products derived > +# from this software without specific prior written permission. > +# > +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > CONTRIBUTORS # > +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > # > +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS > FOR # > +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE > COPYRIGHT # > +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, > INCIDENTAL, # > +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > NOT # > +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF > USE, # > +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND > ON ANY # > +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # > +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF > THE USE # > +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > DAMAGE. > + > +""" > +DPDK Test suite. > +virtual power manager test suite. > +""" > +import os > +import time > +import traceback > + > +from utils import create_mask as dts_create_mask from qemu_libvirt > +import LibvirtKvm from exception import VerifyFailure from test_case > +import TestCase > + > + > +class TestPowerBidirectionChannel(TestCase): > + # temporary file directory > + output_path =3D '/tmp' > + > + @property > + def target_dir(self): > + # get absolute directory of target source code > + target_dir =3D '/root' + self.dut.base_dir[1:] \ > + if self.dut.base_dir.startswith('~') else \ > + self.dut.base_dir > + return target_dir > + > + def get_cores_mask(self, config=3D'all'): > + ports_socket =3D self.dut.get_numa_id(self.dut.get_ports()[0]) > + mask =3D dts_create_mask( > + self.dut.get_core_list(config, socket=3Dports_socket)) > + return mask > + > + def prepare_binary(self, name, host_crb=3DNone): > + _host_crb =3D host_crb if host_crb else self.dut > + example_dir =3D "examples/" + name > + out =3D _host_crb.build_dpdk_apps('./' + example_dir) > + self.verify("Error" not in out, "Compilation error") > + self.verify("No such" not in out, "Compilation error") > + binary_dir =3D os.path.join(self.target_dir, example_dir, 'build= ') > + cmd =3D ["ls -F {0} | grep '*'".format(binary_dir), '# ', 5] > + exec_file =3D self.execute_cmds(cmd, name=3D_host_crb.session.na= me) > + binary_file =3D os.path.join(binary_dir, exec_file[:-1]) > + return binary_file > + > + def add_console(self, session): > + self.ext_con[session.name] =3D [ > + session.send_expect, > + session.session.get_output_all] > + > + def get_console(self, name): > + default_con_table =3D { > + self.dut.session.name: [ > + self.dut.send_expect, > + self.dut.get_session_output], > + self.dut.alt_session.name: [ > + self.dut.alt_session.send_expect, > + self.dut.alt_session.session.get_output_all]} > + if name not in default_con_table: > + return self.ext_con.get(name) or [None, None] > + else: > + return default_con_table.get(name) > + > + def execute_cmds(self, cmds, name=3D'dut'): > + console, msg_pipe =3D self.get_console(name) > + if len(cmds) =3D=3D 0: > + return > + if isinstance(cmds, (str, unicode)): > + cmds =3D [cmds, '# ', 5] > + if not isinstance(cmds[0], list): > + cmds =3D [cmds] > + outputs =3D [] if len(cmds) > 1 else '' > + for item in cmds: > + expected_items =3D item[1] > + if expected_items and isinstance(expected_items, (list, tupl= e)): > + check_output =3D True > + expected_str =3D expected_items[0] or '# ' > + else: > + check_output =3D False > + expected_str =3D expected_items or '# ' > + > + try: > + if len(item) =3D=3D 3: > + timeout =3D int(item[2]) > + output =3D console(item[0], expected_str, timeout) > + output =3D msg_pipe() if not output else output > + else: > + output =3D console(item[0], expected_str) > + output =3D msg_pipe() if not output else output > + except Exception as e: > + msg =3D "execute '{0}' timeout".format(item[0]) > + raise Exception(msg) > + time.sleep(1) > + if len(cmds) > 1: > + outputs.append(output) > + else: > + outputs =3D output > + > + return outputs > + > + def d_con(self, cmds): > + return self.execute_cmds(cmds, name=3Dself.dut.session.name) > + > + def d_a_con(self, cmds): > + return self.execute_cmds(cmds, name=3Dself.dut.alt_session.name) > + > + def vm_con(self, cmds): > + return self.execute_cmds(cmds, name=3Dself.vm_dut.session.name) > + > + def vm_g_con(self, cmds): > + return self.execute_cmds(cmds, name=3Dself.guest_con_name) > + > + def get_sys_power_driver(self): > + drv_file =3D "/sys/devices/system/cpu/cpu0/cpufreq/scaling_drive= r" > + output =3D self.d_a_con('cat ' + drv_file) > + if not output: > + msg =3D 'unknown power driver' > + self.verify(False, msg) > + drv_name =3D output.splitlines()[0].strip() > + return drv_name > + > + @property > + def is_support_pbf(self): > + # check if cpu support bpf feature > + cpu_attr =3D r'/sys/devices/system/cpu/cpu0/cpufreq/base_frequen= cy' > + cmd =3D "ls {0}".format(cpu_attr) > + self.d_a_con(cmd) > + cmd =3D "echo $?" > + output =3D self.d_a_con(cmd) > + ret =3D True if output =3D=3D "0" else False > + return ret > + > + def get_all_cpu_attrs(self): > + ''' > + get all cpus' base_frequency value, if not support pbf, set all = to 0 > + ''' > + if not self.is_support_pbf: > + cpu_topos =3D self.dut.get_all_cores() > + _base_freqs_info =3D {} > + for index, _ in enumerate(cpu_topos): > + _base_freqs_info[index] =3D 0 > + return _base_freqs_info > + # if cpu support high priority core > + key_values =3D ['base_frequency', > + 'cpuinfo_max_freq', > + 'cpuinfo_min_freq'] > + freq =3D r'/sys/devices/system/cpu/cpu{0}/cpufreq/{1}'.format > + # use dut alt session to get dut platform cpu base frequency att= ribute > + cpu_topos =3D self.dut.get_all_cores() > + cpu_info =3D {} > + for cpu_topo in cpu_topos: > + cpu_id =3D int(cpu_topo['thread']) > + cpu_info[cpu_id] =3D {} > + cpu_info[cpu_id]['socket'] =3D cpu_topo['socket'] > + cpu_info[cpu_id]['core'] =3D cpu_topo['core'] > + > + for key_value in key_values: > + cmds =3D [] > + for cpu_id in sorted(cpu_info.keys()): > + cmds.append('cat {0}'.format(freq(cpu_id, key_value))) > + output =3D self.d_a_con(';'.join(cmds)) > + freqs =3D [int(item) for item in output.splitlines()] > + for index, cpu_id in enumerate(sorted(cpu_info.keys())): > + cpu_info[cpu_id][key_value] =3D freqs[index] > + > + # get high priority core and normal core > + base_freqs_info =3D {} > + for core_index, value in cpu_info.iteritems(): > + base_frequency =3D value.get('base_frequency') > + base_freqs_info.setdefault(base_frequency, []).append(core_i= ndex) > + base_freqs =3D base_freqs_info.keys() > + # cpu should have high priority core and normal core > + # high priority core frequency is higher than normal core freque= ncy > + if len(base_freqs) <=3D 1 or \ > + not all([len(value) for value in base_freqs_info.values()]): > + msg =3D 'current cpu has no high priority core' > + raise Exception(msg) > + > + high_pri_freq =3D max(self.base_freqs_info.keys()) > + high_pri_cores =3D base_freqs_info[high_pri_freq] > + _base_freqs_info =3D {} > + for index, _ in enumerate(cpu_topos): > + _base_freqs_info[index] =3D 1 if index in high_pri_cores els= e > + 0 > + > + return _base_freqs_info > + > + def init_vms_params(self): > + self.vm =3D self.vcpu_map =3D self.vcpu_lst =3D self.vm_dut =3D = \ > + self.guest_session =3D self.is_guest_on =3D self.is_vm_on = =3D None > + # vm config > + self.vm_name =3D 'vm0' > + self.vm_max_ch =3D 8 > + self.vm_log_dir =3D '/tmp/powermonitor' > + self.create_powermonitor_folder() > + > + def create_powermonitor_folder(self): > + # create temporary folder for power monitor > + cmd =3D 'mkdir -p {0}; chmod 777 {0}'.format(self.vm_log_dir) > + self.d_a_con(cmd) > + > + def start_vm(self): > + # set vm initialize parameters > + self.init_vms_params() > + # start vm > + self.vm =3D LibvirtKvm(self.dut, self.vm_name, self.suite_name) > + # pass pf to virtual machine > + pci_addr =3D self.dut.get_port_pci(self.dut_ports[0]) > + # add channel > + ch_name =3D 'virtio.serial.port.poweragent.{0}' > + vm_path =3D os.path.join(self.vm_log_dir, '{0}.{1}') > + for cnt in range(self.vm_max_ch): > + channel =3D { > + 'path': vm_path.format(self.vm_name, cnt), > + 'name': ch_name.format(cnt)} > + self.vm.add_vm_virtio_serial_channel(**channel) > + # boot up vm > + self.vm_dut =3D self.vm.start() > + self.is_vm_on =3D True > + self.verify(self.vm_dut, "create vm_dut fail !") > + self.add_console(self.vm_dut.session) > + # get virtual machine cpu cores > + _vcpu_map =3D self.vm.get_vm_cpu() > + self.vcpu_map =3D [int(item) for item in _vcpu_map] > + self.vcpu_lst =3D [int(item['core']) for item in > + self.vm_dut.cores] > + > + def close_vm(self): > + # close vm > + if self.is_vm_on: > + if self.guest_session: > + self.vm_dut.close_session(self.guest_session) > + self.guest_session =3D None > + self.vm.stop() > + self.is_vm_on =3D False > + self.vm =3D None > + self.dut.virt_exit() > + cmd_fmt =3D 'virsh {0} {1} > /dev/null 2>&1'.format > + cmds =3D [ > + [cmd_fmt('shutdown', self.vm_name), '# '], > + [cmd_fmt('undefine', self.vm_name), '# '], ] > + self.d_a_con(cmds) > + > + def init_vm_power_mgr(self): > + self.vm_power_mgr =3D self.prepare_binary('vm_power_manager') > + > + def start_vm_power_mgr(self): > + eal_option =3D ( > + ' ' > + '-c {core_mask} ' > + '-n {mem_channel} ' > + '--no-pci ').format(**{ > + 'core_mask': self.get_cores_mask("1S/3C/1T"), > + 'mem_channel': self.dut.get_memory_channels(), }) > + prompt =3D 'vmpower>' > + option =3D eal_option > + cmd =3D [' '.join([self.vm_power_mgr, option]), prompt, 30] > + self.d_con(cmd) > + self.is_mgr_on =3D True > + > + def set_vm_power_mgr(self): > + vm_name =3D self.vm_name > + cmds =3D [ > + "add_vm %s" % vm_name, > + "add_channels %s all" % vm_name, > + 'set_channel_status %s all enabled' % vm_name, > + "show_vm %s" % vm_name] > + prompt =3D 'vmpower>' > + self.d_con([[cmd, prompt] for cmd in cmds]) > + > + def close_vm_power_mgr(self): > + if not self.is_mgr_on: > + return > + self.d_con(['quit', '# ', 15]) > + self.is_mgr_on =3D False > + > + def host_set_query_enable(self): > + return self.d_con( > + ['set_query {} enable'.format(self.vm_name), 'vmpower>', > + 15]) > + > + def host_set_query_disable(self): > + return self.d_con( > + ['set_query {} disable'.format(self.vm_name), 'vmpower>', > + 15]) > + > + def init_guest_mgr(self): > + name =3D 'vm_power_manager/guest_cli' > + self.guest_cli =3D self.prepare_binary(name, host_crb=3Dself.vm_= dut) > + self.guest_con_name =3D \ > + '_'.join([self.vm_dut.NAME, name.replace('/', '-')]) > + self.guest_session =3D self.vm_dut.create_session(self.guest_con= _name) > + self.add_console(self.guest_session) > + > + def start_guest_mgr(self): > + prompt =3D r"vmpower\(guest\)>" > + option =3D ( > + ' ' > + '-c {core_mask} ' > + '-n {memory_channel} ' > + '-m {memory_size} ' > + '--no-pci ' > + '--file-prefix=3D{file_prefix} ' > + '-- ' > + '--vm-name=3D{vm_name} ' > + '--vcpu-list=3D{vpus} ').format(**{ > + 'core_mask': '0xff', > + 'memory_channel': self.vm_dut.get_memory_channels(), > + 'memory_size': 1024, > + 'file_prefix': 'vmpower1', > + 'vm_name': self.vm_name, > + 'vpus': ','.join([str(core) for core in self.vcpu_lst]), > + }) > + guest_cmd =3D self.guest_cli + option > + self.vm_g_con([guest_cmd, prompt, 120]) > + self.is_guest_on =3D True > + > + def close_guest_mgr(self): > + if not self.is_guest_on: > + return > + self.vm_g_con("quit") > + self.is_guest_on =3D False > + > + def guest_set_cpu_freq_down(self, core_index): > + return self.vm_g_con(['set_cpu_freq {} down'.format(core_index), > + r"vmpower\(guest\)>", 20]) > + > + def guest_query_cpu_caps(self, core=3D'all'): > + return self.vm_g_con( > + ['query_cpu_caps {}'.format(core), r"vmpower\(guest\)>", > + 20]) > + > + def guest_query_cpu_freq(self, core=3D'all'): > + return self.vm_g_con( > + ['query_cpu_freq {}'.format(core), r"vmpower\(guest\)>", > + 20]) > + > + def run_test_pre(self): > + # boot up binary processes > + self.start_vm_power_mgr() > + # set binary process command > + self.set_vm_power_mgr() > + # boot up binary processes > + self.start_guest_mgr() > + > + def run_test_post(self): > + # close all binary processes > + self.close_guest_mgr() > + self.close_vm_power_mgr() > + > + def check_cpupower_tool(self): > + cmd =3D "whereis cpupower > /dev/null 2>&1; echo $?" > + output =3D self.d_a_con(cmd) > + status =3D True if output and output.strip() =3D=3D "0" else Fal= se > + msg =3D 'cpupower tool have not installed on DUT' > + self.verify(status, msg) > + > + def check_policy_command_acked_output(self): > + output =3D self.guest_set_cpu_freq_down(self.vcpu_lst[-1]) > + expected =3D 'ACK received for message sent to host' > + msg =3D "expected message '{}' not in output".format(expected) > + status =3D expected in output > + [self.logger.info(output) if not status else None] > + self.verify(status, msg) > + output =3D self.guest_set_cpu_freq_down(self.vcpu_lst[-1] + 1) > + expected =3D 'Error sending message: Unknown error -1' > + msg =3D "expected message '{}' not in output".format(expected) > + status =3D expected in output > + [self.logger.info(output) if not status else None] > + self.verify(status, msg) > + > + def check_query_cpu_freqs_command(self): > + # Query the CPU frequency for all CPU cores from VM side > + self.host_set_query_enable() > + > + def get_cpu_attribute(cores): > + freq_path_fmt =3D ("cat /sys/devices/system/cpu/cpu{0}" > + "/cpufreq/cpuinfo_cur_freq").format > + cmd =3D ";".join([freq_path_fmt(core) for core in cores]) > + output =3D self.d_a_con(cmd) > + freqs =3D [int(item) for item in output.splitlines()] > + return freqs > + > + def check(core, freq, output): > + expected =3D "Frequency of [{0}] vcore is {1}.".format(core,= freq) > + msg =3D "expected message '{}' not in output".format(expecte= d) > + self.verify(expected in output, msg) > + # check one core > + check_core =3D self.vcpu_lst[-1] > + freqs =3D get_cpu_attribute([self.vcpu_map[-1]]) > + output =3D self.guest_query_cpu_freq(check_core) > + check(check_core, freqs[0], output) > + # check all cores > + freqs =3D get_cpu_attribute(self.vcpu_map) > + output =3D self.guest_query_cpu_freq() > + [check(check_core, freqs[index], output) > + for index, check_core in enumerate(self.vcpu_lst)] > + # disable query permission from VM, check the host CPU frequency > + # won't be returned > + self.host_set_query_disable() > + output =3D self.guest_query_cpu_freq() > + expected =3D "Error during frequency list reception." > + msg =3D "expected message '{}' not in output".format(expected) > + self.verify(expected in output, msg) > + > + def check_cpu_capability_on_vm(self): > + self.host_set_query_enable() > + # check the high priority core is recognized correctly. > + turbo_status =3D 1 > + > + def check(index, output): > + vcore =3D self.vcpu_lst[index] > + pcore =3D self.vcpu_map[index] > + pri =3D self.base_freqs_info[pcore] > + expected =3D ( > + "Capabilities of [{0}] vcore are: " > + "turbo possibility: {1}, " > + "is priority core: {2}.").format(vcore, turbo_status, pr= i) > + msg =3D "expected message '{}' not in output".format(expecte= d) > + self.verify(expected in output, msg) > + > + output =3D self.guest_query_cpu_caps() > + [check(index, output) > + for index, _ in enumerate(self.vcpu_lst)] > + # check no CPU info will be return. > + output =3D self.guest_query_cpu_caps(self.vcpu_lst[-1] + 1) > + expected =3D 'Invalid parameter provided' > + msg =3D "expected message '{}' not in output".format(expected) > + self.verify(expected in output, msg) > + # check the host CPU capability won't be returned. > + self.host_set_query_disable() > + output =3D self.guest_query_cpu_caps() > + expected =3D "Error during capabilities reception" > + msg =3D "expected message '{}' not in output".format(expected) > + self.verify(expected in output, msg) > + > + def verify_policy_command_acked_action(self): > + except_content =3D None > + msg =3D "begin test policy command acked action ..." > + self.logger.info(msg) > + try: > + self.run_test_pre() > + self.check_policy_command_acked_output() > + except Exception as e: > + self.logger.error(traceback.format_exc()) > + except_content =3D e > + finally: > + self.run_test_post() > + > + # check verify result > + if except_content: > + raise VerifyFailure(except_content) > + msg =3D "test policy command acked action successful !!!" > + self.logger.info(msg) > + > + def verify_query_cpu_freqs_from_vm(self): > + except_content =3D None > + msg =3D "begin test query cpu freqs from vm ..." > + self.logger.info(msg) > + try: > + self.run_test_pre() > + self.check_query_cpu_freqs_command() > + except Exception as e: > + self.logger.error(traceback.format_exc()) > + except_content =3D e > + finally: > + self.run_test_post() > + > + # check verify result > + if except_content: > + raise VerifyFailure(except_content) > + msg =3D "test query cpu freqs from vm successful !!!" > + self.logger.info(msg) > + > + def verify_query_cpu_capability(self): > + except_content =3D None > + msg =3D "begin test query cpu capability ..." > + self.logger.info(msg) > + try: > + self.run_test_pre() > + self.check_cpu_capability_on_vm() > + except Exception as e: > + self.logger.error(traceback.format_exc()) > + except_content =3D e > + finally: > + self.run_test_post() > + > + # check verify result > + if except_content: > + raise VerifyFailure(except_content) > + msg =3D "test query cpu capability successful !!!" > + self.logger.info(msg) > + > + def verify_power_driver(self): > + expected_drv =3D 'acpi-cpufreq' > + power_drv =3D self.get_sys_power_driver() > + msg =3D "{0} should work with {1} driver on DUT".format( > + self.suite_name, expected_drv) > + self.verify(power_drv =3D=3D expected_drv, msg) > + > + def preset_test_environment(self): > + self.is_mgr_on =3D None > + self.ext_con =3D {} > + # modprobe msr module to let the application can get the CPU HW = info > + self.d_a_con('modprobe msr') > + self.d_a_con('cpupower frequency-set -g userspace') > + self.dut.init_core_list_uncached_linux() > + # check if cpu support bpf feature > + self.base_freqs_info =3D self.get_all_cpu_attrs() > + # boot up vm > + self.start_vm() > + # init binary > + self.init_vm_power_mgr() > + self.init_guest_mgr() > + > + # > + # Test cases. > + # > + > + def set_up_all(self): > + """ > + Run at the start of each test suite. > + """ > + self.dut_ports =3D self.dut.get_ports(self.nic) > + self.verify(len(self.dut_ports) >=3D 1, "Not enough ports") > + self.check_cpupower_tool() > + self.verify_power_driver() > + # prepare testing environment > + self.preset_test_environment() > + > + def tear_down_all(self): > + """ > + Run after each test suite. > + """ > + self.close_vm() > + > + def set_up(self): > + """ > + Run before each test case. > + """ > + pass > + > + def tear_down(self): > + """ > + Run after each test case. > + """ > + self.vm_dut.kill_all() > + self.dut.kill_all() > + > + def test_policy_command_acked_action(self): > + """ > + Check VM can send power policy command to host and get acked > + """ > + self.verify_policy_command_acked_action() > + > + def test_query_cpu_freqs_from_vm(self): > + """ > + Query Host CPU frequency list from VM > + """ > + self.verify_query_cpu_freqs_from_vm() > + > + def test_query_cpu_capability(self): > + """ > + Query CPU capability from VM > + """ > + self.verify_query_cpu_capability() > -- > 2.21.0