style(hoststack): Apply black formatting 80/42980/1
authorVratko Polak <vrpolak@cisco.com>
Mon, 19 May 2025 11:05:32 +0000 (13:05 +0200)
committerVratko Polak <vrpolak@cisco.com>
Mon, 19 May 2025 11:05:32 +0000 (13:05 +0200)
Change-Id: I4cb0b78d2883d42b04945d0112efc009edb3f3d2
Signed-off-by: Vratko Polak <vrpolak@cisco.com>
resources/libraries/python/HoststackUtil.py

index cb3970f..2855938 100644 (file)
@@ -21,13 +21,14 @@ from robot.api import logger
 from resources.libraries.python.Constants import Constants
 from resources.libraries.python.DUTSetup import DUTSetup
 from resources.libraries.python.model.ExportResult import (
-    export_hoststack_results
+    export_hoststack_results,
 )
 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
 from resources.libraries.python.ssh import exec_cmd, exec_cmd_no_error
 from resources.libraries.python.topology import Topology
 
-class HoststackUtil():
+
+class HoststackUtil:
     """Utilities for Host Stack tests."""
 
     @staticmethod
@@ -58,29 +59,31 @@ class HoststackUtil():
             'args' - command arguments.
         :rtype: dict
         """
-        proto = vpp_echo_attributes[u"uri_protocol"]
-        addr = vpp_echo_attributes[u"uri_ip4_addr"]
-        port = vpp_echo_attributes[u"uri_port"]
+        proto = vpp_echo_attributes["uri_protocol"]
+        addr = vpp_echo_attributes["uri_ip4_addr"]
+        port = vpp_echo_attributes["uri_port"]
         vpp_echo_cmd = {}
-        vpp_echo_cmd[u"name"] = u"vpp_echo"
-        vpp_echo_cmd[u"args"] = f"{vpp_echo_attributes[u'role']} " \
-            f"socket-name {vpp_echo_attributes[u'app_api_socket']} " \
-            f"{vpp_echo_attributes[u'json_output']} " \
-            f"uri {proto}://{addr}/{port} " \
-            f"nthreads {vpp_echo_attributes[u'nthreads']} " \
-            f"mq-size {vpp_echo_attributes[u'mq_size']} " \
-            f"nclients {vpp_echo_attributes[u'nclients']} " \
-            f"quic-streams {vpp_echo_attributes[u'quic_streams']} " \
-            f"time {vpp_echo_attributes[u'time']} " \
-            f"fifo-size {vpp_echo_attributes[u'fifo_size']} " \
-            f"TX={vpp_echo_attributes[u'tx_bytes']} " \
-            f"RX={vpp_echo_attributes[u'rx_bytes']}"
-        if vpp_echo_attributes[u"rx_results_diff"]:
-            vpp_echo_cmd[u"args"] += u" rx-results-diff"
-        if vpp_echo_attributes[u"tx_results_diff"]:
-            vpp_echo_cmd[u"args"] += u" tx-results-diff"
-        if vpp_echo_attributes[u"use_app_socket_api"]:
-            vpp_echo_cmd[u"args"] += u" use-app-socket-api"
+        vpp_echo_cmd["name"] = "vpp_echo"
+        vpp_echo_cmd["args"] = (
+            f"{vpp_echo_attributes['role']} "
+            f"socket-name {vpp_echo_attributes['app_api_socket']} "
+            f"{vpp_echo_attributes['json_output']} "
+            f"uri {proto}://{addr}/{port} "
+            f"nthreads {vpp_echo_attributes['nthreads']} "
+            f"mq-size {vpp_echo_attributes['mq_size']} "
+            f"nclients {vpp_echo_attributes['nclients']} "
+            f"quic-streams {vpp_echo_attributes['quic_streams']} "
+            f"time {vpp_echo_attributes['time']} "
+            f"fifo-size {vpp_echo_attributes['fifo_size']} "
+            f"TX={vpp_echo_attributes['tx_bytes']} "
+            f"RX={vpp_echo_attributes['rx_bytes']}"
+        )
+        if vpp_echo_attributes["rx_results_diff"]:
+            vpp_echo_cmd["args"] += " rx-results-diff"
+        if vpp_echo_attributes["tx_results_diff"]:
+            vpp_echo_cmd["args"] += " tx-results-diff"
+        if vpp_echo_attributes["use_app_socket_api"]:
+            vpp_echo_cmd["args"] += " use-app-socket-api"
         return vpp_echo_cmd
 
     @staticmethod
@@ -98,40 +101,49 @@ class HoststackUtil():
         :rtype: dict
         """
         iperf3_cmd = {}
-        iperf3_cmd[u"env_vars"] = f"VCL_CONFIG={Constants.REMOTE_FW_DIR}/" \
-            f"{Constants.RESOURCES_TPL_VCL}/" \
-            f"{iperf3_attributes[u'vcl_config']}"
-        if iperf3_attributes[u"ld_preload"]:
+        iperf3_cmd["env_vars"] = (
+            f"VCL_CONFIG={Constants.REMOTE_FW_DIR}/"
+            f"{Constants.RESOURCES_TPL_VCL}/"
+            f"{iperf3_attributes['vcl_config']}"
+        )
+        if iperf3_attributes["ld_preload"]:
             ldpreload = HoststackUtil._get_ldpreload_path(node)
-            iperf3_cmd[u"env_vars"] += f" LD_PRELOAD={ldpreload}"
-        if iperf3_attributes[u'transparent_tls']:
-            iperf3_cmd[u"env_vars"] += u" LDP_ENV_TLS_TRANS=1"
-
-        json_results = u" --json" if iperf3_attributes[u'json'] else u""
-        ip_address = f" {iperf3_attributes[u'ip_address']}" if u"ip_address" \
-                     in iperf3_attributes else u""
-        iperf3_cmd[u"name"] = u"iperf3"
-        iperf3_cmd[u"args"] = f"--{iperf3_attributes[u'role']}{ip_address} " \
-                              f"--interval 0{json_results} " \
-                              f"--version{iperf3_attributes[u'ip_version']}"
-
-        if iperf3_attributes[u"role"] == u"server":
-            iperf3_cmd[u"args"] += u" --one-off"
+            iperf3_cmd["env_vars"] += f" LD_PRELOAD={ldpreload}"
+        if iperf3_attributes["transparent_tls"]:
+            iperf3_cmd["env_vars"] += " LDP_ENV_TLS_TRANS=1"
+
+        json_results = " --json" if iperf3_attributes["json"] else ""
+        ip_address = (
+            f" {iperf3_attributes['ip_address']}"
+            if "ip_address" in iperf3_attributes
+            else ""
+        )
+        iperf3_cmd["name"] = "iperf3"
+        iperf3_cmd["args"] = (
+            f"--{iperf3_attributes['role']}{ip_address} "
+            f"--interval 0{json_results} "
+            f"--version{iperf3_attributes['ip_version']}"
+        )
+
+        if iperf3_attributes["role"] == "server":
+            iperf3_cmd["args"] += " --one-off"
         else:
-            iperf3_cmd[u"args"] += u" --get-server-output"
-            if u"parallel" in iperf3_attributes:
-                iperf3_cmd[u"args"] += \
-                    f" --parallel {iperf3_attributes[u'parallel']}"
-            if u"time" in iperf3_attributes:
-                iperf3_cmd[u"args"] += \
-                    f" --time {iperf3_attributes[u'time']}"
-            if iperf3_attributes[u"udp"]:
-                iperf3_cmd[u"args"] += u" --udp"
-                iperf3_cmd[u"args"] += \
-                    f" --bandwidth {iperf3_attributes[u'bandwidth']}"
-            if iperf3_attributes[u"length"] > 0:
-                iperf3_cmd[u"args"] += \
-                    f" --length {iperf3_attributes[u'length']}"
+            iperf3_cmd["args"] += " --get-server-output"
+            if "parallel" in iperf3_attributes:
+                iperf3_cmd[
+                    "args"
+                ] += f" --parallel {iperf3_attributes['parallel']}"
+            if "time" in iperf3_attributes:
+                iperf3_cmd["args"] += f" --time {iperf3_attributes['time']}"
+            if iperf3_attributes["udp"]:
+                iperf3_cmd["args"] += " --udp"
+                iperf3_cmd[
+                    "args"
+                ] += f" --bandwidth {iperf3_attributes['bandwidth']}"
+            if iperf3_attributes["length"] > 0:
+                iperf3_cmd[
+                    "args"
+                ] += f" --length {iperf3_attributes['length']}"
         return iperf3_cmd
 
     @staticmethod
@@ -147,8 +159,9 @@ class HoststackUtil():
         PapiSocketExecutor.run_cli_cmd(node, cmd)
 
     @staticmethod
-    def set_hoststack_quic_crypto_engine(node, quic_crypto_engine,
-                                         fail_on_error=False):
+    def set_hoststack_quic_crypto_engine(
+        node, quic_crypto_engine, fail_on_error=False
+    ):
         """Set the Hoststack QUIC crypto engine on node
 
         :param node: Node to enable/disable HostStack.
@@ -156,17 +169,19 @@ class HoststackUtil():
         :type node: dict
         :type quic_crypto_engine: str
         """
-        vpp_crypto_engines = {u"openssl", u"native", u"ipsecmb"}
-        if quic_crypto_engine == u"nocrypto":
-            logger.trace(u"No QUIC crypto engine.")
+        vpp_crypto_engines = {"openssl", "native", "ipsecmb"}
+        if quic_crypto_engine == "nocrypto":
+            logger.trace("No QUIC crypto engine.")
             return
 
         if quic_crypto_engine in vpp_crypto_engines:
-            cmds = [u"quic set crypto api vpp",
-                    f"set crypto handler aes-128-gcm {quic_crypto_engine}",
-                    f"set crypto handler aes-256-gcm {quic_crypto_engine}"]
-        elif quic_crypto_engine == u"picotls":
-            cmds = [u"quic set crypto api picotls"]
+            cmds = [
+                "quic set crypto api vpp",
+                f"set crypto handler aes-128-gcm {quic_crypto_engine}",
+                f"set crypto handler aes-256-gcm {quic_crypto_engine}",
+            ]
+        elif quic_crypto_engine == "picotls":
+            cmds = ["quic set crypto api picotls"]
         else:
             raise ValueError(f"Unknown QUIC crypto_engine {quic_crypto_engine}")
 
@@ -186,13 +201,21 @@ class HoststackUtil():
         :type node: dict
         :type program_name: str
         """
-        cmd = f"sh -c \'cat /tmp/{program_name}_stdout.log\'"
-        stdout_log, _ = exec_cmd_no_error(node, cmd, sudo=True, \
-            message=f"Get {program_name} stdout log failed!")
-
-        cmd = f"sh -c \'cat /tmp/{program_name}_stderr.log\'"
-        stderr_log, _ = exec_cmd_no_error(node, cmd, sudo=True, \
-            message=f"Get {program_name} stderr log failed!")
+        cmd = f"sh -c 'cat /tmp/{program_name}_stdout.log'"
+        stdout_log, _ = exec_cmd_no_error(
+            node,
+            cmd,
+            sudo=True,
+            message=f"Get {program_name} stdout log failed!",
+        )
+
+        cmd = f"sh -c 'cat /tmp/{program_name}_stderr.log'"
+        stderr_log, _ = exec_cmd_no_error(
+            node,
+            cmd,
+            sudo=True,
+            message=f"Get {program_name} stderr log failed!",
+        )
 
         return stdout_log, stderr_log
 
@@ -205,15 +228,17 @@ class HoststackUtil():
         :type node: dict
         :type program: dict
         """
-        program_name = program[u"name"]
-        program_stdout_log, program_stderr_log = \
-            HoststackUtil._get_hoststack_test_program_logs(node,
-                                                           program_name)
+        program_name = program["name"]
+        program_stdout_log, program_stderr_log = (
+            HoststackUtil._get_hoststack_test_program_logs(node, program_name)
+        )
         if len(program_stdout_log) == 0 and len(program_stderr_log) == 0:
             logger.trace(f"Retrying {program_name} log retrieval")
-            program_stdout_log, program_stderr_log = \
-               HoststackUtil._get_hoststack_test_program_logs(node,
-                                                              program_name)
+            program_stdout_log, program_stderr_log = (
+                HoststackUtil._get_hoststack_test_program_logs(
+                    node, program_name
+                )
+            )
         return program_stdout_log, program_stderr_log
 
     @staticmethod
@@ -236,19 +261,22 @@ class HoststackUtil():
         :rtype: dict
         """
         nginx_cmd = dict()
-        nginx_cmd[u"env_vars"] = f"VCL_CONFIG={Constants.REMOTE_FW_DIR}/" \
-                                 f"{Constants.RESOURCES_TPL_VCL}/" \
-                                 f"{nginx_attributes[u'vcl_config']}"
-        if nginx_attributes[u"ld_preload"]:
+        nginx_cmd["env_vars"] = (
+            f"VCL_CONFIG={Constants.REMOTE_FW_DIR}/"
+            f"{Constants.RESOURCES_TPL_VCL}/"
+            f"{nginx_attributes['vcl_config']}"
+        )
+        if nginx_attributes["ld_preload"]:
             ldpreload = HoststackUtil._get_ldpreload_path(node)
-            nginx_cmd[u"env_vars"] += f" LD_PRELOAD={ldpreload}"
-        if nginx_attributes[u'transparent_tls']:
-            nginx_cmd[u"env_vars"] += u" LDP_ENV_TLS_TRANS=1"
-
-        nginx_cmd[u"name"] = u"nginx"
-        nginx_cmd[u"path"] = f"{nginx_ins_dir}nginx-{nginx_version}/sbin/"
-        nginx_cmd[u"args"] = f"-c {nginx_ins_dir}/" \
-                             f"nginx-{nginx_version}/conf/nginx.conf"
+            nginx_cmd["env_vars"] += f" LD_PRELOAD={ldpreload}"
+        if nginx_attributes["transparent_tls"]:
+            nginx_cmd["env_vars"] += " LDP_ENV_TLS_TRANS=1"
+
+        nginx_cmd["name"] = "nginx"
+        nginx_cmd["path"] = f"{nginx_ins_dir}nginx-{nginx_version}/sbin/"
+        nginx_cmd["args"] = (
+            f"-c {nginx_ins_dir}/" f"nginx-{nginx_version}/conf/nginx.conf"
+        )
         return nginx_cmd
 
     @staticmethod
@@ -268,35 +296,40 @@ class HoststackUtil():
         :rtype: int
         :raises RuntimeError: If node subtype is not a DUT or startup failed.
         """
-        if node[u"type"] != u"DUT":
-            raise RuntimeError(u"Node type is not a DUT!")
+        if node["type"] != "DUT":
+            raise RuntimeError("Node type is not a DUT!")
 
-        program_name = program[u"name"]
+        program_name = program["name"]
         DUTSetup.kill_program(node, program_name, namespace)
 
-        if namespace == u"default":
-            shell_cmd = u"sh -c"
+        if namespace == "default":
+            shell_cmd = "sh -c"
         else:
             shell_cmd = f"ip netns exec {namespace} sh -c"
 
-        env_vars = f"{program[u'env_vars']} " if u"env_vars" in program else u""
-        args = program[u"args"]
-        program_path = program.get(u"path", u"")
+        env_vars = f"{program['env_vars']} " if "env_vars" in program else ""
+        args = program["args"]
+        program_path = program.get("path", "")
         # NGINX used `worker_cpu_affinity` in configuration file
-        taskset_cmd = u"" if program_name == u"nginx" else \
-                                             f"taskset --cpu-list {core_list}"
-        cmd = f"nohup {taskset_cmd} {shell_cmd} \'{env_vars} " \
-              f"{program_path}{program_name} {args} >/tmp/{program_name}_" \
-              f"stdout.log 2>/tmp/{program_name}_stderr.log &\'"
+        taskset_cmd = (
+            "" if program_name == "nginx" else f"taskset --cpu-list {core_list}"
+        )
+        cmd = (
+            f"nohup {taskset_cmd} {shell_cmd} '{env_vars} "
+            f"{program_path}{program_name} {args} >/tmp/{program_name}_"
+            f"stdout.log 2>/tmp/{program_name}_stderr.log &'"
+        )
         try:
             exec_cmd_no_error(node, cmd, sudo=True)
             return DUTSetup.get_pid(node, program_name)[0]
         except RuntimeError:
-            stdout_log, stderr_log = \
-                HoststackUtil.get_hoststack_test_program_logs(node,
-                                                              program)
-            raise RuntimeError(f"Start {program_name} failed!\nSTDERR:\n" \
-                               f"{stderr_log}\nSTDOUT:\n{stdout_log}")
+            stdout_log, stderr_log = (
+                HoststackUtil.get_hoststack_test_program_logs(node, program)
+            )
+            raise RuntimeError(
+                f"Start {program_name} failed!\nSTDERR:\n"
+                f"{stderr_log}\nSTDOUT:\n{stdout_log}"
+            )
         return None
 
     @staticmethod
@@ -310,13 +343,15 @@ class HoststackUtil():
         :type program: dict
         :type pid: int
         """
-        program_name = program[u"name"]
-        if program_name == u"nginx":
-            cmd = u"nginx -s quit"
-            errmsg = u"Quit nginx failed!"
+        program_name = program["name"]
+        if program_name == "nginx":
+            cmd = "nginx -s quit"
+            errmsg = "Quit nginx failed!"
         else:
-            cmd = f'if [ -n "$(ps {pid} | grep {program_name})" ] ; ' \
-                f'then kill -s SIGTERM {pid}; fi'
+            cmd = (
+                f'if [ -n "$(ps {pid} | grep {program_name})" ] ; '
+                f"then kill -s SIGTERM {pid}; fi"
+            )
             errmsg = f"Kill {program_name} ({pid}) failed!"
 
         exec_cmd_no_error(node, cmd, message=errmsg, sudo=True)
@@ -331,8 +366,9 @@ class HoststackUtil():
         sleep(sleep_time + 1)
 
     @staticmethod
-    def hoststack_test_program_finished(node, program_pid, program,
-                                        other_node, other_program):
+    def hoststack_test_program_finished(
+        node, program_pid, program, other_node, other_program
+    ):
         """Wait for the specified HostStack test program process to complete.
 
         :param node: DUT node.
@@ -347,58 +383,69 @@ class HoststackUtil():
         :type other_program: dict
         :raises RuntimeError: If node subtype is not a DUT.
         """
-        if node[u"type"] != u"DUT":
-            raise RuntimeError(u"Node type is not a DUT!")
-        if other_node[u"type"] != u"DUT":
-            raise RuntimeError(u"Other node type is not a DUT!")
+        if node["type"] != "DUT":
+            raise RuntimeError("Node type is not a DUT!")
+        if other_node["type"] != "DUT":
+            raise RuntimeError("Other node type is not a DUT!")
 
         cmd = f"sh -c 'strace -qqe trace=none -p {program_pid}'"
         try:
             exec_cmd(node, cmd, sudo=True)
         except:
             sleep(180)
-            if u"client" in program[u"args"]:
-                role = u"client"
+            if "client" in program["args"]:
+                role = "client"
             else:
-                role = u"server"
-            program_stdout, program_stderr = \
+                role = "server"
+            program_stdout, program_stderr = (
                 HoststackUtil.get_hoststack_test_program_logs(node, program)
+            )
             if len(program_stdout) > 0:
-                logger.debug(f"{program[u'name']} {role} stdout log:\n"
-                             f"{program_stdout}")
+                logger.debug(
+                    f"{program['name']} {role} stdout log:\n"
+                    f"{program_stdout}"
+                )
             else:
-                logger.debug(f"Empty {program[u'name']} {role} stdout log :(")
+                logger.debug(f"Empty {program['name']} {role} stdout log :(")
             if len(program_stderr) > 0:
-                logger.debug(f"{program[u'name']} stderr log:\n"
-                             f"{program_stderr}")
+                logger.debug(
+                    f"{program['name']} stderr log:\n" f"{program_stderr}"
+                )
             else:
-                logger.debug(f"Empty {program[u'name']} stderr log :(")
-            if u"client" in other_program[u"args"]:
-                role = u"client"
+                logger.debug(f"Empty {program['name']} stderr log :(")
+            if "client" in other_program["args"]:
+                role = "client"
             else:
-                role = u"server"
-            program_stdout, program_stderr = \
-                HoststackUtil.get_hoststack_test_program_logs(other_node,
-                                                              other_program)
+                role = "server"
+            program_stdout, program_stderr = (
+                HoststackUtil.get_hoststack_test_program_logs(
+                    other_node, other_program
+                )
+            )
             if len(program_stdout) > 0:
-                logger.debug(f"{other_program[u'name']} {role} stdout log:\n"
-                             f"{program_stdout}")
+                logger.debug(
+                    f"{other_program['name']} {role} stdout log:\n"
+                    f"{program_stdout}"
+                )
             else:
-                logger.debug(f"Empty {other_program[u'name']} "
-                             f"{role} stdout log :(")
+                logger.debug(
+                    f"Empty {other_program['name']} " f"{role} stdout log :("
+                )
             if len(program_stderr) > 0:
-                logger.debug(f"{other_program[u'name']} {role} stderr log:\n"
-                             f"{program_stderr}")
+                logger.debug(
+                    f"{other_program['name']} {role} stderr log:\n"
+                    f"{program_stderr}"
+                )
             else:
-                logger.debug(f"Empty {other_program[u'name']} "
-                             f"{role} stderr log :(")
+                logger.debug(
+                    f"Empty {other_program['name']} " f"{role} stderr log :("
+                )
             raise
         # Wait a bit for stdout/stderr to be flushed to log files
         sleep(1)
 
     @staticmethod
-    def analyze_hoststack_test_program_output(
-            node, role, nsim_attr, program):
+    def analyze_hoststack_test_program_output(node, role, nsim_attr, program):
         """Gather HostStack test program output and check for errors.
 
         The [defer_fail] return bool is used instead of failing immediately
@@ -421,57 +468,61 @@ class HoststackUtil():
         :rtype: bool, str
         :raises RuntimeError: If node subtype is not a DUT.
         """
-        if node[u"type"] != u"DUT":
-            raise RuntimeError(u"Node type is not a DUT!")
+        if node["type"] != "DUT":
+            raise RuntimeError("Node type is not a DUT!")
 
-        program_name = program[u"name"]
-        program_stdout, program_stderr = \
+        program_name = program["name"]
+        program_stdout, program_stderr = (
             HoststackUtil.get_hoststack_test_program_logs(node, program)
+        )
 
-        env_vars = f"{program[u'env_vars']} " if u"env_vars" in program else u""
-        program_cmd = f"{env_vars}{program_name} {program[u'args']}"
+        env_vars = f"{program['env_vars']} " if "env_vars" in program else ""
+        program_cmd = f"{env_vars}{program_name} {program['args']}"
         test_results = f"Test Results of '{program_cmd}':\n"
 
-        if nsim_attr[u"output_nsim_enable"] or \
-            nsim_attr[u"xc_nsim_enable"]:
-            if nsim_attr[u"output_nsim_enable"]:
-                feature_name = u"output"
+        if nsim_attr["output_nsim_enable"] or nsim_attr["xc_nsim_enable"]:
+            if nsim_attr["output_nsim_enable"]:
+                feature_name = "output"
             else:
-                feature_name = u"cross-connect"
-            test_results += \
-                f"NSIM({feature_name}): delay " \
-                f"{nsim_attr[u'delay_in_usec']} usecs, " \
-                f"avg-pkt-size {nsim_attr[u'average_packet_size']}, " \
-                f"bandwidth {nsim_attr[u'bw_in_bits_per_second']} " \
-                f"bits/sec, pkt-drop-rate {nsim_attr[u'packets_per_drop']} " \
+                feature_name = "cross-connect"
+            test_results += (
+                f"NSIM({feature_name}): delay "
+                f"{nsim_attr['delay_in_usec']} usecs, "
+                f"avg-pkt-size {nsim_attr['average_packet_size']}, "
+                f"bandwidth {nsim_attr['bw_in_bits_per_second']} "
+                f"bits/sec, pkt-drop-rate {nsim_attr['packets_per_drop']} "
                 f"pkts/drop\n"
+            )
 
-        if u"error" in program_stderr.lower():
+        if "error" in program_stderr.lower():
             test_results += f"ERROR DETECTED:\n{program_stderr}"
             return (True, test_results)
         if not program_stdout:
             test_results += f"\nNo {program} test data retrieved!\n"
-            ls_stdout, _ = exec_cmd_no_error(node, u"ls -l /tmp/*.log",
-                                             sudo=True)
+            ls_stdout, _ = exec_cmd_no_error(
+                node, "ls -l /tmp/*.log", sudo=True
+            )
             test_results += f"{ls_stdout}\n"
             return (True, test_results)
-        if program[u"name"] == u"vpp_echo":
-            if u"JSON stats" in program_stdout and \
-                    u'"has_failed": "0"' in program_stdout:
-                json_start = program_stdout.find(u"{")
-                json_end = program_stdout.find(u',\n  "closing"')
+        if program["name"] == "vpp_echo":
+            if (
+                "JSON stats" in program_stdout
+                and '"has_failed": "0"' in program_stdout
+            ):
+                json_start = program_stdout.find("{")
+                json_end = program_stdout.find(',\n  "closing"')
                 json_results = f"{program_stdout[json_start:json_end]}\n}}"
                 program_json = json.loads(json_results)
                 export_hoststack_results(
                     bandwidth=program_json["rx_bits_per_second"],
-                    duration=float(program_json["time"])
+                    duration=float(program_json["time"]),
                 )
             else:
-                test_results += u"Invalid test data output!\n" + program_stdout
+                test_results += "Invalid test data output!\n" + program_stdout
                 return (True, test_results)
-        elif program[u"name"] == u"iperf3":
+        elif program["name"] == "iperf3":
             test_results += program_stdout
-            program_json = json.loads(program_stdout)[u"intervals"][0][u"sum"]
+            program_json = json.loads(program_stdout)["intervals"][0]["sum"]
             try:
                 retransmits = program_json["retransmits"]
             except KeyError:
@@ -479,11 +530,10 @@ class HoststackUtil():
             export_hoststack_results(
                 bandwidth=program_json["bits_per_second"],
                 duration=program_json["seconds"],
-                retransmits=retransmits
+                retransmits=retransmits,
             )
         else:
-            test_results += u"Unknown HostStack Test Program!\n" + \
-                            program_stdout
+            test_results += "Unknown HostStack Test Program!\n" + program_stdout
             return (True, program_stdout)
         return (False, json.dumps(program_json))