From abca6b7af0c438970dd2b42851c3ff028a0212ef Mon Sep 17 00:00:00 2001 From: Arun Saravanan Balachandran Date: Wed, 22 Sep 2021 19:31:55 +0530 Subject: [PATCH] [Platform API]: Update test cases to make use of capabilities fields in platform.json Test cases modified: - Chassis: test_status_led - Chassis Fans: test_get_fans_target_speed, test_set_fans_speed, test_set_fans_led - FanDrawer: test_set_fan_drawers_led - FanDrawer Fans: test_get_fans_target_speed, test_set_fans_speed, test_set_fans_led - PSU: test_led - PSU Fans: test_get_fans_target_speed, test_set_fans_speed, test_set_fans_led - Thermal: test_set_low_threshold, test_set_high_threshold Signed-off-by: Arun Saravanan Balachandran --- tests/platform_tests/api/test_chassis.py | 49 ++++++-- tests/platform_tests/api/test_chassis_fans.py | 58 +++++++++ tests/platform_tests/api/test_fan_drawer.py | 67 +++++++--- .../api/test_fan_drawer_fans.py | 117 +++++++++++++++--- tests/platform_tests/api/test_psu.py | 77 +++++++++--- tests/platform_tests/api/test_psu_fans.py | 78 +++++++++++- tests/platform_tests/api/test_thermal.py | 36 ++++++ 7 files changed, 415 insertions(+), 67 deletions(-) diff --git a/tests/platform_tests/api/test_chassis.py b/tests/platform_tests/api/test_chassis.py index 64bcd737093..e8e64fa4ed5 100644 --- a/tests/platform_tests/api/test_chassis.py +++ b/tests/platform_tests/api/test_chassis.py @@ -444,19 +444,42 @@ def test_status_led(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, 2: "off" } - for index, led_type in enumerate(LED_COLOR_TYPES): - led_type_result = False - for color in led_type: - result = chassis.set_status_led(platform_api_conn, color) - if self.expect(result is not None, "Failed to perform set_status_led"): - led_type_result = result or led_type_result - if ((result is None) or (not result)): - continue - color_actual = chassis.get_status_led(platform_api_conn) - if self.expect(color_actual is not None, "Failed to retrieve status_led"): - if self.expect(isinstance(color_actual, STRING_TYPE), "Status LED color appears incorrect"): - self.expect(color == color_actual, "Status LED color incorrect (expected: {}, actual: {})".format(color, color_actual)) - self.expect(led_type_result is True, "Failed to set status_led to {}".format(LED_COLOR_TYPES_DICT[index])) + led_controllable = True + led_supported_colors = [] + if duthost.facts.get("chassis"): + status_led = duthost.facts.get("chassis").get("status_led") + if status_led: + led_controllable = status_led.get("controllable", True) + led_supported_colors = status_led.get("colors") + + if led_controllable: + led_type_skipped = 0 + for index, led_type in enumerate(LED_COLOR_TYPES): + if led_supported_colors: + led_type = set(led_type) & set(led_supported_colors) + if not led_type: + logger.warning("test_status_led: Skipping set status_led to {} (No supported colors)".format(LED_COLOR_TYPES_DICT[index])) + led_type_skipped += 1 + continue + + led_type_result = False + for color in led_type: + result = chassis.set_status_led(platform_api_conn, color) + if self.expect(result is not None, "Failed to perform set_status_led"): + led_type_result = result or led_type_result + if ((result is None) or (not result)): + continue + color_actual = chassis.get_status_led(platform_api_conn) + if self.expect(color_actual is not None, "Failed to retrieve status_led"): + if self.expect(isinstance(color_actual, STRING_TYPE), "Status LED color appears incorrect"): + self.expect(color == color_actual, "Status LED color incorrect (expected: {}, actual: {})".format(color, color_actual)) + self.expect(led_type_result is True, "Failed to set status_led to {}".format(LED_COLOR_TYPES_DICT[index])) + + if led_type_skipped == len(LED_COLOR_TYPES): + pytest.skip("skipped as no supported colors for all types") + + else: + pytest.skip("skipped as chassis's status led is not controllable") self.assert_expectations() diff --git a/tests/platform_tests/api/test_chassis_fans.py b/tests/platform_tests/api/test_chassis_fans.py index 89937e20eae..be32182ca2f 100644 --- a/tests/platform_tests/api/test_chassis_fans.py +++ b/tests/platform_tests/api/test_chassis_fans.py @@ -71,6 +71,19 @@ def compare_value_with_platform_facts(self, duthost, key, value, fan_idx): self.expect(value == expected_value, "'{}' value is incorrect. Got '{}', expected '{}' for fan {}".format(key, value, expected_value, fan_idx)) + def get_fan_facts(self, duthost, fan_idx, def_value, *keys): + if duthost.facts.get("chassis"): + fans = duthost.facts.get("chassis").get("fans") + if fans: + value = fans[fan_idx] + for key in keys: + value = value.get(key) + if value is None: + return def_value + + return value + + return def_value # # Functions to test methods inherited from DeviceBase class @@ -168,8 +181,22 @@ def test_get_direction(self, duthosts, enum_rand_one_per_hwsku_hostname, localho def test_get_fans_target_speed(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, platform_api_conn): + duthost = duthosts[enum_rand_one_per_hwsku_hostname] + fans_skipped = 0 + for i in range(self.num_fans): speed_target_val = 25 + speed_controllable = self.get_fan_facts(duthost, i, True, "speed", "controllable") + if not speed_controllable: + logger.info("test_get_fans_target_speed: Skipping chassis fan {} (speed not controllable)".format(i)) + fans_skipped += 1 + continue + + speed_minimum = self.get_fan_facts(duthost, i, 25, "speed", "minimum") + speed_maximum = self.get_fan_facts(duthost, i, 100, "speed", "maximum") + if speed_minimum > speed_target_val or speed_maximum < speed_target_val: + speed_target_val = random.randint(speed_minimum, speed_maximum) + speed_set = fan.set_speed(platform_api_conn, i, speed_target_val) target_speed = fan.get_target_speed(platform_api_conn, i) if self.expect(target_speed is not None, "Unable to retrieve Fan {} target speed".format(i)): @@ -177,6 +204,9 @@ def test_get_fans_target_speed(self, duthosts, enum_rand_one_per_hwsku_hostname, self.expect(target_speed == speed_target_val, "Fan {} target speed setting is not correct, speed_target_val {} target_speed = {}".format( i, speed_target_val, target_speed)) + if fans_skipped == self.num_fans: + pytest.skip("skipped as all chassis fans' speed is not controllable") + self.assert_expectations() def test_get_fans_speed_tolerance(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, platform_api_conn): @@ -192,8 +222,21 @@ def test_get_fans_speed_tolerance(self, duthosts, enum_rand_one_per_hwsku_hostna def test_set_fans_speed(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, platform_api_conn): target_speed = random.randint(1, 100) + duthost = duthosts[enum_rand_one_per_hwsku_hostname] + fans_skipped = 0 for i in range(self.num_fans): + speed_controllable = self.get_fan_facts(duthost, i, True, "speed", "controllable") + if not speed_controllable: + logger.info("test_set_fans_speed: Skipping chassis fan {} (speed not controllable)".format(i)) + fans_skipped += 1 + continue + + speed_minimum = self.get_fan_facts(duthost, i, 1, "speed", "minimum") + speed_maximum = self.get_fan_facts(duthost, i, 100, "speed", "maximum") + if speed_minimum > target_speed or speed_maximum < target_speed: + target_speed = random.randint(speed_minimum, speed_maximum) + speed = fan.get_speed(platform_api_conn, i) speed_tol = fan.get_speed_tolerance(platform_api_conn, i) @@ -204,6 +247,9 @@ def test_set_fans_speed(self, duthosts, enum_rand_one_per_hwsku_hostname, localh self.expect(abs(act_speed - target_speed) <= speed_tol, "Fan {} speed change from {} to {} is not within tolerance, actual speed {}".format(i, speed, target_speed, act_speed)) + if fans_skipped == self.num_fans: + pytest.skip("skipped as all chassis fans' speed is not controllable") + self.assert_expectations() def test_set_fans_led(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, platform_api_conn): @@ -213,8 +259,17 @@ def test_set_fans_led(self, duthosts, enum_rand_one_per_hwsku_hostname, localhos "amber", "green", ] + duthost = duthosts[enum_rand_one_per_hwsku_hostname] + fans_skipped = 0 for i in range(self.num_fans): + led_controllable = self.get_fan_facts(duthost, i, True, "status_led", "controllable") + if not led_controllable: + logger.info("test_set_fans_led: Skipping chassis fan {} (LED not controllable)".format(i)) + fans_skipped += 1 + continue + + LED_COLOR_LIST = self.get_fan_facts(duthost, i, LED_COLOR_LIST, "status_led", "colors") for color in LED_COLOR_LIST: result = fan.set_status_led(platform_api_conn, i, color) @@ -228,4 +283,7 @@ def test_set_fans_led(self, duthosts, enum_rand_one_per_hwsku_hostname, localhos self.expect(color == color_actual, "Status LED color incorrect (expected: {}, actual: {} for fan {})".format( color, color_actual, i)) + if fans_skipped == self.num_fans: + pytest.skip("skipped as all chassis fans' LED is not controllable") + self.assert_expectations() diff --git a/tests/platform_tests/api/test_fan_drawer.py b/tests/platform_tests/api/test_fan_drawer.py index fac9d50f45d..8f8f891bb21 100644 --- a/tests/platform_tests/api/test_fan_drawer.py +++ b/tests/platform_tests/api/test_fan_drawer.py @@ -69,6 +69,20 @@ def compare_value_with_platform_facts(self, duthost, key, value, fan_drawer_idx) self.expect(value == expected_value, "'{}' value is incorrect. Got '{}', expected '{}' for fan drawer {}".format(key, value, expected_value, fan_drawer_idx)) + def get_fan_drawer_facts(self, duthost, fan_drawer_idx, def_value, *keys): + if duthost.facts.get("chassis"): + fan_drawers = duthost.facts.get("chassis").get("fan_drawers") + if fan_drawers: + value = fan_drawers[fan_drawer_idx] + for key in keys: + value = value.get(key) + if value is None: + return def_value + + return value + + return def_value + # # Functions to test methods inherited from DeviceBase class # @@ -185,21 +199,46 @@ def test_set_fan_drawers_led(self, duthosts, enum_rand_one_per_hwsku_hostname, l 2: "off" } + fan_drawers_skipped = 0 for i in range(self.num_fan_drawers): - for index, led_type in enumerate(LED_COLOR_TYPES): - led_type_result = False - for color in led_type: - result = fan_drawer.set_status_led(platform_api_conn, i, color) - if self.expect(result is not None, "Failed to perform set_status_led"): - led_type_result = result or led_type_result - if ((result is None) or (not result)): - continue - color_actual = fan_drawer.get_status_led(platform_api_conn, i) - if self.expect(color_actual is not None, "Failed to retrieve status_led"): - if self.expect(isinstance(color_actual, STRING_TYPE), "Status LED color appears incorrect"): - self.expect(color == color_actual, "Status LED color incorrect (expected: {}, actual: {} for fan_drawer {})".format( - color, color_actual, i)) - self.expect(led_type_result is True, "Failed to set status_led for fan_drawer {} to {}".format(i, LED_COLOR_TYPES_DICT[index])) + led_controllable = self.get_fan_drawer_facts(duthost, i, True, "status_led", "controllable") + led_supported_colors = self.get_fan_drawer_facts(duthost, i, None, "status_led", "colors") + + if led_controllable: + led_type_skipped = 0 + for index, led_type in enumerate(LED_COLOR_TYPES): + if led_supported_colors: + led_type = set(led_type) & set(led_supported_colors) + if not led_type: + logger.warning("test_status_led: Skipping fandrawer {} set status_led to {} (No supported colors)".format(i, LED_COLOR_TYPES_DICT[index])) + led_type_skipped += 1 + continue + + led_type_result = False + for color in led_type: + result = fan_drawer.set_status_led(platform_api_conn, i, color) + if self.expect(result is not None, "Failed to perform set_status_led"): + led_type_result = result or led_type_result + if ((result is None) or (not result)): + continue + color_actual = fan_drawer.get_status_led(platform_api_conn, i) + if self.expect(color_actual is not None, "Failed to retrieve status_led"): + if self.expect(isinstance(color_actual, STRING_TYPE), "Status LED color appears incorrect"): + self.expect(color == color_actual, "Status LED color incorrect (expected: {}, actual: {} for fan_drawer {})".format( + color, color_actual, i)) + self.expect(led_type_result is True, "Failed to set status_led for fan_drawer {} to {}".format(i, LED_COLOR_TYPES_DICT[index])) + + if led_type_skipped == len(LED_COLOR_TYPES): + logger.info("test_status_led: Skipping fandrawer {} (no supported colors for all types)".format(i)) + fan_drawers_skipped += 1 + + else: + logger.info("test_status_led: Skipping fandrawer {} (LED is not controllable)".format(i)) + fan_drawers_skipped += 1 + + if fan_drawers_skipped == self.num_fan_drawers: + pytest.skip("skipped as all fandrawers' LED is not controllable/no supported colors") + self.assert_expectations() def test_get_maximum_consumed_power(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, platform_api_conn): diff --git a/tests/platform_tests/api/test_fan_drawer_fans.py b/tests/platform_tests/api/test_fan_drawer_fans.py index a12b72c73f6..5773cb8cbfa 100644 --- a/tests/platform_tests/api/test_fan_drawer_fans.py +++ b/tests/platform_tests/api/test_fan_drawer_fans.py @@ -73,6 +73,21 @@ def compare_value_with_platform_facts(self, duthost, key, value, fan_drawer_idx, self.expect(value == expected_value, "'{}' value is incorrect. Got '{}', expected '{}' for fan {} within fan_drawer {}".format(key, value, expected_value, fan_idx, fan_drawer_idx)) + def get_fan_facts(self, duthost, fan_drawer_idx, fan_idx, def_value, *keys): + if duthost.facts.get("chassis"): + fan_drawers = duthost.facts.get("chassis").get("fan_drawers") + if fan_drawers: + fans = fan_drawers[fan_drawer_idx].get("fans") + if fans: + value = fans[fan_idx] + for key in keys: + value = value.get(key) + if value is None: + return def_value + + return value + + return def_value # # Functions to test methods inherited from DeviceBase class @@ -204,12 +219,26 @@ def test_get_direction(self, duthosts, enum_rand_one_per_hwsku_hostname, localho def test_get_fans_target_speed(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, platform_api_conn): + duthost = duthosts[enum_rand_one_per_hwsku_hostname] + fan_drawers_skipped = 0 + for j in range(self.num_fan_drawers): num_fans = fan_drawer.get_num_fans(platform_api_conn, j) + fans_skipped = 0 for i in range(num_fans): - speed_target_val = 25 + speed_controllable = self.get_fan_facts(duthost, j, i, True, "speed", "controllable") + if not speed_controllable: + logger.info("test_get_fans_target_speed: Skipping fandrawer {} fan {} (speed not controllable)".format(j, i)) + fans_skipped += 1 + continue + + speed_minimum = self.get_fan_facts(duthost, j, i, 25, "speed", "minimum") + speed_maximum = self.get_fan_facts(duthost, j, i, 100, "speed", "maximum") + if speed_minimum > speed_target_val or speed_maximum < speed_target_val: + speed_target_val = random.randint(speed_minimum, speed_maximum) + speed_set = fan_drawer_fan.set_speed(platform_api_conn, j, i, speed_target_val) target_speed = fan_drawer_fan.get_target_speed(platform_api_conn, j, i) if self.expect(target_speed is not None, "Unable to retrieve Fan drawer {} fan {} target speed".format(j, i)): @@ -217,6 +246,12 @@ def test_get_fans_target_speed(self, duthosts, enum_rand_one_per_hwsku_hostname, self.expect(target_speed == speed_target_val, "Fan drawer {} fan {} target speed setting is not correct, speed_target_val {} target_speed = {}".format( j, i, speed_target_val, target_speed)) + if fans_skipped == num_fans: + fan_drawers_skipped += 1 + + if fan_drawers_skipped == self.num_fan_drawers: + pytest.skip("skipped as all fandrawer fans' speed is not controllable") + self.assert_expectations() def test_get_fans_speed_tolerance(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, platform_api_conn): @@ -234,12 +269,26 @@ def test_get_fans_speed_tolerance(self, duthosts, enum_rand_one_per_hwsku_hostna def test_set_fans_speed(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, platform_api_conn): - for j in range(self.num_fan_drawers): - num_fans = fan_drawer.get_num_fans(platform_api_conn, j) + duthost = duthosts[enum_rand_one_per_hwsku_hostname] + fan_drawers_skipped = 0 + for j in range(self.num_fan_drawers): target_speed = random.randint(1, 100) + num_fans = fan_drawer.get_num_fans(platform_api_conn, j) + fans_skipped = 0 for i in range(num_fans): + speed_controllable = self.get_fan_facts(duthost, j, i, True, "speed", "controllable") + if not speed_controllable: + logger.info("test_set_fans_speed: Skipping fandrawer {} fan {} (speed not controllable)".format(j, i)) + fans_skipped += 1 + continue + + speed_minimum = self.get_fan_facts(duthost, j, i, 1, "speed", "minimum") + speed_maximum = self.get_fan_facts(duthost, j, i, 100, "speed", "maximum") + if speed_minimum > target_speed or speed_maximum < target_speed: + target_speed = random.randint(speed_minimum, speed_maximum) + speed = fan_drawer_fan.get_speed(platform_api_conn, j, i) speed_tol = fan_drawer_fan.get_speed_tolerance(platform_api_conn, j, i) @@ -250,6 +299,12 @@ def test_set_fans_speed(self, duthosts, enum_rand_one_per_hwsku_hostname, localh self.expect(abs(act_speed - target_speed) <= speed_tol, "Fan drawer {} fan {} speed change from {} to {} is not within tolerance, actual speed {}".format(j, i, speed, target_speed, act_speed)) + if fans_skipped == num_fans: + fan_drawers_skipped += 1 + + if fan_drawers_skipped == self.num_fan_drawers: + pytest.skip("skipped as all fandrawer fans' speed is not controllable") + self.assert_expectations() def test_set_fans_led(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, platform_api_conn): @@ -281,23 +336,51 @@ def test_set_fans_led(self, duthosts, enum_rand_one_per_hwsku_hostname, localhos 2: "off" } + fan_drawers_skipped = 0 for j in range(self.num_fan_drawers): num_fans = fan_drawer.get_num_fans(platform_api_conn, j) + fans_skipped = 0 for i in range(num_fans): - for index, led_type in enumerate(LED_COLOR_TYPES): - led_type_result = False - for color in led_type: - result = fan_drawer_fan.set_status_led(platform_api_conn, j, i, color) - if self.expect(result is not None, "Failed to perform set_status_led"): - led_type_result = result or led_type_result - if ((result is None) or (not result)): - continue - color_actual = fan_drawer_fan.get_status_led(platform_api_conn, j, i) - if self.expect(color_actual is not None, "Failed to retrieve status_led"): - if self.expect(isinstance(color_actual, STRING_TYPE), "Status LED color appears incorrect"): - self.expect(color == color_actual, "Status LED color incorrect (expected: {}, actual: {} for fan {})".format( - color, color_actual, i)) - self.expect(result is True, "Failed to set status_led for fan drawer {} fan {} to {}".format(j , i, LED_COLOR_TYPES_DICT[index])) + led_controllable = self.get_fan_facts(duthost, j, i, True, "status_led", "controllable") + led_supported_colors = self.get_fan_facts(duthost, j, i, None, "status_led", "colors") + + if led_controllable: + led_type_skipped = 0 + for index, led_type in enumerate(LED_COLOR_TYPES): + if led_supported_colors: + led_type = set(led_type) & set(led_supported_colors) + if not led_type: + logger.warning("test_status_led: Skipping fandrawer {} fan {} set status_led to {} (No supported colors)".format(j, i, LED_COLOR_TYPES_DICT[index])) + led_type_skipped += 1 + continue + + led_type_result = False + for color in led_type: + result = fan_drawer_fan.set_status_led(platform_api_conn, j, i, color) + if self.expect(result is not None, "Failed to perform set_status_led"): + led_type_result = result or led_type_result + if ((result is None) or (not result)): + continue + color_actual = fan_drawer_fan.get_status_led(platform_api_conn, j, i) + if self.expect(color_actual is not None, "Failed to retrieve status_led"): + if self.expect(isinstance(color_actual, STRING_TYPE), "Status LED color appears incorrect"): + self.expect(color == color_actual, "Status LED color incorrect (expected: {}, actual: {} for fan {})".format( + color, color_actual, i)) + self.expect(result is True, "Failed to set status_led for fan drawer {} fan {} to {}".format(j , i, LED_COLOR_TYPES_DICT[index])) + + if led_type_skipped == len(LED_COLOR_TYPES): + logger.info("test_status_led: Skipping fandrawer {} fan {} (no supported colors for all types)".format(j, i)) + fans_skipped += 1 + + else: + logger.info("test_status_led: Skipping fandrawer {} fan {} (LED is not controllable)".format(j, i)) + fans_skipped += 1 + + if fans_skipped == num_fans: + fan_drawers_skipped += 1 + + if fan_drawers_skipped == self.num_fan_drawers: + pytest.skip("skipped as all fandrawer fans' LED is not controllable/no supported colors") self.assert_expectations() diff --git a/tests/platform_tests/api/test_psu.py b/tests/platform_tests/api/test_psu.py index 5526726219e..a8787861f45 100644 --- a/tests/platform_tests/api/test_psu.py +++ b/tests/platform_tests/api/test_psu.py @@ -65,6 +65,20 @@ def compare_value_with_platform_facts(self, duthost, key, value, psu_idx): self.expect(value == expected_value, "'{}' value is incorrect. Got '{}', expected '{}' for PSU {}".format(key, value, expected_value, psu_idx)) + def get_psu_facts(self, duthost, psu_idx, def_value, *keys): + if duthost.facts.get("chassis"): + psus = duthost.facts.get("chassis").get("psus") + if psus: + value = psus[psu_idx] + for key in keys: + value = value.get(key) + if value is None: + return def_value + + return value + + return def_value + # # Functions to test methods inherited from DeviceBase class # @@ -257,31 +271,56 @@ def test_led(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, platfo 0: "fault", 1: "normal", 2: "off" - } + } + psus_skipped = 0 for psu_id in range(self.num_psus): name = psu.get_name(platform_api_conn, psu_id) if name in self.psu_skip_list: logger.info("skipping check for {}".format(name)) + psus_skipped += 1 else: - for index, led_type in enumerate(LED_COLOR_TYPES): - led_type_result = False - for color in led_type: - result = psu.set_status_led(platform_api_conn, psu_id, color) - if self.expect(result is not None, "Failed to perform set_status_led of PSU {}".format(psu_id)): - led_type_result = result or led_type_result - if ((result is None) or (not result)): - continue - color_actual = psu.get_status_led(platform_api_conn, psu_id) - if self.expect(color_actual is not None, - "Failed to retrieve status_led of PSU {}".format(psu_id)): - if self.expect(isinstance(color_actual, STRING_TYPE), - "PSU {} status LED color appears incorrect".format(psu_id)): - self.expect(color == color_actual, - "Status LED color incorrect (expected: {}, actual: {}) from PSU {}".format( - color, color_actual, psu_id)) - self.expect(led_type_result is True, - "Failed to set status_led of PSU {} to {}".format(psu_id, LED_COLOR_TYPES_DICT[index])) + led_controllable = self.get_psu_facts(duthost, psu_id, True, "status_led", "controllable") + led_supported_colors = self.get_psu_facts(duthost, psu_id, None, "status_led", "colors") + + if led_controllable: + led_type_skipped = 0 + for index, led_type in enumerate(LED_COLOR_TYPES): + if led_supported_colors: + led_type = set(led_type) & set(led_supported_colors) + if not led_type: + logger.warning("test_status_led: Skipping PSU {} set status_led to {} (No supported colors)".format(psu_id, LED_COLOR_TYPES_DICT[index])) + led_type_skipped += 1 + continue + + led_type_result = False + for color in led_type: + result = psu.set_status_led(platform_api_conn, psu_id, color) + if self.expect(result is not None, "Failed to perform set_status_led of PSU {}".format(psu_id)): + led_type_result = result or led_type_result + if ((result is None) or (not result)): + continue + color_actual = psu.get_status_led(platform_api_conn, psu_id) + if self.expect(color_actual is not None, + "Failed to retrieve status_led of PSU {}".format(psu_id)): + if self.expect(isinstance(color_actual, STRING_TYPE), + "PSU {} status LED color appears incorrect".format(psu_id)): + self.expect(color == color_actual, + "Status LED color incorrect (expected: {}, actual: {}) from PSU {}".format( + color, color_actual, psu_id)) + self.expect(led_type_result is True, + "Failed to set status_led of PSU {} to {}".format(psu_id, LED_COLOR_TYPES_DICT[index])) + + if led_type_skipped == len(LED_COLOR_TYPES): + logger.info("test_status_led: Skipping PSU {} (no supported colors for all types)".format(psu_id)) + psus_skipped += 1 + + else: + logger.info("test_status_led: Skipping PSU {} (LED is not controllable)".format(psu_id)) + psus_skipped += 1 + + if psus_skipped == self.num_psus: + pytest.skip("skipped as all PSUs' LED is not controllable/no supported colors/in skip list") self.assert_expectations() diff --git a/tests/platform_tests/api/test_psu_fans.py b/tests/platform_tests/api/test_psu_fans.py index 94acb3915a4..6075568b691 100644 --- a/tests/platform_tests/api/test_psu_fans.py +++ b/tests/platform_tests/api/test_psu_fans.py @@ -75,6 +75,22 @@ def compare_value_with_platform_facts(self, duthost, key, value, psu_idx, fan_id "'{}' value is incorrect. Got '{}', expected '{}' for fan {} within psu {}".format(key, value, expected_value, fan_idx, psu_idx)) + def get_fan_facts(self, duthost, psu_idx, fan_idx, def_value, *keys): + if duthost.facts.get("chassis"): + psus = duthost.facts.get("chassis").get("psus") + if psus: + fans = psus[psu_idx].get("fans") + if fans: + value = fans[fan_idx] + for key in keys: + value = value.get(key) + if value is None: + return def_value + + return value + + return def_value + # # Functions to test methods inherited from DeviceBase class # @@ -205,12 +221,26 @@ def test_get_direction(self, duthosts, enum_rand_one_per_hwsku_hostname, localho def test_get_fans_target_speed(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, platform_api_conn): + duthost = duthosts[enum_rand_one_per_hwsku_hostname] + psus_skipped = 0 + for j in range(self.num_psus): num_fans = psu.get_num_fans(platform_api_conn, j) + fans_skipped = 0 for i in range(num_fans): - speed_target_val = 25 + speed_controllable = self.get_fan_facts(duthost, j, i, True, "speed", "controllable") + if not speed_controllable: + logger.info("test_get_fans_target_speed: Skipping PSU {} fan {} (speed not controllable)".format(j, i)) + fans_skipped += 1 + continue + + speed_minimum = self.get_fan_facts(duthost, j, i, 25, "speed", "minimum") + speed_maximum = self.get_fan_facts(duthost, j, i, 100, "speed", "maximum") + if speed_minimum > speed_target_val or speed_maximum < speed_target_val: + speed_target_val = random.randint(speed_minimum, speed_maximum) + speed_set = psu_fan.set_speed(platform_api_conn, j, i, speed_target_val) target_speed = psu_fan.get_target_speed(platform_api_conn, j, i) if self.expect(target_speed is not None, "Unable to retrieve psu {} fan {} target speed".format(j, i)): @@ -218,6 +248,12 @@ def test_get_fans_target_speed(self, duthosts, enum_rand_one_per_hwsku_hostname, self.expect(target_speed == speed_target_val, "psu {} fan {} target speed setting is not correct, speed_target_val {} target_speed = {}".format( j, i, speed_target_val, target_speed)) + if fans_skipped == num_fans: + psus_skipped += 1 + + if psus_skipped == self.num_psus: + pytest.skip("skipped as all PSU fans' speed is not controllable") + self.assert_expectations() def test_get_fans_speed_tolerance(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, platform_api_conn): @@ -235,12 +271,26 @@ def test_get_fans_speed_tolerance(self, duthosts, enum_rand_one_per_hwsku_hostna def test_set_fans_speed(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, platform_api_conn): - for j in range(self.num_psus): - num_fans = psu.get_num_fans(platform_api_conn, j) + duthost = duthosts[enum_rand_one_per_hwsku_hostname] + psus_skipped = 0 + for j in range(self.num_psus): target_speed = random.randint(1, 100) + num_fans = psu.get_num_fans(platform_api_conn, j) + fans_skipped = 0 for i in range(num_fans): + speed_controllable = self.get_fan_facts(duthost, j, i, True, "speed", "controllable") + if not speed_controllable: + logger.info("test_set_fans_speed: Skipping PSU {} fan {} (speed not controllable)".format(j, i)) + fans_skipped += 1 + continue + + speed_minimum = self.get_fan_facts(duthost, j, i, 1, "speed", "minimum") + speed_maximum = self.get_fan_facts(duthost, j, i, 100, "speed", "maximum") + if speed_minimum > target_speed or speed_maximum < target_speed: + target_speed = random.randint(speed_minimum, speed_maximum) + speed = psu_fan.get_speed(platform_api_conn, j, i) speed_tol = psu_fan.get_speed_tolerance(platform_api_conn, j, i) @@ -251,6 +301,12 @@ def test_set_fans_speed(self, duthosts, enum_rand_one_per_hwsku_hostname, localh self.expect(abs(act_speed - target_speed) <= speed_tol, "psu {} fan {} speed change from {} to {} is not within tolerance, actual speed {}".format(j, i, speed, target_speed, act_speed)) + if fans_skipped == num_fans: + psus_skipped += 1 + + if psus_skipped == self.num_psus: + pytest.skip("skipped as all PSU fans' speed is not controllable") + self.assert_expectations() def test_set_fans_led(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, platform_api_conn): @@ -260,13 +316,21 @@ def test_set_fans_led(self, duthosts, enum_rand_one_per_hwsku_hostname, localhos "amber", "green", ] - + duthost = duthosts[enum_rand_one_per_hwsku_hostname] + psus_skipped = 0 for j in range(self.num_psus): num_fans = psu.get_num_fans(platform_api_conn, j) + fans_skipped = 0 for i in range(num_fans): + led_controllable = self.get_fan_facts(duthost, j, i, True, "status_led", "controllable") + if not led_controllable: + logger.info("test_set_fans_led: Skipping PSU {} fan {} (LED not controllable)".format(j, i)) + fans_skipped += 1 + continue + LED_COLOR_LIST = self.get_fan_facts(duthost, j, i, LED_COLOR_LIST, "status_led", "colors") for color in LED_COLOR_LIST: result = psu_fan.set_status_led(platform_api_conn, j, i, color) @@ -280,4 +344,10 @@ def test_set_fans_led(self, duthosts, enum_rand_one_per_hwsku_hostname, localhos self.expect(color == color_actual, "Status LED color incorrect (expected: {}, actual: {} for fan {})".format( color, color_actual, i)) + if fans_skipped == num_fans: + psus_skipped += 1 + + if psus_skipped == self.num_psus: + pytest.skip("skipped as all PSU fans' LED is not controllable") + self.assert_expectations() diff --git a/tests/platform_tests/api/test_thermal.py b/tests/platform_tests/api/test_thermal.py index c7399d0cc24..5788636fe39 100644 --- a/tests/platform_tests/api/test_thermal.py +++ b/tests/platform_tests/api/test_thermal.py @@ -65,6 +65,21 @@ def compare_value_with_platform_facts(self, duthost, key, value): "Unable to get thermal name list containing thermal '{}' from platform.json file".format(value)): self.expect(value in expected_values, "Thermal name '{}' is not included in {}".format(value, expected_values)) + + def get_thermal_facts(self, duthost, thermal_idx, def_value, *keys): + if duthost.facts.get("chassis"): + thermals = duthost.facts.get("chassis").get("thermals") + if thermals: + value = thermals[thermal_idx] + for key in keys: + value = value.get(key) + if value is None: + return def_value + + return value + + return def_value + # # Functions to test methods inherited from DeviceBase class # @@ -203,10 +218,17 @@ def test_get_high_critical_threshold(self, duthosts, enum_rand_one_per_hwsku_hos def test_set_low_threshold(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, platform_api_conn): duthost = duthosts[enum_rand_one_per_hwsku_hostname] + thermals_skipped = 0 skip_release_for_platform(duthost, ["202012", "201911", "201811"], ["arista"]) # Ensure the thermal temperature is sane for i in range(self.num_thermals): + threshold_controllable = self.get_thermal_facts(duthost, i, True, "controllable") + if not threshold_controllable: + logger.info("test_set_low_threshold: Skipping thermal {} (threshold not controllable)".format(i)) + thermals_skipped += 1 + continue + low_temperature = 20 result = thermal.set_low_threshold(platform_api_conn, i, low_temperature) if self.expect(result is not None, "Failed to perform set_low_threshold"): @@ -218,14 +240,24 @@ def test_set_low_threshold(self, duthosts, enum_rand_one_per_hwsku_hostname, loc self.expect(temperature == 20, "Thermal {} low threshold {} is not matching the set value {}".format(i, temperature, low_temperature)) + if thermals_skipped == self.num_thermals: + pytest.skip("skipped as all chassis thermals' threshold is not controllable") + self.assert_expectations() def test_set_high_threshold(self, duthosts, enum_rand_one_per_hwsku_hostname, localhost, platform_api_conn): duthost = duthosts[enum_rand_one_per_hwsku_hostname] + thermals_skipped = 0 skip_release_for_platform(duthost, ["202012", "201911", "201811"], ["arista"]) # Ensure the thermal temperature is sane for i in range(self.num_thermals): + threshold_controllable = self.get_thermal_facts(duthost, i, True, "controllable") + if not threshold_controllable: + logger.info("test_set_high_threshold: Skipping thermal {} (threshold not controllable)".format(i)) + thermals_skipped += 1 + continue + high_temperature = 80 result = thermal.set_high_threshold(platform_api_conn, i, high_temperature) if self.expect(result is not None, "Failed to perform set_high_threshold"): @@ -236,4 +268,8 @@ def test_set_high_threshold(self, duthosts, enum_rand_one_per_hwsku_hostname, lo if self.expect(isinstance(temperature, float), "Thermal {} high threshold appears incorrect".format(i)): self.expect(temperature == 80, "Thermal {} high threshold {} is not matching the set value {}".format(i, temperature, high_temperature)) + + if thermals_skipped == self.num_thermals: + pytest.skip("skipped as all chassis thermals' threshold is not controllable") + self.assert_expectations()