diff --git a/tests/common/platform/interface_utils.py b/tests/common/platform/interface_utils.py index 45a7dcd4b06..b166fbfa46b 100644 --- a/tests/common/platform/interface_utils.py +++ b/tests/common/platform/interface_utils.py @@ -1,6 +1,7 @@ """ Helper script for checking status of interfaces + This script contains re-usable functions for checking status of interfaces on SONiC. """ @@ -44,40 +45,31 @@ def check_interface_status(dut, asic_index, interfaces, xcvr_skip_list): asichost = dut.asic_instance(asic_index) namespace = asichost.get_asic_namespace() logging.info("Check interface status using cmd 'show interface'") - #TODO Remove this logic when minigraph facts supports namespace in multi_asic - mg_ports = dut.minigraph_facts(host=dut.hostname)["ansible_facts"]["minigraph_ports"] - if asic_index is not None: - portmap = get_port_map(dut, asic_index) - # Check if the interfaces of this AISC is present in mg_ports - interface_list = {k:v for k, v in portmap.items() if k in mg_ports} - mg_ports = interface_list + ports = get_port_map(dut, asic_index) output = dut.command("show interface description") intf_status = parse_intf_status(output["stdout_lines"][2:]) check_intf_presence_command = 'show interface transceiver presence {}' for intf in interfaces: - expected_oper = "up" if intf in mg_ports else "down" - expected_admin = "up" if intf in mg_ports else "down" + expected_oper = "up" if intf in ports else "down" + expected_admin = "up" if intf in ports else "down" if intf not in intf_status: logging.info("Missing status for interface %s" % intf) return False if intf_status[intf]["oper"] != expected_oper: - logging.info("Oper status of interface %s is %s, expected '%s'" % (intf, intf_status[intf]["oper"], - expected_oper)) + logging.info("Oper status of interface %s is %s, expected '%s'" % (intf, intf_status[intf]["oper"], expected_oper)) return False if intf_status[intf]["admin"] != expected_admin: - logging.info("Admin status of interface %s is %s, expected '%s'" % (intf, intf_status[intf]["admin"], - expected_admin)) + logging.info("Admin status of interface %s is %s, expected '%s'" % (intf, intf_status[intf]["admin"], expected_admin)) return False # Cross check the interface SFP presence status - if intf not in xcvr_skip_list[dut.hostname]: + if xcvr_skip_list and intf not in xcvr_skip_list[dut.hostname]: check_presence_output = dut.command(check_intf_presence_command.format(intf)) presence_list = check_presence_output["stdout_lines"][2].split() assert intf in presence_list, "Wrong interface name in the output: %s" % str(presence_list) assert 'Present' in presence_list, "Status is not expected, presence status: %s" % str(presence_list) - logging.info("Check interface status using the interface_facts module") - intf_facts = dut.interface_facts(up_ports=mg_ports, namespace=namespace)["ansible_facts"] + intf_facts = dut.interface_facts(up_ports=ports, namespace=namespace)["ansible_facts"] down_ports = intf_facts["ansible_interface_link_down_ports"] if len(down_ports) != 0: logging.info("Some interfaces are down: %s" % str(down_ports)) @@ -85,6 +77,7 @@ def check_interface_status(dut, asic_index, interfaces, xcvr_skip_list): return True + # This API to check the interface information actoss all front end ASIC's def check_all_interface_information(dut, interfaces, xcvr_skip_list): for asic_index in dut.get_frontend_asic_ids(): @@ -100,6 +93,7 @@ def check_all_interface_information(dut, interfaces, xcvr_skip_list): return True + # This API to check the interface information per asic. def check_interface_information(dut, asic_index, interfaces, xcvr_skip_list): if not all_transceivers_detected(dut, asic_index, interfaces, xcvr_skip_list): @@ -111,6 +105,7 @@ def check_interface_information(dut, asic_index, interfaces, xcvr_skip_list): return True + def get_port_map(dut, asic_index=None): """ @summary: Get the port mapping info from the DUT diff --git a/tests/common/plugins/sanity_check/checks.py b/tests/common/plugins/sanity_check/checks.py index 38156386cab..cee862a3d74 100644 --- a/tests/common/plugins/sanity_check/checks.py +++ b/tests/common/plugins/sanity_check/checks.py @@ -135,10 +135,12 @@ def _check_interfaces_on_dut(*args, **kwargs): check_result = {"failed": True, "check_item": "interfaces", "host": dut.hostname} for asic in dut.asics: ip_interfaces = [] + phy_interfaces = [] cfg_facts = asic.config_facts(host=dut.hostname, source="persistent", verbose=False)['ansible_facts'] - phy_interfaces = [k for k, v in cfg_facts["PORT"].items() if - "admin_status" in v and v["admin_status"] == "up"] + if "PORT" in cfg_facts: + phy_interfaces = [k for k, v in cfg_facts["PORT"].items() if + "admin_status" in v and v["admin_status"] == "up"] if "PORTCHANNEL_INTERFACE" in cfg_facts: ip_interfaces = cfg_facts["PORTCHANNEL_INTERFACE"].keys() if "VLAN_INTERFACE" in cfg_facts: diff --git a/tests/platform_tests/mellanox/test_check_sfp_presence.py b/tests/platform_tests/mellanox/test_check_sfp_presence.py index 2ed37e17896..96f7861f9d1 100644 --- a/tests/platform_tests/mellanox/test_check_sfp_presence.py +++ b/tests/platform_tests/mellanox/test_check_sfp_presence.py @@ -3,7 +3,6 @@ """ import logging import os -import json import pytest from tests.common.fixtures.conn_graph_facts import conn_graph_facts @@ -13,11 +12,12 @@ pytest.mark.topology('any') ] + def test_check_sfp_presence(duthosts, rand_one_dut_hostname, conn_graph_facts): """This test case is to check SFP presence status with CLI and sysfs. """ duthost = duthosts[rand_one_dut_hostname] - ports_config = json.loads(duthost.command("sudo sonic-cfggen -d --var-json PORT")["stdout"]) + duthost.command("sudo sonic-cfggen -d --var-json PORT") check_intf_presence_command = 'show interface transceiver presence {}' logging.info("Use show interface status information") diff --git a/tests/platform_tests/mellanox/test_check_sfp_using_ethtool.py b/tests/platform_tests/mellanox/test_check_sfp_using_ethtool.py index b7def59b132..ea6f87eec5c 100644 --- a/tests/platform_tests/mellanox/test_check_sfp_using_ethtool.py +++ b/tests/platform_tests/mellanox/test_check_sfp_using_ethtool.py @@ -5,10 +5,11 @@ https://github.com/Azure/SONiC/blob/master/doc/pmon/sonic_platform_test_plan.md """ import logging -import os import json import pytest from tests.common.fixtures.conn_graph_facts import conn_graph_facts +from tests.platform_tests.sfp.util import get_dev_conn +from tests.common.platform.interface_utils import get_port_map, check_interface_status from tests.common.mellanox_data import SPC3_HWSKUS from check_hw_mgmt_service import check_hw_management_service @@ -17,18 +18,23 @@ pytest.mark.topology('any') ] -def test_check_sfp_using_ethtool(duthosts, rand_one_dut_hostname, conn_graph_facts, tbinfo): + +def test_check_sfp_using_ethtool(duthosts, rand_one_dut_hostname, conn_graph_facts, tbinfo, enum_frontend_asic_index): """This test case is to check SFP using the ethtool. """ duthost = duthosts[rand_one_dut_hostname] - ports_config = json.loads(duthost.command("sudo sonic-cfggen -d --var-json PORT")["stdout"]) - + ports_config = {} + ports_config_output = duthost.command("sudo sonic-cfggen -d --var-json PORT")["stdout"] + portmap, dev_conn = get_dev_conn(duthost, conn_graph_facts, enum_frontend_asic_index) + if ports_config_output: + # in the case of zero ports the json output can be none + ports_config = json.loads(ports_config_output) logging.info("Use the ethtool to check SFP information") if duthost.facts["hwsku"] in SPC3_HWSKUS: lanes_divider = 8 else: lanes_divider = 4 - for intf in conn_graph_facts["device_conn"][duthost.hostname]: + for intf in dev_conn: intf_lanes = ports_config[intf]["lanes"] sfp_id = int(intf_lanes.split(",")[0])/lanes_divider + 1 @@ -46,9 +52,8 @@ def test_check_sfp_using_ethtool(duthosts, rand_one_dut_hostname, conn_graph_fac "Unexpected line %s in %s" % (line, str(ethtool_sfp_output["stdout_lines"])) logging.info("Check interface status") - mg_facts = duthost.get_extended_minigraph_facts(tbinfo) - intf_facts = duthost.interface_facts(up_ports=mg_facts["minigraph_ports"])["ansible_facts"] - assert len(intf_facts["ansible_interface_link_down_ports"]) == 0, \ - "Some interfaces are down: %s" % str(intf_facts["ansible_interface_link_down_ports"]) + for asic_index in duthost.get_frontend_asic_ids(): + interface_list = get_port_map(duthost, asic_index) + assert check_interface_status(duthost, asic_index, interface_list, []), "Not all interfaces are up" check_hw_management_service(duthost) diff --git a/tests/platform_tests/sfp/test_sfputil.py b/tests/platform_tests/sfp/test_sfputil.py index 19487e246b4..1d15c0379fc 100644 --- a/tests/platform_tests/sfp/test_sfputil.py +++ b/tests/platform_tests/sfp/test_sfputil.py @@ -14,6 +14,7 @@ from util import parse_eeprom from util import parse_output from util import get_dev_conn +from tests.common.platform.interface_utils import get_port_map, check_interface_status from tests.common.utilities import skip_version cmd_sfp_presence = "sudo sfputil show presence" @@ -119,10 +120,9 @@ def test_check_sfputil_reset(duthosts, enum_rand_one_per_hwsku_frontend_hostname assert parsed_presence[intf] == "Present", "Interface presence is not 'Present'" logging.info("Check interface status") - mg_facts = duthost.get_extended_minigraph_facts(tbinfo) - intf_facts = duthost.interface_facts(up_ports=mg_facts["minigraph_ports"])["ansible_facts"] - assert len(intf_facts["ansible_interface_link_down_ports"]) == 0, \ - "Some interfaces are down: {}".format(intf_facts["ansible_interface_link_down_ports"]) + for asic_index in duthost.get_frontend_asic_ids(): + interface_list = get_port_map(duthost, asic_index) + assert check_interface_status(duthost, asic_index, interface_list, []), "Not all interfaces are up" def test_check_sfputil_low_power_mode(duthosts, enum_rand_one_per_hwsku_frontend_hostname, enum_frontend_asic_index, conn_graph_facts, tbinfo, xcvr_skip_list): diff --git a/tests/platform_tests/sfp/util.py b/tests/platform_tests/sfp/util.py index f0cc2b12e2e..7aeb7d3ca6d 100644 --- a/tests/platform_tests/sfp/util.py +++ b/tests/platform_tests/sfp/util.py @@ -33,15 +33,12 @@ def parse_eeprom(output_lines): def get_dev_conn(duthost, conn_graph_facts, asic_index): - dev_conn = conn_graph_facts["device_conn"][duthost.hostname] - # Get the interface pertaining to that asic portmap = get_port_map(duthost, asic_index) logging.info("Got portmap {}".format(portmap)) - if asic_index is not None: - # Check if the interfaces of this AISC is present in conn_graph_facts - dev_conn = {k: v for k, v in portmap.items() if k in conn_graph_facts["device_conn"][duthost.hostname]} - logging.info("ASIC {} interface_list {}".format(asic_index, dev_conn)) + # Check if the interfaces of this AISC is present in conn_graph_facts + dev_conn = {k: v for k, v in portmap.items() if k in conn_graph_facts["device_conn"][duthost.hostname]} + logging.info("ASIC {} interface_list {}".format(asic_index, dev_conn)) return portmap, dev_conn \ No newline at end of file diff --git a/tests/platform_tests/test_sequential_restart.py b/tests/platform_tests/test_sequential_restart.py index d8f03889c07..869e6ab684c 100644 --- a/tests/platform_tests/test_sequential_restart.py +++ b/tests/platform_tests/test_sequential_restart.py @@ -93,15 +93,11 @@ def test_restart_swss(duthosts, rand_one_dut_hostname, enum_frontend_asic_index, """ duthost = duthosts[rand_one_dut_hostname] all_interfaces = conn_graph_facts["device_conn"][duthost.hostname] - - if enum_frontend_asic_index is not None: - # Get the interface pertaining to that asic - interface_list = get_port_map(duthost, enum_frontend_asic_index) - - # Check if the interfaces of this AISC is present in conn_graph_facts - new_intf_dict = {k:v for k, v in interface_list.items() if k in all_interfaces} - all_interfaces = new_intf_dict - logging.info("ASIC {} interface_list {}".format(enum_frontend_asic_index, all_interfaces)) + interface_list = get_port_map(duthost, enum_frontend_asic_index) + # Check if the interfaces of this AISC is present in conn_graph_facts + new_intf_dict = {k:v for k, v in interface_list.items() if k in all_interfaces} + all_interfaces = new_intf_dict + logging.info("ASIC {} interface_list {}".format(enum_frontend_asic_index, all_interfaces)) restart_service_and_check(localhost, duthost, enum_frontend_asic_index, "swss", all_interfaces, xcvr_skip_list) diff --git a/tests/snmp/conftest.py b/tests/snmp/conftest.py index 3877404cc47..f9dd3229638 100644 --- a/tests/snmp/conftest.py +++ b/tests/snmp/conftest.py @@ -1,4 +1,5 @@ import pytest +from tests.common.platform.interface_utils import get_port_map from tests.common.utilities import wait_until @pytest.fixture(scope="module", autouse=True) @@ -16,3 +17,15 @@ def pytest_addoption(parser): default=False, help="Set percentage difference for snmp test", type=int) + +@pytest.fixture(scope='function') +def skip_if_no_ports(duthosts, enum_rand_one_per_hwsku_frontend_hostname): + """ + Fixture that skips test execution in case dut doesn't have data ports + """ + duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname] + for asic_index in duthost.get_frontend_asic_ids(): + interface_list = get_port_map(duthost, asic_index) + if not interface_list: + pytest.skip("This test is not supported as there are no data ports in dut") + diff --git a/tests/snmp/test_snmp_default_route.py b/tests/snmp/test_snmp_default_route.py index 6dc4c60d3d5..d3bf52789ed 100644 --- a/tests/snmp/test_snmp_default_route.py +++ b/tests/snmp/test_snmp_default_route.py @@ -10,7 +10,8 @@ @pytest.mark.bsl -def test_snmp_default_route(duthosts, enum_rand_one_per_hwsku_frontend_hostname, localhost, creds_all_duts, tbinfo): +def test_snmp_default_route(duthosts, enum_rand_one_per_hwsku_frontend_hostname, localhost, + creds_all_duts, tbinfo, skip_if_no_ports): """compare the snmp facts between observed states and target state""" duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname] diff --git a/tests/snmp/test_snmp_lldp.py b/tests/snmp/test_snmp_lldp.py index 031ef4f403a..55029b741ff 100644 --- a/tests/snmp/test_snmp_lldp.py +++ b/tests/snmp/test_snmp_lldp.py @@ -1,6 +1,5 @@ import pytest import re -from tests.common.helpers.snmp_helpers import get_snmp_facts pytestmark = [ pytest.mark.topology('any'), @@ -38,12 +37,15 @@ def test_snmp_lldp(duthosts, enum_rand_one_per_hwsku_hostname, localhost, creds_ pytest.skip("LLDP not supported on supervisor node") hostip = duthost.host.options['inventory_manager'].get_host(duthost.hostname).vars['ansible_host'] - snmp_facts = get_snmp_facts(localhost, host=hostip, version="v2c", community=creds_all_duts[duthost]["snmp_rocommunity"], wait=True)['ansible_facts'] - mg_facts = {} - for asic_id in duthost.get_asic_ids(): - mg_facts_ns = duthost.asic_instance(asic_id).get_extended_minigraph_facts(tbinfo)['minigraph_neighbors'] - if mg_facts_ns is not None: - mg_facts.update(mg_facts_ns) + snmp_facts = localhost.snmp_facts(host=hostip, version="v2c", community=creds_all_duts[duthost]["snmp_rocommunity"])['ansible_facts'] + for asic in duthost.asics: + lldp_nei = [] + cfg_facts = asic.config_facts(host=duthost.hostname, + source="persistent", verbose=False)['ansible_facts'] + if "PORT" in cfg_facts: + for port, port_info_dict in cfg_facts["PORT"].items(): + if re.search('ARISTA', port_info_dict['description']): + lldp_nei.append(port) print snmp_facts['snmp_lldp'] for k in ['lldpLocChassisIdSubtype', 'lldpLocChassisId', 'lldpLocSysName', 'lldpLocSysDesc']: @@ -65,12 +67,6 @@ def test_snmp_lldp(duthosts, enum_rand_one_per_hwsku_hostname, localhost, creds_ assert snmp_facts['snmp_lldp'][k] assert "No Such Object currently exists" not in snmp_facts['snmp_lldp'][k] - minigraph_lldp_nei = [] - for k, v in mg_facts.items(): - if "server" not in v['name'].lower(): - minigraph_lldp_nei.append(k) - print minigraph_lldp_nei - # Check if lldpRemTable is present active_intf = [] for k, v in snmp_facts['snmp_interfaces'].items(): @@ -86,7 +82,7 @@ def test_snmp_lldp(duthosts, enum_rand_one_per_hwsku_hostname, localhost, creds_ active_intf.append(k) print "lldpRemTable: ", active_intf - assert len(active_intf) >= len(minigraph_lldp_nei) * 0.8 + assert len(active_intf) >= len(lldp_nei) * 0.8 # skip neighbors that do not send chassis information via lldp lldp_facts= {} diff --git a/tests/snmp/test_snmp_loopback.py b/tests/snmp/test_snmp_loopback.py index 069e231850c..75078e864da 100644 --- a/tests/snmp/test_snmp_loopback.py +++ b/tests/snmp/test_snmp_loopback.py @@ -34,7 +34,7 @@ def get_snmp_output(ip, duthost, nbr, creds_all_duts): @pytest.mark.bsl -def test_snmp_loopback(duthosts, enum_rand_one_per_hwsku_frontend_hostname, nbrhosts, tbinfo, localhost, creds_all_duts): +def test_snmp_loopback(duthosts, enum_rand_one_per_hwsku_frontend_hostname, skip_if_no_ports, nbrhosts, tbinfo, localhost, creds_all_duts): """ Test SNMP query to DUT over loopback IP - Send SNMP query over loopback IP from one of the BGP Neighbors diff --git a/tests/telemetry/test_telemetry.py b/tests/telemetry/test_telemetry.py index d0e7344c300..46d802553f1 100644 --- a/tests/telemetry/test_telemetry.py +++ b/tests/telemetry/test_telemetry.py @@ -4,6 +4,7 @@ import re import pytest +from tests.common.platform.interface_utils import get_port_map from pkg_resources import parse_version from tests.common.helpers.assertions import pytest_assert from tests.common.utilities import wait_until, wait_tcp_connection @@ -26,6 +27,7 @@ SUBMODE_ON_CHANGE = 1 SUBMODE_SAMPLE = 2 + # Helper functions def get_dict_stdout(gnmi_out, certs_out): """ Extracts dictionary from redis output. @@ -38,6 +40,7 @@ def get_dict_stdout(gnmi_out, certs_out): params_dict = dict(zip(key_list, value_list)) return params_dict + def get_list_stdout(cmd_out): out_list = [] for x in cmd_out: @@ -45,6 +48,7 @@ def get_list_stdout(cmd_out): out_list.append(result) return out_list + def setup_telemetry_forpyclient(duthost): """ Set client_auth=false. This is needed for pyclient to sucessfully set up channel with gnmi server. Restart telemetry process @@ -57,6 +61,7 @@ def setup_telemetry_forpyclient(duthost): else: logger.info('client auth is false. No need to restart telemetry') + def generate_client_cli(duthost, method=METHOD_GET, xpath="COUNTERS/Ethernet0", target="COUNTERS_DB", subscribe_mode=SUBSCRIBE_MODE_STREAM, submode=SUBMODE_SAMPLE, intervalms=0, update_count=3): """Generate the py_gnmicli command line based on the given params. """ @@ -67,11 +72,13 @@ def generate_client_cli(duthost, method=METHOD_GET, xpath="COUNTERS/Ethernet0", cmd += " --subscribe_mode {0} --submode {1} --interval {2} --update_count {3}".format(subscribe_mode, submode, intervalms, update_count) return cmd + def assert_equal(actual, expected, message): """Helper method to compare an expected value vs the actual value. """ pytest_assert(actual == expected, "{0}. Expected {1} vs actual {2}".format(message, expected, actual)) + @pytest.fixture(scope="module", autouse=True) def verify_telemetry_dockerimage(duthosts, rand_one_dut_hostname): """If telemetry docker is available in image then return true @@ -84,6 +91,7 @@ def verify_telemetry_dockerimage(duthosts, rand_one_dut_hostname): if not (len(matching) > 0): pytest.skip("docker-sonic-telemetry is not part of the image") + @pytest.fixture def setup_streaming_telemetry(duthosts, rand_one_dut_hostname, localhost, ptfhost): """ @@ -104,12 +112,26 @@ def setup_streaming_telemetry(duthosts, rand_one_dut_hostname, localhost, ptfho file_exists = ptfhost.stat(path="/gnxi/gnmi_cli_py/py_gnmicli.py") pytest_assert(file_exists["stat"]["exists"] is True) + def skip_201911_and_older(duthost): """ Skip the current test if the DUT version is 201911 or older. """ if parse_version(duthost.kernel_version) <= parse_version('4.9.0'): pytest.skip("Test not supported for 201911 images. Skipping the test") + +@pytest.fixture(scope='function') +def skip_if_no_data_port(duthosts, rand_one_dut_hostname): + """ + Fixture that skips test execution in case dut doesn't have data port Ethernet0 + """ + duthost = duthosts[rand_one_dut_hostname] + for asic_index in duthost.get_frontend_asic_ids(): + interface_list = get_port_map(duthost, asic_index) + if "Ethernet0" not in interface_list: + pytest.skip("This test is not supported as there is no data port Ethernet0 in dut") + + # Test functions def test_config_db_parameters(duthosts, rand_one_dut_hostname): """Verifies required telemetry parameters from config_db. @@ -137,6 +159,7 @@ def test_config_db_parameters(duthosts, rand_one_dut_hostname): server_crt_expected = "/etc/sonic/telemetry/streamingtelemetryserver.cer" pytest_assert(str(value) == server_crt_expected, "'server_crt' value is not '{}'".format(server_crt_expected)) + def test_telemetry_enabledbydefault(duthosts, rand_one_dut_hostname): """Verify telemetry should be enabled by default """ @@ -153,7 +176,8 @@ def test_telemetry_enabledbydefault(duthosts, rand_one_dut_hostname): status_expected = "enabled"; pytest_assert(str(v) == status_expected, "Telemetry feature is not enabled") -def test_telemetry_ouput(duthosts, rand_one_dut_hostname, ptfhost, setup_streaming_telemetry, localhost): + +def test_telemetry_ouput(duthosts, rand_one_dut_hostname, ptfhost, setup_streaming_telemetry, localhost, skip_if_no_data_port): """Run pyclient from ptfdocker and show gnmi server outputself. """ duthost = duthosts[rand_one_dut_hostname] @@ -169,6 +193,7 @@ def test_telemetry_ouput(duthosts, rand_one_dut_hostname, ptfhost, setup_streami inerrors_match = re.search("SAI_PORT_STAT_IF_IN_ERRORS", result) pytest_assert(inerrors_match is not None, "SAI_PORT_STAT_IF_IN_ERRORS not found in gnmi_output") + def test_osbuild_version(duthosts, rand_one_dut_hostname, ptfhost, localhost): """ Test osbuild/version query. """ @@ -181,6 +206,7 @@ def test_osbuild_version(duthosts, rand_one_dut_hostname, ptfhost, localhost): assert_equal(len(re.findall('"build_version": "sonic\.', result)), 1, "build_version value at {0}".format(result)) assert_equal(len(re.findall('sonic\.NA', result, flags=re.IGNORECASE)), 0, "invalid build_version value at {0}".format(result)) + def test_sysuptime(duthosts, rand_one_dut_hostname, ptfhost, setup_streaming_telemetry, localhost): """ @summary: Run pyclient from ptfdocker and test the dataset 'system uptime' to check @@ -226,7 +252,8 @@ def test_sysuptime(duthosts, rand_one_dut_hostname, ptfhost, setup_streaming_tel if system_uptime_2nd - system_uptime_1st < 10: pytest.fail("The value of system uptime was not updated correctly.") -def test_virtualdb_table_streaming(duthosts, rand_one_dut_hostname, ptfhost, localhost): + +def test_virtualdb_table_streaming(duthosts, rand_one_dut_hostname, skip_if_no_data_port, ptfhost, localhost): """Run pyclient from ptfdocker to stream a virtual-db query multiple times. """ logger.info('start virtual db sample streaming testing')