diff --git a/tests/common/devices/eos.py b/tests/common/devices/eos.py index 97294437cd4..0e7de435c22 100644 --- a/tests/common/devices/eos.py +++ b/tests/common/devices/eos.py @@ -257,8 +257,13 @@ def get_supported_speeds(self, interface_name): Returns: list: A list of supported speed strings or None """ - output = self.eos_command(commands=['show interfaces %s capabilities' % interface_name]) - found_txt = re.search("Speed/Duplex: (.+)", output['stdout'][0]) + commands = ['show interfaces {} capabilities'.format(interface_name), 'show interface {} hardware'.format(interface_name)] + for command in commands: + output = self.eos_command(commands=[command]) + found_txt = re.search("Speed/Duplex: (.+)", output['stdout'][0]) + if found_txt is not None: + break + if found_txt is None: _raise_err('Failed to find port speeds list in output: %s' % output['stdout']) @@ -266,5 +271,5 @@ def get_supported_speeds(self, interface_name): speed_list = speed_list.split(',') speed_list.remove('auto') def extract_speed_only(v): - return re.match('\d+', v).group() + '000' + return re.match('\d+', v.strip()).group() + '000' return list(map(extract_speed_only, speed_list)) diff --git a/tests/common/devices/sonic.py b/tests/common/devices/sonic.py index d21ecf8512a..88701e4c7f1 100644 --- a/tests/common/devices/sonic.py +++ b/tests/common/devices/sonic.py @@ -1546,7 +1546,10 @@ def get_auto_negotiation_mode(self, interface_name): the auto negotiation mode is unknown or unsupported. """ cmd = 'sonic-db-cli APPL_DB HGET \"PORT_TABLE:{}\" \"{}\"'.format(interface_name, 'autoneg') - mode = self.shell(cmd)['stdout'].strip() + try: + mode = self.shell(cmd)['stdout'].strip() + except RunAnsibleModuleFail: + return None if not mode: return None return True if mode == 'on' else False diff --git a/tests/platform_tests/test_auto_negotiation.py b/tests/platform_tests/test_auto_negotiation.py index d50784bdde0..c46e29e820b 100644 --- a/tests/platform_tests/test_auto_negotiation.py +++ b/tests/platform_tests/test_auto_negotiation.py @@ -34,16 +34,16 @@ # To avoid getting candidate test ports again and again, use a global variable # to save all candidate test ports. -# Key: dut host object, value: a list of candidate ports tuple +# Key: dut host name, value: a dictionary of candidate ports tuple with dut port name as key cadidate_test_ports = {} @pytest.fixture(scope='module', autouse=True) -def recover_ports(duthosts, enum_dut_portname_module_fixture, fanouthosts): +def recover_ports(duthosts, fanouthosts): """Module level fixture that automatically do following job: 1. Build global candidate test ports 2. Save fanout port state before the test - 3. Restor fanout and DUT after test + 3. Restore fanout and DUT after test Args: duthosts: DUT object @@ -52,21 +52,28 @@ def recover_ports(duthosts, enum_dut_portname_module_fixture, fanouthosts): """ global cadidate_test_ports fanout_original_port_states = {} - dutname, portname = decode_dut_port_name(enum_dut_portname_module_fixture) logger.info('Collecting existing port configuration for DUT and fanout...') for duthost in duthosts: - if dutname == 'unknown' or dutname == duthost.hostname: - all_ports = build_test_candidates(duthost, fanouthosts, portname) - # Test all ports takes too much time (sometimes more than an hour), - # so we choose 3 ports randomly as the cadidates ports - cadidate_test_ports[duthost] = random.sample(all_ports, 3) - for _, fanout, fanout_port in cadidate_test_ports[duthost]: - auto_neg_mode = fanout.get_auto_negotiation_mode(fanout_port) - speed = fanout.get_speed(fanout_port) - if not fanout in fanout_original_port_states: - fanout_original_port_states[fanout] = {} - fanout_original_port_states[fanout][fanout_port] = (auto_neg_mode, speed) - + # Only do the sampling when there are no candidates + if duthost.hostname in cadidate_test_ports.keys(): + continue + all_ports = build_test_candidates(duthost, fanouthosts, 'all_ports') + all_ports_len = len(all_ports) + # Test all ports takes too much time (sometimes more than an hour), + # so we choose 3 ports randomly as the cadidates ports + candidates = random.sample(all_ports, 3 if all_ports_len > 3 else all_ports_len) + cadidate_test_ports[duthost.hostname] = {} + for dut_port, fanout, fanout_port in candidates: + cadidate_test_ports[duthost.hostname][dut_port] = (duthost, dut_port, fanout, fanout_port) + for _, _, fanout, fanout_port in cadidate_test_ports[duthost.hostname].values(): + auto_neg_mode = fanout.get_auto_negotiation_mode(fanout_port) + if auto_neg_mode is None: + pytest.skip("Skip test due to fanout port {} does not support setting auto-neg mode".format(fanout_port)) + speed = fanout.get_speed(fanout_port) + if not fanout in fanout_original_port_states: + fanout_original_port_states[fanout] = {} + fanout_original_port_states[fanout][fanout_port] = (auto_neg_mode, speed) + yield logger.info('Recovering port configuration for fanout...') @@ -169,11 +176,11 @@ def test_auto_negotiation_advertised_speeds_all(): 1. All ports are up after auto negotiation 2. All ports are negotiated to its highest supported speeds """ - for duthost, candidates in cadidate_test_ports.items(): + for dutname, candidates in cadidate_test_ports.items(): if not candidates: continue - logger.info('Test candidate ports are {}'.format(candidates)) - for dut_port, fanout, fanout_port in candidates: + + for duthost, dut_port, fanout, fanout_port in candidates.values(): logger.info('Start test for DUT port {} and fanout port {}'.format(dut_port, fanout_port)) # Enable auto negotiation on fanout port success = fanout.set_auto_negotiation_mode(fanout_port, True) @@ -197,13 +204,13 @@ def test_auto_negotiation_advertised_speeds_all(): PORT_STATUS_CHECK_INTERVAL, check_ports_up, duthost, - [item[0] for item in candidates]) + [item[1] for item in candidates.values()]) pytest_assert(wait_result, 'Some ports are still down') # Make sure all ports are negotiated to the highest speed logger.info('Checking the actual speed is equal to highest speed') int_status = duthost.show_interface(command="status")["ansible_facts"]['int_status'] - for dut_port, fanout, fanout_port in candidates: + for _, dut_port, fanout, fanout_port in candidates.values(): supported_speeds = get_supported_speeds_for_port(duthost, dut_port, fanout, fanout_port) logger.info('DUT port = {}, fanout port = {}, supported speeds = {}, actual speed = {}'.format( dut_port, @@ -216,93 +223,95 @@ def test_auto_negotiation_advertised_speeds_all(): pytest_assert(actual_speed == highest_speed, 'Actual speed is not the highest speed') -def test_auto_negotiation_advertised_each_speed(): +def test_auto_negotiation_advertised_each_speed(enum_dut_portname_module_fixture): """Test all candidate ports to advertised all supported speeds one by one and verify that the port operational status is up after auto negotiation """ - for duthost, candidates in cadidate_test_ports.items(): - if not candidates: - continue - logger.info('Test candidate ports are {}'.format(candidates)) - for dut_port, fanout, fanout_port in candidates: - logger.info('Start test for DUT port {} and fanout port {}'.format(dut_port, fanout_port)) - # Enable auto negotiation on fanout port - success = fanout.set_auto_negotiation_mode(fanout_port, True) - if not success: - # Fanout does not support set auto negotiation mode for this port - logger.info('Ignore port {} due to fanout port {} does not support setting auto-neg mode'.format(dut_port, fanout_port)) - continue - - # Advertise all supported speeds in fanout port - success = fanout.set_speed(fanout_port, None) - if not success: - # Fanout does not support set advertise speeds for this port - logger.info('Ignore port {} due to fanout port {} does not support setting advertised speeds'.format(dut_port, fanout_port)) - continue - - logger.info('Trying to get a common supported speed set among dut port, fanout port and cable') - supported_speeds = get_supported_speeds_for_port(duthost, dut_port, fanout, fanout_port) - if not supported_speeds: - logger.warn('Ignore test for port {} due to cannot get supported speed for it'.format(dut_port)) - continue - - logger.info('Run test based on supported speeds: {}'.format(supported_speeds)) - duthost.shell('config interface autoneg {} enabled'.format(dut_port)) - for speed in supported_speeds: - duthost.shell('config interface advertised-speeds {} {}'.format(dut_port, speed)) - logger.info('Wait until the port status is up, expected speed: {}'.format(speed)) - wait_result = wait_until(SINGLE_PORT_WAIT_TIME, - PORT_STATUS_CHECK_INTERVAL, - check_ports_up, - duthost, - [dut_port], - speed) - pytest_assert(wait_result, '{} are still down'.format(dut_port)) - fanout_actual_speed = fanout.get_speed(fanout_port) - pytest_assert(fanout_actual_speed == speed, 'expect fanout speed: {}, but got {}'.format(speed, fanout_actual_speed)) - - -def test_force_speed(): + dutname, portname = decode_dut_port_name(enum_dut_portname_module_fixture) + if dutname not in cadidate_test_ports.keys() or portname not in cadidate_test_ports[dutname].keys(): + return + + duthost, dut_port, fanout, fanout_port = cadidate_test_ports[dutname][portname] + + logger.info('Start test for DUT port {} and fanout port {}'.format(dut_port, fanout_port)) + # Enable auto negotiation on fanout port + success = fanout.set_auto_negotiation_mode(fanout_port, True) + if not success: + # Fanout does not support set auto negotiation mode for this port + logger.info('Ignore port {} due to fanout port {} does not support setting auto-neg mode'.format(dut_port, fanout_port)) + return + + # Advertise all supported speeds in fanout port + success = fanout.set_speed(fanout_port, None) + if not success: + # Fanout does not support set advertise speeds for this port + logger.info('Ignore port {} due to fanout port {} does not support setting advertised speeds'.format(dut_port, fanout_port)) + return + + logger.info('Trying to get a common supported speed set among dut port, fanout port and cable') + supported_speeds = get_supported_speeds_for_port(duthost, dut_port, fanout, fanout_port) + if not supported_speeds: + logger.warn('Ignore test for port {} due to cannot get supported speed for it'.format(dut_port)) + return + + logger.info('Run test based on supported speeds: {}'.format(supported_speeds)) + duthost.shell('config interface autoneg {} enabled'.format(dut_port)) + for speed in supported_speeds: + duthost.shell('config interface advertised-speeds {} {}'.format(dut_port, speed)) + logger.info('Wait until the port status is up, expected speed: {}'.format(speed)) + wait_result = wait_until(SINGLE_PORT_WAIT_TIME, + PORT_STATUS_CHECK_INTERVAL, + check_ports_up, + duthost, + [dut_port], + speed) + pytest_assert(wait_result, '{} are still down'.format(dut_port)) + fanout_actual_speed = fanout.get_speed(fanout_port) + pytest_assert(fanout_actual_speed == speed, 'expect fanout speed: {}, but got {}'.format(speed, fanout_actual_speed)) + + +def test_force_speed(enum_dut_portname_module_fixture): """Test all candidate ports to force to all supported speeds one by one and verify that the port operational status is up after auto negotiation """ - for duthost, candidates in cadidate_test_ports.items(): - if not candidates: - continue - logger.info('Test candidate ports are {}'.format(candidates)) - for dut_port, fanout, fanout_port in candidates: - logger.info('Start test for DUT port {} and fanout port {}'.format(dut_port, fanout_port)) - # Disable auto negotiation on fanout port - success = fanout.set_auto_negotiation_mode(fanout_port, False) - if not success: - # Fanout does not support set auto negotiation mode for this port - logger.info('Ignore port {} due to fanout port {} does not support setting auto-neg mode'.format(dut_port, fanout_port)) - continue + dutname, portname = decode_dut_port_name(enum_dut_portname_module_fixture) + if dutname not in cadidate_test_ports.keys() or portname not in cadidate_test_ports[dutname].keys(): + return - logger.info('Trying to get a common supported speeds set among dut port, fanout port and cable') - supported_speeds = get_supported_speeds_for_port(duthost, dut_port, fanout, fanout_port) - if not supported_speeds: - logger.warn('Ignore test for port {} due to cannot get supported speed for it'.format(dut_port)) - continue + duthost, dut_port, fanout, fanout_port = cadidate_test_ports[dutname][portname] + + logger.info('Start test for DUT port {} and fanout port {}'.format(dut_port, fanout_port)) + # Disable auto negotiation on fanout port + success = fanout.set_auto_negotiation_mode(fanout_port, False) + if not success: + # Fanout does not support set auto negotiation mode for this port + logger.info('Ignore port {} due to fanout port {} does not support setting auto-neg mode'.format(dut_port, fanout_port)) + return - logger.info('Run test based on supported speeds: {}'.format(supported_speeds)) - duthost.shell('config interface autoneg {} disabled'.format(dut_port)) - for speed in supported_speeds: - success = fanout.set_speed(fanout_port, speed) - if not success: - logger.info('Skip speed {} because fanout does not support it'.format(speed)) - continue - duthost.shell('config interface speed {} {}'.format(dut_port, speed)) - logger.info('Wait until the port status is up, expected speed: {}'.format(speed)) - wait_result = wait_until(SINGLE_PORT_WAIT_TIME, - PORT_STATUS_CHECK_INTERVAL, - check_ports_up, - duthost, - [dut_port], - speed) - pytest_assert(wait_result, '{} are still down'.format(dut_port)) - fanout_actual_speed = fanout.get_speed(fanout_port) - pytest_assert(fanout_actual_speed == speed, 'expect fanout speed: {}, but got {}'.format(speed, fanout_actual_speed)) + logger.info('Trying to get a common supported speeds set among dut port, fanout port and cable') + supported_speeds = get_supported_speeds_for_port(duthost, dut_port, fanout, fanout_port) + if not supported_speeds: + logger.warn('Ignore test for port {} due to cannot get supported speed for it'.format(dut_port)) + return + + logger.info('Run test based on supported speeds: {}'.format(supported_speeds)) + duthost.shell('config interface autoneg {} disabled'.format(dut_port)) + for speed in supported_speeds: + success = fanout.set_speed(fanout_port, speed) + if not success: + logger.info('Skip speed {} because fanout does not support it'.format(speed)) + continue + duthost.shell('config interface speed {} {}'.format(dut_port, speed)) + logger.info('Wait until the port status is up, expected speed: {}'.format(speed)) + wait_result = wait_until(SINGLE_PORT_WAIT_TIME, + PORT_STATUS_CHECK_INTERVAL, + check_ports_up, + duthost, + [dut_port], + speed) + pytest_assert(wait_result, '{} are still down'.format(dut_port)) + fanout_actual_speed = fanout.get_speed(fanout_port) + pytest_assert(fanout_actual_speed == speed, 'expect fanout speed: {}, but got {}'.format(speed, fanout_actual_speed)) def get_cable_supported_speeds_helper(duthost):