From 87abdf2e54deea851bd8afd2b5241cd2f4bdf290 Mon Sep 17 00:00:00 2001 From: jtrejoespinoza-grid Date: Fri, 7 Feb 2025 15:42:18 -0700 Subject: [PATCH 01/11] Min fixes --- src/python_testing/TC_MOD_1_2.py | 166 +++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 src/python_testing/TC_MOD_1_2.py diff --git a/src/python_testing/TC_MOD_1_2.py b/src/python_testing/TC_MOD_1_2.py new file mode 100644 index 00000000000000..89b3174e187b8a --- /dev/null +++ b/src/python_testing/TC_MOD_1_2.py @@ -0,0 +1,166 @@ +# +# Copyright (c) 2023 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 typing + +import logging +import chip.clusters as Clusters +from chip.testing.matter_testing import (MatterBaseTest, TestStep, async_test_body, default_matter_test_main) +from mobly import asserts +from chip.clusters.Types import Nullable + +logger = logging.getLogger(__name__) + + +class MOD_1_2(MatterBaseTest): + """Proposal test for Mode Select Cluster attributes as a server.""" + + def TC_MOD_1_2(self) -> str: + return "80.2.1. [TC-MOD-1.2] Cluster attributes with DUT as Server" + + def pics_MOD_1_2(self): + """Return PICS definitions asscociated with this test.""" + pics = [ + "MOD.S" + ] + return pics + + def steps_MOD_1_2(self) -> list[TestStep]: + steps = [ + TestStep(1, "Commission DUT to TH (can be skipped if done in a preceding test).", is_commissioning=True), + TestStep(2, "TH reads the SupportedModes attribute from DUT"), + TestStep(3, "TH reads the CurrentMode attribute from the DUT"), + TestStep(4, "TH reads the OnMode attribute from the DUT"), + TestStep(5, "TH reads the StartUpMode attribute from the DUT"), + TestStep(6, "TH reads the Description attribute from the DUT"), + TestStep(7, "TH reads the StandardNamespace attribute from the DUT") + ] + return steps + + def _verify_supported_mode(self, supported_mode): + """Verify supported mode. + Each mode should be a struct containing a label (user understandable string describing the mode), mode number (integer that identifies the mode and is unique within this SupportedMode list) and list of semantic tags + MfgCode and Value fields present in the SemanticTags structs should be no larger than 16 bits on the TH (Chip-tool).""" + if not hasattr(supported_mode, 'label') and not isinstance(supported_mode.label, str): + asserts.fail("Supported mode struct does not have attribute label or does not contain string ") + + if not hasattr(supported_mode, 'mode') and not isinstance(supported_mode.mode, int): + asserts.fail("Supported modes struct does not have attribute mode or does not contain int") + + if not hasattr(supported_mode, 'semanticTags'): + asserts.fail("Supported mode struct does not have attribute semanticTags") + + # veirfy if we have entries for semanticTags if there are any verfy values no larger that 16 bits + # entries must have the value and manufacturer code. + self._log_attribute("Semantic tags", supported_mode.semanticTags) + + if isinstance(supported_mode.semanticTags, list) and len(supported_mode.semanticTags) > 0: + logger.info( + "SupportedMode.semanticTags contains values, verifying attributes for manufacturedcode and value are not longer than 16bits int") + for semantictag in supported_mode.semanticTags: + asserts.assert_true(semantictag.mfgCode <= self._16bitshex, "Element semantictag.Mfgcode is greater than 16 bits") + asserts.assert_true(semantictag.value <= self._16bitshex, "Element semantictag.Value is greater than 16 bits") + + def _log_attribute(self, name, value): + logger.info(f"{name} attribute {value} with type {type(value)}") + + @async_test_body + async def test_MOD_1_2(self): + self.cluster = Clusters.ModeSelect + self.endpoint = self.get_endpoint(1) + self._16bitshex = 0xFFFF + + # commision device + # in the test plan step 1 is defined as a precondition. + self.step(1) + + # veirfy the Supported modes + # Verify contains attributes label and mode + # Verify if semantic tags has elements in list , and if there are values assert the values + self.step(2) + supported_modes = await self.read_single_attribute_check_success(endpoint=1, cluster=self.cluster, attribute=self.cluster.Attributes.SupportedModes) + logger.info(f"Supported modes {supported_modes}") + # List must not be empty + asserts.assert_true(len(supported_modes) > 0, "Supported modes can not be empty.") + supported_modes_values = [] + for supported_mode in supported_modes: + logger.info( + f"Label {supported_mode} with type {type(supported_mode)} and {supported_mode.label} and {supported_mode.mode} and {supported_mode.semanticTags}") + # verify the struct values + self._verify_supported_mode(supported_mode=supported_mode) + # after verifying the struct is correct append the mode value. + supported_modes_values.append(supported_mode.mode) + logger.info(f"Supported modes values {supported_modes_values}") + + # Currentmode attribute check must be int and must be in the supported modes values. + self.step(3) + current_mode = await self.read_single_attribute_check_success(endpoint=1, cluster=self.cluster, attribute=self.cluster.Attributes.CurrentMode) + self._log_attribute('CurrentMode', current_mode) + asserts.assert_true(isinstance(current_mode, int), "Current mode is not int") + asserts.assert_in(current_mode, supported_modes_values, f"Current mode {current_mode} is not in {supported_modes_values}") + + # Onmode can be null + self.step(4) + on_mode = await self.read_single_attribute_check_success(endpoint=1, cluster=self.cluster, attribute=self.cluster.Attributes.OnMode) + # on mode can be null + self._log_attribute("OnMode", on_mode) + asserts.assert_true((isinstance(on_mode, int) or isinstance(on_mode, Nullable)), + "Onmode is not int or is not clusters.Types.Nullable") + if not isinstance(on_mode, Nullable): + asserts.assert_in(on_mode, supported_modes_values, f"Onmode {current_mode} is not in {supported_modes_values}") + + # Validate startup mode + self.step(5) + startup_mode = await self.read_single_attribute_check_success(endpoint=1, cluster=self.cluster, attribute=self.cluster.Attributes.StartUpMode) + self._log_attribute("StartupMode", startup_mode) + asserts.assert_true(isinstance(startup_mode, int), "Startupmode is not int") + asserts.assert_in(startup_mode, supported_modes_values, f"Startupmode {current_mode} is not in {supported_modes_values}") + + # string and readable + self.step(6) + description = await self.read_single_attribute_check_success(endpoint=1, cluster=self.cluster, attribute=self.cluster.Attributes.Description) + self._log_attribute("Description", description) + asserts.assert_true(isinstance(description, str), "Description attribute is not instance of str") + + # Verify the StandardNamespace can be 16bits integer or null + self.step(7) + standard_namepace = await self.read_single_attribute_check_success(endpoint=1, cluster=self.cluster, attribute=self.cluster.Attributes.StandardNamespace) + self._log_attribute("StandardNamespace", standard_namepace) + asserts.assert_true((isinstance(standard_namepace, Nullable) or (isinstance(standard_namepace, int) and standard_namepace <= self._16bitshex)), + "Standard namespace is not 16bit or not nullable") + + +if __name__ == "__main__": + default_matter_test_main() From 80c28db7dc8df47bf1d7fff3b35ee9575adfad86 Mon Sep 17 00:00:00 2001 From: jtrejoespinoza-grid Date: Mon, 10 Feb 2025 09:25:44 -0700 Subject: [PATCH 02/11] Added manual step for confirm humnan readable text. --- src/python_testing/TC_MOD_1_2.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/python_testing/TC_MOD_1_2.py b/src/python_testing/TC_MOD_1_2.py index 89b3174e187b8a..85d5f1de10eaa0 100644 --- a/src/python_testing/TC_MOD_1_2.py +++ b/src/python_testing/TC_MOD_1_2.py @@ -21,7 +21,7 @@ # === BEGIN CI TEST ARGUMENTS === # test-runner-runs: # run1: -# app: ALL_CLUSTERS_APP +# app: ${ALL_CLUSTERS_APP} # app-args: --discriminator 1234 --KVS kvs1 --trace-to json:TRACE_APP.json # script-args: > # --storage-path admin_storage.json @@ -101,6 +101,7 @@ async def test_MOD_1_2(self): self.cluster = Clusters.ModeSelect self.endpoint = self.get_endpoint(1) self._16bitshex = 0xFFFF + self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") # commision device # in the test plan step 1 is defined as a precondition. @@ -148,11 +149,19 @@ async def test_MOD_1_2(self): asserts.assert_true(isinstance(startup_mode, int), "Startupmode is not int") asserts.assert_in(startup_mode, supported_modes_values, f"Startupmode {current_mode} is not in {supported_modes_values}") - # string and readable + # Verify the string for ci is larger that 1 char. + # If is non ci ask the user if can read and understand the string. self.step(6) description = await self.read_single_attribute_check_success(endpoint=1, cluster=self.cluster, attribute=self.cluster.Attributes.Description) self._log_attribute("Description", description) - asserts.assert_true(isinstance(description, str), "Description attribute is not instance of str") + if self.is_ci: + asserts.assert_true(isinstance(description, str), "Description attribute is not str") + asserts.assert_true(len(description) >= 1, "Description is lower that 1 char.") + else: + user_response = self.wait_for_user_input(prompt_msg=f"Is the value \"{description}\" for attribute Description a readable and understandable string? Enter 'y' or 'n'", + prompt_msg_placeholder="y", + default_value="y") + asserts.assert_true(user_response.lower() == 'y', f"The description is not understandable to the user.") # Verify the StandardNamespace can be 16bits integer or null self.step(7) From 2e72b2e8bb8cb0bc5be9cbb2c6c339f3dbe78aca Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Mon, 10 Feb 2025 16:26:32 +0000 Subject: [PATCH 03/11] Restyled by isort --- src/python_testing/TC_MOD_1_2.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/python_testing/TC_MOD_1_2.py b/src/python_testing/TC_MOD_1_2.py index 85d5f1de10eaa0..91070d5a2549c2 100644 --- a/src/python_testing/TC_MOD_1_2.py +++ b/src/python_testing/TC_MOD_1_2.py @@ -36,10 +36,11 @@ # === END CI TEST ARGUMENTS ===""import typing import logging + import chip.clusters as Clusters -from chip.testing.matter_testing import (MatterBaseTest, TestStep, async_test_body, default_matter_test_main) -from mobly import asserts from chip.clusters.Types import Nullable +from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts logger = logging.getLogger(__name__) From 84f710d3486e444ae51625775fc4bcfd4ac00814 Mon Sep 17 00:00:00 2001 From: jtrejoespinoza-grid Date: Mon, 10 Feb 2025 10:59:20 -0700 Subject: [PATCH 04/11] Fixes from code-lint --- src/python_testing/TC_MOD_1_2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python_testing/TC_MOD_1_2.py b/src/python_testing/TC_MOD_1_2.py index 91070d5a2549c2..201be7c8fc35ef 100644 --- a/src/python_testing/TC_MOD_1_2.py +++ b/src/python_testing/TC_MOD_1_2.py @@ -162,7 +162,7 @@ async def test_MOD_1_2(self): user_response = self.wait_for_user_input(prompt_msg=f"Is the value \"{description}\" for attribute Description a readable and understandable string? Enter 'y' or 'n'", prompt_msg_placeholder="y", default_value="y") - asserts.assert_true(user_response.lower() == 'y', f"The description is not understandable to the user.") + asserts.assert_true(user_response.lower() == 'y', "The description is not understandable to the user.") # Verify the StandardNamespace can be 16bits integer or null self.step(7) From cabfd794144def3067f7050ba932decdff3d5a0b Mon Sep 17 00:00:00 2001 From: jtrejoespinoza-grid Date: Mon, 10 Feb 2025 13:40:53 -0700 Subject: [PATCH 05/11] Fix 16bit assert. Update to use self.endpoint --- src/python_testing/TC_MOD_1_2.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/python_testing/TC_MOD_1_2.py b/src/python_testing/TC_MOD_1_2.py index 201be7c8fc35ef..1cac0628c477fe 100644 --- a/src/python_testing/TC_MOD_1_2.py +++ b/src/python_testing/TC_MOD_1_2.py @@ -91,8 +91,10 @@ def _verify_supported_mode(self, supported_mode): logger.info( "SupportedMode.semanticTags contains values, verifying attributes for manufacturedcode and value are not longer than 16bits int") for semantictag in supported_mode.semanticTags: - asserts.assert_true(semantictag.mfgCode <= self._16bitshex, "Element semantictag.Mfgcode is greater than 16 bits") - asserts.assert_true(semantictag.value <= self._16bitshex, "Element semantictag.Value is greater than 16 bits") + asserts.assert_true(semantictag >= 0 and semantictag.mfgCode <= self._16bitshex, + "Element semantictag.Mfgcode is greater than 16 bits") + asserts.assert_true(semantictag >= 0 and semantictag.value <= self._16bitshex, + "Element semantictag.Value is greater than 16 bits") def _log_attribute(self, name, value): logger.info(f"{name} attribute {value} with type {type(value)}") @@ -112,7 +114,7 @@ async def test_MOD_1_2(self): # Verify contains attributes label and mode # Verify if semantic tags has elements in list , and if there are values assert the values self.step(2) - supported_modes = await self.read_single_attribute_check_success(endpoint=1, cluster=self.cluster, attribute=self.cluster.Attributes.SupportedModes) + supported_modes = await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.cluster.Attributes.SupportedModes) logger.info(f"Supported modes {supported_modes}") # List must not be empty asserts.assert_true(len(supported_modes) > 0, "Supported modes can not be empty.") @@ -128,24 +130,24 @@ async def test_MOD_1_2(self): # Currentmode attribute check must be int and must be in the supported modes values. self.step(3) - current_mode = await self.read_single_attribute_check_success(endpoint=1, cluster=self.cluster, attribute=self.cluster.Attributes.CurrentMode) + current_mode = await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.cluster.Attributes.CurrentMode) self._log_attribute('CurrentMode', current_mode) asserts.assert_true(isinstance(current_mode, int), "Current mode is not int") asserts.assert_in(current_mode, supported_modes_values, f"Current mode {current_mode} is not in {supported_modes_values}") - # Onmode can be null self.step(4) - on_mode = await self.read_single_attribute_check_success(endpoint=1, cluster=self.cluster, attribute=self.cluster.Attributes.OnMode) - # on mode can be null + on_mode = await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.cluster.Attributes.OnMode) + # On mode can be null self._log_attribute("OnMode", on_mode) asserts.assert_true((isinstance(on_mode, int) or isinstance(on_mode, Nullable)), "Onmode is not int or is not clusters.Types.Nullable") + # verify that OnMode is in the list of Supported Modes, but if null, cant be verified. if not isinstance(on_mode, Nullable): asserts.assert_in(on_mode, supported_modes_values, f"Onmode {current_mode} is not in {supported_modes_values}") # Validate startup mode self.step(5) - startup_mode = await self.read_single_attribute_check_success(endpoint=1, cluster=self.cluster, attribute=self.cluster.Attributes.StartUpMode) + startup_mode = await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.cluster.Attributes.StartUpMode) self._log_attribute("StartupMode", startup_mode) asserts.assert_true(isinstance(startup_mode, int), "Startupmode is not int") asserts.assert_in(startup_mode, supported_modes_values, f"Startupmode {current_mode} is not in {supported_modes_values}") @@ -153,7 +155,7 @@ async def test_MOD_1_2(self): # Verify the string for ci is larger that 1 char. # If is non ci ask the user if can read and understand the string. self.step(6) - description = await self.read_single_attribute_check_success(endpoint=1, cluster=self.cluster, attribute=self.cluster.Attributes.Description) + description = await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.cluster.Attributes.Description) self._log_attribute("Description", description) if self.is_ci: asserts.assert_true(isinstance(description, str), "Description attribute is not str") @@ -164,12 +166,12 @@ async def test_MOD_1_2(self): default_value="y") asserts.assert_true(user_response.lower() == 'y', "The description is not understandable to the user.") - # Verify the StandardNamespace can be 16bits integer or null + # Verify the StandardNamespace can be 16 bits enum or null self.step(7) - standard_namepace = await self.read_single_attribute_check_success(endpoint=1, cluster=self.cluster, attribute=self.cluster.Attributes.StandardNamespace) + standard_namepace = await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.cluster.Attributes.StandardNamespace) self._log_attribute("StandardNamespace", standard_namepace) - asserts.assert_true((isinstance(standard_namepace, Nullable) or (isinstance(standard_namepace, int) and standard_namepace <= self._16bitshex)), - "Standard namespace is not 16bit or not nullable") + asserts.assert_true((isinstance(standard_namepace, Nullable) or (isinstance(standard_namepace, int) and (standard_namepace >= 0 and standard_namepace <= self._16bitshex))), + "Standard namespace is not 16bit enum or not Nullable") if __name__ == "__main__": From a4b29b94daad489ab95b27357a25410dad5748c7 Mon Sep 17 00:00:00 2001 From: jtrejoespinoza-grid Date: Wed, 12 Feb 2025 16:49:54 -0700 Subject: [PATCH 06/11] Fixing issue from code review. --- src/python_testing/TC_MOD_1_2.py | 62 ++++++++++++++++---------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/python_testing/TC_MOD_1_2.py b/src/python_testing/TC_MOD_1_2.py index 1cac0628c477fe..50f3299987a581 100644 --- a/src/python_testing/TC_MOD_1_2.py +++ b/src/python_testing/TC_MOD_1_2.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2023 Project CHIP Authors +# Copyright (c) 2025 Project CHIP Authors # All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,9 +38,9 @@ import logging import chip.clusters as Clusters -from chip.clusters.Types import Nullable from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main from mobly import asserts +from chip.clusters.Types import NullValue logger = logging.getLogger(__name__) @@ -48,7 +48,7 @@ class MOD_1_2(MatterBaseTest): """Proposal test for Mode Select Cluster attributes as a server.""" - def TC_MOD_1_2(self) -> str: + def desc_MOD_1_2(self) -> str: return "80.2.1. [TC-MOD-1.2] Cluster attributes with DUT as Server" def pics_MOD_1_2(self): @@ -91,26 +91,25 @@ def _verify_supported_mode(self, supported_mode): logger.info( "SupportedMode.semanticTags contains values, verifying attributes for manufacturedcode and value are not longer than 16bits int") for semantictag in supported_mode.semanticTags: - asserts.assert_true(semantictag >= 0 and semantictag.mfgCode <= self._16bitshex, + asserts.assert_true(semantictag.mfgCode >= 0 and semantictag.mfgCode <= self._16bitshex, "Element semantictag.Mfgcode is greater than 16 bits") - asserts.assert_true(semantictag >= 0 and semantictag.value <= self._16bitshex, + asserts.assert_true(semantictag.value >= 0 and semantictag.value <= self._16bitshex, "Element semantictag.Value is greater than 16 bits") def _log_attribute(self, name, value): - logger.info(f"{name} attribute {value} with type {type(value)}") + logger.info(f"{name} attribute with value: {value} with type: {type(value)}") @async_test_body async def test_MOD_1_2(self): self.cluster = Clusters.ModeSelect self.endpoint = self.get_endpoint(1) self._16bitshex = 0xFFFF - self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") - # commision device - # in the test plan step 1 is defined as a precondition. + # Commision device + # In the test plan step 1 is defined as a precondition. self.step(1) - # veirfy the Supported modes + # Veirfy the Supported modes # Verify contains attributes label and mode # Verify if semantic tags has elements in list , and if there are values assert the values self.step(2) @@ -122,9 +121,9 @@ async def test_MOD_1_2(self): for supported_mode in supported_modes: logger.info( f"Label {supported_mode} with type {type(supported_mode)} and {supported_mode.label} and {supported_mode.mode} and {supported_mode.semanticTags}") - # verify the struct values + # Verify the struct values self._verify_supported_mode(supported_mode=supported_mode) - # after verifying the struct is correct append the mode value. + # After verifying the struct is correct append the mode value. supported_modes_values.append(supported_mode.mode) logger.info(f"Supported modes values {supported_modes_values}") @@ -137,30 +136,31 @@ async def test_MOD_1_2(self): self.step(4) on_mode = await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.cluster.Attributes.OnMode) - # On mode can be null + # On mode can be Nullvalue self._log_attribute("OnMode", on_mode) - asserts.assert_true((isinstance(on_mode, int) or isinstance(on_mode, Nullable)), - "Onmode is not int or is not clusters.Types.Nullable") - # verify that OnMode is in the list of Supported Modes, but if null, cant be verified. - if not isinstance(on_mode, Nullable): - asserts.assert_in(on_mode, supported_modes_values, f"Onmode {current_mode} is not in {supported_modes_values}") + asserts.assert_true((isinstance(on_mode, int) or on_mode is NullValue), + "Onmode is not int or is not Nullvalue") + # Verify that OnMode is in the list of Supported Modes, but if null, cant be verified. + if on_mode is not NullValue: + asserts.assert_in(on_mode, supported_modes_values, f"Onmode {on_mode} is not in {supported_modes_values}") - # Validate startup mode + # Validate startup mode ( attribute Startup is optional) self.step(5) - startup_mode = await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.cluster.Attributes.StartUpMode) - self._log_attribute("StartupMode", startup_mode) - asserts.assert_true(isinstance(startup_mode, int), "Startupmode is not int") - asserts.assert_in(startup_mode, supported_modes_values, f"Startupmode {current_mode} is not in {supported_modes_values}") - - # Verify the string for ci is larger that 1 char. + if await self.attribute_guard(endpoint=self.endpoint, attribute=self.cluster.Attributes.StartUpMode): + startup_mode = await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.cluster.Attributes.StartUpMode) + self._log_attribute("StartupMode", startup_mode) + asserts.assert_true(isinstance(startup_mode, int), "Startupmode is not int") + asserts.assert_in(startup_mode, supported_modes_values, + f"Startupmode {startup_mode} is not in {supported_modes_values}") + + # Verify the string is str and larger that 1 char. # If is non ci ask the user if can read and understand the string. self.step(6) description = await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.cluster.Attributes.Description) self._log_attribute("Description", description) - if self.is_ci: - asserts.assert_true(isinstance(description, str), "Description attribute is not str") - asserts.assert_true(len(description) >= 1, "Description is lower that 1 char.") - else: + asserts.assert_true(isinstance(description, str), "Description attribute is not str") + asserts.assert_true(len(description) >= 1, "Description is lower that 1 char.") + if not self.is_pics_sdk_ci_only: user_response = self.wait_for_user_input(prompt_msg=f"Is the value \"{description}\" for attribute Description a readable and understandable string? Enter 'y' or 'n'", prompt_msg_placeholder="y", default_value="y") @@ -170,8 +170,8 @@ async def test_MOD_1_2(self): self.step(7) standard_namepace = await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.cluster.Attributes.StandardNamespace) self._log_attribute("StandardNamespace", standard_namepace) - asserts.assert_true((isinstance(standard_namepace, Nullable) or (isinstance(standard_namepace, int) and (standard_namepace >= 0 and standard_namepace <= self._16bitshex))), - "Standard namespace is not 16bit enum or not Nullable") + asserts.assert_true((standard_namepace is NullValue or (isinstance(standard_namepace, int) and (standard_namepace >= 0 and standard_namepace <= self._16bitshex))), + "Standard namespace is not 16bit enum or not Nullvalue") if __name__ == "__main__": From 2a816f320a924ac1e3f2858e90c05475dcdbedbb Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Wed, 12 Feb 2025 23:51:29 +0000 Subject: [PATCH 07/11] Restyled by isort --- src/python_testing/TC_MOD_1_2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python_testing/TC_MOD_1_2.py b/src/python_testing/TC_MOD_1_2.py index 50f3299987a581..387913f6a4b725 100644 --- a/src/python_testing/TC_MOD_1_2.py +++ b/src/python_testing/TC_MOD_1_2.py @@ -38,9 +38,9 @@ import logging import chip.clusters as Clusters +from chip.clusters.Types import NullValue from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main from mobly import asserts -from chip.clusters.Types import NullValue logger = logging.getLogger(__name__) From 23e6dda3ce19b40187fd3018f8d94eb761a38eec Mon Sep 17 00:00:00 2001 From: jtrejoespinoza-grid Date: Fri, 14 Feb 2025 12:22:08 -0700 Subject: [PATCH 08/11] Added attribute_guard to OnMode attribute with DEPONOFF type. --- src/python_testing/TC_MOD_1_2.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/python_testing/TC_MOD_1_2.py b/src/python_testing/TC_MOD_1_2.py index 387913f6a4b725..b60bf6752730de 100644 --- a/src/python_testing/TC_MOD_1_2.py +++ b/src/python_testing/TC_MOD_1_2.py @@ -135,16 +135,18 @@ async def test_MOD_1_2(self): asserts.assert_in(current_mode, supported_modes_values, f"Current mode {current_mode} is not in {supported_modes_values}") self.step(4) - on_mode = await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.cluster.Attributes.OnMode) - # On mode can be Nullvalue - self._log_attribute("OnMode", on_mode) - asserts.assert_true((isinstance(on_mode, int) or on_mode is NullValue), - "Onmode is not int or is not Nullvalue") - # Verify that OnMode is in the list of Supported Modes, but if null, cant be verified. - if on_mode is not NullValue: - asserts.assert_in(on_mode, supported_modes_values, f"Onmode {on_mode} is not in {supported_modes_values}") - - # Validate startup mode ( attribute Startup is optional) + # DEPONOFF in the Mandatory/Optional Column + if await self.attribute_guard(endpoint=self.endpoint, attribute=self.cluster.Attributes.OnMode): + on_mode = await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.cluster.Attributes.OnMode) + # On mode can be Nullvalue + self._log_attribute("OnMode", on_mode) + asserts.assert_true((isinstance(on_mode, int) or on_mode is NullValue), + "Onmode is not int or is not Nullvalue") + # Verify that OnMode is in the list of Supported Modes, but if null, cant be verified. + if on_mode is not NullValue: + asserts.assert_in(on_mode, supported_modes_values, f"Onmode {on_mode} is not in {supported_modes_values}") + + # Validate startup mode (attribute Startup is optional) self.step(5) if await self.attribute_guard(endpoint=self.endpoint, attribute=self.cluster.Attributes.StartUpMode): startup_mode = await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.cluster.Attributes.StartUpMode) From cdf71690e1af85fe0254df3f414596d932936625 Mon Sep 17 00:00:00 2001 From: jtrejoespinoza-grid Date: Tue, 25 Feb 2025 11:34:09 -0700 Subject: [PATCH 09/11] Used Hex valie instead of variable. Confirm mode values are unique. Removed manual check for description value. --- src/python_testing/TC_MOD_1_2.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/python_testing/TC_MOD_1_2.py b/src/python_testing/TC_MOD_1_2.py index b60bf6752730de..9fd470b9a3bea1 100644 --- a/src/python_testing/TC_MOD_1_2.py +++ b/src/python_testing/TC_MOD_1_2.py @@ -91,9 +91,9 @@ def _verify_supported_mode(self, supported_mode): logger.info( "SupportedMode.semanticTags contains values, verifying attributes for manufacturedcode and value are not longer than 16bits int") for semantictag in supported_mode.semanticTags: - asserts.assert_true(semantictag.mfgCode >= 0 and semantictag.mfgCode <= self._16bitshex, + asserts.assert_true(semantictag.mfgCode >= 0 and semantictag.mfgCode <= 0xFFFF, "Element semantictag.Mfgcode is greater than 16 bits") - asserts.assert_true(semantictag.value >= 0 and semantictag.value <= self._16bitshex, + asserts.assert_true(semantictag.value >= 0 and semantictag.value <= 0xFFFF, "Element semantictag.Value is greater than 16 bits") def _log_attribute(self, name, value): @@ -103,7 +103,6 @@ def _log_attribute(self, name, value): async def test_MOD_1_2(self): self.cluster = Clusters.ModeSelect self.endpoint = self.get_endpoint(1) - self._16bitshex = 0xFFFF # Commision device # In the test plan step 1 is defined as a precondition. @@ -125,6 +124,9 @@ async def test_MOD_1_2(self): self._verify_supported_mode(supported_mode=supported_mode) # After verifying the struct is correct append the mode value. supported_modes_values.append(supported_mode.mode) + # Verify mode numbers are unique + asserts.assert_equal(len(supported_modes_values), len(set(supported_modes_values)), + f"Duplicate value found for supported mode values :{supported_modes_values}.") logger.info(f"Supported modes values {supported_modes_values}") # Currentmode attribute check must be int and must be in the supported modes values. @@ -156,23 +158,17 @@ async def test_MOD_1_2(self): f"Startupmode {startup_mode} is not in {supported_modes_values}") # Verify the string is str and larger that 1 char. - # If is non ci ask the user if can read and understand the string. self.step(6) description = await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.cluster.Attributes.Description) self._log_attribute("Description", description) asserts.assert_true(isinstance(description, str), "Description attribute is not str") asserts.assert_true(len(description) >= 1, "Description is lower that 1 char.") - if not self.is_pics_sdk_ci_only: - user_response = self.wait_for_user_input(prompt_msg=f"Is the value \"{description}\" for attribute Description a readable and understandable string? Enter 'y' or 'n'", - prompt_msg_placeholder="y", - default_value="y") - asserts.assert_true(user_response.lower() == 'y', "The description is not understandable to the user.") # Verify the StandardNamespace can be 16 bits enum or null self.step(7) standard_namepace = await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.cluster.Attributes.StandardNamespace) self._log_attribute("StandardNamespace", standard_namepace) - asserts.assert_true((standard_namepace is NullValue or (isinstance(standard_namepace, int) and (standard_namepace >= 0 and standard_namepace <= self._16bitshex))), + asserts.assert_true((standard_namepace is NullValue or (isinstance(standard_namepace, int) and (standard_namepace >= 0 and standard_namepace <= 0xFFFF))), "Standard namespace is not 16bit enum or not Nullvalue") From 1e2ddf69213ff7ce2f62ad405819940f00325803 Mon Sep 17 00:00:00 2001 From: jtrejoespinoza-grid Date: Wed, 26 Feb 2025 14:57:51 -0700 Subject: [PATCH 10/11] Fix typos --- src/python_testing/TC_MOD_1_2.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/python_testing/TC_MOD_1_2.py b/src/python_testing/TC_MOD_1_2.py index 9fd470b9a3bea1..2169816d4f08d3 100644 --- a/src/python_testing/TC_MOD_1_2.py +++ b/src/python_testing/TC_MOD_1_2.py @@ -22,21 +22,20 @@ # test-runner-runs: # run1: # app: ${ALL_CLUSTERS_APP} -# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:TRACE_APP.json +# 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 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # factory-reset: true # quiet: true -# === END CI TEST ARGUMENTS ===""import typing +# === END CI TEST ARGUMENTS ==="" import logging - import chip.clusters as Clusters from chip.clusters.Types import NullValue from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main From 46994c3b7aa46ed8554ca7b76b151474e632caf0 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Wed, 26 Feb 2025 21:59:26 +0000 Subject: [PATCH 11/11] Restyled by isort --- src/python_testing/TC_MOD_1_2.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/python_testing/TC_MOD_1_2.py b/src/python_testing/TC_MOD_1_2.py index 2169816d4f08d3..adb9fb27098aa8 100644 --- a/src/python_testing/TC_MOD_1_2.py +++ b/src/python_testing/TC_MOD_1_2.py @@ -36,6 +36,7 @@ # === END CI TEST ARGUMENTS ==="" import logging + import chip.clusters as Clusters from chip.clusters.Types import NullValue from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main