From 9b6bad149c924585d7de3c603ded5729dd8773b6 Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Wed, 22 Jan 2025 23:44:31 +0000 Subject: [PATCH 01/24] read ServerList --- src/python_testing/TC_CNET_4_3.py | 77 +++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/python_testing/TC_CNET_4_3.py diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py new file mode 100644 index 00000000000000..c1141124ee3325 --- /dev/null +++ b/src/python_testing/TC_CNET_4_3.py @@ -0,0 +1,77 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import chip.clusters as Clusters +import test_plan_support +from chip.testing.matter_testing import MatterBaseTest, TestStep, default_matter_test_main, has_feature, run_if_endpoint_matches +from mobly import asserts + + +class TC_CNET_4_3(MatterBaseTest): + + def desc_TC_CNET_4_3(self) -> str: + return "[TC-CNET-4.3] [Ethernet] Verification for attributes check [DUT-Server]" + + def pics_TC_CNET_4_3(self) -> list[str]: + """Return the PICS definitions associated with this test.""" + pics = [ + "CNET.S.F02" + ] + return pics + + def steps_TC_CNET_4_3(self) -> list[TestStep]: + steps = [ + TestStep(1, test_plan_support.commission_if_required(), "", is_commissioning=True), + TestStep(2, "TH reads Descriptor Cluster from the DUT with EP0 TH reads ServerList from the DUT") + ] + return steps + + @run_if_endpoint_matches(has_feature(Clusters.NetworkCommissioning, + Clusters.NetworkCommissioning.Bitmaps.Feature.kEthernetNetworkInterface)) + async def test_TC_CNET_4_3(self): + # Comissioning already done + self.step(1) + + self.step(2) + server_list = await self.read_single_attribute_check_success( + cluster=Clusters.Descriptor, + attribute=Clusters.Descriptor.Attributes.ServerList) + asserts.assert_true(49 in server_list, msg="Verify for the presence of an element with value 49 (0x0031) in the ServerList") + + +if __name__ == "__main__": + default_matter_test_main() From 6d499b7a85b47a19e783280703812158cde8e7b9 Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Fri, 31 Jan 2025 21:54:08 +0000 Subject: [PATCH 02/24] WIP step 4 --- src/python_testing/TC_CNET_4_3.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index c1141124ee3325..11b956a16f02ad 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -24,6 +24,8 @@ # app: ${ALL_CLUSTERS_APP} # app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json # script-args: > +# --endpoint 0 +# --networkID ens4 # --storage-path admin_storage.json # --commissioning-method on-network # --discriminator 1234 @@ -39,6 +41,7 @@ import test_plan_support from chip.testing.matter_testing import MatterBaseTest, TestStep, default_matter_test_main, has_feature, run_if_endpoint_matches from mobly import asserts +from chip.testing import matter_asserts class TC_CNET_4_3(MatterBaseTest): @@ -56,7 +59,9 @@ def pics_TC_CNET_4_3(self) -> list[str]: def steps_TC_CNET_4_3(self) -> list[TestStep]: steps = [ TestStep(1, test_plan_support.commission_if_required(), "", is_commissioning=True), - TestStep(2, "TH reads Descriptor Cluster from the DUT with EP0 TH reads ServerList from the DUT") + TestStep(2, "TH reads Descriptor Cluster from the DUT with EP0 TH reads ServerList from the DUT"), + TestStep(3, "TH reads the MaxNetworks attribute from the DUT"), + TestStep(4, "TH reads the Networks attribute list from the DUT") ] return steps @@ -72,6 +77,19 @@ async def test_TC_CNET_4_3(self): attribute=Clusters.Descriptor.Attributes.ServerList) asserts.assert_true(49 in server_list, msg="Verify for the presence of an element with value 49 (0x0031) in the ServerList") + self.step(3) + max_networks = await self.read_single_attribute_check_success( + cluster=Clusters.NetworkCommissioning, + attribute=Clusters.NetworkCommissioning.Attributes.MaxNetworks) + matter_asserts.assert_int_in_range(max_networks, min_value=1, max_value=255, description="MaxNetworks") + + self.step(4) + networks = await self.read_single_attribute_check_success( + cluster=Clusters.NetworkCommissioning, + attribute=Clusters.NetworkCommissioning.Attributes.Networks) + # [NetworkCommissioning.Structs.NetworkInfoStruct(networkID=b'ens4', connected=True, networkIdentifier=None, clientIdentifier=None)] + print(networks) + if __name__ == "__main__": default_matter_test_main() From 2b508ea632d80cf13fd4ad1c4edff642232fb616 Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Fri, 31 Jan 2025 23:42:45 -0600 Subject: [PATCH 03/24] impl step 4 --- src/python_testing/TC_CNET_4_3.py | 21 ++++++++---- .../chip/testing/matter_asserts.py | 34 ++++++++++++++----- .../chip/testing/test_matter_asserts.py | 34 +++++++++---------- 3 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index 11b956a16f02ad..5bd55d043106b8 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -39,7 +39,8 @@ import chip.clusters as Clusters import test_plan_support -from chip.testing.matter_testing import MatterBaseTest, TestStep, default_matter_test_main, has_feature, run_if_endpoint_matches +from chip.testing.matter_testing import MatterBaseTest, TestStep, default_matter_test_main, has_feature, \ + run_if_endpoint_matches from mobly import asserts from chip.testing import matter_asserts @@ -68,27 +69,33 @@ def steps_TC_CNET_4_3(self) -> list[TestStep]: @run_if_endpoint_matches(has_feature(Clusters.NetworkCommissioning, Clusters.NetworkCommissioning.Bitmaps.Feature.kEthernetNetworkInterface)) async def test_TC_CNET_4_3(self): - # Comissioning already done + # Commissioning already done self.step(1) self.step(2) server_list = await self.read_single_attribute_check_success( cluster=Clusters.Descriptor, attribute=Clusters.Descriptor.Attributes.ServerList) - asserts.assert_true(49 in server_list, msg="Verify for the presence of an element with value 49 (0x0031) in the ServerList") + asserts.assert_true(49 in server_list, + msg="Verify for the presence of an element with value 49 (0x0031) in the ServerList") self.step(3) - max_networks = await self.read_single_attribute_check_success( + max_networks_count = await self.read_single_attribute_check_success( cluster=Clusters.NetworkCommissioning, attribute=Clusters.NetworkCommissioning.Attributes.MaxNetworks) - matter_asserts.assert_int_in_range(max_networks, min_value=1, max_value=255, description="MaxNetworks") + matter_asserts.assert_int_in_range(max_networks_count, min_value=1, max_value=255, description="MaxNetworks") self.step(4) networks = await self.read_single_attribute_check_success( cluster=Clusters.NetworkCommissioning, attribute=Clusters.NetworkCommissioning.Attributes.Networks) - # [NetworkCommissioning.Structs.NetworkInfoStruct(networkID=b'ens4', connected=True, networkIdentifier=None, clientIdentifier=None)] - print(networks) + matter_asserts.assert_list_element_type(networks, Clusters.NetworkCommissioning.Structs.NetworkInfoStruct, + "All elements in list are of type NetworkInfoStruct") + matter_asserts.assert_all(networks, lambda x: isinstance(x, bytes) and 1 <= len(x.networkID) <= 32, + "NetworkID field is an octet string within a length range 1 to 32") + connected_networks_count = sum(map(lambda x: x.connected, networks)) + asserts.assert_equal(connected_networks_count, 1, "Verify that only one entry has connected status as TRUE") + asserts.assert_less_equal(connected_networks_count, max_networks_count) if __name__ == "__main__": diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_asserts.py b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_asserts.py index 2371b21557d8bd..9ff75d04434e2b 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_asserts.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_asserts.py @@ -2,7 +2,7 @@ Matter-specific assertions building on top of Mobly asserts. """ -from typing import Any, List, Optional, Type, TypeVar +from typing import Any, List, Optional, Type, TypeVar, Callable from mobly import asserts @@ -134,7 +134,8 @@ def assert_int_in_range(value: Any, min_value: int, max_value: int, description: # List assertions -def assert_list(value: Any, description: str, min_length: Optional[int] = None, max_length: Optional[int] = None) -> None: +def assert_list(value: Any, description: str, min_length: Optional[int] = None, + max_length: Optional[int] = None) -> None: """ Asserts that the value is a list with optional length constraints. @@ -158,22 +159,36 @@ def assert_list(value: Any, description: str, min_length: Optional[int] = None, f"{description} must not exceed {max_length} elements") -def assert_list_element_type(value: List[Any], description: str, expected_type: Type[T]) -> None: +def assert_all(value: List[T], condition: Callable[[T], bool], description: str) -> None: + """ + Asserts that all elements in the list satisfy the provided condition. + + Args: + value (List[T]): The list of elements to check. + condition (Callable[[T], bool]): A function that takes an element from value and returns True if it meets the condition, False otherwise. + description: User-defined description for error messages + + Raises: + AssertionError: If any element in the list does not satisfy the condition. + """ + assert_list(value, description) + for i, item in enumerate(value): + asserts.assert_true(condition(item), f"Element at index {i} does not satisfy the condition: {description}") + + +def assert_list_element_type(value: List[Any], expected_type: Type[T], description: str) -> None: """ Asserts that all elements in the list are of the expected type. Args: value: The list to validate - description: User-defined description for error messages expected_type: The type that all elements should match + description: User-defined description for error messages Raises: AssertionError: If value is not a list or contains elements of wrong type """ - assert_list(value, description) - for i, item in enumerate(value): - asserts.assert_true(isinstance(item, expected_type), - f"{description}[{i}] must be of type {expected_type.__name__}") + assert_all(value, lambda x: isinstance(x, expected_type), f"{description} must be of type {expected_type.__name__}") # String assertions @@ -192,7 +207,8 @@ def assert_is_string(value: Any, description: str) -> None: asserts.assert_true(isinstance(value, str), f"{description} must be a string") -def assert_string_length(value: Any, description: str, min_length: Optional[int] = None, max_length: Optional[int] = None) -> None: +def assert_string_length(value: Any, description: str, min_length: Optional[int] = None, + max_length: Optional[int] = None) -> None: """ Asserts that the string length is within the specified bounds. diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/test_matter_asserts.py b/src/python_testing/matter_testing_infrastructure/chip/testing/test_matter_asserts.py index 88df62ffdad721..11e1a632e94600 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/test_matter_asserts.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/test_matter_asserts.py @@ -79,42 +79,42 @@ def test_assert_valid_uint8(self): def test_assert_valid_int64(self): """Test assert_valid_int64 with valid and invalid values.""" # Valid cases - matter_asserts.assert_valid_int64(-2**63, "test_min") - matter_asserts.assert_valid_int64(2**63 - 1, "test_max") + matter_asserts.assert_valid_int64(-2 ** 63, "test_min") + matter_asserts.assert_valid_int64(2 ** 63 - 1, "test_max") # Invalid cases with self.assertRaises(signals.TestFailure): - matter_asserts.assert_valid_int64(-2**63 - 1, "test_too_small") + matter_asserts.assert_valid_int64(-2 ** 63 - 1, "test_too_small") with self.assertRaises(signals.TestFailure): - matter_asserts.assert_valid_int64(2**63, "test_too_large") + matter_asserts.assert_valid_int64(2 ** 63, "test_too_large") with self.assertRaises(signals.TestFailure): matter_asserts.assert_valid_int64("42", "test_string") def test_assert_valid_int32(self): """Test assert_valid_int32 with valid and invalid values.""" # Valid cases - matter_asserts.assert_valid_int32(-2**31, "test_min") - matter_asserts.assert_valid_int32(2**31 - 1, "test_max") + matter_asserts.assert_valid_int32(-2 ** 31, "test_min") + matter_asserts.assert_valid_int32(2 ** 31 - 1, "test_max") # Invalid cases with self.assertRaises(signals.TestFailure): - matter_asserts.assert_valid_int32(-2**31 - 1, "test_too_small") + matter_asserts.assert_valid_int32(-2 ** 31 - 1, "test_too_small") with self.assertRaises(signals.TestFailure): - matter_asserts.assert_valid_int32(2**31, "test_too_large") + matter_asserts.assert_valid_int32(2 ** 31, "test_too_large") with self.assertRaises(signals.TestFailure): matter_asserts.assert_valid_int32("42", "test_string") def test_assert_valid_int16(self): """Test assert_valid_int16 with valid and invalid values.""" # Valid cases - matter_asserts.assert_valid_int16(-2**15, "test_min") - matter_asserts.assert_valid_int16(2**15 - 1, "test_max") + matter_asserts.assert_valid_int16(-2 ** 15, "test_min") + matter_asserts.assert_valid_int16(2 ** 15 - 1, "test_max") # Invalid cases with self.assertRaises(signals.TestFailure): - matter_asserts.assert_valid_int16(-2**15 - 1, "test_too_small") + matter_asserts.assert_valid_int16(-2 ** 15 - 1, "test_too_small") with self.assertRaises(signals.TestFailure): - matter_asserts.assert_valid_int16(2**15, "test_too_large") + matter_asserts.assert_valid_int16(2 ** 15, "test_too_large") with self.assertRaises(signals.TestFailure): matter_asserts.assert_valid_int16("42", "test_string") @@ -167,15 +167,15 @@ def test_assert_list(self): def test_assert_list_element_type(self): """Test assert_list_element_type with valid and invalid values.""" # Valid cases - matter_asserts.assert_list_element_type([], "test_empty", str) - matter_asserts.assert_list_element_type(["a", "b"], "test_strings", str) - matter_asserts.assert_list_element_type([1, 2, 3], "test_ints", int) + matter_asserts.assert_list_element_type([], str, "test_empty") + matter_asserts.assert_list_element_type(["a", "b"], str, "test_strings") + matter_asserts.assert_list_element_type([1, 2, 3], int, "test_ints") # Invalid cases with self.assertRaises(signals.TestFailure): - matter_asserts.assert_list_element_type("not_a_list", "test_not_list", str) + matter_asserts.assert_list_element_type("not_a_list", str, "test_not_list") with self.assertRaises(signals.TestFailure): - matter_asserts.assert_list_element_type([1, "2", 3], "test_mixed", int) + matter_asserts.assert_list_element_type([1, "2", 3], int, "test_mixed") # String assertion tests def test_assert_is_string(self): From 1e4bf6ae40ed7e904f7f660da8d0bd65515f1be8 Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Sat, 1 Feb 2025 00:44:29 -0600 Subject: [PATCH 04/24] impl step 5 --- src/python_testing/TC_CNET_4_3.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index 5bd55d043106b8..249058b4d3002c 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -62,7 +62,8 @@ def steps_TC_CNET_4_3(self) -> list[TestStep]: TestStep(1, test_plan_support.commission_if_required(), "", is_commissioning=True), TestStep(2, "TH reads Descriptor Cluster from the DUT with EP0 TH reads ServerList from the DUT"), TestStep(3, "TH reads the MaxNetworks attribute from the DUT"), - TestStep(4, "TH reads the Networks attribute list from the DUT") + TestStep(4, "TH reads the Networks attribute list from the DUT"), + TestStep(5, "TH reads InterfaceEnabled attribute from the DUT") ] return steps @@ -91,11 +92,18 @@ async def test_TC_CNET_4_3(self): attribute=Clusters.NetworkCommissioning.Attributes.Networks) matter_asserts.assert_list_element_type(networks, Clusters.NetworkCommissioning.Structs.NetworkInfoStruct, "All elements in list are of type NetworkInfoStruct") - matter_asserts.assert_all(networks, lambda x: isinstance(x, bytes) and 1 <= len(x.networkID) <= 32, + matter_asserts.assert_all(networks, lambda x: isinstance(x.networkID, bytes) and 1 <= len(x.networkID) <= 32, "NetworkID field is an octet string within a length range 1 to 32") connected_networks_count = sum(map(lambda x: x.connected, networks)) - asserts.assert_equal(connected_networks_count, 1, "Verify that only one entry has connected status as TRUE") - asserts.assert_less_equal(connected_networks_count, max_networks_count) + # asserts.assert_equal(connected_networks_count, 1, "Verify that only one entry has connected status as TRUE") + asserts.assert_less_equal(connected_networks_count, max_networks_count, + "Number of entries in the Networks attribute is less than or equal to 'MaxNetworksValue'") + + self.step(5) + interface_enabled = await self.read_single_attribute_check_success( + cluster=Clusters.NetworkCommissioning, + attribute=Clusters.NetworkCommissioning.Attributes.InterfaceEnabled) + asserts.assert_true(interface_enabled, "InterfaceEnabled") if __name__ == "__main__": From 6d847a48f4c3c8d21f986c13c14f66f0719b3a77 Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Sat, 1 Feb 2025 00:49:02 -0600 Subject: [PATCH 05/24] imple step 6 --- src/python_testing/TC_CNET_4_3.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index 249058b4d3002c..d3b8f45624ab5c 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -25,7 +25,6 @@ # app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json # script-args: > # --endpoint 0 -# --networkID ens4 # --storage-path admin_storage.json # --commissioning-method on-network # --discriminator 1234 @@ -43,6 +42,7 @@ run_if_endpoint_matches from mobly import asserts from chip.testing import matter_asserts +from chip.clusters.Types import NullValue class TC_CNET_4_3(MatterBaseTest): @@ -63,7 +63,8 @@ def steps_TC_CNET_4_3(self) -> list[TestStep]: TestStep(2, "TH reads Descriptor Cluster from the DUT with EP0 TH reads ServerList from the DUT"), TestStep(3, "TH reads the MaxNetworks attribute from the DUT"), TestStep(4, "TH reads the Networks attribute list from the DUT"), - TestStep(5, "TH reads InterfaceEnabled attribute from the DUT") + TestStep(5, "TH reads InterfaceEnabled attribute from the DUT"), + TestStep(6, "TH reads LastNetworkingStatus attribute from the DUT") ] return steps @@ -103,7 +104,13 @@ async def test_TC_CNET_4_3(self): interface_enabled = await self.read_single_attribute_check_success( cluster=Clusters.NetworkCommissioning, attribute=Clusters.NetworkCommissioning.Attributes.InterfaceEnabled) - asserts.assert_true(interface_enabled, "InterfaceEnabled") + asserts.assert_true(interface_enabled, "Verify that InterfaceEnabled attribute value is true") + + self.step(6) + last_networking_status = await self.read_single_attribute_check_success( + cluster=Clusters.NetworkCommissioning, + attribute=Clusters.NetworkCommissioning.Attributes.LastNetworkingStatus) + asserts.assert_is(last_networking_status, NullValue, "Verify that LastNetworkingStatus attribute value is null") if __name__ == "__main__": From 94c09f1d56d7921abaed153583bb34d0e32ea092 Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Sat, 1 Feb 2025 01:50:24 -0600 Subject: [PATCH 06/24] impl step 7 --- src/python_testing/TC_CNET_4_3.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index d3b8f45624ab5c..c6d0b09eacfee8 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -64,7 +64,8 @@ def steps_TC_CNET_4_3(self) -> list[TestStep]: TestStep(3, "TH reads the MaxNetworks attribute from the DUT"), TestStep(4, "TH reads the Networks attribute list from the DUT"), TestStep(5, "TH reads InterfaceEnabled attribute from the DUT"), - TestStep(6, "TH reads LastNetworkingStatus attribute from the DUT") + TestStep(6, "TH reads LastNetworkingStatus attribute from the DUT"), + TestStep(7, "TH reads the LastNetworkID attribute from the DUT") ] return steps @@ -96,8 +97,8 @@ async def test_TC_CNET_4_3(self): matter_asserts.assert_all(networks, lambda x: isinstance(x.networkID, bytes) and 1 <= len(x.networkID) <= 32, "NetworkID field is an octet string within a length range 1 to 32") connected_networks_count = sum(map(lambda x: x.connected, networks)) - # asserts.assert_equal(connected_networks_count, 1, "Verify that only one entry has connected status as TRUE") - asserts.assert_less_equal(connected_networks_count, max_networks_count, + asserts.assert_less_equal(connected_networks_count, 1, "Verify that only one entry has connected status as TRUE") + asserts.assert_less_equal(len(networks), max_networks_count, "Number of entries in the Networks attribute is less than or equal to 'MaxNetworksValue'") self.step(5) @@ -112,6 +113,18 @@ async def test_TC_CNET_4_3(self): attribute=Clusters.NetworkCommissioning.Attributes.LastNetworkingStatus) asserts.assert_is(last_networking_status, NullValue, "Verify that LastNetworkingStatus attribute value is null") + self.step(7) + last_network_id = await self.read_single_attribute_check_success( + cluster=Clusters.NetworkCommissioning, + attribute=Clusters.NetworkCommissioning.Attributes.LastNetworkID) + if networks: + matching_networks_count = sum(map(lambda x: x.networkID == last_network_id, networks)) + asserts.assert_equal(matching_networks_count, 1, + "Verify that LastNetworkID attribute matches the NetworkID value of one of the entries") + else: + asserts.assert_is(last_network_id, NullValue, + "Verify if the Networks attribute list is Empty, then LastNetworkID attribute value is null") + if __name__ == "__main__": default_matter_test_main() From c26a9b90594485e39880a4a267e593b52d07ee91 Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Sat, 1 Feb 2025 01:53:16 -0600 Subject: [PATCH 07/24] impl step 8 --- src/python_testing/TC_CNET_4_3.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index c6d0b09eacfee8..913acf50e1ec20 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -65,7 +65,8 @@ def steps_TC_CNET_4_3(self) -> list[TestStep]: TestStep(4, "TH reads the Networks attribute list from the DUT"), TestStep(5, "TH reads InterfaceEnabled attribute from the DUT"), TestStep(6, "TH reads LastNetworkingStatus attribute from the DUT"), - TestStep(7, "TH reads the LastNetworkID attribute from the DUT") + TestStep(7, "TH reads the LastNetworkID attribute from the DUT"), + TestStep(8, "TH reads the LastConnectErrorValue attribute from the DUT") ] return steps @@ -125,6 +126,12 @@ async def test_TC_CNET_4_3(self): asserts.assert_is(last_network_id, NullValue, "Verify if the Networks attribute list is Empty, then LastNetworkID attribute value is null") + self.step(8) + last_connect_error_value = await self.read_single_attribute_check_success( + cluster=Clusters.NetworkCommissioning, + attribute=Clusters.NetworkCommissioning.Attributes.LastConnectErrorValue) + asserts.assert_is(last_connect_error_value, NullValue, "Verify that LastConnectErrorValue attribute value is null") + if __name__ == "__main__": default_matter_test_main() From 7cb1c4a2231a3f48acf5efd8207474f4f92b7a07 Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Sat, 1 Feb 2025 01:56:44 -0600 Subject: [PATCH 08/24] fix step 4 --- src/python_testing/TC_CNET_4_3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index 913acf50e1ec20..c878017dbf1340 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -98,7 +98,7 @@ async def test_TC_CNET_4_3(self): matter_asserts.assert_all(networks, lambda x: isinstance(x.networkID, bytes) and 1 <= len(x.networkID) <= 32, "NetworkID field is an octet string within a length range 1 to 32") connected_networks_count = sum(map(lambda x: x.connected, networks)) - asserts.assert_less_equal(connected_networks_count, 1, "Verify that only one entry has connected status as TRUE") + asserts.assert_equal(connected_networks_count, 1, "Verify that only one entry has connected status as TRUE") asserts.assert_less_equal(len(networks), max_networks_count, "Number of entries in the Networks attribute is less than or equal to 'MaxNetworksValue'") From 098b8c3c6f1cf65ad7160acbb35fa07c3e8bcbd3 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Tue, 4 Feb 2025 16:58:05 +0000 Subject: [PATCH 09/24] Restyled by isort --- src/python_testing/TC_CNET_4_3.py | 7 +++---- .../chip/testing/matter_asserts.py | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index c878017dbf1340..35bbed81a62750 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -38,11 +38,10 @@ import chip.clusters as Clusters import test_plan_support -from chip.testing.matter_testing import MatterBaseTest, TestStep, default_matter_test_main, has_feature, \ - run_if_endpoint_matches -from mobly import asserts -from chip.testing import matter_asserts from chip.clusters.Types import NullValue +from chip.testing import matter_asserts +from chip.testing.matter_testing import MatterBaseTest, TestStep, default_matter_test_main, has_feature, run_if_endpoint_matches +from mobly import asserts class TC_CNET_4_3(MatterBaseTest): diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_asserts.py b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_asserts.py index 9ff75d04434e2b..f1aecd548953ce 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_asserts.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_asserts.py @@ -2,7 +2,7 @@ Matter-specific assertions building on top of Mobly asserts. """ -from typing import Any, List, Optional, Type, TypeVar, Callable +from typing import Any, Callable, List, Optional, Type, TypeVar from mobly import asserts From 71d816f454213f1a0b7a48347893297d5df24b5c Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Tue, 4 Feb 2025 20:02:31 +0000 Subject: [PATCH 10/24] change year --- src/python_testing/TC_CNET_4_3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index 35bbed81a62750..ccc7209cc0707f 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2024 Project CHIP Authors +# Copyright (c) 2025 Project CHIP Authors # All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); From 47d1133ce423d86fea54693f3913a307c07bb46a Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Fri, 7 Feb 2025 18:14:36 +0000 Subject: [PATCH 11/24] fix step 7 --- src/python_testing/TC_CNET_4_3.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index ccc7209cc0707f..640334a7fbf4a9 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -117,13 +117,8 @@ async def test_TC_CNET_4_3(self): last_network_id = await self.read_single_attribute_check_success( cluster=Clusters.NetworkCommissioning, attribute=Clusters.NetworkCommissioning.Attributes.LastNetworkID) - if networks: - matching_networks_count = sum(map(lambda x: x.networkID == last_network_id, networks)) - asserts.assert_equal(matching_networks_count, 1, - "Verify that LastNetworkID attribute matches the NetworkID value of one of the entries") - else: - asserts.assert_is(last_network_id, NullValue, - "Verify if the Networks attribute list is Empty, then LastNetworkID attribute value is null") + asserts.assert_is(last_network_id, NullValue, + "Verify that the LastNetworkID attribute value is null") self.step(8) last_connect_error_value = await self.read_single_attribute_check_success( From 9fbc49f8ea103bcf5ba04aecefade54b15358347 Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Mon, 10 Feb 2025 05:09:44 +0000 Subject: [PATCH 12/24] decouple assert_all and assert_list_element_type --- .../chip/testing/matter_asserts.py | 15 +++--- .../chip/testing/test_matter_asserts.py | 46 ++++++++++++------- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_asserts.py b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_asserts.py index f1aecd548953ce..bf42166f5ae24e 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_asserts.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_asserts.py @@ -134,8 +134,7 @@ def assert_int_in_range(value: Any, min_value: int, max_value: int, description: # List assertions -def assert_list(value: Any, description: str, min_length: Optional[int] = None, - max_length: Optional[int] = None) -> None: +def assert_list(value: Any, description: str, min_length: Optional[int] = None, max_length: Optional[int] = None) -> None: """ Asserts that the value is a list with optional length constraints. @@ -176,19 +175,22 @@ def assert_all(value: List[T], condition: Callable[[T], bool], description: str) asserts.assert_true(condition(item), f"Element at index {i} does not satisfy the condition: {description}") -def assert_list_element_type(value: List[Any], expected_type: Type[T], description: str) -> None: +def assert_list_element_type(value: List[Any], description: str, expected_type: Type[T]) -> None: """ Asserts that all elements in the list are of the expected type. Args: value: The list to validate + description: User-defined description for error messages expected_type: The type that all elements should match - description: User-defined description for error messages Raises: AssertionError: If value is not a list or contains elements of wrong type """ - assert_all(value, lambda x: isinstance(x, expected_type), f"{description} must be of type {expected_type.__name__}") + assert_list(value, description) + for i, item in enumerate(value): + asserts.assert_true(isinstance(item, expected_type), + f"{description}[{i}] must be of type {expected_type.__name__}") # String assertions @@ -207,8 +209,7 @@ def assert_is_string(value: Any, description: str) -> None: asserts.assert_true(isinstance(value, str), f"{description} must be a string") -def assert_string_length(value: Any, description: str, min_length: Optional[int] = None, - max_length: Optional[int] = None) -> None: +def assert_string_length(value: Any, description: str, min_length: Optional[int] = None, max_length: Optional[int] = None) -> None: """ Asserts that the string length is within the specified bounds. diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/test_matter_asserts.py b/src/python_testing/matter_testing_infrastructure/chip/testing/test_matter_asserts.py index 11e1a632e94600..dc43052699bb8f 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/test_matter_asserts.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/test_matter_asserts.py @@ -79,42 +79,42 @@ def test_assert_valid_uint8(self): def test_assert_valid_int64(self): """Test assert_valid_int64 with valid and invalid values.""" # Valid cases - matter_asserts.assert_valid_int64(-2 ** 63, "test_min") - matter_asserts.assert_valid_int64(2 ** 63 - 1, "test_max") + matter_asserts.assert_valid_int64(-2**63, "test_min") + matter_asserts.assert_valid_int64(2**63 - 1, "test_max") # Invalid cases with self.assertRaises(signals.TestFailure): - matter_asserts.assert_valid_int64(-2 ** 63 - 1, "test_too_small") + matter_asserts.assert_valid_int64(-2**63 - 1, "test_too_small") with self.assertRaises(signals.TestFailure): - matter_asserts.assert_valid_int64(2 ** 63, "test_too_large") + matter_asserts.assert_valid_int64(2**63, "test_too_large") with self.assertRaises(signals.TestFailure): matter_asserts.assert_valid_int64("42", "test_string") def test_assert_valid_int32(self): """Test assert_valid_int32 with valid and invalid values.""" # Valid cases - matter_asserts.assert_valid_int32(-2 ** 31, "test_min") - matter_asserts.assert_valid_int32(2 ** 31 - 1, "test_max") + matter_asserts.assert_valid_int32(-2**31, "test_min") + matter_asserts.assert_valid_int32(2**31 - 1, "test_max") # Invalid cases with self.assertRaises(signals.TestFailure): - matter_asserts.assert_valid_int32(-2 ** 31 - 1, "test_too_small") + matter_asserts.assert_valid_int32(-2**31 - 1, "test_too_small") with self.assertRaises(signals.TestFailure): - matter_asserts.assert_valid_int32(2 ** 31, "test_too_large") + matter_asserts.assert_valid_int32(2**31, "test_too_large") with self.assertRaises(signals.TestFailure): matter_asserts.assert_valid_int32("42", "test_string") def test_assert_valid_int16(self): """Test assert_valid_int16 with valid and invalid values.""" # Valid cases - matter_asserts.assert_valid_int16(-2 ** 15, "test_min") - matter_asserts.assert_valid_int16(2 ** 15 - 1, "test_max") + matter_asserts.assert_valid_int16(-2**15, "test_min") + matter_asserts.assert_valid_int16(2**15 - 1, "test_max") # Invalid cases with self.assertRaises(signals.TestFailure): - matter_asserts.assert_valid_int16(-2 ** 15 - 1, "test_too_small") + matter_asserts.assert_valid_int16(-2**15 - 1, "test_too_small") with self.assertRaises(signals.TestFailure): - matter_asserts.assert_valid_int16(2 ** 15, "test_too_large") + matter_asserts.assert_valid_int16(2**15, "test_too_large") with self.assertRaises(signals.TestFailure): matter_asserts.assert_valid_int16("42", "test_string") @@ -164,18 +164,30 @@ def test_assert_list(self): with self.assertRaises(signals.TestFailure): matter_asserts.assert_list([1, 2, 3], "test_max_length", max_length=2) + def test_assert_all(self): + """Test assert_all with valid and invalid values.""" + # Valid cases + matter_asserts.assert_all([], lambda x: isinstance(x, str), "empty list") + matter_asserts.assert_all([1, 2, 3], lambda x: isinstance(x, int), "list of ints") + + # Invalid cases + with self.assertRaises(signals.TestFailure): + matter_asserts.assert_all([1, 2, 'a'], lambda x: isinstance(x, int), "mixed types") + with self.assertRaises(signals.TestFailure): + matter_asserts.assert_all("not a list", lambda x: True, "not a list") + def test_assert_list_element_type(self): """Test assert_list_element_type with valid and invalid values.""" # Valid cases - matter_asserts.assert_list_element_type([], str, "test_empty") - matter_asserts.assert_list_element_type(["a", "b"], str, "test_strings") - matter_asserts.assert_list_element_type([1, 2, 3], int, "test_ints") + matter_asserts.assert_list_element_type([], "test_empty", str) + matter_asserts.assert_list_element_type(["a", "b"], "test_strings", str) + matter_asserts.assert_list_element_type([1, 2, 3], "test_ints", int) # Invalid cases with self.assertRaises(signals.TestFailure): - matter_asserts.assert_list_element_type("not_a_list", str, "test_not_list") + matter_asserts.assert_list_element_type("not_a_list", "test_not_list", str) with self.assertRaises(signals.TestFailure): - matter_asserts.assert_list_element_type([1, "2", 3], int, "test_mixed") + matter_asserts.assert_list_element_type([1, "2", 3], "test_mixed", int) # String assertion tests def test_assert_is_string(self): From 5903c557441c3ef700325ffb3de250153947c36e Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Mon, 10 Feb 2025 06:07:29 +0000 Subject: [PATCH 13/24] network list should not be empty --- src/python_testing/TC_CNET_4_3.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index 640334a7fbf4a9..055fa598877618 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -92,6 +92,7 @@ async def test_TC_CNET_4_3(self): networks = await self.read_single_attribute_check_success( cluster=Clusters.NetworkCommissioning, attribute=Clusters.NetworkCommissioning.Attributes.Networks) + asserts.assert_true(networks, "NetworkInfoStruct list should not be empty") matter_asserts.assert_list_element_type(networks, Clusters.NetworkCommissioning.Structs.NetworkInfoStruct, "All elements in list are of type NetworkInfoStruct") matter_asserts.assert_all(networks, lambda x: isinstance(x.networkID, bytes) and 1 <= len(x.networkID) <= 32, From 2269801f151bed6f2bb4bb8715ce09836ad0f41c Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Mon, 10 Feb 2025 12:40:37 +0000 Subject: [PATCH 14/24] fix argument order --- src/python_testing/TC_CNET_4_3.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index 055fa598877618..cd577f0811dad8 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -93,8 +93,8 @@ async def test_TC_CNET_4_3(self): cluster=Clusters.NetworkCommissioning, attribute=Clusters.NetworkCommissioning.Attributes.Networks) asserts.assert_true(networks, "NetworkInfoStruct list should not be empty") - matter_asserts.assert_list_element_type(networks, Clusters.NetworkCommissioning.Structs.NetworkInfoStruct, - "All elements in list are of type NetworkInfoStruct") + matter_asserts.assert_list_element_type(networks, "All elements in list are of type NetworkInfoStruct", + Clusters.NetworkCommissioning.Structs.NetworkInfoStruct) matter_asserts.assert_all(networks, lambda x: isinstance(x.networkID, bytes) and 1 <= len(x.networkID) <= 32, "NetworkID field is an octet string within a length range 1 to 32") connected_networks_count = sum(map(lambda x: x.connected, networks)) From 09824491b3723c1538305ddb93e5ea34058ae3bf Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Tue, 25 Feb 2025 17:55:37 +0000 Subject: [PATCH 15/24] remove CI arguments for manual tests --- src/python_testing/TC_CNET_4_3.py | 21 --------------------- src/python_testing/test_metadata.yaml | 2 ++ 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index cd577f0811dad8..391cdf8fd81695 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -15,27 +15,6 @@ # limitations under the License. # -# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments -# for details about the block below. -# -# === BEGIN CI TEST ARGUMENTS === -# test-runner-runs: -# run1: -# app: ${ALL_CLUSTERS_APP} -# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json -# script-args: > -# --endpoint 0 -# --storage-path admin_storage.json -# --commissioning-method on-network -# --discriminator 1234 -# --passcode 20202021 -# --PICS src/app/tests/suites/certification/ci-pics-values -# --trace-to json:${TRACE_TEST_JSON}.json -# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto -# factory-reset: true -# quiet: true -# === END CI TEST ARGUMENTS === - import chip.clusters as Clusters import test_plan_support from chip.clusters.Types import NullValue diff --git a/src/python_testing/test_metadata.yaml b/src/python_testing/test_metadata.yaml index 5bd91ecf542152..79988ed6f2432e 100644 --- a/src/python_testing/test_metadata.yaml +++ b/src/python_testing/test_metadata.yaml @@ -3,6 +3,8 @@ not_automated: - name: MinimalRepresentation.py reason: Code/Test not being used or not shared code for any other tests + - name: TC_CNET_4_3.py + reason: CI is not configured for running CNET tests - name: TC_CNET_4_4.py reason: It has no CI execution block, is not executed in CI - name: TC_DGGEN_3_2.py From 6941fa4eecece45498dea68f16710afce2d6f1b6 Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Tue, 25 Feb 2025 17:09:16 -0600 Subject: [PATCH 16/24] Revert "remove CI arguments for manual tests" This reverts commit 09824491b3723c1538305ddb93e5ea34058ae3bf. --- src/python_testing/TC_CNET_4_3.py | 21 +++++++++++++++++++++ src/python_testing/test_metadata.yaml | 2 -- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index 391cdf8fd81695..cd577f0811dad8 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -15,6 +15,27 @@ # limitations under the License. # +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --endpoint 0 +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + import chip.clusters as Clusters import test_plan_support from chip.clusters.Types import NullValue diff --git a/src/python_testing/test_metadata.yaml b/src/python_testing/test_metadata.yaml index 79988ed6f2432e..5bd91ecf542152 100644 --- a/src/python_testing/test_metadata.yaml +++ b/src/python_testing/test_metadata.yaml @@ -3,8 +3,6 @@ not_automated: - name: MinimalRepresentation.py reason: Code/Test not being used or not shared code for any other tests - - name: TC_CNET_4_3.py - reason: CI is not configured for running CNET tests - name: TC_CNET_4_4.py reason: It has no CI execution block, is not executed in CI - name: TC_DGGEN_3_2.py From 986ada67e58edbeedf5566c578670e22522d99e6 Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Tue, 25 Feb 2025 17:15:19 -0600 Subject: [PATCH 17/24] impl step 7 correctly --- src/python_testing/TC_CNET_4_3.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index cd577f0811dad8..56484463067f11 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -118,8 +118,9 @@ async def test_TC_CNET_4_3(self): last_network_id = await self.read_single_attribute_check_success( cluster=Clusters.NetworkCommissioning, attribute=Clusters.NetworkCommissioning.Attributes.LastNetworkID) - asserts.assert_is(last_network_id, NullValue, - "Verify that the LastNetworkID attribute value is null") + matching_networks_count = sum(map(lambda x: x.networkID == last_network_id, networks)) + asserts.assert_equal(matching_networks_count, 1, + "Verify that LastNetworkID attribute matches the NetworkID value of one of the entries") self.step(8) last_connect_error_value = await self.read_single_attribute_check_success( From 3778f06eafd2aceaaa75169ccd2531113f73fab2 Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Tue, 25 Feb 2025 17:24:04 -0600 Subject: [PATCH 18/24] remove PICS --- src/python_testing/TC_CNET_4_3.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index 56484463067f11..2b31e59f410f1a 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -29,7 +29,6 @@ # --commissioning-method on-network # --discriminator 1234 # --passcode 20202021 -# --PICS src/app/tests/suites/certification/ci-pics-values # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # factory-reset: true @@ -49,13 +48,6 @@ class TC_CNET_4_3(MatterBaseTest): def desc_TC_CNET_4_3(self) -> str: return "[TC-CNET-4.3] [Ethernet] Verification for attributes check [DUT-Server]" - def pics_TC_CNET_4_3(self) -> list[str]: - """Return the PICS definitions associated with this test.""" - pics = [ - "CNET.S.F02" - ] - return pics - def steps_TC_CNET_4_3(self) -> list[TestStep]: steps = [ TestStep(1, test_plan_support.commission_if_required(), "", is_commissioning=True), From fce427ddf8cf64555e85db0d594073c73965f7e7 Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Tue, 25 Feb 2025 18:35:13 -0600 Subject: [PATCH 19/24] add expected steps & fix steps 6-7 --- src/python_testing/TC_CNET_4_3.py | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index 2b31e59f410f1a..8e0396a40919b5 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -51,13 +51,24 @@ def desc_TC_CNET_4_3(self) -> str: def steps_TC_CNET_4_3(self) -> list[TestStep]: steps = [ TestStep(1, test_plan_support.commission_if_required(), "", is_commissioning=True), - TestStep(2, "TH reads Descriptor Cluster from the DUT with EP0 TH reads ServerList from the DUT"), - TestStep(3, "TH reads the MaxNetworks attribute from the DUT"), - TestStep(4, "TH reads the Networks attribute list from the DUT"), - TestStep(5, "TH reads InterfaceEnabled attribute from the DUT"), - TestStep(6, "TH reads LastNetworkingStatus attribute from the DUT"), - TestStep(7, "TH reads the LastNetworkID attribute from the DUT"), - TestStep(8, "TH reads the LastConnectErrorValue attribute from the DUT") + TestStep(2, "TH reads Descriptor Cluster from the DUT with EP0 TH reads ServerList from the DUT", + "Verify for the presence of an element with value 49 (0x0031) in the ServerList"), + TestStep(3, "TH reads the MaxNetworks attribute from the DUT", + "Verify that MaxNetworks attribute value is within a range of 1 to 255"), + TestStep(4, "TH reads the Networks attribute list from the DUT", + "Verify that each element in the Networks attribute list has the following fields: 'NetworkID', 'connected'.\n\ + NetworkID field is of type octstr with a length range 1 to 32 \n\ + The connected field is of type bool \n\ + Verify that only one entry has connected status as TRUE \n\ + Verify that the number of entries in the Networks attribute is less than or equal to 'MaxNetworksValue'"), + TestStep(5, "TH reads InterfaceEnabled attribute from the DUT", "Verify that InterfaceEnabled attribute value is true"), + TestStep(6, "TH reads LastNetworkingStatus attribute from the DUT", + "LastNetworkingStatus attribute value will be within any one of the following values \ + Success, NetworkNotFound, OutOfRange, RegulatoryError, UnknownError, null"), + TestStep(7, "TH reads the LastNetworkID attribute from the DUT", + "Verify that LastNetworkID attribute matches the NetworkID value of one of the entries in the Networks attribute list"), + TestStep(8, "TH reads the LastConnectErrorValue attribute from the DUT", + "Verify that LastConnectErrorValue attribute value is null") ] return steps @@ -104,7 +115,8 @@ async def test_TC_CNET_4_3(self): last_networking_status = await self.read_single_attribute_check_success( cluster=Clusters.NetworkCommissioning, attribute=Clusters.NetworkCommissioning.Attributes.LastNetworkingStatus) - asserts.assert_is(last_networking_status, NullValue, "Verify that LastNetworkingStatus attribute value is null") + expected_status = Clusters.NetworkCommissioning.Enums.NetworkCommissioningStatusEnum.kSuccess + asserts.assert_is(last_networking_status, expected_status, "Verify that LastNetworkingStatus attribute value is success") self.step(7) last_network_id = await self.read_single_attribute_check_success( @@ -113,6 +125,7 @@ async def test_TC_CNET_4_3(self): matching_networks_count = sum(map(lambda x: x.networkID == last_network_id, networks)) asserts.assert_equal(matching_networks_count, 1, "Verify that LastNetworkID attribute matches the NetworkID value of one of the entries") + asserts.assert_true(isinstance(last_network_id, bytes) and 1 <= len(last_network_id) <= 32) self.step(8) last_connect_error_value = await self.read_single_attribute_check_success( From f58f8a327dcc5e1290f072baa0a345b3879a90c7 Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Thu, 27 Feb 2025 16:39:31 -0600 Subject: [PATCH 20/24] fix step 4 --- src/python_testing/TC_CNET_4_3.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index 8e0396a40919b5..9abe4a8577840c 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -96,8 +96,8 @@ async def test_TC_CNET_4_3(self): cluster=Clusters.NetworkCommissioning, attribute=Clusters.NetworkCommissioning.Attributes.Networks) asserts.assert_true(networks, "NetworkInfoStruct list should not be empty") - matter_asserts.assert_list_element_type(networks, "All elements in list are of type NetworkInfoStruct", - Clusters.NetworkCommissioning.Structs.NetworkInfoStruct) + matter_asserts.assert_list_element_type(networks, Clusters.NetworkCommissioning.Structs.NetworkInfoStruct, + "All elements in list are of type NetworkInfoStruct") matter_asserts.assert_all(networks, lambda x: isinstance(x.networkID, bytes) and 1 <= len(x.networkID) <= 32, "NetworkID field is an octet string within a length range 1 to 32") connected_networks_count = sum(map(lambda x: x.connected, networks)) From 59f663ac9d4c1f43256efff2103d6f1c5c9390d9 Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Thu, 27 Feb 2025 17:57:58 -0600 Subject: [PATCH 21/24] fix step 7 --- src/python_testing/TC_CNET_4_3.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/python_testing/TC_CNET_4_3.py b/src/python_testing/TC_CNET_4_3.py index 9abe4a8577840c..ddabd5ad00f550 100644 --- a/src/python_testing/TC_CNET_4_3.py +++ b/src/python_testing/TC_CNET_4_3.py @@ -125,7 +125,8 @@ async def test_TC_CNET_4_3(self): matching_networks_count = sum(map(lambda x: x.networkID == last_network_id, networks)) asserts.assert_equal(matching_networks_count, 1, "Verify that LastNetworkID attribute matches the NetworkID value of one of the entries") - asserts.assert_true(isinstance(last_network_id, bytes) and 1 <= len(last_network_id) <= 32) + asserts.assert_true(isinstance(last_network_id, bytes) and 1 <= len(last_network_id) <= 32, + "Verify LastNetworkID attribute value will be of type octstr with a length range of 1 to 32") self.step(8) last_connect_error_value = await self.read_single_attribute_check_success( From 7275d0c47cad7d66f9eb784053f9cbe6b1d92226 Mon Sep 17 00:00:00 2001 From: Andrey Khodyrev Date: Fri, 28 Feb 2025 13:38:59 -0600 Subject: [PATCH 22/24] disable test on CI --- src/python_testing/test_metadata.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/python_testing/test_metadata.yaml b/src/python_testing/test_metadata.yaml index 5bd91ecf542152..72428d3ec5c003 100644 --- a/src/python_testing/test_metadata.yaml +++ b/src/python_testing/test_metadata.yaml @@ -3,6 +3,10 @@ not_automated: - name: MinimalRepresentation.py reason: Code/Test not being used or not shared code for any other tests + - name: TC_CNET_4_3.py + reason: + network commissioning cluster does not return expected values on linux example apps - + https://github.com/project-chip/connectedhomeip/issues/37824 - name: TC_CNET_4_4.py reason: It has no CI execution block, is not executed in CI - name: TC_DGGEN_3_2.py From b8d5985e8f358d6bc3deb1a3f77b7aa5df712446 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Fri, 28 Feb 2025 19:39:46 +0000 Subject: [PATCH 23/24] Restyled by whitespace --- src/python_testing/test_metadata.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python_testing/test_metadata.yaml b/src/python_testing/test_metadata.yaml index 72428d3ec5c003..4fcd7da3b35fee 100644 --- a/src/python_testing/test_metadata.yaml +++ b/src/python_testing/test_metadata.yaml @@ -4,7 +4,7 @@ not_automated: - name: MinimalRepresentation.py reason: Code/Test not being used or not shared code for any other tests - name: TC_CNET_4_3.py - reason: + reason: network commissioning cluster does not return expected values on linux example apps - https://github.com/project-chip/connectedhomeip/issues/37824 - name: TC_CNET_4_4.py From 45840684f4004196b6b1b3b5af89489488f1ed45 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Fri, 28 Feb 2025 19:39:51 +0000 Subject: [PATCH 24/24] Restyled by prettier-yaml --- src/python_testing/test_metadata.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/python_testing/test_metadata.yaml b/src/python_testing/test_metadata.yaml index 4fcd7da3b35fee..e56c2daf1d0877 100644 --- a/src/python_testing/test_metadata.yaml +++ b/src/python_testing/test_metadata.yaml @@ -5,7 +5,8 @@ not_automated: reason: Code/Test not being used or not shared code for any other tests - name: TC_CNET_4_3.py reason: - network commissioning cluster does not return expected values on linux example apps - + network commissioning cluster does not return expected values on linux + example apps - https://github.com/project-chip/connectedhomeip/issues/37824 - name: TC_CNET_4_4.py reason: It has no CI execution block, is not executed in CI