From f85fa1ebc35f6b25f19765ce6a070b4af4bf2777 Mon Sep 17 00:00:00 2001 From: sanmalho Date: Thu, 14 Jan 2021 17:06:10 -0500 Subject: [PATCH 1/6] Optimizing dut selection fixtures in pytest_generate_tests This is a fix for issue #2790 - pytest_generate_tests in tests/conftest.py takes much more time than before The reason for the issue was that creating the TestbedInfo takes 1-9 seconds, and was part of pytest_generate_tests. Since pytest_generate_tests is called for all the tests/fixtures, this was adding a long time when trying to execute many tests. For some of the other dut selection fixtures we were also getting variables for the duts from the inventory files - which also takes a long time - adding to the execution delay. To fix is to use create the TestbedInfo and getting the variables from the inventory files for all the DUTS only once - by storing it in global variables. If these global variables are not set, then we would set them. Thus, creating TestbedInfo and getting variables only once per pytest run --- tests/common/helpers/dut_utils.py | 11 ++++-- tests/conftest.py | 66 ++++++++++++++++++++----------- 2 files changed, 50 insertions(+), 27 deletions(-) diff --git a/tests/common/helpers/dut_utils.py b/tests/common/helpers/dut_utils.py index 00304a94cb..4855538e3f 100644 --- a/tests/common/helpers/dut_utils.py +++ b/tests/common/helpers/dut_utils.py @@ -1,5 +1,8 @@ from tests.common.utilities import get_host_visible_vars +def is_supervisor_node_in_vars(dut_vars): + if 'type' in dut_vars and dut_vars['type'] == 'supervisor': + return True def is_supervisor_node(inv_files, hostname): """Check if the current node is a supervisor node in case of multi-DUT. @@ -11,11 +14,11 @@ def is_supervisor_node(inv_files, hostname): the inventory, and it is 'supervisor', then return True, else return False. In future, we can change this logic if possible to derive it from the DUT. """ - node_type = get_host_visible_vars(inv_files, hostname, variable='type') - if node_type and node_type == 'supervisor': - return True - return False + dut_vars = get_host_visible_vars(inv_files, hostname) + return is_supervisor_node_in_vars(dut_vars) +def is_frontend_node_in_vars(dut_vars): + return not is_supervisor_node_in_vars(dut_vars) def is_frontend_node(inv_files, hostname): """Check if the current node is a frontend node in case of multi-DUT. diff --git a/tests/conftest.py b/tests/conftest.py index 03e6943178..a264c44dda 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -22,7 +22,9 @@ from tests.common.utilities import get_host_vars from tests.common.utilities import get_host_visible_vars from tests.common.helpers.dut_utils import is_supervisor_node, is_frontend_node +from tests.common.utilities import get_inventory_files, get_host_visible_vars from tests.common.cache import FactsCache +from tests.common.helpers.dut_utils import is_supervisor_node_in_vars, is_frontend_node_in_vars from tests.common.connections import ConsoleHost @@ -614,7 +616,8 @@ def generate_params_frontend_hostname(request, duts_in_testbed, tbname): frontend_duts = [] inv_files = get_inventory_files(request) for dut in duts_in_testbed: - if is_frontend_node(inv_files, dut): + dut_vars = duts_vars[dut] + if is_frontend_node_in_vars(dut_vars): frontend_duts.append(dut) assert len(frontend_duts) > 0, \ "Test selected require at-least one frontend node, " \ @@ -622,16 +625,19 @@ def generate_params_frontend_hostname(request, duts_in_testbed, tbname): return frontend_duts -def generate_params_frontend_hostname_rand_per_hwsku(request, duts_in_testbed, tbname): - frontend_hosts = generate_params_frontend_hostname(request, duts_in_testbed, tbname) +def generate_params_frontend_hostname_rand_per_hwsku(request, duts_in_testbed, tbname, duts_vars): + frontend_hosts = generate_params_frontend_hostname(request, duts_in_testbed, tbname, duts_vars) inv_files = get_inventory_files(request) # Create a list of hosts per hwsku host_hwskus = {} for a_host in frontend_hosts: - a_host_hwsku = get_host_visible_vars(inv_files, a_host, variable='hwsku') - if not a_host_hwsku: + host_vars = duts_vars[a_host] + if 'hwsku' in host_vars: + a_host_hwsku = host_vars['hwsku'] + else: # Lets try 'sonic_hwsku' as well - a_host_hwsku = get_host_visible_vars(inv_files, a_host, variable='sonic_hwsku') + if 'sonic_hwsku' in host_vars: + a_host_hwsku = host_vars['sonic_hwsku'] if a_host_hwsku: if a_host_hwsku not in host_hwskus: host_hwskus[a_host_hwsku] = [a_host] @@ -650,30 +656,32 @@ def generate_params_frontend_hostname_rand_per_hwsku(request, duts_in_testbed, t return frontend_hosts_per_hwsku -def generate_params_supervisor_hostname(request, duts_in_testbed, tbname): +def generate_params_supervisor_hostname(request, duts_in_testbed, tbname, duts_vars): if len(duts_in_testbed) == 1: # We have a single node - dealing with pizza box, return it return [duts_in_testbed[0]] inv_files = get_inventory_files(request) for dut in duts_in_testbed: # Expecting only a single supervisor node - if is_supervisor_node(inv_files, dut): + dut_vars = duts_vars[dut] + if is_supervisor_node_in_vars(dut_vars): return [dut] pytest.fail("Test selected require a supervisor node, " + "none of the DUTs '{}' in testbed '{}' are a supervisor node".format(duts_in_testbed, tbname)) - - -def generate_param_asic_index(request, duts_in_testbed, dut_indices, param_type): - logging.info("generating {} asic indices for DUT [{}] in ".format(param_type, dut_indices)) +def generate_param_asic_index(request, duts_in_testbed, dut_indices, param_type, duts_vars): + logging.info("generating {} asic indicies for DUT [{}] in ".format(param_type, dut_indices)) #if the params are not present treat the device as a single asic device asic_index_params = [DEFAULT_ASIC_ID] for dut_id in dut_indices: dut = duts_in_testbed[dut_id] - inv_data = get_host_data(request, dut) + inv_data = duts_vars[dut] if inv_data is not None: if param_type == ASIC_PARAM_TYPE_ALL and ASIC_PARAM_TYPE_ALL in inv_data: - asic_index_params = range(int(inv_data[ASIC_PARAM_TYPE_ALL])) + if int(inv_data[ASIC_PARAM_TYPE_ALL]) == 1: + asic_index_params = [DEFAULT_ASIC_ID] + else: + asic_index_params = range(int(inv_data[ASIC_PARAM_TYPE_ALL])) elif param_type == ASIC_PARAM_TYPE_FRONTEND and ASIC_PARAM_TYPE_FRONTEND in inv_data: asic_index_params = inv_data[ASIC_PARAM_TYPE_FRONTEND] logging.info("dut_index {} dut name {} asics params = {}".format( @@ -795,24 +803,32 @@ def generate_priority_lists(request, prio_scope): return ret if ret else empty -_frontend_hosts_per_hwsku_per_module = {} def pytest_generate_tests(metafunc): # The topology always has atleast 1 dut dut_indices = [0] - tbname, testbedinfo = get_tbinfo(metafunc) - duts_in_testbed = testbedinfo["duts"] + global _duthosts_in_testbed, _frontend_hosts_per_hwsku_per_module + tbname = None + if _duthosts_in_testbed is None: + tbname, testbedinfo = get_tbinfo(metafunc) + _duthosts_in_testbed = testbedinfo["duts"] + # Get vars defined for each DUT in the inventory + inv_files = get_inventory_files(metafunc) + for dutname in _duthosts_in_testbed: + _duts_vars_in_inv[dutname] = get_host_visible_vars(inv_files, dutname) + logging.info('get tb info takes {}'.format(t2 - t1)) + # Enumerators ("enum_dut_index", "enum_dut_hostname", "rand_one_dut_hostname") are mutually exclusive if "enum_dut_index" in metafunc.fixturenames: - dut_indices = generate_params_dut_index(duts_in_testbed, tbname) + dut_indices = generate_params_dut_index(_duthosts_in_testbed, tbname) metafunc.parametrize("enum_dut_index", dut_indices, scope="module") elif "enum_dut_hostname" in metafunc.fixturenames: - dut_hostnames = generate_params_dut_hostname(duts_in_testbed, tbname) + dut_hostnames = generate_params_dut_hostname(_duthosts_in_testbed, tbname) metafunc.parametrize("enum_dut_hostname", dut_hostnames, scope="module") elif "enum_supervisor_dut_hostname" in metafunc.fixturenames: - supervisor_hosts = generate_params_supervisor_hostname(metafunc, duts_in_testbed, tbname) + supervisor_hosts = generate_params_supervisor_hostname(metafunc, _duthosts_in_testbed, tbname, _duts_vars_in_inv) metafunc.parametrize("enum_supervisor_dut_hostname", supervisor_hosts, scope="module") elif "enum_frontend_dut_hostname" in metafunc.fixturenames: - frontend_hosts = generate_params_frontend_hostname(metafunc, duts_in_testbed, tbname) + frontend_hosts = generate_params_frontend_hostname(metafunc, _duthosts_in_testbed, tbname, _duts_vars_in_inv) metafunc.parametrize("enum_frontend_dut_hostname", frontend_hosts, scope="module") elif "enum_rand_one_per_hwsku_frontend_hostname" in metafunc.fixturenames: if metafunc.module not in _frontend_hosts_per_hwsku_per_module: @@ -820,14 +836,18 @@ def pytest_generate_tests(metafunc): _frontend_hosts_per_hwsku_per_module[metafunc.module] = frontend_hosts_per_hwsku frontend_hosts = _frontend_hosts_per_hwsku_per_module[metafunc.module] metafunc.parametrize("enum_rand_one_per_hwsku_frontend_hostname", frontend_hosts, scope="module") + frontend_hosts_per_hwsku = generate_params_frontend_hostname_rand_per_hwsku(metafunc, duts_in_testbed, tbname, _duts_vars_in_inv) + metafunc.parametrize("enum_rand_one_per_hwsku_frontend_hostname", frontend_hosts_per_hwsku, scope="module") if "enum_asic_index" in metafunc.fixturenames: metafunc.parametrize("enum_asic_index", - generate_param_asic_index(metafunc, duts_in_testbed, dut_indices, ASIC_PARAM_TYPE_ALL)) + generate_param_asic_index(metafunc, _duthosts_in_testbed, dut_indices, + ASIC_PARAM_TYPE_ALL, _duts_vars_in_inv)) if "enum_frontend_asic_index" in metafunc.fixturenames: metafunc.parametrize("enum_frontend_asic_index", - generate_param_asic_index(metafunc, duts_in_testbed, dut_indices, ASIC_PARAM_TYPE_FRONTEND)) + generate_param_asic_index(metafunc, _duthosts_in_testbed, dut_indices, + ASIC_PARAM_TYPE_FRONTEND, _duts_vars_in_inv)) if "enum_dut_portname" in metafunc.fixturenames: metafunc.parametrize("enum_dut_portname", generate_port_lists(metafunc, "all_ports")) From 052e460b37aac4ee5cf8f8ae0feb122f5d735ecc Mon Sep 17 00:00:00 2001 From: sanmalho Date: Thu, 14 Jan 2021 19:05:59 -0500 Subject: [PATCH 2/6] Fixes for lgtm warnings and vm test failures --- tests/conftest.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index a264c44dda..6b32d5d967 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -233,7 +233,11 @@ def rand_one_frontend_dut_hostname(request): """ tbname, testbedinfo = get_tbinfo(request) duts_in_testbed = testbedinfo["duts"] - frontend_dut_hostnames = generate_params_frontend_hostname(request, duts_in_testbed, tbname) + duts_vars = {} + inv_files = get_inventory_files(metafunc) + for dutname in _duthosts_in_testbed: + duts_vars_in_inv[dutname] = get_host_visible_vars(inv_files, dutname) + frontend_dut_hostnames = generate_params_frontend_hostname(request, duts_in_testbed, tbname, duts_vars) dut_hostnames = random.sample(frontend_dut_hostnames, 1) return dut_hostnames[0] @@ -614,7 +618,6 @@ def get_host_data(request, dut): def generate_params_frontend_hostname(request, duts_in_testbed, tbname): frontend_duts = [] - inv_files = get_inventory_files(request) for dut in duts_in_testbed: dut_vars = duts_vars[dut] if is_frontend_node_in_vars(dut_vars): @@ -627,7 +630,6 @@ def generate_params_frontend_hostname(request, duts_in_testbed, tbname): def generate_params_frontend_hostname_rand_per_hwsku(request, duts_in_testbed, tbname, duts_vars): frontend_hosts = generate_params_frontend_hostname(request, duts_in_testbed, tbname, duts_vars) - inv_files = get_inventory_files(request) # Create a list of hosts per hwsku host_hwskus = {} for a_host in frontend_hosts: @@ -660,7 +662,6 @@ def generate_params_supervisor_hostname(request, duts_in_testbed, tbname, duts_v if len(duts_in_testbed) == 1: # We have a single node - dealing with pizza box, return it return [duts_in_testbed[0]] - inv_files = get_inventory_files(request) for dut in duts_in_testbed: # Expecting only a single supervisor node dut_vars = duts_vars[dut] @@ -815,7 +816,6 @@ def pytest_generate_tests(metafunc): inv_files = get_inventory_files(metafunc) for dutname in _duthosts_in_testbed: _duts_vars_in_inv[dutname] = get_host_visible_vars(inv_files, dutname) - logging.info('get tb info takes {}'.format(t2 - t1)) # Enumerators ("enum_dut_index", "enum_dut_hostname", "rand_one_dut_hostname") are mutually exclusive if "enum_dut_index" in metafunc.fixturenames: From 7f123f80371acd209ff54d1b1f2e757aa2333c33 Mon Sep 17 00:00:00 2001 From: sanmalho Date: Mon, 18 Jan 2021 10:17:59 -0500 Subject: [PATCH 3/6] Adding helper function for setting testbed info and calling it only when any of the 'enum_*' fixtures are needed. --- tests/conftest.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 6b32d5d967..2e14cd4fa8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -809,25 +809,38 @@ def pytest_generate_tests(metafunc): dut_indices = [0] global _duthosts_in_testbed, _frontend_hosts_per_hwsku_per_module tbname = None - if _duthosts_in_testbed is None: - tbname, testbedinfo = get_tbinfo(metafunc) + if _duthosts_in_testbed is None: + tbname, testbedinfo = get_tbinfo(request) _duthosts_in_testbed = testbedinfo["duts"] # Get vars defined for each DUT in the inventory - inv_files = get_inventory_files(metafunc) + inv_files = get_inventory_files(request) for dutname in _duthosts_in_testbed: _duts_vars_in_inv[dutname] = get_host_visible_vars(inv_files, dutname) + return tbname + + +_frontend_hosts_per_hwsku_per_module = {} +def pytest_generate_tests(metafunc): + # The topology always has atleast 1 dut + dut_indices = [0] + global _duthosts_in_testbed, _frontend_hosts_per_hwsku_per_module, _duts_vars_in_inv + # Enumerators ("enum_dut_index", "enum_dut_hostname", "rand_one_dut_hostname") are mutually exclusive if "enum_dut_index" in metafunc.fixturenames: + tbname = _setup_duts_in_testbed(metafunc) dut_indices = generate_params_dut_index(_duthosts_in_testbed, tbname) metafunc.parametrize("enum_dut_index", dut_indices, scope="module") elif "enum_dut_hostname" in metafunc.fixturenames: + tbname = _setup_duts_in_testbed(metafunc) dut_hostnames = generate_params_dut_hostname(_duthosts_in_testbed, tbname) metafunc.parametrize("enum_dut_hostname", dut_hostnames, scope="module") elif "enum_supervisor_dut_hostname" in metafunc.fixturenames: + tbname = _setup_duts_in_testbed(metafunc) supervisor_hosts = generate_params_supervisor_hostname(metafunc, _duthosts_in_testbed, tbname, _duts_vars_in_inv) metafunc.parametrize("enum_supervisor_dut_hostname", supervisor_hosts, scope="module") elif "enum_frontend_dut_hostname" in metafunc.fixturenames: + tbname = _setup_duts_in_testbed(metafunc) frontend_hosts = generate_params_frontend_hostname(metafunc, _duthosts_in_testbed, tbname, _duts_vars_in_inv) metafunc.parametrize("enum_frontend_dut_hostname", frontend_hosts, scope="module") elif "enum_rand_one_per_hwsku_frontend_hostname" in metafunc.fixturenames: @@ -841,10 +854,12 @@ def pytest_generate_tests(metafunc): if "enum_asic_index" in metafunc.fixturenames: + tbname = _setup_duts_in_testbed(metafunc) metafunc.parametrize("enum_asic_index", generate_param_asic_index(metafunc, _duthosts_in_testbed, dut_indices, ASIC_PARAM_TYPE_ALL, _duts_vars_in_inv)) if "enum_frontend_asic_index" in metafunc.fixturenames: + tbname = _setup_duts_in_testbed(metafunc) metafunc.parametrize("enum_frontend_asic_index", generate_param_asic_index(metafunc, _duthosts_in_testbed, dut_indices, ASIC_PARAM_TYPE_FRONTEND, _duts_vars_in_inv)) From 01bcaaeee1340cf767d2750fb97bb15a1dca9bff Mon Sep 17 00:00:00 2001 From: sanmalho Date: Mon, 18 Jan 2021 11:06:23 -0500 Subject: [PATCH 4/6] Fixes for lgtm warning --- tests/conftest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 2e14cd4fa8..98e56a3ca9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -854,12 +854,12 @@ def pytest_generate_tests(metafunc): if "enum_asic_index" in metafunc.fixturenames: - tbname = _setup_duts_in_testbed(metafunc) + _setup_duts_in_testbed(metafunc) metafunc.parametrize("enum_asic_index", generate_param_asic_index(metafunc, _duthosts_in_testbed, dut_indices, ASIC_PARAM_TYPE_ALL, _duts_vars_in_inv)) if "enum_frontend_asic_index" in metafunc.fixturenames: - tbname = _setup_duts_in_testbed(metafunc) + _setup_duts_in_testbed(metafunc) metafunc.parametrize("enum_frontend_asic_index", generate_param_asic_index(metafunc, _duthosts_in_testbed, dut_indices, ASIC_PARAM_TYPE_FRONTEND, _duts_vars_in_inv)) From ba1a98e8194963f2426be079625a7f6fbb1a294c Mon Sep 17 00:00:00 2001 From: sanmalho Date: Sat, 30 Jan 2021 14:40:13 -0500 Subject: [PATCH 5/6] Using cache instead of global variables in dut selection. Added 'enum_rand_one_per_hwsku_hostname' fixture. With caching of facts, the tbInfo and vars in inventory for a host are cached. Instead of using global variables '_dut_in_testbeds', _dut_vars, we would call the methods again, but since it is cached, it is not re-creating testbed info or reading the vars from the inventory. Added enum_rand_one_per_hwsku_hostname fixture to pytest_generate_tests. This is needed as there are tests like platform tests (test_show_platform_syseeprom) that need to run on both the supervisor and linecard of a T2 chassis. --- tests/common/helpers/dut_utils.py | 9 +- tests/conftest.py | 149 ++++++++++++------------------ 2 files changed, 64 insertions(+), 94 deletions(-) diff --git a/tests/common/helpers/dut_utils.py b/tests/common/helpers/dut_utils.py index 4855538e3f..ca97682505 100644 --- a/tests/common/helpers/dut_utils.py +++ b/tests/common/helpers/dut_utils.py @@ -1,8 +1,5 @@ from tests.common.utilities import get_host_visible_vars -def is_supervisor_node_in_vars(dut_vars): - if 'type' in dut_vars and dut_vars['type'] == 'supervisor': - return True def is_supervisor_node(inv_files, hostname): """Check if the current node is a supervisor node in case of multi-DUT. @@ -15,10 +12,10 @@ def is_supervisor_node(inv_files, hostname): logic if possible to derive it from the DUT. """ dut_vars = get_host_visible_vars(inv_files, hostname) - return is_supervisor_node_in_vars(dut_vars) + if 'type' in dut_vars and dut_vars['type'] == 'supervisor': + return True + return False -def is_frontend_node_in_vars(dut_vars): - return not is_supervisor_node_in_vars(dut_vars) def is_frontend_node(inv_files, hostname): """Check if the current node is a frontend node in case of multi-DUT. diff --git a/tests/conftest.py b/tests/conftest.py index 98e56a3ca9..633f98d0d5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -22,9 +22,7 @@ from tests.common.utilities import get_host_vars from tests.common.utilities import get_host_visible_vars from tests.common.helpers.dut_utils import is_supervisor_node, is_frontend_node -from tests.common.utilities import get_inventory_files, get_host_visible_vars from tests.common.cache import FactsCache -from tests.common.helpers.dut_utils import is_supervisor_node_in_vars, is_frontend_node_in_vars from tests.common.connections import ConsoleHost @@ -206,9 +204,7 @@ def duthost(duthosts, request): def rand_one_dut_hostname(request): """ """ - tbname, testbedinfo = get_tbinfo(request) - duts_in_testbed = testbedinfo["duts"] - dut_hostnames = generate_params_dut_hostname(duts_in_testbed, tbname) + dut_hostnames = generate_params_dut_hostname(request) if len(dut_hostnames) > 1: dut_hostnames = random.sample(dut_hostnames, 1) return dut_hostnames[0] @@ -227,20 +223,6 @@ def rand_one_dut_lossless_prio(request): lossless_prio_list = random.sample(lossless_prio_list, 1) return lossless_prio_list[0] -@pytest.fixture(scope="module") -def rand_one_frontend_dut_hostname(request): - """ - """ - tbname, testbedinfo = get_tbinfo(request) - duts_in_testbed = testbedinfo["duts"] - duts_vars = {} - inv_files = get_inventory_files(metafunc) - for dutname in _duthosts_in_testbed: - duts_vars_in_inv[dutname] = get_host_visible_vars(inv_files, dutname) - frontend_dut_hostnames = generate_params_frontend_hostname(request, duts_in_testbed, tbname, duts_vars) - dut_hostnames = random.sample(frontend_dut_hostnames, 1) - return dut_hostnames[0] - @pytest.fixture(scope="module", autouse=True) def reset_critical_services_list(duthosts): """ @@ -616,24 +598,30 @@ def get_host_data(request, dut): return get_host_vars(inv_files, dut) -def generate_params_frontend_hostname(request, duts_in_testbed, tbname): +def generate_params_frontend_hostname(request): frontend_duts = [] - for dut in duts_in_testbed: - dut_vars = duts_vars[dut] - if is_frontend_node_in_vars(dut_vars): + tbname, tbinfo = get_tbinfo(request) + duts = tbinfo['duts'] + inv_files = get_inventory_files(request) + for dut in duts: + if is_frontend_node(inv_files, dut): frontend_duts.append(dut) assert len(frontend_duts) > 0, \ "Test selected require at-least one frontend node, " \ - "none of the DUTs '{}' in testbed '{}' are a supervisor node".format(duts_in_testbed, tbname) + "none of the DUTs '{}' in testbed '{}' are a supervisor node".format(duts, tbname) return frontend_duts -def generate_params_frontend_hostname_rand_per_hwsku(request, duts_in_testbed, tbname, duts_vars): - frontend_hosts = generate_params_frontend_hostname(request, duts_in_testbed, tbname, duts_vars) +def generate_params_hostname_rand_per_hwsku(request, frontend_only=False): + tbname, tbinfo = get_tbinfo(request) + hosts = tbinfo['duts'] + if frontend_only: + hosts = generate_params_frontend_hostname(request) + inv_files = get_inventory_files(request) # Create a list of hosts per hwsku host_hwskus = {} - for a_host in frontend_hosts: - host_vars = duts_vars[a_host] + for a_host in hosts: + host_vars = get_host_visible_vars(inv_files, a_host) if 'hwsku' in host_vars: a_host_hwsku = host_vars['hwsku'] else: @@ -648,35 +636,40 @@ def generate_params_frontend_hostname_rand_per_hwsku(request, duts_in_testbed, t else: pytest.fail("Test selected require a node per hwsku, but 'hwsku' for '{}' not defined in the inventory".format(a_host)) - frontend_hosts_per_hwsku = [] + hosts_per_hwsku = [] for hosts in host_hwskus.values(): if len(hosts) == 1: - frontend_hosts_per_hwsku.append(hosts[0]) + hosts_per_hwsku.append(hosts[0]) else: - frontend_hosts_per_hwsku.extend(random.sample(hosts, 1)) + hosts_per_hwsku.extend(random.sample(hosts, 1)) - return frontend_hosts_per_hwsku + return hosts_per_hwsku -def generate_params_supervisor_hostname(request, duts_in_testbed, tbname, duts_vars): - if len(duts_in_testbed) == 1: +def generate_params_supervisor_hostname(request): + tbname, tbinfo = get_tbinfo(request) + duts = tbinfo['duts'] + if len(duts) == 1: # We have a single node - dealing with pizza box, return it - return [duts_in_testbed[0]] - for dut in duts_in_testbed: + return [duts[0]] + inv_files = get_inventory_files(request) + for dut in duts: # Expecting only a single supervisor node - dut_vars = duts_vars[dut] - if is_supervisor_node_in_vars(dut_vars): + if is_supervisor_node(inv_files, dut): return [dut] pytest.fail("Test selected require a supervisor node, " + - "none of the DUTs '{}' in testbed '{}' are a supervisor node".format(duts_in_testbed, tbname)) -def generate_param_asic_index(request, duts_in_testbed, dut_indices, param_type, duts_vars): + "none of the DUTs '{}' in testbed '{}' are a supervisor node".format(duts, tbname)) + +def generate_param_asic_index(request, dut_indices, param_type): + _, tbinfo = get_tbinfo(request) + inv_files = get_inventory_files(request) logging.info("generating {} asic indicies for DUT [{}] in ".format(param_type, dut_indices)) #if the params are not present treat the device as a single asic device asic_index_params = [DEFAULT_ASIC_ID] for dut_id in dut_indices: - dut = duts_in_testbed[dut_id] - inv_data = duts_vars[dut] + dut = tbinfo['duts'][dut_id] + inv_data = get_host_visible_vars(inv_files, dut) if inv_data is not None: if param_type == ASIC_PARAM_TYPE_ALL and ASIC_PARAM_TYPE_ALL in inv_data: if int(inv_data[ASIC_PARAM_TYPE_ALL]) == 1: @@ -690,15 +683,18 @@ def generate_param_asic_index(request, duts_in_testbed, dut_indices, param_type, return asic_index_params -def generate_params_dut_index(duts_in_testbeds, tbname): - num_duts = len(duts_in_testbeds) +def generate_params_dut_index(request): + tbname, tbinfo = get_tbinfo(request) + num_duts = len(tbinfo['duts']) logging.info("Num of duts in testbed '{}' is {}".format(tbname, num_duts)) return range(num_duts) -def generate_params_dut_hostname(duts_in_testbed, tbname): - logging.info("DUTs in testbed '{}' are: {}".format(tbname, str(duts_in_testbed))) - return duts_in_testbed +def generate_params_dut_hostname(request): + tbname, tbinfo = get_tbinfo(request) + duts = tbinfo["duts"] + logging.info("DUTs in testbed '{}' are: {}".format(tbname, str(duts))) + return duts def generate_port_lists(request, port_scope): @@ -804,65 +800,42 @@ def generate_priority_lists(request, prio_scope): return ret if ret else empty -def pytest_generate_tests(metafunc): - # The topology always has atleast 1 dut - dut_indices = [0] - global _duthosts_in_testbed, _frontend_hosts_per_hwsku_per_module - tbname = None - if _duthosts_in_testbed is None: - tbname, testbedinfo = get_tbinfo(request) - _duthosts_in_testbed = testbedinfo["duts"] - # Get vars defined for each DUT in the inventory - inv_files = get_inventory_files(request) - for dutname in _duthosts_in_testbed: - _duts_vars_in_inv[dutname] = get_host_visible_vars(inv_files, dutname) - - return tbname - - _frontend_hosts_per_hwsku_per_module = {} +_hosts_per_hwsku_per_module = {} def pytest_generate_tests(metafunc): # The topology always has atleast 1 dut dut_indices = [0] - global _duthosts_in_testbed, _frontend_hosts_per_hwsku_per_module, _duts_vars_in_inv - + global _frontend_hosts_per_hwsku_per_module, _hosts_per_hwsku_per_module # Enumerators ("enum_dut_index", "enum_dut_hostname", "rand_one_dut_hostname") are mutually exclusive if "enum_dut_index" in metafunc.fixturenames: - tbname = _setup_duts_in_testbed(metafunc) - dut_indices = generate_params_dut_index(_duthosts_in_testbed, tbname) + dut_indices = generate_params_dut_index(metafunc) metafunc.parametrize("enum_dut_index", dut_indices, scope="module") elif "enum_dut_hostname" in metafunc.fixturenames: - tbname = _setup_duts_in_testbed(metafunc) - dut_hostnames = generate_params_dut_hostname(_duthosts_in_testbed, tbname) + dut_hostnames = generate_params_dut_hostname(metafunc) metafunc.parametrize("enum_dut_hostname", dut_hostnames, scope="module") elif "enum_supervisor_dut_hostname" in metafunc.fixturenames: - tbname = _setup_duts_in_testbed(metafunc) - supervisor_hosts = generate_params_supervisor_hostname(metafunc, _duthosts_in_testbed, tbname, _duts_vars_in_inv) + supervisor_hosts = generate_params_supervisor_hostname(metafunc) metafunc.parametrize("enum_supervisor_dut_hostname", supervisor_hosts, scope="module") elif "enum_frontend_dut_hostname" in metafunc.fixturenames: - tbname = _setup_duts_in_testbed(metafunc) - frontend_hosts = generate_params_frontend_hostname(metafunc, _duthosts_in_testbed, tbname, _duts_vars_in_inv) + frontend_hosts = generate_params_frontend_hostname(metafunc) metafunc.parametrize("enum_frontend_dut_hostname", frontend_hosts, scope="module") + elif "enum_rand_one_per_hwsku_hostname" in metafunc.fixturenames: + if metafunc.module not in _hosts_per_hwsku_per_module: + hosts_per_hwsku = generate_params_hostname_rand_per_hwsku(metafunc) + _hosts_per_hwsku_per_module[metafunc.module] = hosts_per_hwsku + hosts = _hosts_per_hwsku_per_module[metafunc.module] + metafunc.parametrize("enum_rand_one_per_hwsku_hostname", hosts, scope="module") elif "enum_rand_one_per_hwsku_frontend_hostname" in metafunc.fixturenames: if metafunc.module not in _frontend_hosts_per_hwsku_per_module: - frontend_hosts_per_hwsku = generate_params_frontend_hostname_rand_per_hwsku(metafunc, duts_in_testbed, tbname) - _frontend_hosts_per_hwsku_per_module[metafunc.module] = frontend_hosts_per_hwsku - frontend_hosts = _frontend_hosts_per_hwsku_per_module[metafunc.module] - metafunc.parametrize("enum_rand_one_per_hwsku_frontend_hostname", frontend_hosts, scope="module") - frontend_hosts_per_hwsku = generate_params_frontend_hostname_rand_per_hwsku(metafunc, duts_in_testbed, tbname, _duts_vars_in_inv) - metafunc.parametrize("enum_rand_one_per_hwsku_frontend_hostname", frontend_hosts_per_hwsku, scope="module") - + hosts_per_hwsku = generate_params_hostname_rand_per_hwsku(metafunc, frontend_only=True) + _frontend_hosts_per_hwsku_per_module[metafunc.module] = hosts_per_hwsku + hosts = _frontend_hosts_per_hwsku_per_module[metafunc.module] + metafunc.parametrize("enum_rand_one_per_hwsku_frontend_hostname", hosts, scope="module") if "enum_asic_index" in metafunc.fixturenames: - _setup_duts_in_testbed(metafunc) - metafunc.parametrize("enum_asic_index", - generate_param_asic_index(metafunc, _duthosts_in_testbed, dut_indices, - ASIC_PARAM_TYPE_ALL, _duts_vars_in_inv)) + metafunc.parametrize("enum_asic_index", generate_param_asic_index(metafunc, dut_indices, ASIC_PARAM_TYPE_ALL)) if "enum_frontend_asic_index" in metafunc.fixturenames: - _setup_duts_in_testbed(metafunc) - metafunc.parametrize("enum_frontend_asic_index", - generate_param_asic_index(metafunc, _duthosts_in_testbed, dut_indices, - ASIC_PARAM_TYPE_FRONTEND, _duts_vars_in_inv)) + metafunc.parametrize("enum_frontend_asic_index",generate_param_asic_index(metafunc, dut_indices, ASIC_PARAM_TYPE_FRONTEND)) if "enum_dut_portname" in metafunc.fixturenames: metafunc.parametrize("enum_dut_portname", generate_port_lists(metafunc, "all_ports")) From 6a11c36fa496ed5f50af69781e3d29cca12864e8 Mon Sep 17 00:00:00 2001 From: sanmalho Date: Mon, 1 Feb 2021 10:03:26 -0500 Subject: [PATCH 6/6] Fixing a potential exception in generate_params_hostname_rand_per_hwsku where a_host_hwsku could be undefined. --- tests/conftest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/conftest.py b/tests/conftest.py index 633f98d0d5..bedb7fa88a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -622,6 +622,7 @@ def generate_params_hostname_rand_per_hwsku(request, frontend_only=False): host_hwskus = {} for a_host in hosts: host_vars = get_host_visible_vars(inv_files, a_host) + a_host_hwsku = None if 'hwsku' in host_vars: a_host_hwsku = host_vars['hwsku'] else: