[dts] [PATCH V1 2/2] meson_build_system: upload automation script

yufengx.mo at intel.com yufengx.mo at intel.com
Wed Jun 6 07:36:14 CEST 2018


From: yufengmx <yufengx.mo at intel.com>


This automation script is for meson build system feature.

meson and ninja tools are used to compile and install DPDK. It is aimed
at taking the place of direct using make (GNU make) to get more convenience
and efficiency for compilation.

Signed-off-by: yufengmx <yufengx.mo at intel.com>
---
 tests/TestSuite_meson_build_system.py | 1665 +++++++++++++++++++++++++++++++++
 1 file changed, 1665 insertions(+)
 create mode 100644 tests/TestSuite_meson_build_system.py

diff --git a/tests/TestSuite_meson_build_system.py b/tests/TestSuite_meson_build_system.py
new file mode 100644
index 0000000..25fb246
--- /dev/null
+++ b/tests/TestSuite_meson_build_system.py
@@ -0,0 +1,1665 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2018 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.
+
+import os
+import time
+import re
+
+from socket import htons, htonl
+
+from packet import Packet, NVGRE, IPPROTO_NVGRE
+from scapy.sendrecv import sendp
+
+import utils
+from test_case import TestCase
+from exception import TimeoutException, VerifyFailure
+from settings import HEADER_SIZE
+from serializer import Serializer
+from pmd_output import PmdOutput
+
+# used for debug
+from functools import wraps
+from pprint import pprint, pformat
+import inspect
+import traceback
+import pdb
+import shutil
+
+join = os.sep.join
+
+FRAME_SIZE_64=64
+
+#  overload ``start_testpmd``
+class _PmdOutput(PmdOutput):
+    def start_testpmd(self, cores, param='', eal_param='', socket=0, 
+                      bin_path=''):
+        if "--tx-offloads" not in param:
+            param += " --tx-offloads=0x3f"
+
+        if type(cores) == list:
+            core_list = cores
+        elif cores == "Default":
+            core_list = self.dut.get_core_list(self.default_cores)
+        else:
+            core_list = self.dut.get_core_list(cores, socket=socket)
+        self.coremask = utils.create_mask(core_list)
+        command = "%s -c %s -n %d %s -- -i %s" \
+            % (bin_path, self.coremask, self.dut.get_memory_channels(), 
+               eal_param, param)
+        out = self.dut.send_expect(command, "testpmd> ", 200)
+        self.command = command
+        return out
+
+class ExecBinProcess(object):
+    '''
+    support single process start/close
+    '''
+    def __init__(self, **kwargs):
+        # initialize process parameter
+        self.f_session = kwargs.get('fore_session')
+        self.d_session = kwargs.get('daemon_session')
+        self.name = kwargs.get('name')
+        self.output = kwargs.get('output')
+        # target source code
+        self.binary_type = kwargs.get('binary_type', 'example')
+        self.compile_type = kwargs.get('compile_type')
+        self.target_name = kwargs.get('target_name')
+        if self.binary_type == 'example':
+            if self.compile_type == "Dexamples options":
+                self.target_code = kwargs.get('target_src') #+ "/build"
+            else:
+                self.target_code = kwargs.get('target_src') + "/examples"
+        elif self.binary_type == 'app':
+            self.target_code = kwargs.get('target_src')
+        self.ignore_compile = kwargs.get('ignore_compile', False)
+        self.logger = kwargs.get('logger')
+        # initialize process
+        self.process_pid = None
+        self.output_log = join([self.output, 
+                                self.name.replace('/', '@') + '.log'])
+        # compile and get executable binary file
+        if self.binary_type == 'example':
+            self.bin = self.compile(self.target_code, self.name)
+        elif self.binary_type == 'app':
+            self.bin = kwargs.get('binary_file')
+        self.bin_name = os.path.basename(self.bin)
+        # set process status
+        self.status = 'close'
+
+    def f_console(self, cmds):
+        return self.execute_cmds(cmds, con_name='fore')
+
+    def d_console(self, cmds):
+        return self.execute_cmds(cmds, con_name='daemon')
+
+    def get_console(self, name):
+        if name == 'fore':
+            console = self.f_session.send_expect
+            msg_pipe = self.f_session.session.get_output_all
+        elif name == 'daemon':
+            console = self.d_session.send_expect
+            msg_pipe = self.d_session.session.get_output_all
+        return console, msg_pipe
+
+    def execute_cmds(self, cmds, con_name='fore'):
+        console, msg_pipe = self.get_console(con_name)
+        if len(cmds) == 0:
+            return
+        if isinstance(cmds, (str, unicode)):
+            cmds = [cmds, '# ', 5]
+        if not isinstance(cmds[0], list):
+            cmds = [cmds]
+        if len(cmds) > 1:
+            outputs = []
+        else:
+            outputs = ''
+        for item in cmds:
+            expected_items = item[1]
+            if expected_items and isinstance(expected_items, (list, tuple)):
+                check_output = True
+                expected_str = expected_items[0] or '# '
+            else:
+                check_output = False
+                expected_str = expected_items or '# '
+
+            try:
+                if len(item) == 3:
+                    timeout = int(item[2])
+                    output = console(item[0], expected_str, timeout)
+                else:
+                    #timeout = 5
+                    output = console(item[0], expected_str)
+            except TimeoutException:
+                output = msg_pipe()
+                self.logger.info(output)
+                msg = "execute '{0}' timeout".format(item[0])
+                raise TimeoutException(msg)
+            finally:
+                pass
+            # when execute "port start", LSC event will cause next command 
+            # execution fail. So wait 10s here
+            time.sleep(1)
+            if len(cmds) > 1:
+                outputs.append(output)
+            else:
+                outputs = output
+            if check_output and len(expected_items) >= 2:
+                self.logger.info(output)
+                expected_output = expected_items[1]
+                check_type = True if len(expected_items) == 2 \
+                                  else expected_items[2]
+                if check_type and expected_output in output:
+                    msg = "expected '{0}' is in output".format(expected_output)
+                    self.logger.info(msg)
+                elif not check_type and expected_output not in output:
+                    msg = "unexpected '{0}' is not in output".format(
+                                                                expected_output)
+                    self.logger.info(msg)
+                else:
+                    status = "isn't in" if check_type else "is in"
+                    msg = "[{0}] {1} output".format(expected_output, status)
+                    self.logger.error(msg)
+                    raise VerifyFailure(msg)
+
+        return outputs
+
+    def is_existed(self, path, console_name='daemon'):
+        ''' check if file existed '''
+        cmd = "ls {0}".format(path)
+        self.execute_cmds(cmd, con_name=console_name)
+        cmd = "echo $?"
+        output = self.execute_cmds(cmd, con_name=console_name)
+        ret = True if output == "0" else False
+        
+        return ret
+
+    def match_error_log(self, output):
+        pats =['\d+:\d+: error:',
+               'ninja.*build.*failed']
+        for pat in pats:
+            ret = re.findall(pat, output)
+            if len(ret):
+                return True
+
+    def compile(self, target_code, name):
+        '''
+        : support examples binary compile using ``make -C`` or ``meson``
+        '''
+        # if it is a multiple binary example
+        compile_fd, _, sub_fd = name.partition("/")
+        compile_path = join([target_code, compile_fd])
+        # meson build system, using Dexamples options
+        if self.compile_type == "Dexamples options":
+            meson = "meson"
+            option = "-Dexamples={0}".format(compile_fd)
+            build_dir = self.target_code
+            configs = {"meson": meson,
+                       "option": option,
+                       "build_dir": build_dir}
+            cmds = [
+               ";".join([
+                 "export LD_LIBRARY_PATH=/usr/local/lib64/",
+                 "{meson} {build_dir}".format(**configs),
+                 "cd {0}".format(build_dir),
+                 "ninja clean",
+                 "{meson} configure {option} {build_dir}".format(**configs),
+                 "ninja"]), '', 35]
+        else:
+            cmds = ['make -C {0}'.format(compile_path), '', 15]
+        if self.ignore_compile:
+            msg = "ignore compile {0}".format(compile_path)
+            self.logger.info(msg)
+        else:
+            outputs = self.f_console(cmds)
+            # check compile result
+            for output in outputs:
+                if self.match_error_log(output):
+                    msg = "meson build example failed"
+                    raise VerifyFailure(msg)
+            else:
+                msg = "meson build example successful"
+                self.logger.info(msg)
+        # check executable binary file
+        _temp = compile_fd if not sub_fd else join([compile_fd, sub_fd])
+        if self.binary_type == 'example':
+            key_words = ['build', self.target_name]
+            tool_path = join([target_code, "examples"])
+        else:
+            # under app, compile_fd is the name of app
+            tool_path = join([target_code, _temp])
+            key_words = []
+        exec_bin = self.get_exec_bin_file(tool_path, key_words)
+        if not exec_bin or not self.is_existed(exec_bin):
+            msg = 'expected tool <{0}> does not exist'.format(name)
+            self.logger.error(msg)
+            raise VerifyFailure(msg)
+
+        return exec_bin
+
+    def get_exec_bin_file(self, tool_path, key_words):
+        bin_dir = []
+        for key_word in key_words:
+            cmds = ['find {0} -name {1}'.format(tool_path, key_word), '', 5]
+            output = self.f_console(cmds)
+            if output == '':
+                continue
+            bin_dir.extend(output.splitlines())
+        if not bin_dir:
+            bin_dir = [tool_path]
+
+        for dir in bin_dir:
+            cmds = ["ls -F {0} | grep '*'".format(dir), '', 5]
+            exec_file = self.f_console(cmds)
+            exec_bin = join([dir, exec_file[:-1]])
+            msg = "binary file is <{0}>".format(exec_bin)
+            self.logger.info(msg) 
+            return exec_bin
+        else:
+            return None
+
+    def check_process(self, process_name, check_status):
+        # check subprocess in task space
+        cmd = "ps aux | grep -i '%s' | grep -v grep | awk {'print $2'}"%(
+                                                                process_name)
+        out = self.d_console([cmd, '# ', 5])
+        if out != "":
+            self.process_pid = out.splitlines()[0]
+            self.logger.info("{0}'s pid is {1}".format(self.bin_name,
+                                                       self.process_pid))
+            status = True
+        else:
+            status = False
+
+        if check_status == 'start' and not status:
+            raise_flg = True
+        elif check_status == 'close' and status:
+            raise_flg = True
+        else:
+            raise_flg = False
+
+        if raise_flg:
+            raise VerifyFailure("{0} {1} failed".format(process_name, 
+                                                    check_status))
+        else:
+            self.logger.info("{0} {1} success".format(process_name,
+                                                      check_status))
+
+        return status
+
+    def start(self, eal_option='', prompt='EAL',
+              ps_type="block", timeout=None):
+        if self.status == 'running':
+            return
+        cmd =['{0} {1} 2>&1'.format(self.bin, eal_option), prompt, 25]
+        output = self.f_console(cmd)
+        # save output in log file
+        log = self.output_log
+        with open(log, 'wb') as fp:
+            fp.write(output)
+        #--------------------------------
+        # if example is block processs
+        # check if process has bootep up
+        if ps_type == "block":
+            time.sleep(10)
+            self.check_process(self.bin, "start")
+            self.status = 'running'
+
+    def close(self, quit=None, log=None):
+        output = self.f_session.session.get_output_all()
+        log = self.output_log
+        with open(log, 'a') as fp:
+            fp.write(output)
+        if not quit:
+            return output
+        if self.status == 'close':
+            return output
+        if quit.startswith("SIG"):
+            cmds =['kill -TERM {0}'.format(self.process_pid), '# ']
+            output = self.d_console(cmds)
+        else:
+            cmds =[quit, '# ']
+            output = self.f_console(cmds)
+        max_try = 3
+        exec_info = None
+        # check close action is done
+        while max_try:
+            try:
+                self.check_process(self.bin, 'close')
+            except Exception as e:
+                exec_info = e
+                time.sleep(2)
+                max_try -= 1
+                continue
+            else:
+                break
+        else:
+            raise exec_info
+        self.status = 'close'
+
+        return output
+#############
+
+#############
+class TestMesonBuildSystem(TestCase):
+    #---------------------------------------------------------
+    # execute ssh session command 
+    #---------------------------------------------------------
+    def is_existed(self, path, console_name='dut_alt'):
+        ''' check if file existed '''
+        cmd = "ls {0}".format(path)
+        self.execute_cmds(cmd, con_name=console_name)
+        cmd = "echo $?"
+        output = self.execute_cmds(cmd, con_name=console_name)
+        ret = True if output == "0" else False
+        
+        return ret
+    
+    def d_console(self, cmds):
+        return self.execute_cmds(cmds, con_name='dut')
+
+    def d_a_console(self, cmds):
+        return self.execute_cmds(cmds, con_name='dut_alt')
+
+    def t_console(self, cmds):
+        return self.execute_cmds(cmds, con_name='tester')
+
+    def get_console(self, name):
+        if name == 'tester':
+            console = self.tester.send_expect
+            msg_pipe = self.tester.get_session_output
+        elif name == 'dut':
+            console = self.dut.send_expect
+            msg_pipe = self.dut.get_session_output
+        elif name == 'dut_alt':
+            console = self.dut.alt_session.send_expect
+            msg_pipe = self.dut.alt_session.session.get_output_all
+        return console, msg_pipe
+
+    def execute_cmds(self, cmds, con_name='dut'):
+        console, msg_pipe = self.get_console(con_name)
+        if len(cmds) == 0:
+            return
+        if isinstance(cmds, (str, unicode)):
+            cmds = [cmds, '# ', 5]
+        if not isinstance(cmds[0], list):
+            cmds = [cmds]
+        if len(cmds) > 1:
+            outputs = []
+        else:
+            outputs = ''
+        for item in cmds:
+            expected_items = item[1]
+            if expected_items and isinstance(expected_items, (list, tuple)):
+                check_output = True
+                expected_str = expected_items[0] or '# '
+            else:
+                check_output = False
+                expected_str = expected_items or '# '
+
+            try:
+                if len(item) == 3:
+                    timeout = int(item[2])
+                    output = console(item[0], expected_str, timeout)
+                else:
+                    #timeout = 5
+                    output = console(item[0], expected_str)
+                    
+            except TimeoutException:
+                output = msg_pipe()
+                self.logger.info(output)
+                #self.check_process_status()
+                msg = "execute '{0}' timeout".format(item[0])
+                raise TimeoutException(msg)
+            finally:
+                pass
+            # when execute "port start", LSC event will cause next command 
+            # execution fail. So wait 10s here
+            time.sleep(1)
+            if len(cmds) > 1:
+                outputs.append(output)
+            else:
+                outputs = output
+            if check_output and len(expected_items) >= 2:
+                self.logger.info(output)
+                expected_output = expected_items[1]
+                check_type = True if len(expected_items) == 2 \
+                                  else expected_items[2]
+                if check_type and expected_output in output:
+                    msg = "expected '{0}' is in output".format(expected_output)
+                    self.logger.info(msg)
+                elif not check_type and expected_output not in output:
+                    msg = "unexpected '{0}' is not in output".format(
+                                                            expected_output)
+                    self.logger.info(msg)
+                else:
+                    status = "isn't in" if check_type else "is in"
+                    msg = "[{0}] {1} output".format(expected_output, status)
+                    self.logger.error(msg)
+                    raise TimeoutException(msg)
+
+        time.sleep(2)
+        return outputs
+
+    #
+    # On tester platform, packet transmission
+    #
+    def get_pkt_len(self, pkt_type):
+        # packet size
+        frame_size = FRAME_SIZE_64
+        headers_size = sum(map(lambda x: HEADER_SIZE[x],
+                               ['eth', 'ip', pkt_type]))
+        pktlen = frame_size - headers_size
+        return pktlen
+
+    def set_stream(self, stm_names=None):
+        '''
+        '''
+        #----------------------------------------------------------------------
+        # set streams for traffic
+        pkt_configs = {
+        # UDP_1: 
+        #    Frame Data/Protocols: Ethernet 2 0800, IPv4,UDP/IP, Fixed 64.
+        #    IPv4 Header Page: Dest Address: 2.2.2.7 Src  Address: 2.2.2.3
+        #    UDP Header: Src Port: 32  Dest Port: 33
+        #
+            'UDP_1': {
+            'type': 'UDP',
+            'pkt_layers': {
+                #'ether': {'src': srcmac, 'dst': nutmac},
+                'ipv4': {'src': '2.2.2.3', 'dst': '2.2.2.7'},
+                'udp': {'src': 32, 'dst': 33},
+                'raw': {'payload': ['58'] * self.get_pkt_len('udp')}}},
+        }
+
+        # create packet for send
+        streams = []
+        for stm_name in stm_names:
+            if stm_name not in pkt_configs.keys():
+                continue
+            values = pkt_configs[stm_name]
+            savePath = os.sep.join([self.dpdk_src,
+                                    "pkt_{0}.pcap".format(stm_name)])
+            pkt_type = values.get('type')
+            pkt_layers = values.get('pkt_layers')
+            pkt = Packet(pkt_type=pkt_type)
+            for layer in pkt_layers.keys():
+                pkt.config_layer(layer, pkt_layers[layer])
+            # save a backup pcap file for debug 
+            pkt.pktgen.write_pcap(savePath)
+            # set stream for traffic
+            streams.append(pkt.pktgen.pkt)
+
+        return streams
+
+    def send_stream_by_scapy(self, **ports_topo):
+        pkts = ports_topo.get('stream')
+        if not pkts:
+            return None
+        intf = ports_topo.get('tx_intf')
+        stream_configs = ports_topo.get('stream configs')
+        count = stream_configs.get('count')
+        pkt_size = stream_configs.get('pkt_size')
+        sendp(pkts, iface=intf, count=count)
+        
+        return {'count': count,
+                'pkt_size': pkt_size,}
+
+    def traffic(self, ports_topo):
+        """
+        stream transmission on specified link topology
+        """
+        time.sleep(2)
+        result = self.send_stream_by_scapy(**ports_topo)
+        # end traffic
+        self.logger.info("complete transmission")
+
+        return result
+    
+    def run_traffic(self):
+        burst_packet = 100
+        stm_types= ['UDP_1']
+        #-----------------------------------------
+        # set traffic topology
+        # for lack ixia port, one of ixia port use normal link peer 
+        # so there set a hard code for temporarily usage
+        tx_port = self.get_peer_intf(0)
+        ports_topo = {'tx_intf': tx_port,
+                      'stream': self.set_stream(stm_types),
+                      'stream configs': {
+                            'count': burst_packet,
+                            'pkt_size': FRAME_SIZE_64,
+                            }}
+        # begin traffic checking
+        result = self.traffic(ports_topo)
+
+        return result
+    #
+    # process status on dut
+    #
+    def check_process(self, process_name, check_status):
+        # check subprocess in task space
+        cmd = "ps aux | grep -i %s | grep -v grep"%(process_name)
+        out = self.d_a_console(cmd)
+        status = True if out != "" else False
+        
+        if check_status == 'start' and not status:
+            raise_flg = True
+        elif check_status == 'close' and status:
+            raise_flg = True
+        else:
+            raise_flg = False
+
+        if raise_flg:
+            msg = "{0} {1} failed".format(process_name, check_status)
+            raise VerifyFailure(msg)
+        else:
+            msg = "{0} {1} success".format(process_name, check_status)
+            self.logger.info(msg)
+
+        return status
+    #
+    # On dut, dpdk testpmd
+    #
+    def execute_testpmd_cmd(self, cmds):
+        if len(cmds) == 0:
+            return
+        if not isinstance(cmds[0], list):
+            cmds = [cmds]
+        if len(cmds) > 1:
+            outputs = []
+        else:
+            outputs = ''
+        for item in cmds:
+            expected_items = item[1]
+            if expected_items and isinstance(expected_items, (list, tuple)):
+                check_output = True
+                expected_str = expected_items[0] or 'testpmd> '
+            else:
+                check_output = False
+                expected_str = expected_items or 'testpmd> '
+            #----------------
+            try:
+                cmd_channel = self.testpmd.execute_cmd
+                output_ch = self.testpmd.get_output
+                if len(item) == 3:
+                    timeout = int(item[2])
+                    output = cmd_channel(item[0], expected_str, timeout)
+                    output = output_ch(timeout) if not output else output
+                else:
+                    output = cmd_channel(item[0], expected_str)
+                    output = output_ch(timeout) if not output else output
+            except TimeoutException:
+                self.check_process_status()
+                msg = "execute '{0}' timeout".format(item[0])
+                raise TimeoutException(msg)
+            finally:
+                pass
+            # when execute "port start", LSC event will cause next command 
+            # execution fail. So wait 10s here
+            if 'port start' in item[0]:
+                wait_times = len(self.ports)
+                time.sleep(2*wait_times)
+            # when it is a group of command, save every output in a list
+            if len(cmds) > 1:
+                outputs.append(output)
+            else:
+                outputs = output
+            if check_output and len(expected_items) >= 2:
+                self.logger.info(output)
+                expected_output = expected_items[1]
+                check_type = True if len(expected_items) == 2 \
+                                  else expected_items[2]
+                if check_type and expected_output in output:
+                    msg = "expected '{0}' is in output".format(expected_output)
+                    self.logger.info(msg)
+                elif not check_type and expected_output not in output:
+                    msg = "unexpected '{0}' is not in output".format(
+                                                               expected_output)
+                    self.logger.info(msg)
+                else:
+                    status = "isn't in" if check_type else "is in"
+                    msg = "[{0}] {1} output".format(expected_output, status)
+                    self.logger.error(msg)
+                    raise VerifyFailure(msg)
+
+        time.sleep(2)
+        return outputs
+
+    def start_testpmd(self, eal_option=''):
+        if self.testpmd_status == 'running':
+            return
+        # boot up testpmd
+        hw_mask = '1S/2C/1T'
+        self.preset_testpmd_cmds = [['port stop all', '']]
+        
+        self.preset_testpmd(hw_mask, eal_param=eal_option)
+        self.testpmd_status = 'running'
+
+    def preset_testpmd(self, core_mask, options='', eal_param=''):
+        bin = self.testpmd_bin = self.get_exec_app_bin('testpmd')
+        if not bin:
+            msg = "testpmd doesn't existed"
+            raise VerifyFailure(msg)
+        offloadd = '0x1fbf' if self.driver == 'i40e' else '0x2203f'
+        param_opt = "--port-topology=chained --tx-offloads={0}".format(offloadd)
+        self.testpmd.start_testpmd( core_mask, param=param_opt,
+                                    eal_param=eal_param, bin_path=bin)
+        time.sleep(5)
+        ############################
+        # check if testpmd has bootep up
+        self.check_process(self.testpmd_bin, "start")
+        ############################
+        self.execute_testpmd_cmd(self.preset_testpmd_cmds)
+        self.preset_testpmd_cmds = list()
+        time.sleep(1)
+
+    def start_all_ports(self):
+        """
+        Start all the ports which the testpmd can see.
+        """
+        self.start_port("all")
+
+    def start_port(self, port):
+        """
+        Start a port which the testpmd can see.
+        """
+        cmds = []
+        cmds.append(["port start %s" % str(port), ""])
+        self.execute_testpmd_cmd(cmds)
+        time.sleep(3)
+
+    def stop_testpmd(self):
+        time.sleep(1)
+        testpmd_cmds = ['port stop all', '']
+        output = self.execute_testpmd_cmd(testpmd_cmds)
+        time.sleep(1)
+        return output
+
+    def close_testpmd(self):
+        if self.testpmd_status == 'close':
+            return None
+        output = self.stop_testpmd()
+        time.sleep(1)
+        self.testpmd.quit()
+        time.sleep(10)
+        self.check_process(self.testpmd_bin, 'close')
+        self.testpmd_status = 'close'
+        return output
+
+    def check_traffic_result(self, traffic_info, pmd_info):
+        pkt_bytes = (traffic_info['pkt_size'] - 4) * traffic_info['count']
+        pmd_rx_bytes = pmd_info['RX-bytes']
+        if pkt_bytes != pmd_info['RX-bytes']:
+            msg = os.linesep.join([
+                    "expected RX-bytes <{0}>".format(pkt_bytes),
+                    "pmd received RX-bytes <{0}>".format(pmd_rx_bytes)])
+            raise VerifyFailure(msg)
+
+    def basic_testpmd(self):
+        self.testpmd = _PmdOutput(self.dut)
+        self.start_testpmd()
+        self.start_all_ports()
+        traffic_info = self.run_traffic()
+        pmd_info = self.testpmd.get_pmd_stats(0)
+        self.check_traffic_result(traffic_info, pmd_info)
+        self.close_testpmd()
+
+    def basic_testpmd_with_secondary(self):
+        self.testpmd = _PmdOutput(self.dut)
+        self.start_testpmd()
+        self.start_all_ports()
+        # check dpdk-procinfo binary status
+        self.run_apps()
+        self.close_testpmd()
+    ###############################
+    # meson/ninja related commands
+    ###############################
+    def rebind_ports(self):
+        for port in self.ports:
+            netdev = port['port']
+            # bind to default driver
+            netdev.bind_driver('igb_uio')
+
+    def match_error_log(self, output):
+        pats =['\d+:\d+: error:',
+               'ninja.*build.*failed']
+        for pat in pats:
+            ret = re.findall(pat, output)
+            if len(ret):
+                return True
+
+    def meson_build(self):
+        if self.meson_status == "builded":
+            return
+        meson_tool = self.meson_tool
+        meson_build = self.meson_build_dir
+        if self.is_existed(meson_build):
+            self.d_a_console("rm -fr {0}".format(meson_build))
+        _cmds = [
+            'cd {0}'.format(self.dpdk_src),
+            '{0} {1}'.format(meson_tool, meson_build),
+            'cd {0}'.format(meson_build),
+            'ninja']
+        cmds = map(lambda x: [x, '# ', 50], _cmds)
+        outputs = self.d_console(cmds)
+        for output in outputs:
+            if self.match_error_log(output):
+                msg = "meson build failed"
+                raise VerifyFailure(msg)
+        else:
+            msg = "meson build successful"
+            self.logger.info(msg)
+        # check if igb_uio ko is loadable
+        igb_uio_ko = os.sep.join([meson_build, 
+                                  'kernel/linux/igb_uio/igb_uio.ko'])
+        if not self.is_existed(meson_build):
+            msg = "{0} not existed".format(igb_uio_ko)
+            raise VerifyFailure(msg)
+        cmd = "rmmod igb_uio"
+        output = self.d_console(cmd)
+        # check if ko can be loaded successful
+        cmd = "insmod {0}".format(igb_uio_ko)
+        output = self.d_console(cmd)
+        if 'fail' in output.lower() or 'error' in output.lower():
+            msg = "{0} failed to load".format(igb_uio_ko)
+            raise VerifyFailure(msg)
+        else:
+            msg = "load igb_uio successful"
+            self.logger.info(msg)
+        # rebind port 
+        self.rebind_ports()
+        # set meson builed flag
+        self.meson_status = "builded"
+
+    def rebuild_meson(self):
+        if self.meson_status == "builded":
+            return
+        self.meson_build()
+
+    def build_all_examples(self):
+        meson_tool = self.meson_tool
+        meson_build = self.meson_build_dir
+        _cmds = [
+            'cd {0}'.format(self.dpdk_src),
+            '{0} configure -Dexamples=all {1}'.format(meson_tool, meson_build),
+            'cd {0}'.format(meson_build),
+            'ninja']
+        output = self.d_console([";".join(_cmds), '# ', 120])
+        if self.match_error_log(output):
+            msg = "{0} failed to build".format(igb_uio_ko)
+            raise VerifyFailure(msg)
+        else:
+            msg = "build all examples successful"
+            self.logger.info(msg)
+
+    def check_bin_files(self):
+        bin_dir = join([self.meson_build_dir, 'examples'])
+        cmd = "ls -F {0} | grep '*'".format(bin_dir)
+        output = self.d_a_console(cmd)
+        exec_bins = output.splitlines()
+        if not len(exec_bins):
+            msg = "failed to build with -Dexamples=all, no binary files"
+            raise VerifyFailure(msg)
+        else:
+            self.logger.info('binary files')
+            self.logger.info(exec_bins)
+            
+    def check_build_all_Dexamples(self):
+        self.build_all_examples()
+        self.check_bin_files()
+            
+    def listdir(self, path):
+        cmd = "ll {0} ".format(path) + "| awk {'print $9'}"
+        output = self.execute_cmds(cmd)
+        filelist = [item for item in output.splitlines() if item.strip()]
+        return filelist
+
+    def check_bin(self, path):
+        _bin = join([path, 'bin'])
+        if not self.is_existed(_bin):
+            return False
+        _files = self.listdir(_bin)
+        # check if binary file has been installed
+        for item in _files:
+            if item.startswith('dpdk'):
+                return True
+        else:
+            return False
+
+    def check_include(self, path):
+        include = join([path, 'include'])
+        if not self.is_existed(include):
+            return False
+        _files = self.listdir(include)
+        # check if .h file has been installed
+        for item in _files:
+            if item.endswith('.h'):
+                return True
+        else:
+            return False
+
+    def check_lib(self, path):
+        lib64 = join([path, 'lib64'])
+        if not self.is_existed(lib64):
+            return False
+        _files = self.listdir(lib64)
+        # check if .a file has been installed
+        for item in _files:
+            if item.endswith('.a'):
+                break
+        else:
+            return False
+        # check if .so file has been installed
+        for item in _files:
+            if item.endswith('.so'):
+                break
+        else:
+            return False
+        
+        return True
+
+    def config_install_dir(self, build_dir):
+        install_dir = join([self.output_path, 'install_dir'])
+        if self.is_existed(install_dir):
+            self.d_a_console("rm -fr {0}".format(install_dir))
+        # install dpdk compiled target in a custom directory
+        cmd = [
+            'cd {0}'.format(os.path.dirname(build_dir)),
+            'meson configure -Dprefix={0} {1}'.format(install_dir, build_dir),
+            'cd {0}'.format(build_dir),
+            'ninja install'
+        ]
+        self.d_a_console([';'.join(cmd), '# ', 50])
+        if not self.is_existed(install_dir):
+            msg == "ninja install failed"
+            raise VerifyFailure(msg)
+        # check content inside (bin)
+        if not self.check_bin(install_dir):
+            msg == "ninja install bin failed"
+            raise VerifyFailure(msg)
+        # check content inside (header files)
+        if not self.check_include(install_dir):
+            msg == "ninja install include failed"
+            raise VerifyFailure(msg)
+        # check content inside (lib files)
+        if not self.check_lib(install_dir):
+            msg == "ninja install lib so files failed"
+            raise VerifyFailure(msg)
+        self.d_a_console(['ninja uninstall', "# ", 30])
+    ###############################
+    # binary files under examples
+    ###############################
+    def get_exec_app_bin(self, name):
+        bin_dir = os.sep.join([self.meson_build_dir, 'app'])
+        output = self.d_a_console("ls {0} -F | grep '*'".format(bin_dir))
+        exe_files = output.splitlines()
+        if len(exe_files) <= 0:
+            self.verify(False, "no executable binary !")
+        bin_path = None
+        for bin in exe_files:
+            if name in bin:
+                bin_path = os.sep.join([bin_dir, bin[:-1]])
+                break
+        return bin_path
+
+    def get_binary_configs(self, name):
+        examples = {
+        'cmdline': {
+            # command option
+            'option': '-n 1 -c 4',
+            # boot up expected string
+            'prompt': 'example>',
+            'quit': 'SIGINT'
+            },
+        
+        'distributor': {
+            # command option
+            'option': '-- -p 0x01',
+            # boot up expected string
+            'prompt': 'Starting worker on worker_id',
+            'quit': 'SIGINT'
+            },
+        
+        'ethtool': {
+            # command option
+            'option': '-c f -n 4', 
+            # boot up expected string
+            'prompt': 'EthApp>',
+            'quit': 'quit'
+            #'quit': 'SIGINT'
+            },
+        
+        'eventdev_pipeline_sw_pmd':{
+            # command option
+            'option': ('--vdev event_sw0 -- -r1 -t1 -e4 -w FF00 '
+                       '-s4 -n0 -c32 -W1000 -D'),
+            # boot up expected string
+            'prompt': 'executing scheduler',
+            'quit': 'SIGINT'
+            }, 
+        
+        'exception_path': {
+            # command option
+            'option': '-l 0-3 -n 4 -- -p 3 -i 3 -o c',
+            # boot up expected string
+            'prompt': ('APP: Lcore 3 is reading from '
+                       'tap_dpdk_03 and writing to port 1'),
+            'quit': 'SIGINT'
+            }, 
+        
+        'flow_classify': {
+            # command option
+            'option': ' -c 4 -n 4 -- --rule_ipv4={0}'.format(
+                                join([
+                                self.dpdk_src,
+                                'examples',
+                                'flow_classify',
+                                'ipv4_rules_file.txt'])),
+            # boot up expected string
+            'prompt': 'table_entry_delete succeeded',
+            'quit': 'SIGINT'
+            }, 
+        
+        'helloworld': {
+            # command option
+            'option': '',
+            # boot up expected string
+            'prompt': 'hello from core',
+            'quit': None
+            },
+
+        'ipv4_multicast': {
+            # command option
+            'option': '-l 0-3 -n 3 --socket-mem=512,512 -- -p 0x3 -q 1',
+            # boot up expected string
+            'prompt': 'IPv4_MULTICAST: entering main loop on lcore',
+            'quit': 'SIGINT'
+            },
+        
+        'ip_fragmentation': {
+            # command option
+            'option': '-l 4 -n 3 -- -p 0x03 -q 2', 
+            # boot up expected string
+            'prompt': 'IP_FRAG: entering main loop on lcore',
+            'quit': 'SIGINT'
+            },
+           # should bind 4 port at least, so ignore this binary with only 2
+           # ports
+#         'ip_pipeline': { 
+#             # command option
+#             'option': '-l 1 -p  0x0f -f ip_pipeline/config/ip_pipeline.cfg',
+#             # boot up expected string
+#             'prompt': 'pipeline> [APP] Initializing PIPELINE',
+#             'ports': 4, 
+#             'quit': 'SIGINT'
+#             },
+        
+        'ip_reassembly': {
+            # command option
+            'option': '-l 4 -n 3 -- -p 0x03 -q 2',
+            # boot up expected string
+            'prompt': 'IP_RSMBL: entering main loop on lcore',
+            'quit': 'SIGINT'
+            },
+        
+        'l2fwd': {
+            # command option
+            'option': '-l 0-3 -n 4 -- -q 8 -p 0x03',
+            # boot up expected string
+            'prompt': 'Port statistics',
+            'quit': 'SIGINT'
+            },
+
+        'l2fwd-crypto': {
+            # command option
+            'option': ('-l 1 -n 4 --vdev="crypto_null,socket_id=0,'
+                       'max_nb_sessions=128" -- -p 1 --cdev SW '
+                       '--chain CIPHER_ONLY --cipher_algo "null"'), 
+            # boot up expected string
+            'prompt': 'Crypto statistics',
+            # quit method
+            'quit': 'SIGINT'
+            },
+
+        'l2fwd-jobstats': {
+            # command option
+            'option': '-l 0-3 -n 4 -- -q 8 -p ffff -l',
+            # boot up expected string
+            'prompt': 'LCore   0: statistics',
+            'quit': 'SIGINT'
+            },
+        
+        'l2fwd-keepalive': {
+            # command option
+            'option': '-l 0-3 -n 4 -- -q 8 -p ffff -K 10', 
+            # boot up expected string
+            'prompt': 'L2FWD: entering main loop on lcore',
+            'quit': 'SIGINT'
+            },
+        
+        'l3fwd': {
+            # command option
+            'option': "-l 1,2 -n 4 -- -p 0x3 --config='(0,0,1),(1,0,2)'", 
+            # boot up expected string
+            'prompt': 'L3FWD: entering main loop on lcore',
+            'quit': 'SIGINT'
+            },
+        
+        'l3fwd-power': {
+            # command option
+            'option': ("-l 0-1 -- -p 1 -P --config='(0,0,1)' "
+                       "--no-numa --parse-ptype"), 
+            # boot up expected string
+            'prompt': 'L3FWD_POWER: entering main loop on lcore',
+            'quit': 'SIGINT'
+            },
+        
+        'l3fwd-vf': {
+            # command option
+            'option': "-l 1,2 -n 4 -- -p 0x3 --config='(0,0,1),(1,0,2)'",
+            # boot up expected string
+            'prompt': 'L3FWD: entering main loop on lcore',
+            'quit': 'SIGINT'
+            },
+        
+        'link_status_interrupt': {
+            # command option
+            'option': '-l 0-3 -n 4 -- -q 8 -p ffff', 
+            # boot up expected string
+            'prompt': 'Port statistics',
+            'quit': 'SIGINT'
+            },
+        
+        'load_balancer': {
+            # command option
+            'option': ('-l 3-7 -n 4 -- '
+                       '--rx "(0,0,3),(1,0,3)" '
+                       '--tx "(0,3),(1,3)"'
+                       ' --w "4,5,6,7" '
+                       '--lpm "1.0.0.0/24=>0; 1.0.1.0/24=>1;"'
+                       ' --pos-lb 29'), 
+            # boot up expected string
+            'prompt': 'Logical core 7 \(worker 3\) main loop',
+            'quit': 'SIGINT'
+            },
+
+        'multi_process': [
+            {   'sub': 'simple_mp',
+                # command option
+                'option': '-c 3 --proc-type=primary',
+                # boot up expected string
+                'prompt': 'simple_mp >',
+                'quit': 'SIGINT'
+            },
+        
+            {   'sub': 'symmetric_mp',
+                 # command option
+                'option': (' -l 1 -n 4 --proc-type=auto -- '
+                           '-p 3 --num-procs=4 --proc-id=0'),
+                # boot up expected string
+                'prompt': 'APP: Finished Process Init',
+                'quit': 'SIGINT'}
+            ],
+
+        'netmap_compat': {
+            # command option
+            'option': '-c 0x1e -n 4 -- -i 0', 
+            # boot up expected string
+            'prompt': 'Bridge up and running',
+            'quit': 'SIGINT'
+            },
+
+        'packet_ordering': {
+            # command option
+            'option': '-- -p 0x03', 
+            # boot up expected string
+            'prompt': 'REORDERAPP: worker_thread\(\) started on lcore',
+            'quit': 'SIGINT'
+            },
+
+        'performance-thread': {
+            # command option
+            'option': ("-l 0-3 -n 2 -- -P -p 3 "
+                       "--rx='(0,0,0,0)(1,0,1,1)' --tx='(2,0)(3,1)'"),
+            # boot up expected string
+            'prompt': 'L3FWD: entering main tx loop on lcore',
+            'quit': 'SIGINT'
+            },
+        
+        'ptpclient': {
+            # command option
+            'option': '-l 1 -n 4 -- -p 0x1 -T 0', 
+            # boot up expected string
+            'prompt': 'Core 1 Waiting for SYNC packets',
+            'quit': 'SIGINT'
+            },
+        
+        'qos_meter': {
+            # command option
+            'option': '-c 0x01 -- -p 0x03', 
+            # boot up expected string
+            'prompt': 'METER: Low level srTCM config',
+            'quit': 'SIGINT'
+            },
+
+        'rxtx_callbacks': {
+            # command option
+            'option': '-l 1 -n 4', 
+            # boot up expected string
+            'prompt': 'Core 1 forwarding packets',
+            'quit': 'SIGINT'
+            },
+        
+        'service_cores': {
+            # command option
+            'option': '', 
+            # boot up expected string
+            'prompt': 'Profile: Mid-Low Performance',
+            'quit': 'SIGINT'
+            },
+        
+        'server_node_efd': {
+            # command option
+            'option': '-- -p 0x03 -n 1 -f 1', 
+            # boot up expected string
+            'prompt': 'Core 1 displaying statistics',
+            'quit': 'SIGINT'
+            },
+        
+        'skeleton': {
+            # command option
+            'option': '-l 1 -n 4', 
+            # boot up expected string
+            'prompt': 'Core 1 forwarding packets',
+            'quit': 'SIGINT'
+            },
+
+        'timer':{
+            # command option
+            'option': '', 
+            # boot up expected string
+            'prompt': 'Starting mainloop on core',
+            'quit': 'SIGINT'
+            },
+        
+        'vhost': {
+            # command option
+            'option': '-c f -n 4  -- -p 1',
+            # boot up expected string
+            'prompt': 'VHOST_DATA: Procesing on Core',
+            'preset': ("sed -i -e 's/MAX_QUEUES 128$/MAX_QUEUES 256/' "
+                       "vhost/main.c"),
+            'quit': 'SIGINT'
+            },
+        
+        'vhost_scsi': {
+            # command option
+            'option': '-m 1024', 
+            # boot up expected string
+            'prompt': 'VHOST_CONFIG: bind to',
+            'quit': 'SIGINT'
+            },
+        
+        'vmdq': {
+            # command option
+            'option': '-n 4 -c 0x01 -- -p 0x03 --nb-pools 8', 
+            # boot up expected string
+            'prompt': 'vmdq queue base: 64 pool base 1',
+            'quit': 'SIGINT'
+            },
+        
+        'vmdq_dcb': {
+            # command option
+            'option': '-l 0-3 -n 4 -- -p 0x3 --nb-pools 32 --nb-tcs 4', 
+            # boot up expected string
+            'prompt': 'Configured vmdq pool num',
+            'quit': 'SIGINT'
+            },
+        
+        'vm_power_manager': {
+            # command option
+            'option': ' -c 0x3 -n 4',
+            # boot up expected string
+            'prompt': 'vmpower> ',
+            'quit': 'quit'
+            },
+        #----------------------------------
+        # app binary 
+        # run with testpmd
+        'pdump': {
+            # command option
+            'option': (" -- --pdump  "
+                       "'port=0,queue=*,tx-dev=/tmp/pdump-tx.pcap'"),
+            # boot up expected string
+            # 2018.0504 change it temporarily for 18.05 rc1's isssue
+            #'prompt': 'Creating pcap-backed ethdev on numa socket',
+            'prompt': 'Port 2 MAC',
+            'quit': 'SIGINT'
+            },
+
+        'proc_info': {
+            # command option
+            'option': " -- --stats",
+            # boot up expected string
+            'prompt': 'NIC statistics for port',
+            'quit': None
+            },
+        #----------------------------------
+        'quota_watermark': [
+            {'sub': "qw",
+             'preset': ("sed -i 's/^\(.*RING_SIZE\)\s*[[:digit:]]*/\1 64/'"
+                        " examples/quota_watermark/include/conf.h"),
+            # command option
+            'option': " -c 0x0f -n 4 -- -p 0x3",
+            # boot up expected string
+            'prompt': 'USER1: receive_stage',
+            'quit': 'SIGINT'},
+
+            {'sub': "qwctl",
+            # command option
+            'option': " -c 1 -n 4 --proc-type=secondary",
+            # boot up expected string
+            'prompt': 'qwctl> ',
+            'quit': 'SIGINT'}
+            ]
+        }
+
+        if name in examples.keys():
+            return examples[name]
+        else:
+            return None
+
+    def get_special_examples(self, name):
+        ignore_examples = [
+                'ethtool',
+                'multi_process',
+                'netmap_compat',
+                'l2fwd-cat',
+                'performance-thread',
+                'quota_watermark',
+                'server_node_efd',
+                'vm_power_manager']
+        return name in ignore_examples
+
+    def run_apps(self):
+        bins = {}
+        results = {}
+        session_exd = self.new_dut_session()
+        appsDir = join([self.meson_build_dir, "app"])
+        for appName in sorted(os.listdir(appsDir)):
+            msg = "check {0}".format(appName)
+            self.logger.info(msg)
+            if appName not in ['proc-info', 'pdump']:
+                continue
+            
+            item = join([appsDir, appName])
+            if os.path.isfile(item):
+                continue
+            configs = self.get_binary_configs(appName)
+            if not configs:
+                continue
+            if isinstance(configs, dict):
+                configs = [configs]
+            
+            for config in configs:
+                if not config:
+                    continue
+                sub = config.get('sub')
+                subAppName = appName + '/' + sub if sub else appName
+                option = config['option']
+                prompt = config['prompt']
+                quit = config['quit']
+                timeout = config.get('timeout', 15)
+                if quit != 'SIGINT':
+                    pass
+                binary_file = self.get_exec_app_bin(appName)
+                psInfo = {
+                      'fore_session': session_exd,
+                      'daemon_session': self.dut_alt_session,
+                      'name': subAppName,
+                      'target_src': appsDir,
+                      'target_name': self.target_name,
+                      'binary_type': 'app',
+                      'binary_file': binary_file,
+                      'ignore_compile': True,
+                      'output': self.output_path,
+                      'logger': self.logger}
+                #--------------------------------------------
+                try:
+                    app = ExecBinProcess(**psInfo)
+                    if quit == 'non-block' or quit == None:
+                        ps_type = 'non-block'
+                    else:
+                        ps_type = 'block'
+                    app.start(option, prompt, ps_type, timeout)
+                except Exception as e:
+                    if app:
+                        results[subAppName.replace('/', '@')] = [app.bin, 
+                                                                 'failed']
+                    self.logger.info(traceback.format_exc())
+                finally:
+                    if app:
+                        app.close(quit=quit)
+                        app = None
+        #---------------------------------------------
+        session_exd.close()
+        # show results
+        if results:
+            log = join([self.output_path, 'bin.log'])
+            status = pformat(results)
+            self.logger.error(status)
+            with open(log, 'wb') as fp:
+                fp.write(status)
+            msg = "Exception happened"
+            raise VerifyFailure(msg)
+
+    def run_examples(self):
+        examplesDir = join([self.dpdk_src, "examples"])
+        bins = {}
+        results = {}
+        for exampleName in sorted(os.listdir(examplesDir)):
+            # for debug
+            #if exampleName not in ['helloworld', 'l2fwd']:
+            if self.get_special_examples(exampleName):
+                continue
+            
+            item = join([examplesDir, exampleName])
+            if os.path.isfile(item):
+                continue
+            configs = self.get_binary_configs(exampleName)
+            if not configs:
+                continue
+            if isinstance(configs, dict):
+                configs = [configs]
+            
+            for config in configs:
+                if not config:
+                    continue
+                sub = config.get('sub')
+                subExampleName = exampleName + '/' + sub if sub else exampleName
+                option = config['option']
+                prompt = config['prompt']
+                quit = config['quit']
+                timeout = config.get('timeout', 15)
+                if quit != 'SIGINT':
+                    pass
+                psInfo = {
+                    'fore_session': self.dut_session,
+                    'daemon_session': self.dut_alt_session,
+                    'name': subExampleName,
+                    #'target_src': examplesDir,
+                    'target_src': self.meson_build_dir,
+                    'target_name': self.target_name,
+                    'compile_type': self.compile_type,
+                    'output': self.output_path,
+                    'logger': self.logger}
+                #--------------------------------------------
+                example = None
+                try:
+                    example = ExecBinProcess(**psInfo)
+                    if quit == 'non-block' or quit == None:
+                        ps_type = 'non-block'
+                    else:
+                        ps_type = 'block'
+                    example.start(option, prompt, ps_type, timeout)
+                except Exception as e:
+                    if example:
+                        results[exampleName.replace('/', '@')] = [example.bin,
+                                                                  'failed']
+                    self.logger.info(traceback.format_exc())
+                finally:
+                    if example:
+                        example.close(quit=quit)
+                        example = None
+                break
+            # used for debug
+            if self.is_deubg:
+                break
+        #---------------------------------------------
+        if results:
+            log = join([self.output_path, 'bin.log'])
+            status = pformat(results)
+            self.logger.error(status)
+            with open(log, 'wb') as fp:
+                fp.write(status)
+            msg = "Exception happened"
+            raise VerifyFailure(msg)
+
+    def run_examples_multi_process(self):
+        examplesDir = join([self.dpdk_src, "examples"])
+        bins = {}
+        results = {}
+        session_exd = self.new_dut_session()
+        for exampleName in sorted(os.listdir(examplesDir)):
+            # for debug
+            if exampleName not in ['quota_watermark']:
+                continue
+
+            item = join([examplesDir, exampleName])
+            if os.path.isfile(item):
+                continue
+            configs = self.get_binary_configs(exampleName)
+            if not configs:
+                continue
+            if not isinstance(configs, list):
+                continue
+            
+            config, config_2 = configs
+            
+            # primary process
+            sub = config.get('sub')
+            subExampleName = exampleName + '/' + sub
+            option = config['option']
+            prompt = config['prompt']
+            quit = config['quit']
+            timeout = config.get('timeout', 15)
+            psInfo = {
+                  'fore_session': self.dut_session,
+                  'daemon_session': self.dut_alt_session,
+                  'name': subExampleName,
+                  'target_src': examplesDir,
+                  'target_name': self.target_name,
+                  'output': self.output_path,
+                  'logger': self.logger}
+            # secondary process
+            sub_2 = config_2.get('sub')
+            subExampleName_2 = exampleName + '/' + sub_2
+            option_2 = config_2['option']
+            prompt_2 = config_2['prompt']
+            quit_2 = config_2['quit']
+            timeout_2 = config_2.get('timeout', 15)
+            psInfo_2 = {
+                  'fore_session': session_exd,
+                  'daemon_session': self.dut_alt_session,
+                  'name': subExampleName_2,
+                  'target_src': examplesDir,
+                  'target_name': self.target_name,
+                  'ignore_compile': True,
+                  'output': self.output_path,
+                  'logger': self.logger}
+            #--------------------------------------------
+            try:
+                # primary process
+                example = ExecBinProcess(**psInfo)
+                if quit == 'non-block' or quit == None:
+                    ps_type = 'non-block'
+                else:
+                    ps_type = 'block'
+                example.start(option, prompt, ps_type, timeout)
+                # secondary process
+                example_2 = ExecBinProcess(**psInfo_2)
+                if quit_2 == 'non-block' or quit_2 == None:
+                    ps_type_2 = 'non-block'
+                else:
+                    ps_type_2 = 'block'
+                example_2.start(option_2, prompt_2, ps_type_2, timeout_2)
+            except Exception as e:
+                # secondary process
+                if example_2:
+                    results[subExampleName_2.replace('/', '@')] = \
+                                                    [example_2.bin, 'failed']
+                # primary process
+                if example:
+                    results[subExampleName.replace('/', '@')] = \
+                                                    [example.bin, 'failed']
+                self.logger.info(traceback.format_exc())
+            finally:
+                # secondary process
+                if example_2:
+                    example_2.close(quit=quit_2)
+                    example_2 = None
+                # primary process
+                if example:
+                    example.close(quit=quit)
+                    example = None
+            # used for debug
+            if self.is_deubg:
+                break
+        #---------------------------------------------
+        session_exd.close()
+        if results:
+            log = join([self.output_path, 'bin.log'])
+            status = pformat(results)
+            self.logger.error(status)
+            with open(log, 'wb') as fp:
+                fp.write(status)
+            msg = "Exception happened"
+            raise VerifyFailure(msg)
+
+    def check_examples_without_Dexamples_option(self):
+        bins = {
+            'ethtool',
+            'multi-process',
+            'netmap_compat',
+            'performance-thread',
+            'quota_watermark',
+            'server_node_efd',
+            'vm_power_manager'}
+
+    #
+    # framework related methods/parameter
+    #
+    @property
+    def dut_alt_session(self):
+        return self.dut.alt_session
+    
+    @property
+    def dut_session(self):
+        return self.dut.session
+
+    @property
+    def driver(self):
+        return self.kdriver
+
+    def get_peer_intf(self, dut_port_id):
+        tester_port_id = self.tester.get_local_port(dut_port_id)
+        tx_port = self.tester.get_interface(tester_port_id)
+        return tx_port
+    
+    def set_target_dir(self):
+        return self.dut.base_dir
+    
+    def new_dut_session(self):
+        return self.dut.new_session()
+
+    @property
+    def is_deubg(self):
+        return self._enable_debug
+
+    @property
+    def ports(self):
+        return self.dut.ports_info
+    #
+    # Test cases.
+    #
+    def set_up_all(self):
+        """
+        Run before each test suite
+        """
+        #------------------------------------------------------------------
+        # initialize ports topology
+        dut_ports = self.dut.get_ports()
+        self.verify(len(dut_ports) >= 1, "Insufficient ports")
+        self.dpdk_src = self.set_target_dir()
+        self.target_name = self.dut.target
+        #------------------------------------------------------------------
+        # meson build status
+        self.meson_status = "unbuild"
+        self.compile_type = "Dexamples options"
+        self.meson_tool = "meson"
+        self.meson_build_dir = os.sep.join([os.path.dirname(self.dpdk_src),
+                                        "meson_build"])
+        self.testpmd_status = None
+        #------------------------------------------------------------------
+        # used for save log 
+        # get output path
+        if self.logger.log_path.startswith(os.sep):
+            self.output_path = self.logger.log_path
+        else:
+            cur_path = os.path.dirname(
+                                os.path.dirname(os.path.realpath(__file__)))
+            self.output_path = join([cur_path, self.logger.log_path])
+
+    def tear_down_all(self):
+        """ Run after each test suite. """
+        pass
+
+    def set_up(self):
+        """ Run before each test case. """
+        pass
+
+    def tear_down(self):
+        """ Run after each test case. """
+        pass
+
+    def test_basic_build(self):
+        self.meson_build()
+
+    def test_basic_configure(self):
+        self.rebuild_meson()
+        self.config_install_dir(self.meson_build_dir)
+        self.meson_status = "unbuild" # TBD,clear meson_build folder for bug 5108
+
+    def test_basic_testpmd(self):
+        self.rebuild_meson()
+        self.basic_testpmd()
+
+    def test_binary_under_apps(self):
+        self.rebuild_meson()
+        self.basic_testpmd_with_secondary()
+
+    def test_build_with_Dexamples_all_option(self):
+        self.rebuild_meson()
+        self.check_build_all_Dexamples()
+
+    def test_example_with_Dexamples_option(self):
+        self.rebuild_meson()
+        self.run_examples()
-- 
1.9.3



More information about the dts mailing list