From 218292407ccc9cbc76d7da4354a852f564995cbd Mon Sep 17 00:00:00 2001 From: James Swan Date: Thu, 9 Jan 2025 18:22:06 +0000 Subject: [PATCH 01/23] test: Implement TC acknowledgement test cases 2.5-2.8 Implements test cases for Terms & Conditions acknowledgement verification: - TC-*-2.5: SetTCAcknowledgements verification - TC-*-2.6: CommissioningComplete with no terms accepted - TC-*-2.7: CommissioningComplete with invalid terms - TC-*-2.8: TCAcknowledgements reset after Factory Reset Remaining test cases to be implemented in follow-up changes: - TC-*-2.9: Reset after fabric removal - TC-*-2.10: Required terms validation - TC-*-2.11: Post-commission updates Testing: Test cases implemented according to test plan specifications. Each test verifies specific TC acknowledgement behaviors. --- src/python_testing/TC_CGEN_2_5.py | 157 ++++++++++++++++++++++++++++++ src/python_testing/TC_CGEN_2_6.py | 66 +++++++++++++ src/python_testing/TC_CGEN_2_7.py | 81 +++++++++++++++ src/python_testing/TC_CGEN_2_8.py | 98 +++++++++++++++++++ 4 files changed, 402 insertions(+) create mode 100644 src/python_testing/TC_CGEN_2_5.py create mode 100644 src/python_testing/TC_CGEN_2_6.py create mode 100644 src/python_testing/TC_CGEN_2_7.py create mode 100644 src/python_testing/TC_CGEN_2_8.py diff --git a/src/python_testing/TC_CGEN_2_5.py b/src/python_testing/TC_CGEN_2_5.py new file mode 100644 index 00000000000000..79adaba1e4df53 --- /dev/null +++ b/src/python_testing/TC_CGEN_2_5.py @@ -0,0 +1,157 @@ +# +# 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${TERMS_AND_CONDITIONS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --KVS kvs1 --tc-min-required-version 1 --tc-required-acknowledgements 1 +# test-runner-run/run1/script-args: --in-test-commissioning-method on-network --qr-code MT:-24J0AFN00KA0648G00 --trace-to json:log +# === END CI TEST ARGUMENTS === + + +import chip.clusters as Clusters +from chip import ChipDeviceCtrl +from chip.commissioning import ROOT_ENDPOINT_ID +from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts + + +class TC_CGEN_2_5(MatterBaseTest): + def desc_TC_CGEN_2_5(self) -> str: + return "[TC-CGEN-2.5] Verification For SetTCAcknowledgements [DUT as Server]" + + def steps_TC_CGEN_2_5(self) -> list[TestStep]: + return [ + TestStep(1, "TH starts commissioning the DUT. It performs all commissioning steps from ArmFailSafe, except SetTCAcknowledgements and CommissioningComplete.", is_commissioning=False), + TestStep(2, "TH reads TCAcknowledgementsRequired attribute from the DUT."), + TestStep(3, "TH sends SetTCAcknowledgements to DUT with the following values:\nTCVersion: Greater than or equal to TCMinRequiredVersion on DUT\nTCUserResponse: All terms required by DUT accepted"), + TestStep(4, "TH sends CommissioningComplete to DUT."), + TestStep(5, "TH reads TCAcceptedVersion attribute from the DUT."), + TestStep(6, "TH reads TCAcknowledgements attribute from the DUT."), + TestStep(7, "TH reads TCMinRequiredVersion attribute from the DUT."), + TestStep(8, "TH reads TCAcknowledgementsRequired attribute from the DUT."), + TestStep(9, "TH sends the SetTCAcknowledgements command to the DUT with the fields set as follows:\nTCVersion: 0\nTCUserResponse: 0"), + ] + + @async_test_body + async def test_TC_CGEN_2_5(self): + commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + + # Don't set TCs for the next commissioning and skip CommissioningComplete so we can manually call CommissioningComplete in order to check the response error code + self.step(1) + commissioner.SetTCRequired(False) + commissioner.SetSkipCommissioningComplete(True) + self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + await self.commission_devices() + + self.step(2) + response: dict[int, Clusters.GeneralCommissioning] = await commissioner.ReadAttribute( + nodeid=self.dut_node_id, + attributes=[ + (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion), + (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion), + (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements), + (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired), + ]) + tcAcceptedVersion = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] + tcMinRequiredVersion = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion] + tcAcknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] + tcAcknowledgementsRequired = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired] + + print(f'tcAcceptedVersion= {tcAcceptedVersion}') + print(f'tcMinRequiredVersion= {tcMinRequiredVersion}') + print(f'tcAcknowledgements= {tcAcknowledgements}') + print(f'tcAcknowledgementsRequired= {tcAcknowledgementsRequired}') + + # Verify that TCAcknowledgementsRequired value is representable in the 'Bool' type + # Verify that TCAcknowledgementsRequired value is True + asserts.assert_equal(tcAcknowledgementsRequired, True, 'Incorrect TCAcknowledgementsRequired') + + self.step(3) + response: Clusters.GeneralCommissioning.Commands.SetTCAcknowledgementsResponse = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements(TCVersion=2**16 - 1, TCUserResponse=2**16 - 1), + timedRequestTimeoutMs=1000) + # Verify that DUT sends SetTCAcknowledgementsResponse Command to TH With ErrorCode as 'OK'(0). + asserts.assert_equal(response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + 'Incorrect error code') + + self.step(4) + response: Clusters.GeneralCommissioning.Commands.CommissioningCompleteResponse = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), + timedRequestTimeoutMs=1000) + # Verify that DUT sends CommissioningCompleteResponse Command to TH With ErrorCode as 'OK'(0). + asserts.assert_equal(response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + 'Incorrect error code') + + # Read attributes of interest + response: dict[int, Clusters.GeneralCommissioning] = await commissioner.ReadAttribute( + nodeid=self.dut_node_id, + attributes=[ + (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion), + (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion), + (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements), + (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired), + ]) + tcAcceptedVersion = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] + tcMinRequiredVersion = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion] + tcAcknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] + tcAcknowledgementsRequired = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired] + + print(f'tcAcceptedVersion= {tcAcceptedVersion}') + print(f'tcMinRequiredVersion= {tcMinRequiredVersion}') + print(f'tcAcknowledgements= {tcAcknowledgements}') + print(f'tcAcknowledgementsRequired= {tcAcknowledgementsRequired}') + + self.step(5) + # Verify that TCAcceptedVersion value fits in the 'uint16' type + asserts.assert_less(tcAcceptedVersion, 2**16, 'Incorrect TCAcceptedVersion') + # Verify that TCAcceptedVersion is the value sent in step 3 + asserts.assert_equal(tcAcceptedVersion, 2**16 - 1, 'Incorrect TCAcceptedVersion') + + self.step(6) + # Verify that TCAcknowledgements is a value representable in the map16 type + # Verify that TCAcknowledgements is the value sent in step 3 + asserts.assert_equal(tcAcknowledgements, 2**16 - 1, 'Incorrect TCAcknowledgements') + + self.step(7) + # Verify that TCMinRequiredVersion value fits in the 'uint16' type + asserts.assert_less(tcMinRequiredVersion, 2**16, 'Incorrect TCMinRequiredVersion') + + self.step(8) + # Verify that TCAcknowledgementsRequired value is False + asserts.assert_equal(tcAcknowledgementsRequired, False, 'Incorrect TCAcknowledgementsRequired') + + self.step(9) + response: Clusters.GeneralCommissioning.Commands.SetTCAcknowledgementsResponse = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements(TCVersion=0, TCUserResponse=0), + timedRequestTimeoutMs=1000) + # Verify that DUT sends SetTCAcknowledgementsResponse Command to TH With ErrorCode as 'TCMinVersionNotMet'(7) + asserts.assert_equal(response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCMinVersionNotMet, 'Incorrect error code') + # Verify that TCAcceptedVersion and TCAcknowledgements still contain the values sent in step 3. + + +if __name__ == "__main__": + default_matter_test_main() \ No newline at end of file diff --git a/src/python_testing/TC_CGEN_2_6.py b/src/python_testing/TC_CGEN_2_6.py new file mode 100644 index 00000000000000..ce30424a6be218 --- /dev/null +++ b/src/python_testing/TC_CGEN_2_6.py @@ -0,0 +1,66 @@ +# +# 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${TERMS_AND_CONDITIONS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --KVS kvs1 --tc-min-required-version 1 --tc-required-acknowledgements 1 +# test-runner-run/run1/script-args: --in-test-commissioning-method on-network --qr-code MT:-24J0AFN00KA0648G00 --trace-to json:log +# === END CI TEST ARGUMENTS === + +import chip.clusters as Clusters +from chip import ChipDeviceCtrl +from chip.commissioning import ROOT_ENDPOINT_ID +from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts + + +class TC_CGEN_2_6(MatterBaseTest): + def desc_TC_CGEN_2_6(self) -> str: + return "[TC-CGEN-2.6] Verification For CommissioningComplete no terms accepted when required [DUT as Server]" + + def steps_TC_CGEN_2_6(self) -> list[TestStep]: + return [ + TestStep(1, "TH starts commissioning the DUT. It performs all commissioning steps from ArmFailSafe to CommissioningComplete, except for TC configuration with SetTCAcknowledgements.", is_commissioning=False), + ] + + @async_test_body + async def test_TC_CGEN_2_6(self): + commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + + # Don't set TCs for the next commissioning and skip CommissioningComplete so we can manually call CommissioningComplete in order to check the response error code + commissioner.SetTCRequired(False) + commissioner.SetSkipCommissioningComplete(True) + self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + + self.step(1) + await self.commission_devices() + response: Clusters.GeneralCommissioning.Commands.CommissioningCompleteResponse = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), + timedRequestTimeoutMs=1000) + + # Verify that DUT sends CommissioningCompleteResponse Command to TH With ErrorCode as 'TCAcknowledgementsNotReceived'(6). + asserts.assert_equal( + response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCAcknowledgementsNotReceived, 'Incorrect error code') + + +if __name__ == "__main__": + default_matter_test_main() \ No newline at end of file diff --git a/src/python_testing/TC_CGEN_2_7.py b/src/python_testing/TC_CGEN_2_7.py new file mode 100644 index 00000000000000..477f6b15de0849 --- /dev/null +++ b/src/python_testing/TC_CGEN_2_7.py @@ -0,0 +1,81 @@ +# +# 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${TERMS_AND_CONDITIONS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --KVS kvs1 --tc-min-required-version 1 --tc-required-acknowledgements 1 +# test-runner-run/run1/script-args: --in-test-commissioning-method on-network --qr-code MT:-24J0AFN00KA0648G00 --trace-to json:log +# === END CI TEST ARGUMENTS === + +import chip.clusters as Clusters +from chip import ChipDeviceCtrl +from chip.commissioning import ROOT_ENDPOINT_ID +from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts + + +class TC_CGEN_2_7(MatterBaseTest): + def desc_TC_CGEN_2_7(self) -> str: + return "[TC-CGEN-2.7] Verification For CommissioningComplete when SetTCAcknowledgements provides invalid terms [DUT as Server]" + + def steps_TC_CGEN_2_7(self) -> list[TestStep]: + return [ + TestStep(1, "TH starts commissioning the DUT. It performs all commissioning steps from ArmFailSafe, except SetTCAcknowledgements and CommissioningComplete.", is_commissioning=False), + TestStep(2, "TH sends SetTCAcknowledgements to DUT with the following values:\nTCVersion: Greater than or equal to TCMinRequiredVersion on DUT\nTCUserResponse: 0"), + TestStep(3, "TH sends CommissioningComplete to DUT."), + ] + + @async_test_body + async def test_TC_CGEN_2_7(self): + commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + + # Don't set TCs for the next commissioning and skip CommissioningComplete so we can manually call CommissioningComplete in order to check the response error code + commissioner.SetTCRequired(False) + commissioner.SetSkipCommissioningComplete(True) + self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + + self.step(1) + await self.commission_devices() + + self.step(2) + response: Clusters.GeneralCommissioning.Commands.SetTCAcknowledgementsResponse = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements(TCVersion=2**16 - 1, TCUserResponse=0), + timedRequestTimeoutMs=1000) + + # Verify that DUT sends SetTCAcknowledgementsResponse Command to TH With ErrorCode as 'RequiredTCNotAccepted'(5). + asserts.assert_equal( + response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kRequiredTCNotAccepted, 'Incorrect error code') + + self.step(3) + response: Clusters.GeneralCommissioning.Commands.CommissioningCompleteResponse = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), + timedRequestTimeoutMs=1000) + + # Verify that DUT sends CommissioningCompleteResponse Command to TH With ErrorCode as 'TCAcknowledgementsNotReceived'(6). + asserts.assert_equal( + response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCAcknowledgementsNotReceived, 'Incorrect error code') + + +if __name__ == "__main__": + default_matter_test_main() \ No newline at end of file diff --git a/src/python_testing/TC_CGEN_2_8.py b/src/python_testing/TC_CGEN_2_8.py new file mode 100644 index 00000000000000..c7ba6f36fd9004 --- /dev/null +++ b/src/python_testing/TC_CGEN_2_8.py @@ -0,0 +1,98 @@ +# +# 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${TERMS_AND_CONDITIONS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --KVS kvs1 --tc-min-required-version 1 --tc-required-acknowledgements 1 +# test-runner-run/run1/script-args: --in-test-commissioning-method on-network --qr-code MT:-24J0AFN00KA0648G00 --trace-to json:log +# === END CI TEST ARGUMENTS === + +from typing import List + +import chip.clusters as Clusters +from chip import ChipDeviceCtrl +from chip.commissioning import ROOT_ENDPOINT_ID +from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts + + +class TC_CGEN_2_8(MatterBaseTest): + + async def remove_commissioner_fabric(self): + commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + + fabrics: List[Clusters.OperationalCredentials.Structs.FabricDescriptorStruct] = await self.read_single_attribute( + dev_ctrl=commissioner, + node_id=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + attribute=Clusters.OperationalCredentials.Attributes.Fabrics) + + # Re-order the list of fabrics so that the test harness admin fabric is removed last + commissioner_fabric = next((fabric for fabric in fabrics if fabric.fabricIndex == commissioner.fabricId), None) + fabrics.remove(commissioner_fabric) + fabrics.append(commissioner_fabric) + + for fabric in fabrics: + response: Clusters.OperationalCredentials.Commands.NOCResponse = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.OperationalCredentials.Commands.RemoveFabric(fabric.fabricIndex), + timedRequestTimeoutMs=1000) + asserts.assert_equal(response.statusCode, Clusters.OperationalCredentials.Enums.NodeOperationalCertStatusEnum.kOk) + + def desc_TC_CGEN_2_8(self) -> str: + return "[TC-CGEN-2.8] Verification For Terms and Conditions Reset [DUT as Server]" + + def steps_TC_CGEN_2_8(self) -> list[TestStep]: + return [ + TestStep(1, "DUT requires terms and conditions. DUT has been successfully commissioned."), + TestStep(2, "User performs factory reset."), + TestStep(3, "User triggers USER INTENT to set the device to be in commissioning mode."), + TestStep(4, "TH starts commissioning the DUT. It performs all commissioning steps, except for TC configuration with SetTCAcknowledgements."), + ] + + @async_test_body + async def test_TC_CGEN_2_8(self): + commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + + self.step(1) + self.step(2) + self.step(3) + self.wait_for_user_input(prompt_msg="Set the DUT into commissioning mode") + + # Don't set TCs for the next commissioning and skip CommissioningComplete so we can manually call CommissioningComplete in order to check the response error code + commissioner.SetTCRequired(False) + commissioner.SetSkipCommissioningComplete(True) + self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + await self.commission_devices() + + self.step(4) + response: Clusters.GeneralCommissioning.Commands.CommissioningCompleteResponse = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), + timedRequestTimeoutMs=1000) + # Verify that DUT sends CommissioningCompleteResponse Command to TH With ErrorCode as 'TCAcknowledgementsNotReceived'(6). + asserts.assert_equal( + response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCAcknowledgementsNotReceived, 'Incorrect error code') + + +if __name__ == "__main__": + default_matter_test_main() \ No newline at end of file From 0bf60996e132a541df8cc23aef7b96d4ccba3809 Mon Sep 17 00:00:00 2001 From: James Swan Date: Mon, 13 Jan 2025 20:00:49 +0000 Subject: [PATCH 02/23] --- src/python_testing/TC_CGEN_2_6.py | 2 +- src/python_testing/TC_CGEN_2_7.py | 2 +- src/python_testing/TC_CGEN_2_8.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/python_testing/TC_CGEN_2_6.py b/src/python_testing/TC_CGEN_2_6.py index ce30424a6be218..606730dcf0f8ab 100644 --- a/src/python_testing/TC_CGEN_2_6.py +++ b/src/python_testing/TC_CGEN_2_6.py @@ -63,4 +63,4 @@ async def test_TC_CGEN_2_6(self): if __name__ == "__main__": - default_matter_test_main() \ No newline at end of file + default_matter_test_main() diff --git a/src/python_testing/TC_CGEN_2_7.py b/src/python_testing/TC_CGEN_2_7.py index 477f6b15de0849..d1ded4f4b06514 100644 --- a/src/python_testing/TC_CGEN_2_7.py +++ b/src/python_testing/TC_CGEN_2_7.py @@ -78,4 +78,4 @@ async def test_TC_CGEN_2_7(self): if __name__ == "__main__": - default_matter_test_main() \ No newline at end of file + default_matter_test_main() diff --git a/src/python_testing/TC_CGEN_2_8.py b/src/python_testing/TC_CGEN_2_8.py index c7ba6f36fd9004..2991a733ffabd0 100644 --- a/src/python_testing/TC_CGEN_2_8.py +++ b/src/python_testing/TC_CGEN_2_8.py @@ -95,4 +95,4 @@ async def test_TC_CGEN_2_8(self): if __name__ == "__main__": - default_matter_test_main() \ No newline at end of file + default_matter_test_main() From 98a4ec80f9753034f2498f470f59117288d0eeed Mon Sep 17 00:00:00 2001 From: James Swan Date: Mon, 13 Jan 2025 20:33:46 +0000 Subject: [PATCH 03/23] test: Implement remaining TC acknowledgement test cases 2.9-2.11 Implements remaining test cases for Terms & Conditions acknowledgement verification: - TC-*-2.9: TCAcknowledgements reset after fabric removal - TC-*-2.10: Required terms validation - TC-*-2.11: Post-commission TC updates This completes the test coverage for TC acknowledgement verification, following up on the previous implementation of test cases 2.5-2.8. The new test cases verify: - TC state after fabric removal - Protection of required terms - Ability to update TC version and acknowledgements post-commissioning Testing: Test cases implemented according to test plan specifications. Each test verifies specific TC acknowledgement behaviors. --- src/python_testing/TC_CGEN_2_10.py | 146 +++++++++++++++++++++++++++ src/python_testing/TC_CGEN_2_11.py | 146 +++++++++++++++++++++++++++ src/python_testing/TC_CGEN_2_5.py | 155 +++++++++++++++-------------- src/python_testing/TC_CGEN_2_6.py | 47 ++++++--- src/python_testing/TC_CGEN_2_7.py | 110 ++++++++++++++++---- src/python_testing/TC_CGEN_2_8.py | 113 +++++++++++++-------- src/python_testing/TC_CGEN_2_9.py | 150 ++++++++++++++++++++++++++++ 7 files changed, 719 insertions(+), 148 deletions(-) create mode 100644 src/python_testing/TC_CGEN_2_10.py create mode 100644 src/python_testing/TC_CGEN_2_11.py create mode 100644 src/python_testing/TC_CGEN_2_9.py diff --git a/src/python_testing/TC_CGEN_2_10.py b/src/python_testing/TC_CGEN_2_10.py new file mode 100644 index 00000000000000..262d34b95909b9 --- /dev/null +++ b/src/python_testing/TC_CGEN_2_10.py @@ -0,0 +1,146 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${TERMS_AND_CONDITIONS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --KVS kvs1 --tc-min-required-version 1 --tc-required-acknowledgements 1 +# test-runner-run/run1/script-args: --in-test-commissioning-method on-network --qr-code MT:-24J0AFN00KA0648G00 --trace-to json:log +# === END CI TEST ARGUMENTS === + +import chip.clusters as Clusters +from chip import ChipDeviceCtrl +from chip.commissioning import ROOT_ENDPOINT_ID +from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts + + +class TC_CGEN_2_10(MatterBaseTest): + def desc_TC_CGEN_2_10(self) -> str: + return "[TC-CGEN-2.10] Verification that required terms can't be unset from TCAcknowledgements with SetTCAcknowledgements [DUT as Server]" + + def steps_TC_CGEN_2_10(self) -> list[TestStep]: + return [ + TestStep(1, "Read TCAcceptedVersion attribute"), + TestStep(2, "Read TCAcknowledgements attribute"), + TestStep(3, "Send SetTCAcknowledgements with TCVersion=0 and TCUserResponse=65535"), + TestStep(4, "Verify TCAcceptedVersion unchanged"), + TestStep(5, "Verify TCAcknowledgements unchanged"), + TestStep(6, "Send SetTCAcknowledgements with TCVersion=acceptedVersion+1 and TCUserResponse=0"), + TestStep(7, "Verify TCAcceptedVersion unchanged"), + TestStep(8, "Verify TCAcknowledgements unchanged") + ] + + @async_test_body + async def test_TC_CGEN_2_10(self): + commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + + # Step 1: Read TCAcceptedVersion + self.step(1) + response = await commissioner.ReadAttribute( + nodeid=self.dut_node_id, + attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion)]) + accepted_version = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] + + # Step 2: Read TCAcknowledgements + self.step(2) + response = await commissioner.ReadAttribute( + nodeid=self.dut_node_id, + attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements)]) + user_acknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] + + # Step 3: Send SetTCAcknowledgements with invalid version + self.step(3) + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( + TCVersion=0, + TCUserResponse=65535), + timedRequestTimeoutMs=1000) + + # Verify TCMinVersionNotMet error + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCMinVersionNotMet, + 'Expected TCMinVersionNotMet error') + + # Step 4: Verify TCAcceptedVersion unchanged + self.step(4) + response = await commissioner.ReadAttribute( + nodeid=self.dut_node_id, + attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion)]) + current_version = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] + asserts.assert_equal( + current_version, + accepted_version, + 'TCAcceptedVersion changed unexpectedly') + + # Step 5: Verify TCAcknowledgements unchanged + self.step(5) + response = await commissioner.ReadAttribute( + nodeid=self.dut_node_id, + attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements)]) + current_acknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] + asserts.assert_equal( + current_acknowledgements, + user_acknowledgements, + 'TCAcknowledgements changed unexpectedly') + + # Step 6: Send SetTCAcknowledgements with invalid response + self.step(6) + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( + TCVersion=accepted_version + 1, + TCUserResponse=0), + timedRequestTimeoutMs=1000) + + # Verify RequiredTCNotAccepted error + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kRequiredTCNotAccepted, + 'Expected RequiredTCNotAccepted error') + + # Step 7: Verify TCAcceptedVersion still unchanged + self.step(7) + response = await commissioner.ReadAttribute( + nodeid=self.dut_node_id, + attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion)]) + current_version = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] + asserts.assert_equal( + current_version, + accepted_version, + 'TCAcceptedVersion changed unexpectedly after second attempt') + + # Step 8: Verify TCAcknowledgements still unchanged + self.step(8) + response = await commissioner.ReadAttribute( + nodeid=self.dut_node_id, + attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements)]) + current_acknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] + asserts.assert_equal( + current_acknowledgements, + user_acknowledgements, + 'TCAcknowledgements changed unexpectedly after second attempt') + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_CGEN_2_11.py b/src/python_testing/TC_CGEN_2_11.py new file mode 100644 index 00000000000000..5d1780635f734d --- /dev/null +++ b/src/python_testing/TC_CGEN_2_11.py @@ -0,0 +1,146 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${TERMS_AND_CONDITIONS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --KVS kvs1 --tc-min-required-version 1 --tc-required-acknowledgements 1 +# test-runner-run/run1/script-args: --in-test-commissioning-method on-network --qr-code MT:-24J0AFN00KA0648G00 --trace-to json:log +# === END CI TEST ARGUMENTS === + +import chip.clusters as Clusters +from chip import ChipDeviceCtrl +from chip.commissioning import ROOT_ENDPOINT_ID +from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts + + +class TC_CGEN_2_11(MatterBaseTest): + def desc_TC_CGEN_2_11(self) -> str: + return "[TC-CGEN-2.11] Verification that TCAcknowledgements and TCAcceptedVersion can be updated after being commissioned [DUT as Server]" + + def steps_TC_CGEN_2_11(self) -> list[TestStep]: + return [ + TestStep(1, "TH begins commissioning the DUT with PASE, failsafe setup, and basic configuration"), + TestStep(2, "TH sends SetTCAcknowledgements with initial TC values"), + TestStep(3, "TH sends CommissioningComplete to DUT"), + TestStep(4, "TH sends SetTCAcknowledgements with updated TC version"), + TestStep(5, "Verify TCAcceptedVersion is updated"), + TestStep(6, "TH sends SetTCAcknowledgements with maximum acknowledgements"), + TestStep(7, "Verify TCAcknowledgements is updated") + ] + + @async_test_body + async def test_TC_CGEN_2_11(self): + commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + + # Step 1: Begin commissioning with PASE and failsafe + self.step(1) + commissioner.SetSkipCommissioningComplete(True) + self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + await self.commission_devices() + + # Step 2: Send initial SetTCAcknowledgements + self.step(2) + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( + TCVersion=self.pixit['CGEN']['TCRevision'], + TCUserResponse=self.pixit['CGEN']['RequiredTCAcknowledgements']), + timedRequestTimeoutMs=1000) + + # Verify initial SetTCAcknowledgements response + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + 'Initial SetTCAcknowledgements failed') + + # Step 3: Send CommissioningComplete + self.step(3) + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), + timedRequestTimeoutMs=1000) + + # Verify CommissioningComplete response + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + 'CommissioningComplete failed') + + # Step 4: Send SetTCAcknowledgements with updated version + self.step(4) + updated_tc_version = self.pixit['CGEN']['TCRevision'] + 1 + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( + TCVersion=updated_tc_version, + TCUserResponse=self.pixit['CGEN']['RequiredTCAcknowledgements']), + timedRequestTimeoutMs=1000) + + # Verify SetTCAcknowledgements response with updated version + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + 'SetTCAcknowledgements with updated version failed') + + # Step 5: Verify TCAcceptedVersion is updated + self.step(5) + response = await commissioner.ReadAttribute( + nodeid=self.dut_node_id, + attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion)]) + current_version = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] + asserts.assert_equal( + current_version, + updated_tc_version, + 'TCAcceptedVersion not updated correctly') + + # Step 6: Send SetTCAcknowledgements with maximum acknowledgements + self.step(6) + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( + TCVersion=updated_tc_version, + TCUserResponse=65535), + timedRequestTimeoutMs=1000) + + # Verify SetTCAcknowledgements response with maximum acknowledgements + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + 'SetTCAcknowledgements with maximum acknowledgements failed') + + # Step 7: Verify TCAcknowledgements is updated + self.step(7) + response = await commissioner.ReadAttribute( + nodeid=self.dut_node_id, + attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements)]) + current_acknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] + asserts.assert_equal( + current_acknowledgements, + 65535, + 'TCAcknowledgements not updated to maximum value') + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_CGEN_2_5.py b/src/python_testing/TC_CGEN_2_5.py index 79adaba1e4df53..f59ff55fc446ce 100644 --- a/src/python_testing/TC_CGEN_2_5.py +++ b/src/python_testing/TC_CGEN_2_5.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2024 Project CHIP Authors +# Copyright (c) 2024-2025 Project CHIP Authors # All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,12 +16,23 @@ # # === BEGIN CI TEST ARGUMENTS === -# test-runner-runs: run1 -# test-runner-run/run1/app: ${TERMS_AND_CONDITIONS_APP} -# test-runner-run/run1/factoryreset: True -# test-runner-run/run1/quiet: True -# test-runner-run/run1/app-args: --KVS kvs1 --tc-min-required-version 1 --tc-required-acknowledgements 1 -# test-runner-run/run1/script-args: --in-test-commissioning-method on-network --qr-code MT:-24J0AFN00KA0648G00 --trace-to json:log +# test-runner-runs: +# run1: +# app: ${TERMS_AND_CONDITIONS_APP} +# app-args: > +# --KVS kvs1 +# --tc-min-required-version 1 +# --tc-required-acknowledgements 1 +# --custom-flow 2 +# --capabilities 6 +# script-args: +# --in-test-commissioning-method on-network +# --tc-version-to-simulate 1 +# --tc-user-response-to-simulate 1 +# --qr-code MT:-24J0AFN00KA0648G00 +# --trace-to json:log +# factoryreset: True +# quiet: True # === END CI TEST ARGUMENTS === @@ -53,58 +64,75 @@ def steps_TC_CGEN_2_5(self) -> list[TestStep]: async def test_TC_CGEN_2_5(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller - # Don't set TCs for the next commissioning and skip CommissioningComplete so we can manually call CommissioningComplete in order to check the response error code + # Step 1: Begin commissioning with PASE and failsafe self.step(1) commissioner.SetTCRequired(False) commissioner.SetSkipCommissioningComplete(True) self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method await self.commission_devices() + # Step 2: Read TCAcknowledgementsRequired self.step(2) - response: dict[int, Clusters.GeneralCommissioning] = await commissioner.ReadAttribute( + response = await commissioner.ReadAttribute( nodeid=self.dut_node_id, - attributes=[ - (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion), - (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion), - (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements), - (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired), - ]) - tcAcceptedVersion = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] - tcMinRequiredVersion = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion] - tcAcknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] + attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired)]) tcAcknowledgementsRequired = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired] - - print(f'tcAcceptedVersion= {tcAcceptedVersion}') - print(f'tcMinRequiredVersion= {tcMinRequiredVersion}') - print(f'tcAcknowledgements= {tcAcknowledgements}') - print(f'tcAcknowledgementsRequired= {tcAcknowledgementsRequired}') - - # Verify that TCAcknowledgementsRequired value is representable in the 'Bool' type - # Verify that TCAcknowledgementsRequired value is True asserts.assert_equal(tcAcknowledgementsRequired, True, 'Incorrect TCAcknowledgementsRequired') + # Step 3: Read TCUpdateDeadline self.step(3) - response: Clusters.GeneralCommissioning.Commands.SetTCAcknowledgementsResponse = await commissioner.SendCommand( + response = await commissioner.ReadAttribute( + nodeid=self.dut_node_id, + attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCUpdateDeadline)]) + tcUpdateDeadline = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCUpdateDeadline] + asserts.assert_less(tcUpdateDeadline, 2**32, 'TCUpdateDeadline exceeds uint32 range') + + # Step 4: Read FeatureMap + self.step(4) + response = await commissioner.ReadAttribute( + nodeid=self.dut_node_id, + attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.FeatureMap)]) + featureMap = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.FeatureMap] + asserts.assert_equal(featureMap & 0x1, 0x1, 'TC feature flag not set') + + # Step 5: Send SetTCAcknowledgements + self.step(5) + response = await commissioner.SendCommand( nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, - payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements(TCVersion=2**16 - 1, TCUserResponse=2**16 - 1), + payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( + TCVersion=self.pixit['CGEN']['TCRevision'], + TCUserResponse=self.pixit['CGEN']['RequiredTCAcknowledgements']), timedRequestTimeoutMs=1000) - # Verify that DUT sends SetTCAcknowledgementsResponse Command to TH With ErrorCode as 'OK'(0). - asserts.assert_equal(response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + asserts.assert_equal(response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, 'Incorrect error code') - self.step(4) - response: Clusters.GeneralCommissioning.Commands.CommissioningCompleteResponse = await commissioner.SendCommand( + # Step 6: Verify TCAcknowledgementsRequired is False + self.step(6) + response = await commissioner.ReadAttribute( + nodeid=self.dut_node_id, + attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired)]) + tcAcknowledgementsRequired = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired] + asserts.assert_equal(tcAcknowledgementsRequired, False, 'TCAcknowledgementsRequired should be False') + + # Step 7: Complete CSR exchange and CASE security setup + self.step(7) + # Note: Implementation needed for CSR exchange and CASE setup + + # Step 8: Send CommissioningComplete + self.step(8) + response = await commissioner.SendCommand( nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), timedRequestTimeoutMs=1000) - # Verify that DUT sends CommissioningCompleteResponse Command to TH With ErrorCode as 'OK'(0). - asserts.assert_equal(response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + asserts.assert_equal(response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, 'Incorrect error code') - # Read attributes of interest - response: dict[int, Clusters.GeneralCommissioning] = await commissioner.ReadAttribute( + # Steps 9-12: Read and verify final attribute values + response = await commissioner.ReadAttribute( nodeid=self.dut_node_id, attributes=[ (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion), @@ -112,46 +140,29 @@ async def test_TC_CGEN_2_5(self): (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements), (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired), ]) - tcAcceptedVersion = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] - tcMinRequiredVersion = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion] - tcAcknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] - tcAcknowledgementsRequired = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired] - - print(f'tcAcceptedVersion= {tcAcceptedVersion}') - print(f'tcMinRequiredVersion= {tcMinRequiredVersion}') - print(f'tcAcknowledgements= {tcAcknowledgements}') - print(f'tcAcknowledgementsRequired= {tcAcknowledgementsRequired}') - - self.step(5) - # Verify that TCAcceptedVersion value fits in the 'uint16' type - asserts.assert_less(tcAcceptedVersion, 2**16, 'Incorrect TCAcceptedVersion') - # Verify that TCAcceptedVersion is the value sent in step 3 - asserts.assert_equal(tcAcceptedVersion, 2**16 - 1, 'Incorrect TCAcceptedVersion') - self.step(6) - # Verify that TCAcknowledgements is a value representable in the map16 type - # Verify that TCAcknowledgements is the value sent in step 3 - asserts.assert_equal(tcAcknowledgements, 2**16 - 1, 'Incorrect TCAcknowledgements') + # Step 9: Verify TCAcceptedVersion + self.step(9) + tcAcceptedVersion = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] + asserts.assert_less(tcAcceptedVersion, 2**16, 'TCAcceptedVersion exceeds uint16 range') + asserts.assert_equal(tcAcceptedVersion, self.pixit['CGEN']['TCRevision'], 'Incorrect TCAcceptedVersion') - self.step(7) - # Verify that TCMinRequiredVersion value fits in the 'uint16' type - asserts.assert_less(tcMinRequiredVersion, 2**16, 'Incorrect TCMinRequiredVersion') + # Step 10: Verify TCAcknowledgements + self.step(10) + tcAcknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] + asserts.assert_less(tcAcknowledgements, 2**16, 'TCAcknowledgements exceeds map16 range') + asserts.assert_equal(tcAcknowledgements, self.pixit['CGEN']['RequiredTCAcknowledgements'], 'Incorrect TCAcknowledgements') - self.step(8) - # Verify that TCAcknowledgementsRequired value is False - asserts.assert_equal(tcAcknowledgementsRequired, False, 'Incorrect TCAcknowledgementsRequired') + # Step 11: Verify TCMinRequiredVersion + self.step(11) + tcMinRequiredVersion = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion] + asserts.assert_less(tcMinRequiredVersion, 2**16, 'TCMinRequiredVersion exceeds uint16 range') - self.step(9) - response: Clusters.GeneralCommissioning.Commands.SetTCAcknowledgementsResponse = await commissioner.SendCommand( - nodeid=self.dut_node_id, - endpoint=ROOT_ENDPOINT_ID, - payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements(TCVersion=0, TCUserResponse=0), - timedRequestTimeoutMs=1000) - # Verify that DUT sends SetTCAcknowledgementsResponse Command to TH With ErrorCode as 'TCMinVersionNotMet'(7) - asserts.assert_equal(response.errorCode, - Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCMinVersionNotMet, 'Incorrect error code') - # Verify that TCAcceptedVersion and TCAcknowledgements still contain the values sent in step 3. + # Step 12: Verify TCAcknowledgementsRequired + self.step(12) + tcAcknowledgementsRequired = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired] + asserts.assert_equal(tcAcknowledgementsRequired, False, 'TCAcknowledgementsRequired should be False') if __name__ == "__main__": - default_matter_test_main() \ No newline at end of file + default_matter_test_main() diff --git a/src/python_testing/TC_CGEN_2_6.py b/src/python_testing/TC_CGEN_2_6.py index 606730dcf0f8ab..b63408218608dd 100644 --- a/src/python_testing/TC_CGEN_2_6.py +++ b/src/python_testing/TC_CGEN_2_6.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"); @@ -16,12 +16,23 @@ # # === BEGIN CI TEST ARGUMENTS === -# test-runner-runs: run1 -# test-runner-run/run1/app: ${TERMS_AND_CONDITIONS_APP} -# test-runner-run/run1/factoryreset: True -# test-runner-run/run1/quiet: True -# test-runner-run/run1/app-args: --KVS kvs1 --tc-min-required-version 1 --tc-required-acknowledgements 1 -# test-runner-run/run1/script-args: --in-test-commissioning-method on-network --qr-code MT:-24J0AFN00KA0648G00 --trace-to json:log +# test-runner-runs: +# run1: +# app: ${TERMS_AND_CONDITIONS_APP} +# app-args: > +# --KVS kvs1 +# --tc-min-required-version 1 +# --tc-required-acknowledgements 1 +# --custom-flow 2 +# --capabilities 6 +# script-args: +# --in-test-commissioning-method on-network +# --tc-version-to-simulate 1 +# --tc-user-response-to-simulate 1 +# --qr-code MT:-24J0AFN00KA0648G00 +# --trace-to json:log +# factoryreset: True +# quiet: True # === END CI TEST ARGUMENTS === import chip.clusters as Clusters @@ -33,33 +44,41 @@ class TC_CGEN_2_6(MatterBaseTest): def desc_TC_CGEN_2_6(self) -> str: - return "[TC-CGEN-2.6] Verification For CommissioningComplete no terms accepted when required [DUT as Server]" + return "[TC-CGEN-2.6] Verification for CommissioningComplete no terms accepted when required [DUT as Server]" def steps_TC_CGEN_2_6(self) -> list[TestStep]: return [ - TestStep(1, "TH starts commissioning the DUT. It performs all commissioning steps from ArmFailSafe to CommissioningComplete, except for TC configuration with SetTCAcknowledgements.", is_commissioning=False), + TestStep(1, "TH starts commissioning the DUT. It performs all commissioning steps from 'Device discovery and establish commissioning channel' to 'Security setup using CASE', except for TC configuration with SetTCAcknowledgements."), + TestStep(2, "TH sends CommissioningComplete to DUT and verifies error response."), ] @async_test_body async def test_TC_CGEN_2_6(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller - # Don't set TCs for the next commissioning and skip CommissioningComplete so we can manually call CommissioningComplete in order to check the response error code + # Step 1: Commission device without setting TC acknowledgements + self.step(1) + # Don't set TCs for the next commissioning and skip CommissioningComplete + # so we can manually call CommissioningComplete to check the response error code commissioner.SetTCRequired(False) commissioner.SetSkipCommissioningComplete(True) self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method - - self.step(1) await self.commission_devices() + + # Step 2: Send CommissioningComplete and verify error response + self.step(2) response: Clusters.GeneralCommissioning.Commands.CommissioningCompleteResponse = await commissioner.SendCommand( nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), timedRequestTimeoutMs=1000) - # Verify that DUT sends CommissioningCompleteResponse Command to TH With ErrorCode as 'TCAcknowledgementsNotReceived'(6). + # Verify that DUT sends CommissioningCompleteResponse Command to TH + # With ErrorCode as 'TCAcknowledgementsNotReceived'(6) asserts.assert_equal( - response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCAcknowledgementsNotReceived, 'Incorrect error code') + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCAcknowledgementsNotReceived, + 'Expected TCAcknowledgementsNotReceived error code') if __name__ == "__main__": diff --git a/src/python_testing/TC_CGEN_2_7.py b/src/python_testing/TC_CGEN_2_7.py index d1ded4f4b06514..edec706079461a 100644 --- a/src/python_testing/TC_CGEN_2_7.py +++ b/src/python_testing/TC_CGEN_2_7.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"); @@ -16,12 +16,23 @@ # # === BEGIN CI TEST ARGUMENTS === -# test-runner-runs: run1 -# test-runner-run/run1/app: ${TERMS_AND_CONDITIONS_APP} -# test-runner-run/run1/factoryreset: True -# test-runner-run/run1/quiet: True -# test-runner-run/run1/app-args: --KVS kvs1 --tc-min-required-version 1 --tc-required-acknowledgements 1 -# test-runner-run/run1/script-args: --in-test-commissioning-method on-network --qr-code MT:-24J0AFN00KA0648G00 --trace-to json:log +# test-runner-runs: +# run1: +# app: ${TERMS_AND_CONDITIONS_APP} +# app-args: > +# --KVS kvs1 +# --tc-min-required-version 1 +# --tc-required-acknowledgements 1 +# --custom-flow 2 +# --capabilities 6 +# script-args: +# --in-test-commissioning-method on-network +# --tc-version-to-simulate 1 +# --tc-user-response-to-simulate 1 +# --qr-code MT:-24J0AFN00KA0648G00 +# --trace-to json:log +# factoryreset: True +# quiet: True # === END CI TEST ARGUMENTS === import chip.clusters as Clusters @@ -33,48 +44,103 @@ class TC_CGEN_2_7(MatterBaseTest): def desc_TC_CGEN_2_7(self) -> str: - return "[TC-CGEN-2.7] Verification For CommissioningComplete when SetTCAcknowledgements provides invalid terms [DUT as Server]" + return "[TC-CGEN-2.7] Verification for CommissioningComplete when SetTCAcknowledgements provides invalid terms [DUT as Server]" def steps_TC_CGEN_2_7(self) -> list[TestStep]: return [ - TestStep(1, "TH starts commissioning the DUT. It performs all commissioning steps from ArmFailSafe, except SetTCAcknowledgements and CommissioningComplete.", is_commissioning=False), - TestStep(2, "TH sends SetTCAcknowledgements to DUT with the following values:\nTCVersion: Greater than or equal to TCMinRequiredVersion on DUT\nTCUserResponse: 0"), - TestStep(3, "TH sends CommissioningComplete to DUT."), + TestStep(1, "TH begins commissioning the DUT and performs the following steps in order:\n" + "* Security setup using PASE\n" + "* Setup fail-safe timer, with ExpiryLengthSeconds field set to PIXIT.CGEN.FailsafeExpiryLengthSeconds and the Breadcrumb value as 1\n" + "* Configure information- UTC time, regulatory, etc."), + TestStep(2, "TH reads TCMinRequiredVersion attribute."), + TestStep(3, "TH sends SetTCAcknowledgements with TCVersion=minVersion and TCUserResponse=0"), + TestStep(4, "TH continues commissioning with the DUT and performs the steps from 'Operation CSR exchange' through 'Security setup using CASE'"), + TestStep(5, "TH sends CommissioningComplete to DUT."), + TestStep(6, "TH sends SetTCAcknowledgements with valid TC values"), + TestStep(7, "TH sends CommissioningComplete to DUT.") ] @async_test_body async def test_TC_CGEN_2_7(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller - # Don't set TCs for the next commissioning and skip CommissioningComplete so we can manually call CommissioningComplete in order to check the response error code + # Step 1: Begin commissioning with PASE and failsafe + self.step(1) commissioner.SetTCRequired(False) commissioner.SetSkipCommissioningComplete(True) self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method - - self.step(1) await self.commission_devices() + # Step 2: Read TCMinRequiredVersion self.step(2) - response: Clusters.GeneralCommissioning.Commands.SetTCAcknowledgementsResponse = await commissioner.SendCommand( + response = await commissioner.ReadAttribute( + nodeid=self.dut_node_id, + attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion)]) + min_version = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion] + + # Step 3: Send SetTCAcknowledgements with invalid response + self.step(3) + response = await commissioner.SendCommand( nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, - payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements(TCVersion=2**16 - 1, TCUserResponse=0), + payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( + TCVersion=min_version, + TCUserResponse=0), timedRequestTimeoutMs=1000) - # Verify that DUT sends SetTCAcknowledgementsResponse Command to TH With ErrorCode as 'RequiredTCNotAccepted'(5). + # Verify error code is RequiredTCNotAccepted asserts.assert_equal( - response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kRequiredTCNotAccepted, 'Incorrect error code') + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kRequiredTCNotAccepted, + 'Expected RequiredTCNotAccepted error code') - self.step(3) - response: Clusters.GeneralCommissioning.Commands.CommissioningCompleteResponse = await commissioner.SendCommand( + # Step 4: Continue with CSR and CASE setup + self.step(4) + # Note: CSR and CASE setup is handled by the commissioning process + + # Step 5: Send CommissioningComplete and verify it fails + self.step(5) + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), + timedRequestTimeoutMs=1000) + + # Verify error code is TCAcknowledgementsNotReceived + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCAcknowledgementsNotReceived, + 'Expected TCAcknowledgementsNotReceived error code') + + # Step 6: Send SetTCAcknowledgements with valid values + self.step(6) + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( + TCVersion=self.pixit['CGEN']['TCRevision'], + TCUserResponse=self.pixit['CGEN']['RequiredTCAcknowledgements']), + timedRequestTimeoutMs=1000) + + # Verify error code is OK + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + 'Expected OK response for valid TC acknowledgements') + + # Step 7: Send CommissioningComplete and verify success + self.step(7) + response = await commissioner.SendCommand( nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), timedRequestTimeoutMs=1000) - # Verify that DUT sends CommissioningCompleteResponse Command to TH With ErrorCode as 'TCAcknowledgementsNotReceived'(6). + # Verify error code is OK asserts.assert_equal( - response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCAcknowledgementsNotReceived, 'Incorrect error code') + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + 'Expected OK response for CommissioningComplete') if __name__ == "__main__": diff --git a/src/python_testing/TC_CGEN_2_8.py b/src/python_testing/TC_CGEN_2_8.py index 2991a733ffabd0..b319527101e1fb 100644 --- a/src/python_testing/TC_CGEN_2_8.py +++ b/src/python_testing/TC_CGEN_2_8.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"); @@ -16,12 +16,23 @@ # # === BEGIN CI TEST ARGUMENTS === -# test-runner-runs: run1 -# test-runner-run/run1/app: ${TERMS_AND_CONDITIONS_APP} -# test-runner-run/run1/factoryreset: True -# test-runner-run/run1/quiet: True -# test-runner-run/run1/app-args: --KVS kvs1 --tc-min-required-version 1 --tc-required-acknowledgements 1 -# test-runner-run/run1/script-args: --in-test-commissioning-method on-network --qr-code MT:-24J0AFN00KA0648G00 --trace-to json:log +# test-runner-runs: +# run1: +# app: ${TERMS_AND_CONDITIONS_APP} +# app-args: > +# --KVS kvs1 +# --tc-min-required-version 1 +# --tc-required-acknowledgements 1 +# --custom-flow 2 +# --capabilities 6 +# script-args: +# --in-test-commissioning-method on-network +# --tc-version-to-simulate 1 +# --tc-user-response-to-simulate 1 +# --qr-code MT:-24J0AFN00KA0648G00 +# --trace-to json:log +# factoryreset: True +# quiet: True # === END CI TEST ARGUMENTS === from typing import List @@ -34,64 +45,86 @@ class TC_CGEN_2_8(MatterBaseTest): - - async def remove_commissioner_fabric(self): - commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller - - fabrics: List[Clusters.OperationalCredentials.Structs.FabricDescriptorStruct] = await self.read_single_attribute( - dev_ctrl=commissioner, - node_id=self.dut_node_id, - endpoint=ROOT_ENDPOINT_ID, - attribute=Clusters.OperationalCredentials.Attributes.Fabrics) - - # Re-order the list of fabrics so that the test harness admin fabric is removed last - commissioner_fabric = next((fabric for fabric in fabrics if fabric.fabricIndex == commissioner.fabricId), None) - fabrics.remove(commissioner_fabric) - fabrics.append(commissioner_fabric) - - for fabric in fabrics: - response: Clusters.OperationalCredentials.Commands.NOCResponse = await commissioner.SendCommand( - nodeid=self.dut_node_id, - endpoint=ROOT_ENDPOINT_ID, - payload=Clusters.OperationalCredentials.Commands.RemoveFabric(fabric.fabricIndex), - timedRequestTimeoutMs=1000) - asserts.assert_equal(response.statusCode, Clusters.OperationalCredentials.Enums.NodeOperationalCertStatusEnum.kOk) - def desc_TC_CGEN_2_8(self) -> str: - return "[TC-CGEN-2.8] Verification For Terms and Conditions Reset [DUT as Server]" + return "[TC-CGEN-2.8] Verification that TCAcknowledgements is reset after Factory Reset [DUT as Server]" def steps_TC_CGEN_2_8(self) -> list[TestStep]: return [ - TestStep(1, "DUT requires terms and conditions. DUT has been successfully commissioned."), - TestStep(2, "User performs factory reset."), - TestStep(3, "User triggers USER INTENT to set the device to be in commissioning mode."), - TestStep(4, "TH starts commissioning the DUT. It performs all commissioning steps, except for TC configuration with SetTCAcknowledgements."), + TestStep(1, "TH begins commissioning with PASE, failsafe setup, and basic configuration."), + TestStep(2, "TH sends SetTCAcknowledgements to DUT with required values."), + TestStep(3, "TH continues commissioning with CSR exchange through CASE setup."), + TestStep(4, "TH sends CommissioningComplete to DUT."), + TestStep(5, "DUT is factory reset."), + TestStep(6, "Put DUT into commissionable state."), + TestStep(7, "TH begins commissioning without TC acknowledgements."), + TestStep(8, "Verify CommissioningComplete fails with TCAcknowledgementsNotReceived.") ] @async_test_body async def test_TC_CGEN_2_8(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + # Steps 1-4: Initial commissioning with TC acknowledgements self.step(1) + commissioner.SetSkipCommissioningComplete(True) + self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + await self.commission_devices() + + # Step 2: Send SetTCAcknowledgements self.step(2) + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( + TCVersion=self.pixit['CGEN']['TCRevision'], + TCUserResponse=self.pixit['CGEN']['RequiredTCAcknowledgements']), + timedRequestTimeoutMs=1000) + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + 'SetTCAcknowledgements failed') + + # Step 3: Continue with CSR and CASE setup self.step(3) + # Note: CSR and CASE setup is handled by the commissioning process + + # Step 4: Send CommissioningComplete + self.step(4) + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), + timedRequestTimeoutMs=1000) + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + 'First CommissioningComplete failed') + + # Step 5: Factory reset is handled by test runner configuration + self.step(5) + + # Step 6: Put device in commissioning mode + self.step(6) self.wait_for_user_input(prompt_msg="Set the DUT into commissioning mode") - # Don't set TCs for the next commissioning and skip CommissioningComplete so we can manually call CommissioningComplete in order to check the response error code + # Step 7: Commission without TC acknowledgements + self.step(7) commissioner.SetTCRequired(False) commissioner.SetSkipCommissioningComplete(True) self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method await self.commission_devices() - self.step(4) - response: Clusters.GeneralCommissioning.Commands.CommissioningCompleteResponse = await commissioner.SendCommand( + # Step 8: Verify CommissioningComplete fails + self.step(8) + response = await commissioner.SendCommand( nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), timedRequestTimeoutMs=1000) - # Verify that DUT sends CommissioningCompleteResponse Command to TH With ErrorCode as 'TCAcknowledgementsNotReceived'(6). asserts.assert_equal( - response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCAcknowledgementsNotReceived, 'Incorrect error code') + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCAcknowledgementsNotReceived, + 'Expected TCAcknowledgementsNotReceived error after factory reset') if __name__ == "__main__": diff --git a/src/python_testing/TC_CGEN_2_9.py b/src/python_testing/TC_CGEN_2_9.py new file mode 100644 index 00000000000000..406976e6a6eb86 --- /dev/null +++ b/src/python_testing/TC_CGEN_2_9.py @@ -0,0 +1,150 @@ +# +# Copyright (c) 2025 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${TERMS_AND_CONDITIONS_APP} +# app-args: > +# --KVS kvs1 +# --tc-min-required-version 1 +# --tc-required-acknowledgements 1 +# --custom-flow 2 +# --capabilities 6 +# script-args: +# --in-test-commissioning-method on-network +# --tc-version-to-simulate 1 +# --tc-user-response-to-simulate 1 +# --qr-code MT:-24J0AFN00KA0648G00 +# --trace-to json:log +# factoryreset: True +# quiet: True +# === END CI TEST ARGUMENTS === + +import chip.clusters as Clusters +from chip import ChipDeviceCtrl +from chip.commissioning import ROOT_ENDPOINT_ID +from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts + + +class TC_CGEN_2_9(MatterBaseTest): + def desc_TC_CGEN_2_9(self) -> str: + return "[TC-CGEN-2.9] Verification that TCAcknowledgements is reset after all fabrics removed [DUT as Server]" + + def steps_TC_CGEN_2_9(self) -> list[TestStep]: + return [ + TestStep(1, "TH begins commissioning the DUT and performs the following steps in order:\n" + "* Security setup using PASE\n" + "* Setup fail-safe timer, with ExpiryLengthSeconds field set to PIXIT.CGEN.FailsafeExpiryLengthSeconds and the Breadcrumb value as 1\n" + "* Configure information- UTC time, regulatory, etc."), + TestStep(2, "TH sends SetTCAcknowledgements with required values"), + TestStep(3, "TH continues commissioning with CSR exchange through CASE setup"), + TestStep(4, "TH sends CommissioningComplete to DUT"), + TestStep(5, "TH removes all fabrics from DUT with RemoveFabric"), + TestStep(6, "Put DUT into commissionable state"), + TestStep(7, "TH begins commissioning without TC acknowledgements"), + TestStep(8, "Verify CommissioningComplete fails with TCAcknowledgementsNotReceived") + ] + + @async_test_body + async def test_TC_CGEN_2_9(self): + commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + + # Step 1: Begin commissioning with PASE and failsafe + self.step(1) + commissioner.SetSkipCommissioningComplete(True) + self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + await self.commission_devices() + + # Step 2: Send SetTCAcknowledgements + self.step(2) + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( + TCVersion=self.pixit['CGEN']['TCRevision'], + TCUserResponse=self.pixit['CGEN']['RequiredTCAcknowledgements']), + timedRequestTimeoutMs=1000) + + # Verify SetTCAcknowledgements response + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + 'SetTCAcknowledgements failed') + + # Step 3: Continue with CSR and CASE setup + self.step(3) + # Note: CSR and CASE setup is handled by the commissioning process + + # Step 4: Send CommissioningComplete + self.step(4) + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), + timedRequestTimeoutMs=1000) + + # Verify CommissioningComplete response + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + 'First CommissioningComplete failed') + + # Step 5: Remove all fabrics + self.step(5) + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.OperationalCredentials.Commands.RemoveFabric(), + timedRequestTimeoutMs=1000) + + # Verify RemoveFabric response + asserts.assert_equal( + response.errorCode, + Clusters.OperationalCredentials.Enums.OperationalCredentialsStatusEnum.kSuccess, + 'RemoveFabric failed') + + # Step 6: Put device in commissioning mode + self.step(6) + self.wait_for_user_input(prompt_msg="Set the DUT into commissioning mode") + + # Step 7: Commission without TC acknowledgements + self.step(7) + commissioner.SetTCRequired(False) + commissioner.SetSkipCommissioningComplete(True) + self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + await self.commission_devices() + + # Step 8: Verify CommissioningComplete fails + self.step(8) + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), + timedRequestTimeoutMs=1000) + + # Verify CommissioningComplete fails with correct error + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCAcknowledgementsNotReceived, + 'Expected TCAcknowledgementsNotReceived error after fabric removal') + + +if __name__ == "__main__": + default_matter_test_main() From 87deee8934a5e91fbe6f37f2c28997a8e347c25c Mon Sep 17 00:00:00 2001 From: James Swan Date: Mon, 13 Jan 2025 22:39:19 +0000 Subject: [PATCH 04/23] --- src/python_testing/TC_CGEN_2_10.py | 23 +++++++++++++++++------ src/python_testing/TC_CGEN_2_11.py | 23 +++++++++++++++++------ src/python_testing/TC_CGEN_2_8.py | 2 -- src/python_testing/TC_CGEN_2_9.py | 1 - 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/python_testing/TC_CGEN_2_10.py b/src/python_testing/TC_CGEN_2_10.py index 262d34b95909b9..729b574ecac0dc 100644 --- a/src/python_testing/TC_CGEN_2_10.py +++ b/src/python_testing/TC_CGEN_2_10.py @@ -16,12 +16,23 @@ # # === BEGIN CI TEST ARGUMENTS === -# test-runner-runs: run1 -# test-runner-run/run1/app: ${TERMS_AND_CONDITIONS_APP} -# test-runner-run/run1/factoryreset: True -# test-runner-run/run1/quiet: True -# test-runner-run/run1/app-args: --KVS kvs1 --tc-min-required-version 1 --tc-required-acknowledgements 1 -# test-runner-run/run1/script-args: --in-test-commissioning-method on-network --qr-code MT:-24J0AFN00KA0648G00 --trace-to json:log +# test-runner-runs: +# run1: +# app: ${TERMS_AND_CONDITIONS_APP} +# app-args: > +# --KVS kvs1 +# --tc-min-required-version 1 +# --tc-required-acknowledgements 1 +# --custom-flow 2 +# --capabilities 6 +# script-args: +# --in-test-commissioning-method on-network +# --tc-version-to-simulate 1 +# --tc-user-response-to-simulate 1 +# --qr-code MT:-24J0AFN00KA0648G00 +# --trace-to json:log +# factoryreset: True +# quiet: True # === END CI TEST ARGUMENTS === import chip.clusters as Clusters diff --git a/src/python_testing/TC_CGEN_2_11.py b/src/python_testing/TC_CGEN_2_11.py index 5d1780635f734d..58f8f0608cd213 100644 --- a/src/python_testing/TC_CGEN_2_11.py +++ b/src/python_testing/TC_CGEN_2_11.py @@ -16,12 +16,23 @@ # # === BEGIN CI TEST ARGUMENTS === -# test-runner-runs: run1 -# test-runner-run/run1/app: ${TERMS_AND_CONDITIONS_APP} -# test-runner-run/run1/factoryreset: True -# test-runner-run/run1/quiet: True -# test-runner-run/run1/app-args: --KVS kvs1 --tc-min-required-version 1 --tc-required-acknowledgements 1 -# test-runner-run/run1/script-args: --in-test-commissioning-method on-network --qr-code MT:-24J0AFN00KA0648G00 --trace-to json:log +# test-runner-runs: +# run1: +# app: ${TERMS_AND_CONDITIONS_APP} +# app-args: > +# --KVS kvs1 +# --tc-min-required-version 1 +# --tc-required-acknowledgements 1 +# --custom-flow 2 +# --capabilities 6 +# script-args: +# --in-test-commissioning-method on-network +# --tc-version-to-simulate 1 +# --tc-user-response-to-simulate 1 +# --qr-code MT:-24J0AFN00KA0648G00 +# --trace-to json:log +# factoryreset: True +# quiet: True # === END CI TEST ARGUMENTS === import chip.clusters as Clusters diff --git a/src/python_testing/TC_CGEN_2_8.py b/src/python_testing/TC_CGEN_2_8.py index b319527101e1fb..09a40f1947793c 100644 --- a/src/python_testing/TC_CGEN_2_8.py +++ b/src/python_testing/TC_CGEN_2_8.py @@ -35,8 +35,6 @@ # quiet: True # === END CI TEST ARGUMENTS === -from typing import List - import chip.clusters as Clusters from chip import ChipDeviceCtrl from chip.commissioning import ROOT_ENDPOINT_ID diff --git a/src/python_testing/TC_CGEN_2_9.py b/src/python_testing/TC_CGEN_2_9.py index 406976e6a6eb86..16084633ba340e 100644 --- a/src/python_testing/TC_CGEN_2_9.py +++ b/src/python_testing/TC_CGEN_2_9.py @@ -15,7 +15,6 @@ # limitations under the License. # -# === BEGIN CI TEST ARGUMENTS === # === BEGIN CI TEST ARGUMENTS === # test-runner-runs: # run1: From e9b30ed03e4ec0d7783277bc04c7db4d92d81778 Mon Sep 17 00:00:00 2001 From: James Swan Date: Mon, 13 Jan 2025 22:52:46 +0000 Subject: [PATCH 05/23] --- src/python_testing/TC_CGEN_2_5.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/python_testing/TC_CGEN_2_5.py b/src/python_testing/TC_CGEN_2_5.py index f59ff55fc446ce..58796799a40ab4 100644 --- a/src/python_testing/TC_CGEN_2_5.py +++ b/src/python_testing/TC_CGEN_2_5.py @@ -101,8 +101,8 @@ async def test_TC_CGEN_2_5(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( - TCVersion=self.pixit['CGEN']['TCRevision'], - TCUserResponse=self.pixit['CGEN']['RequiredTCAcknowledgements']), + TCVersion=self.matter_test_config.tc_version_to_simulate, + TCUserResponse=self.matter_test_config.tc_user_response_to_simulate), timedRequestTimeoutMs=1000) asserts.assert_equal(response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, From 3046d6a49c01006db0917ce1387380475b20cf3e Mon Sep 17 00:00:00 2001 From: James Swan Date: Mon, 13 Jan 2025 23:32:08 +0000 Subject: [PATCH 06/23] wip --- src/python_testing/TC_CGEN_2_5.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/python_testing/TC_CGEN_2_5.py b/src/python_testing/TC_CGEN_2_5.py index 58796799a40ab4..8941eeee71d5fe 100644 --- a/src/python_testing/TC_CGEN_2_5.py +++ b/src/python_testing/TC_CGEN_2_5.py @@ -63,6 +63,8 @@ def steps_TC_CGEN_2_5(self) -> list[TestStep]: @async_test_body async def test_TC_CGEN_2_5(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + tc_version_to_simulate: int = self.matter_test_config.tc_version_to_simulate + tc_user_response_to_simulate: int = self.matter_test_config.tc_user_response_to_simulate # Step 1: Begin commissioning with PASE and failsafe self.step(1) @@ -76,8 +78,8 @@ async def test_TC_CGEN_2_5(self): response = await commissioner.ReadAttribute( nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired)]) - tcAcknowledgementsRequired = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired] - asserts.assert_equal(tcAcknowledgementsRequired, True, 'Incorrect TCAcknowledgementsRequired') + tc_acknowledgements_required = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired] + asserts.assert_equal(tc_acknowledgements_required, True, 'Incorrect TCAcknowledgementsRequired') # Step 3: Read TCUpdateDeadline self.step(3) @@ -101,8 +103,8 @@ async def test_TC_CGEN_2_5(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( - TCVersion=self.matter_test_config.tc_version_to_simulate, - TCUserResponse=self.matter_test_config.tc_user_response_to_simulate), + TCVersion=tc_version_to_simulate, + TCUserResponse=tc_user_response_to_simulate), timedRequestTimeoutMs=1000) asserts.assert_equal(response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, @@ -113,8 +115,8 @@ async def test_TC_CGEN_2_5(self): response = await commissioner.ReadAttribute( nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired)]) - tcAcknowledgementsRequired = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired] - asserts.assert_equal(tcAcknowledgementsRequired, False, 'TCAcknowledgementsRequired should be False') + tc_acknowledgements_required = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired] + asserts.assert_equal(tc_acknowledgements_required, False, 'TCAcknowledgementsRequired should be False') # Step 7: Complete CSR exchange and CASE security setup self.step(7) @@ -145,13 +147,13 @@ async def test_TC_CGEN_2_5(self): self.step(9) tcAcceptedVersion = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] asserts.assert_less(tcAcceptedVersion, 2**16, 'TCAcceptedVersion exceeds uint16 range') - asserts.assert_equal(tcAcceptedVersion, self.pixit['CGEN']['TCRevision'], 'Incorrect TCAcceptedVersion') + asserts.assert_equal(tcAcceptedVersion, tc_version_to_simulate, 'Incorrect TCAcceptedVersion') # Step 10: Verify TCAcknowledgements self.step(10) tcAcknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] asserts.assert_less(tcAcknowledgements, 2**16, 'TCAcknowledgements exceeds map16 range') - asserts.assert_equal(tcAcknowledgements, self.pixit['CGEN']['RequiredTCAcknowledgements'], 'Incorrect TCAcknowledgements') + asserts.assert_equal(tcAcknowledgements, tc_user_response_to_simulate, 'Incorrect TCAcknowledgements') # Step 11: Verify TCMinRequiredVersion self.step(11) @@ -160,8 +162,8 @@ async def test_TC_CGEN_2_5(self): # Step 12: Verify TCAcknowledgementsRequired self.step(12) - tcAcknowledgementsRequired = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired] - asserts.assert_equal(tcAcknowledgementsRequired, False, 'TCAcknowledgementsRequired should be False') + tc_acknowledgements_required = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired] + asserts.assert_equal(tc_acknowledgements_required, False, 'TCAcknowledgementsRequired should be False') if __name__ == "__main__": From 5c8d3ad6f01ac544202e291449974dbb1e51e27c Mon Sep 17 00:00:00 2001 From: James Swan Date: Wed, 15 Jan 2025 21:50:17 +0000 Subject: [PATCH 07/23] --- .github/workflows/tests.yaml | 2 + .../docker/images/chip-cert-bins/Dockerfile | 5 + scripts/tests/local.py | 1 + src/python_testing/TC_CGEN_2_10.py | 79 +++++------- src/python_testing/TC_CGEN_2_11.py | 70 +++++----- src/python_testing/TC_CGEN_2_5.py | 122 +++++++++--------- src/python_testing/TC_CGEN_2_6.py | 18 ++- src/python_testing/TC_CGEN_2_7.py | 50 +++---- src/python_testing/TC_CGEN_2_8.py | 38 +++--- src/python_testing/TC_CGEN_2_9.py | 50 +++---- 10 files changed, 219 insertions(+), 216 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 1ed2a01bdbc018..9259fdcb135828 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -500,6 +500,7 @@ jobs: --target linux-x64-fabric-bridge-rpc-ipv6only-no-ble-no-wifi-clang \ --target linux-x64-fabric-sync-ipv6only-no-ble-no-wifi-clang \ --target linux-x64-light-data-model-no-unique-id-ipv6only-no-ble-no-wifi-clang \ + --target linux-x64-terms-and-conditions \ --target linux-x64-python-bindings \ build \ --copy-artifacts-to objdir-clone \ @@ -518,6 +519,7 @@ jobs: echo "FABRIC_BRIDGE_APP: out/linux-x64-fabric-bridge-rpc-ipv6only-no-ble-no-wifi-clang/fabric-bridge-app" >> /tmp/test_env.yaml echo "FABRIC_SYNC_APP: out/linux-x64-fabric-sync-ipv6only-no-ble-no-wifi-clang/fabric-sync" >> /tmp/test_env.yaml echo "LIGHTING_APP_NO_UNIQUE_ID: out/linux-x64-light-data-model-no-unique-id-ipv6only-no-ble-no-wifi-clang/chip-lighting-app" >> /tmp/test_env.yaml + echo "TERMS_AND_CONDITIONS_APP: out/linux-x64-terms-and-conditions/chip-terms-and-conditions-app" >> /tmp/test_env.yaml echo "TRACE_APP: out/trace_data/app-{SCRIPT_BASE_NAME}" >> /tmp/test_env.yaml echo "TRACE_TEST_JSON: out/trace_data/test-{SCRIPT_BASE_NAME}" >> /tmp/test_env.yaml echo "TRACE_TEST_PERFETTO: out/trace_data/test-{SCRIPT_BASE_NAME}" >> /tmp/test_env.yaml diff --git a/integrations/docker/images/chip-cert-bins/Dockerfile b/integrations/docker/images/chip-cert-bins/Dockerfile index ef823f7eeb674d..633f4e849cb100 100644 --- a/integrations/docker/images/chip-cert-bins/Dockerfile +++ b/integrations/docker/images/chip-cert-bins/Dockerfile @@ -168,6 +168,7 @@ RUN case ${TARGETPLATFORM} in \ --target linux-x64-fabric-admin-rpc-ipv6only \ --target linux-x64-light-data-model-no-unique-id-ipv6only \ --target linux-x64-network-manager-ipv6only \ + --target linux-x64-terms-and-conditions \ build \ && mv out/linux-x64-chip-tool-ipv6only-platform-mdns/chip-tool out/chip-tool \ && mv out/linux-x64-shell-ipv6only-platform-mdns/chip-shell out/chip-shell \ @@ -192,6 +193,7 @@ RUN case ${TARGETPLATFORM} in \ && mv out/linux-x64-fabric-admin-rpc-ipv6only/fabric-admin out/fabric-admin \ && mv out/linux-x64-light-data-model-no-unique-id-ipv6only/chip-lighting-app out/chip-lighting-data-model-no-unique-id-app \ && mv out/linux-x64-network-manager-ipv6only/matter-network-manager-app out/matter-network-manager-app \ + && mv out/linux-x64-terms-and-conditions/chip-terms-and-conditions-app out/chip-terms-and-conditions-app \ ;; \ "linux/arm64")\ set -x \ @@ -220,6 +222,7 @@ RUN case ${TARGETPLATFORM} in \ --target linux-arm64-fabric-admin-rpc-ipv6only \ --target linux-arm64-light-data-model-no-unique-id-ipv6only \ --target linux-arm64-network-manager-ipv6only \ + --target linux-arm64-terms-and-conditions \ build \ && mv out/linux-arm64-chip-tool-ipv6only-platform-mdns/chip-tool out/chip-tool \ && mv out/linux-arm64-shell-ipv6only-platform-mdns/chip-shell out/chip-shell \ @@ -244,6 +247,7 @@ RUN case ${TARGETPLATFORM} in \ && mv out/linux-arm64-fabric-admin-rpc-ipv6only/fabric-admin out/fabric-admin \ && mv out/linux-arm64-light-data-model-no-unique-id-ipv6only/chip-lighting-app out/chip-lighting-data-model-no-unique-id-app \ && mv out/linux-arm64-network-manager-ipv6only/matter-network-manager-app out/matter-network-manager-app \ + && mv out/linux-arm64-terms-and-conditions/chip-terms-and-conditions-app out/chip-terms-and-conditions-app \ ;; \ *) ;; \ esac @@ -283,6 +287,7 @@ COPY --from=chip-build-cert-bins /root/connectedhomeip/out/fabric-bridge-app app COPY --from=chip-build-cert-bins /root/connectedhomeip/out/fabric-admin apps/fabric-admin COPY --from=chip-build-cert-bins /root/connectedhomeip/out/chip-lighting-data-model-no-unique-id-app apps/chip-lighting-data-model-no-unique-id-app COPY --from=chip-build-cert-bins /root/connectedhomeip/out/matter-network-manager-app apps/matter-network-manager-app +COPY --from=chip-build-cert-bins /root/connectedhomeip/out/chip-terms-and-conditions-app apps/chip-terms-and-conditions-app # Create symbolic links for now since this allows users to use existing configurations # for running just `app-name` instead of `apps/app-name` diff --git a/scripts/tests/local.py b/scripts/tests/local.py index 7321c1b1bead4c..eb9cbce8c0af68 100755 --- a/scripts/tests/local.py +++ b/scripts/tests/local.py @@ -387,6 +387,7 @@ def as_runner(path): FABRIC_SYNC_APP: { as_runner(f'out/{target_prefix}-fabric-sync-no-ble-no-wifi-ipv6only-clang-boringssl/fabric-sync')} LIGHTING_APP_NO_UNIQUE_ID: {as_runner(f'out/{target_prefix}-light-data-model-no-unique-id-ipv6only-no-ble-no-wifi-clang/chip-lighting-app')} + TERMS_AND_CONDITIONS_APP: {as_runner(f'out/{target_prefix}-terms-and-conditions/chip-terms-and-conditions-app')} TRACE_APP: out/trace_data/app-{{SCRIPT_BASE_NAME}} TRACE_TEST_JSON: out/trace_data/test-{{SCRIPT_BASE_NAME}} TRACE_TEST_PERFETTO: out/trace_data/test-{{SCRIPT_BASE_NAME}} diff --git a/src/python_testing/TC_CGEN_2_10.py b/src/python_testing/TC_CGEN_2_10.py index 729b574ecac0dc..ce5ac7b01199d7 100644 --- a/src/python_testing/TC_CGEN_2_10.py +++ b/src/python_testing/TC_CGEN_2_10.py @@ -26,7 +26,7 @@ # --custom-flow 2 # --capabilities 6 # script-args: -# --in-test-commissioning-method on-network +# --commissioning-method on-network # --tc-version-to-simulate 1 # --tc-user-response-to-simulate 1 # --qr-code MT:-24J0AFN00KA0648G00 @@ -48,32 +48,29 @@ def desc_TC_CGEN_2_10(self) -> str: def steps_TC_CGEN_2_10(self) -> list[TestStep]: return [ - TestStep(1, "Read TCAcceptedVersion attribute"), - TestStep(2, "Read TCAcknowledgements attribute"), - TestStep(3, "Send SetTCAcknowledgements with TCVersion=0 and TCUserResponse=65535"), - TestStep(4, "Verify TCAcceptedVersion unchanged"), - TestStep(5, "Verify TCAcknowledgements unchanged"), - TestStep(6, "Send SetTCAcknowledgements with TCVersion=acceptedVersion+1 and TCUserResponse=0"), - TestStep(7, "Verify TCAcceptedVersion unchanged"), - TestStep(8, "Verify TCAcknowledgements unchanged") + TestStep(1, "TH reads from the DUT the attribute TCAcceptedVersion. Store the value as acceptedVersion."), + TestStep(2, "TH reads from the DUT the attribute TCAcknowledgements. Store the value as userAcknowledgements."), + TestStep(3, "TH Sends the SetTCAcknowledgements command to the DUT with the fields set as follows:\n* TCVersion: 0\n* TCUserResponse: 65535"), + TestStep(4, "TH reads from the DUT the attribute TCAcceptedVersion."), + TestStep(5, "TH reads from the DUT the attribute TCAcknowledgements."), + TestStep(6, "TH Sends the SetTCAcknowledgements command to the DUT with the fields set as follows:\n* TCVersion: acceptedVersion + 1\n* TCUserResponse: 0"), + TestStep(7, "TH reads from the DUT the attribute TCAcceptedVersion."), + TestStep(8, "TH reads from the DUT the attribute TCAcknowledgements."), ] @async_test_body async def test_TC_CGEN_2_10(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + await self.commission_devices() # Step 1: Read TCAcceptedVersion self.step(1) - response = await commissioner.ReadAttribute( - nodeid=self.dut_node_id, - attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion)]) + response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion)]) accepted_version = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] # Step 2: Read TCAcknowledgements self.step(2) - response = await commissioner.ReadAttribute( - nodeid=self.dut_node_id, - attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements)]) + response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements)]) user_acknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] # Step 3: Send SetTCAcknowledgements with invalid version @@ -81,38 +78,27 @@ async def test_TC_CGEN_2_10(self): response = await commissioner.SendCommand( nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, - payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( - TCVersion=0, - TCUserResponse=65535), - timedRequestTimeoutMs=1000) + payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements(TCVersion=0, TCUserResponse=65535), + ) # Verify TCMinVersionNotMet error asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCMinVersionNotMet, - 'Expected TCMinVersionNotMet error') + "Expected TCMinVersionNotMet error", + ) # Step 4: Verify TCAcceptedVersion unchanged self.step(4) - response = await commissioner.ReadAttribute( - nodeid=self.dut_node_id, - attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion)]) + response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion)]) current_version = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] - asserts.assert_equal( - current_version, - accepted_version, - 'TCAcceptedVersion changed unexpectedly') + asserts.assert_equal(current_version, accepted_version, "TCAcceptedVersion changed unexpectedly") # Step 5: Verify TCAcknowledgements unchanged self.step(5) - response = await commissioner.ReadAttribute( - nodeid=self.dut_node_id, - attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements)]) + response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements)]) current_acknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] - asserts.assert_equal( - current_acknowledgements, - user_acknowledgements, - 'TCAcknowledgements changed unexpectedly') + asserts.assert_equal(current_acknowledgements, user_acknowledgements, "TCAcknowledgements changed unexpectedly") # Step 6: Send SetTCAcknowledgements with invalid response self.step(6) @@ -120,37 +106,32 @@ async def test_TC_CGEN_2_10(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( - TCVersion=accepted_version + 1, - TCUserResponse=0), - timedRequestTimeoutMs=1000) + TCVersion=accepted_version + 1, TCUserResponse=0 + ), + ) # Verify RequiredTCNotAccepted error asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kRequiredTCNotAccepted, - 'Expected RequiredTCNotAccepted error') + "Expected RequiredTCNotAccepted error", + ) # Step 7: Verify TCAcceptedVersion still unchanged self.step(7) - response = await commissioner.ReadAttribute( - nodeid=self.dut_node_id, - attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion)]) + response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion)]) current_version = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] - asserts.assert_equal( - current_version, - accepted_version, - 'TCAcceptedVersion changed unexpectedly after second attempt') + asserts.assert_equal(current_version, accepted_version, "TCAcceptedVersion changed unexpectedly after second attempt") # Step 8: Verify TCAcknowledgements still unchanged self.step(8) - response = await commissioner.ReadAttribute( - nodeid=self.dut_node_id, - attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements)]) + response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements)]) current_acknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] asserts.assert_equal( current_acknowledgements, user_acknowledgements, - 'TCAcknowledgements changed unexpectedly after second attempt') + "TCAcknowledgements changed unexpectedly after second attempt", + ) if __name__ == "__main__": diff --git a/src/python_testing/TC_CGEN_2_11.py b/src/python_testing/TC_CGEN_2_11.py index 58f8f0608cd213..7ec275f1a59ea3 100644 --- a/src/python_testing/TC_CGEN_2_11.py +++ b/src/python_testing/TC_CGEN_2_11.py @@ -48,23 +48,27 @@ def desc_TC_CGEN_2_11(self) -> str: def steps_TC_CGEN_2_11(self) -> list[TestStep]: return [ - TestStep(1, "TH begins commissioning the DUT with PASE, failsafe setup, and basic configuration"), - TestStep(2, "TH sends SetTCAcknowledgements with initial TC values"), - TestStep(3, "TH sends CommissioningComplete to DUT"), - TestStep(4, "TH sends SetTCAcknowledgements with updated TC version"), - TestStep(5, "Verify TCAcceptedVersion is updated"), - TestStep(6, "TH sends SetTCAcknowledgements with maximum acknowledgements"), - TestStep(7, "Verify TCAcknowledgements is updated") + TestStep(1, "TH begins commissioning the DUT and performs the following steps in order:\n* Security setup using PASE\n* Setup fail-safe timer, with ExpiryLengthSeconds field set to PIXIT.CGEN.FailsafeExpiryLengthSeconds and the Breadcrumb value as 1\n* Configure information- UTC time, regulatory, etc."), + TestStep(2, "TH sends SetTCAcknowledgements to DUT with the following values:\n* TCVersion: PIXIT.CGEN.TCRevision\n* TCUserResponse: PIXIT.CGEN.RequiredTCAcknowledgements"), + TestStep(3, "TH sends CommissioningComplete to DUT."), + TestStep(4, "TH Sends the SetTCAcknowledgements command to the DUT with the fields set as follows:\n* TCVersion: PIXIT.CGEN.TCRevision + 1\n* TCUserResponse: PIXIT.CGEN.RequiredTCAcknowledgements"), + TestStep(5, "TH reads from the DUT the attribute TCAcceptedVersion."), + TestStep(6, "TH Sends the SetTCAcknowledgements command to the DUT with the fields set as follows:\n* TCVersion: PIXIT.CGEN.TCRevision + 1\n* TCUserResponse: 65535"), + TestStep(7, "TH reads from the DUT the attribute TCAcknowledgements."), ] @async_test_body async def test_TC_CGEN_2_11(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + tc_version_to_simulate: int = self.matter_test_config.tc_version_to_simulate + tc_user_response_to_simulate: int = self.matter_test_config.tc_user_response_to_simulate # Step 1: Begin commissioning with PASE and failsafe self.step(1) commissioner.SetSkipCommissioningComplete(True) self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + self.matter_test_config.tc_version_to_simulate = None + self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() # Step 2: Send initial SetTCAcknowledgements @@ -73,15 +77,16 @@ async def test_TC_CGEN_2_11(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( - TCVersion=self.pixit['CGEN']['TCRevision'], - TCUserResponse=self.pixit['CGEN']['RequiredTCAcknowledgements']), - timedRequestTimeoutMs=1000) + TCVersion=tc_version_to_simulate, TCUserResponse=tc_user_response_to_simulate + ), + ) # Verify initial SetTCAcknowledgements response asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, - 'Initial SetTCAcknowledgements failed') + "Initial SetTCAcknowledgements failed", + ) # Step 3: Send CommissioningComplete self.step(3) @@ -89,41 +94,38 @@ async def test_TC_CGEN_2_11(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), - timedRequestTimeoutMs=1000) + ) # Verify CommissioningComplete response asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, - 'CommissioningComplete failed') + "CommissioningComplete failed", + ) # Step 4: Send SetTCAcknowledgements with updated version self.step(4) - updated_tc_version = self.pixit['CGEN']['TCRevision'] + 1 + updated_tc_version = tc_version_to_simulate + 1 response = await commissioner.SendCommand( nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( - TCVersion=updated_tc_version, - TCUserResponse=self.pixit['CGEN']['RequiredTCAcknowledgements']), - timedRequestTimeoutMs=1000) + TCVersion=updated_tc_version, TCUserResponse=tc_user_response_to_simulate + ), + ) # Verify SetTCAcknowledgements response with updated version asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, - 'SetTCAcknowledgements with updated version failed') + "SetTCAcknowledgements with updated version failed", + ) # Step 5: Verify TCAcceptedVersion is updated self.step(5) - response = await commissioner.ReadAttribute( - nodeid=self.dut_node_id, - attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion)]) + response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion)]) current_version = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] - asserts.assert_equal( - current_version, - updated_tc_version, - 'TCAcceptedVersion not updated correctly') + asserts.assert_equal(current_version, updated_tc_version, "TCAcceptedVersion not updated correctly") # Step 6: Send SetTCAcknowledgements with maximum acknowledgements self.step(6) @@ -131,26 +133,22 @@ async def test_TC_CGEN_2_11(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( - TCVersion=updated_tc_version, - TCUserResponse=65535), - timedRequestTimeoutMs=1000) + TCVersion=updated_tc_version, TCUserResponse=65535 + ), + ) # Verify SetTCAcknowledgements response with maximum acknowledgements asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, - 'SetTCAcknowledgements with maximum acknowledgements failed') + "SetTCAcknowledgements with maximum acknowledgements failed", + ) # Step 7: Verify TCAcknowledgements is updated self.step(7) - response = await commissioner.ReadAttribute( - nodeid=self.dut_node_id, - attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements)]) + response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements)]) current_acknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] - asserts.assert_equal( - current_acknowledgements, - 65535, - 'TCAcknowledgements not updated to maximum value') + asserts.assert_equal(current_acknowledgements, 65535, "TCAcknowledgements not updated to maximum value") if __name__ == "__main__": diff --git a/src/python_testing/TC_CGEN_2_5.py b/src/python_testing/TC_CGEN_2_5.py index 8941eeee71d5fe..9e2991f5989746 100644 --- a/src/python_testing/TC_CGEN_2_5.py +++ b/src/python_testing/TC_CGEN_2_5.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2024-2025 Project CHIP Authors +# Copyright (c) 2025 Project CHIP Authors # All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,9 +35,9 @@ # quiet: True # === END CI TEST ARGUMENTS === - import chip.clusters as Clusters from chip import ChipDeviceCtrl +from chip.clusters.Attribute import ValueDecodeFailure from chip.commissioning import ROOT_ENDPOINT_ID from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main from mobly import asserts @@ -45,19 +45,22 @@ class TC_CGEN_2_5(MatterBaseTest): def desc_TC_CGEN_2_5(self) -> str: - return "[TC-CGEN-2.5] Verification For SetTCAcknowledgements [DUT as Server]" + return "[TC-CGEN-2.5] Verification for SetTCAcknowledgements [DUT as Server]" def steps_TC_CGEN_2_5(self) -> list[TestStep]: return [ - TestStep(1, "TH starts commissioning the DUT. It performs all commissioning steps from ArmFailSafe, except SetTCAcknowledgements and CommissioningComplete.", is_commissioning=False), - TestStep(2, "TH reads TCAcknowledgementsRequired attribute from the DUT."), - TestStep(3, "TH sends SetTCAcknowledgements to DUT with the following values:\nTCVersion: Greater than or equal to TCMinRequiredVersion on DUT\nTCUserResponse: All terms required by DUT accepted"), - TestStep(4, "TH sends CommissioningComplete to DUT."), - TestStep(5, "TH reads TCAcceptedVersion attribute from the DUT."), - TestStep(6, "TH reads TCAcknowledgements attribute from the DUT."), - TestStep(7, "TH reads TCMinRequiredVersion attribute from the DUT."), - TestStep(8, "TH reads TCAcknowledgementsRequired attribute from the DUT."), - TestStep(9, "TH sends the SetTCAcknowledgements command to the DUT with the fields set as follows:\nTCVersion: 0\nTCUserResponse: 0"), + TestStep(1, "TH begins commissioning the DUT and performs the following steps in order:\n* Security setup using PASE\n* Setup fail-safe timer, with ExpiryLengthSeconds field set to PIXIT.CGEN.FailsafeExpiryLengthSeconds and the Breadcrumb value as 1\n* Configure information- UTC time, regulatory, etc."), + TestStep(2, "TH reads TCAcknowledgementsRequired attribute from the DUT"), + TestStep(3, "TH reads TCUpdateDeadline attribute from the DUT"), + TestStep(4, "TH reads the FeatureMap from the General Commissioning Cluster."), + TestStep(5, "TH sends SetTCAcknowledgements to DUT with the following values:\n* TCVersion: PIXIT.CGEN.TCRevision\n* TCUserResponse: PIXIT.CGEN.RequiredTCAcknowledgements"), + TestStep(6, "TH reads TCAcknowledgementsRequired attribute from the DUT"), + TestStep(7, "TH continues commissioning with the DUT and performs the steps from 'Operation CSR exchange' through 'Security setup using CASE'"), + TestStep(8, "TH sends CommissioningComplete to DUT."), + TestStep(9, "TH reads from the DUT the attribute TCAcceptedVersion."), + TestStep(10, "TH reads from the DUT the attribute TCAcknowledgements."), + TestStep(11, "TH reads from the DUT the attribute."), + TestStep(12, "TH reads from the DUT the attribute TCAcknowledgementsRequired."), ] @async_test_body @@ -68,34 +71,40 @@ async def test_TC_CGEN_2_5(self): # Step 1: Begin commissioning with PASE and failsafe self.step(1) - commissioner.SetTCRequired(False) commissioner.SetSkipCommissioningComplete(True) self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + self.matter_test_config.tc_version_to_simulate = None + self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() # Step 2: Read TCAcknowledgementsRequired self.step(2) - response = await commissioner.ReadAttribute( - nodeid=self.dut_node_id, - attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired)]) + response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired)]) tc_acknowledgements_required = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired] - asserts.assert_equal(tc_acknowledgements_required, True, 'Incorrect TCAcknowledgementsRequired') + asserts.assert_equal(tc_acknowledgements_required, True, "TCAcknowledgementsRequired should be True.") # Step 3: Read TCUpdateDeadline self.step(3) response = await commissioner.ReadAttribute( nodeid=self.dut_node_id, - attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCUpdateDeadline)]) - tcUpdateDeadline = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCUpdateDeadline] - asserts.assert_less(tcUpdateDeadline, 2**32, 'TCUpdateDeadline exceeds uint32 range') + attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCUpdateDeadline)], + ) + tc_update_deadline = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCUpdateDeadline] - # Step 4: Read FeatureMap + # Validate the value is of type Optional[uint32], e.g. either None or within the 32-bit range. + if isinstance(tc_update_deadline, ValueDecodeFailure): + asserts.assert_is_none(tc_update_deadline.TLVValue) + else: + asserts.assert_less(tc_update_deadline, 2**32, "TCUpdateDeadline exceeds uint32 range") + + # Step 4: Verify TC feature flag in FeatureMap self.step(4) response = await commissioner.ReadAttribute( nodeid=self.dut_node_id, - attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.FeatureMap)]) - featureMap = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.FeatureMap] - asserts.assert_equal(featureMap & 0x1, 0x1, 'TC feature flag not set') + attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.FeatureMap)], + ) + feature_map = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.FeatureMap] + asserts.assert_equal(feature_map & 0x1, 0x1, "TC feature flag is not set.") # Step 5: Send SetTCAcknowledgements self.step(5) @@ -103,24 +112,23 @@ async def test_TC_CGEN_2_5(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( - TCVersion=tc_version_to_simulate, - TCUserResponse=tc_user_response_to_simulate), - timedRequestTimeoutMs=1000) - asserts.assert_equal(response.errorCode, - Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, - 'Incorrect error code') + TCVersion=tc_version_to_simulate, TCUserResponse=tc_user_response_to_simulate + ), + ) + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + "SetTCAcknowledgementsResponse error code is not OK.", + ) # Step 6: Verify TCAcknowledgementsRequired is False self.step(6) - response = await commissioner.ReadAttribute( - nodeid=self.dut_node_id, - attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired)]) + response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired)]) tc_acknowledgements_required = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired] - asserts.assert_equal(tc_acknowledgements_required, False, 'TCAcknowledgementsRequired should be False') + asserts.assert_equal(tc_acknowledgements_required, False, "TCAcknowledgementsRequired should be False.") - # Step 7: Complete CSR exchange and CASE security setup + # Step 7: Continue with CSR and CASE setup self.step(7) - # Note: Implementation needed for CSR exchange and CASE setup # Step 8: Send CommissioningComplete self.step(8) @@ -128,42 +136,36 @@ async def test_TC_CGEN_2_5(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), - timedRequestTimeoutMs=1000) - asserts.assert_equal(response.errorCode, - Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, - 'Incorrect error code') - - # Steps 9-12: Read and verify final attribute values - response = await commissioner.ReadAttribute( - nodeid=self.dut_node_id, - attributes=[ - (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion), - (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion), - (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements), - (ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired), - ]) + ) + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + "CommissioningCompleteResponse error code is not OK.", + ) # Step 9: Verify TCAcceptedVersion self.step(9) - tcAcceptedVersion = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] - asserts.assert_less(tcAcceptedVersion, 2**16, 'TCAcceptedVersion exceeds uint16 range') - asserts.assert_equal(tcAcceptedVersion, tc_version_to_simulate, 'Incorrect TCAcceptedVersion') + response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion)]) + accepted_version = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] + asserts.assert_equal(accepted_version, tc_version_to_simulate, "TCAcceptedVersion does not match expected value.") # Step 10: Verify TCAcknowledgements self.step(10) - tcAcknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] - asserts.assert_less(tcAcknowledgements, 2**16, 'TCAcknowledgements exceeds map16 range') - asserts.assert_equal(tcAcknowledgements, tc_user_response_to_simulate, 'Incorrect TCAcknowledgements') + response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements)]) + acknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] + asserts.assert_equal(acknowledgements, tc_user_response_to_simulate, "TCAcknowledgements does not match expected value.") # Step 11: Verify TCMinRequiredVersion self.step(11) - tcMinRequiredVersion = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion] - asserts.assert_less(tcMinRequiredVersion, 2**16, 'TCMinRequiredVersion exceeds uint16 range') + response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion)]) + min_required_version = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion] + asserts.assert_is_instance(min_required_version, int, "TCMinRequiredVersion is not a uint16 type.") - # Step 12: Verify TCAcknowledgementsRequired + # Step 12: Verify TCAcknowledgementsRequired is False again self.step(12) + response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired)]) tc_acknowledgements_required = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired] - asserts.assert_equal(tc_acknowledgements_required, False, 'TCAcknowledgementsRequired should be False') + asserts.assert_equal(tc_acknowledgements_required, False, "TCAcknowledgementsRequired should be False.") if __name__ == "__main__": diff --git a/src/python_testing/TC_CGEN_2_6.py b/src/python_testing/TC_CGEN_2_6.py index b63408218608dd..188e8d0dafe42b 100644 --- a/src/python_testing/TC_CGEN_2_6.py +++ b/src/python_testing/TC_CGEN_2_6.py @@ -27,8 +27,6 @@ # --capabilities 6 # script-args: # --in-test-commissioning-method on-network -# --tc-version-to-simulate 1 -# --tc-user-response-to-simulate 1 # --qr-code MT:-24J0AFN00KA0648G00 # --trace-to json:log # factoryreset: True @@ -49,7 +47,7 @@ def desc_TC_CGEN_2_6(self) -> str: def steps_TC_CGEN_2_6(self) -> list[TestStep]: return [ TestStep(1, "TH starts commissioning the DUT. It performs all commissioning steps from 'Device discovery and establish commissioning channel' to 'Security setup using CASE', except for TC configuration with SetTCAcknowledgements."), - TestStep(2, "TH sends CommissioningComplete to DUT and verifies error response."), + TestStep(2, "TH sends CommissioningComplete to DUT."), ] @async_test_body @@ -58,11 +56,11 @@ async def test_TC_CGEN_2_6(self): # Step 1: Commission device without setting TC acknowledgements self.step(1) - # Don't set TCs for the next commissioning and skip CommissioningComplete - # so we can manually call CommissioningComplete to check the response error code - commissioner.SetTCRequired(False) + # Don't set TCs for the next commissioning and skip CommissioningComplete so we can manually call CommissioningComplete to check the response error code commissioner.SetSkipCommissioningComplete(True) self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + self.matter_test_config.tc_version_to_simulate = None + self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() # Step 2: Send CommissioningComplete and verify error response @@ -71,14 +69,14 @@ async def test_TC_CGEN_2_6(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), - timedRequestTimeoutMs=1000) + ) - # Verify that DUT sends CommissioningCompleteResponse Command to TH - # With ErrorCode as 'TCAcknowledgementsNotReceived'(6) + # Verify that DUT sends CommissioningCompleteResponse Command to TH with ErrorCode as 'TCAcknowledgementsNotReceived'(6) asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCAcknowledgementsNotReceived, - 'Expected TCAcknowledgementsNotReceived error code') + "Expected TCAcknowledgementsNotReceived error code", + ) if __name__ == "__main__": diff --git a/src/python_testing/TC_CGEN_2_7.py b/src/python_testing/TC_CGEN_2_7.py index edec706079461a..b037055436d1e4 100644 --- a/src/python_testing/TC_CGEN_2_7.py +++ b/src/python_testing/TC_CGEN_2_7.py @@ -48,34 +48,32 @@ def desc_TC_CGEN_2_7(self) -> str: def steps_TC_CGEN_2_7(self) -> list[TestStep]: return [ - TestStep(1, "TH begins commissioning the DUT and performs the following steps in order:\n" - "* Security setup using PASE\n" - "* Setup fail-safe timer, with ExpiryLengthSeconds field set to PIXIT.CGEN.FailsafeExpiryLengthSeconds and the Breadcrumb value as 1\n" - "* Configure information- UTC time, regulatory, etc."), - TestStep(2, "TH reads TCMinRequiredVersion attribute."), - TestStep(3, "TH sends SetTCAcknowledgements with TCVersion=minVersion and TCUserResponse=0"), + TestStep(1, "TH begins commissioning the DUT and performs the following steps in order:\n* Security setup using PASE\n* Setup fail-safe timer, with ExpiryLengthSeconds field set to PIXIT.CGEN.FailsafeExpiryLengthSeconds and the Breadcrumb value as 1\n* Configure information- UTC time, regulatory, etc."), + TestStep(2, "TH reads from the DUT the attribute TCMinRequiredVersion. Store the value as minVersion."), + TestStep(3, "TH sends SetTCAcknowledgements to DUT with the following values:\n* TCVersion: minVersion\n* TCUserResponse: 0"), TestStep(4, "TH continues commissioning with the DUT and performs the steps from 'Operation CSR exchange' through 'Security setup using CASE'"), TestStep(5, "TH sends CommissioningComplete to DUT."), - TestStep(6, "TH sends SetTCAcknowledgements with valid TC values"), - TestStep(7, "TH sends CommissioningComplete to DUT.") + TestStep(6, "TH sends SetTCAcknowledgements to DUT with the following values:\n* TCVersion: PIXIT.CGEN.TCRevision\n* TCUserResponse: PIXIT.CGEN.RequiredTCAcknowledgements"), + TestStep(7, "TH sends CommissioningComplete to DUT."), ] @async_test_body async def test_TC_CGEN_2_7(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + tc_version_to_simulate: int = self.matter_test_config.tc_version_to_simulate + tc_user_response_to_simulate: int = self.matter_test_config.tc_user_response_to_simulate # Step 1: Begin commissioning with PASE and failsafe self.step(1) - commissioner.SetTCRequired(False) commissioner.SetSkipCommissioningComplete(True) self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + self.matter_test_config.tc_version_to_simulate = None + self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() # Step 2: Read TCMinRequiredVersion self.step(2) - response = await commissioner.ReadAttribute( - nodeid=self.dut_node_id, - attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion)]) + response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion)]) min_version = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion] # Step 3: Send SetTCAcknowledgements with invalid response @@ -84,15 +82,16 @@ async def test_TC_CGEN_2_7(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( - TCVersion=min_version, - TCUserResponse=0), - timedRequestTimeoutMs=1000) + TCVersion=min_version, TCUserResponse=0 + ), + ) # Verify error code is RequiredTCNotAccepted asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kRequiredTCNotAccepted, - 'Expected RequiredTCNotAccepted error code') + "Expected RequiredTCNotAccepted error code", + ) # Step 4: Continue with CSR and CASE setup self.step(4) @@ -104,13 +103,14 @@ async def test_TC_CGEN_2_7(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), - timedRequestTimeoutMs=1000) + ) # Verify error code is TCAcknowledgementsNotReceived asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCAcknowledgementsNotReceived, - 'Expected TCAcknowledgementsNotReceived error code') + "Expected TCAcknowledgementsNotReceived error code", + ) # Step 6: Send SetTCAcknowledgements with valid values self.step(6) @@ -118,15 +118,16 @@ async def test_TC_CGEN_2_7(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( - TCVersion=self.pixit['CGEN']['TCRevision'], - TCUserResponse=self.pixit['CGEN']['RequiredTCAcknowledgements']), - timedRequestTimeoutMs=1000) + TCVersion=tc_version_to_simulate, TCUserResponse=tc_user_response_to_simulate + ), + ) # Verify error code is OK asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, - 'Expected OK response for valid TC acknowledgements') + "Expected OK response for valid TC acknowledgements", + ) # Step 7: Send CommissioningComplete and verify success self.step(7) @@ -134,13 +135,14 @@ async def test_TC_CGEN_2_7(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), - timedRequestTimeoutMs=1000) + ) # Verify error code is OK asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, - 'Expected OK response for CommissioningComplete') + "Expected OK response for CommissioningComplete", + ) if __name__ == "__main__": diff --git a/src/python_testing/TC_CGEN_2_8.py b/src/python_testing/TC_CGEN_2_8.py index 09a40f1947793c..aa1b11ba9c5842 100644 --- a/src/python_testing/TC_CGEN_2_8.py +++ b/src/python_testing/TC_CGEN_2_8.py @@ -48,24 +48,28 @@ def desc_TC_CGEN_2_8(self) -> str: def steps_TC_CGEN_2_8(self) -> list[TestStep]: return [ - TestStep(1, "TH begins commissioning with PASE, failsafe setup, and basic configuration."), - TestStep(2, "TH sends SetTCAcknowledgements to DUT with required values."), - TestStep(3, "TH continues commissioning with CSR exchange through CASE setup."), + TestStep(1, "TH begins commissioning the DUT and performs the following steps in order:\n* Security setup using PASE\n* Setup fail-safe timer, with ExpiryLengthSeconds field set to PIXIT.CGEN.FailsafeExpiryLengthSeconds and the Breadcrumb value as 1\n* Configure information- UTC time, regulatory, etc."), + TestStep(2, "TH sends SetTCAcknowledgements to DUT with the following values:\n* TCVersion: PIXIT.CGEN.TCRevision\n* TCUserResponse: PIXIT.CGEN.RequiredTCAcknowledgements"), + TestStep(3, "TH continues commissioning steps with the DUT and performs steps 'Operation CSR exchange' through 'Security setup using CASE'"), TestStep(4, "TH sends CommissioningComplete to DUT."), TestStep(5, "DUT is factory reset."), - TestStep(6, "Put DUT into commissionable state."), - TestStep(7, "TH begins commissioning without TC acknowledgements."), - TestStep(8, "Verify CommissioningComplete fails with TCAcknowledgementsNotReceived.") + TestStep(6, "Perform the necessary actions to put the DUT into a commissionable state."), + TestStep(7, "TH begins commissioning the DUT and performs the steps 'Device discovery and establish commissioning channel' through 'Security setup using CASE', skipping 'Configure information- TC Acknowledgements'"), + TestStep(8, "TH sends CommissioningComplete to DUT."), ] @async_test_body async def test_TC_CGEN_2_8(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + tc_version_to_simulate: int = self.matter_test_config.tc_version_to_simulate + tc_user_response_to_simulate: int = self.matter_test_config.tc_user_response_to_simulate # Steps 1-4: Initial commissioning with TC acknowledgements self.step(1) commissioner.SetSkipCommissioningComplete(True) self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + self.matter_test_config.tc_version_to_simulate = None + self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() # Step 2: Send SetTCAcknowledgements @@ -74,13 +78,14 @@ async def test_TC_CGEN_2_8(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( - TCVersion=self.pixit['CGEN']['TCRevision'], - TCUserResponse=self.pixit['CGEN']['RequiredTCAcknowledgements']), - timedRequestTimeoutMs=1000) + TCVersion=tc_version_to_simulate, TCUserResponse=tc_user_response_to_simulate + ), + ) asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, - 'SetTCAcknowledgements failed') + "SetTCAcknowledgements failed", + ) # Step 3: Continue with CSR and CASE setup self.step(3) @@ -92,11 +97,12 @@ async def test_TC_CGEN_2_8(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), - timedRequestTimeoutMs=1000) + ) asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, - 'First CommissioningComplete failed') + "First CommissioningComplete failed", + ) # Step 5: Factory reset is handled by test runner configuration self.step(5) @@ -107,9 +113,10 @@ async def test_TC_CGEN_2_8(self): # Step 7: Commission without TC acknowledgements self.step(7) - commissioner.SetTCRequired(False) commissioner.SetSkipCommissioningComplete(True) self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + self.matter_test_config.tc_version_to_simulate = None + self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() # Step 8: Verify CommissioningComplete fails @@ -118,11 +125,12 @@ async def test_TC_CGEN_2_8(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), - timedRequestTimeoutMs=1000) + ) asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCAcknowledgementsNotReceived, - 'Expected TCAcknowledgementsNotReceived error after factory reset') + "Expected TCAcknowledgementsNotReceived error after factory reset", + ) if __name__ == "__main__": diff --git a/src/python_testing/TC_CGEN_2_9.py b/src/python_testing/TC_CGEN_2_9.py index 16084633ba340e..2362e2f9c6df36 100644 --- a/src/python_testing/TC_CGEN_2_9.py +++ b/src/python_testing/TC_CGEN_2_9.py @@ -48,27 +48,28 @@ def desc_TC_CGEN_2_9(self) -> str: def steps_TC_CGEN_2_9(self) -> list[TestStep]: return [ - TestStep(1, "TH begins commissioning the DUT and performs the following steps in order:\n" - "* Security setup using PASE\n" - "* Setup fail-safe timer, with ExpiryLengthSeconds field set to PIXIT.CGEN.FailsafeExpiryLengthSeconds and the Breadcrumb value as 1\n" - "* Configure information- UTC time, regulatory, etc."), - TestStep(2, "TH sends SetTCAcknowledgements with required values"), - TestStep(3, "TH continues commissioning with CSR exchange through CASE setup"), - TestStep(4, "TH sends CommissioningComplete to DUT"), - TestStep(5, "TH removes all fabrics from DUT with RemoveFabric"), - TestStep(6, "Put DUT into commissionable state"), - TestStep(7, "TH begins commissioning without TC acknowledgements"), - TestStep(8, "Verify CommissioningComplete fails with TCAcknowledgementsNotReceived") + TestStep(1, "TH begins commissioning the DUT and performs the following steps in order:\n* Security setup using PASE\n* Setup fail-safe timer, with ExpiryLengthSeconds field set to PIXIT.CGEN.FailsafeExpiryLengthSeconds and the Breadcrumb value as 1\n* Configure information- UTC time, regulatory, etc."), + TestStep(2, "TH sends SetTCAcknowledgements to DUT with the following values:\n* TCVersion: PIXIT.CGEN.TCRevision\n* TCUserResponse: PIXIT.CGEN.RequiredTCAcknowledgements"), + TestStep(3, "TH continues commissioning with the DUT and performs the steps from 'Operation CSR exchange' through 'Security setup using CASE'"), + TestStep(4, "TH sends CommissioningComplete to DUT."), + TestStep(5, "TH removes all fabrics from DUT with RemoveFabric."), + TestStep(6, "Perform the necessary actions to put the DUT into a commissionable state."), + TestStep(7, "TH begins commissioning the DUT and performs all steps from 'Device discovery and establish commissioning channel' through 'Security setup using CASE', skipping the 'Configure TC acknowledgements' step"), + TestStep(8, "TH sends CommissioningComplete to DUT."), ] @async_test_body async def test_TC_CGEN_2_9(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + tc_version_to_simulate: int = self.matter_test_config.tc_version_to_simulate + tc_user_response_to_simulate: int = self.matter_test_config.tc_user_response_to_simulate # Step 1: Begin commissioning with PASE and failsafe self.step(1) commissioner.SetSkipCommissioningComplete(True) self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + self.matter_test_config.tc_version_to_simulate = None + self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() # Step 2: Send SetTCAcknowledgements @@ -77,15 +78,16 @@ async def test_TC_CGEN_2_9(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.SetTCAcknowledgements( - TCVersion=self.pixit['CGEN']['TCRevision'], - TCUserResponse=self.pixit['CGEN']['RequiredTCAcknowledgements']), - timedRequestTimeoutMs=1000) + TCVersion=tc_version_to_simulate, TCUserResponse=tc_user_response_to_simulate + ), + ) # Verify SetTCAcknowledgements response asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, - 'SetTCAcknowledgements failed') + "SetTCAcknowledgements failed", + ) # Step 3: Continue with CSR and CASE setup self.step(3) @@ -97,13 +99,14 @@ async def test_TC_CGEN_2_9(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), - timedRequestTimeoutMs=1000) + ) # Verify CommissioningComplete response asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, - 'First CommissioningComplete failed') + "First CommissioningComplete failed", + ) # Step 5: Remove all fabrics self.step(5) @@ -111,13 +114,14 @@ async def test_TC_CGEN_2_9(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.OperationalCredentials.Commands.RemoveFabric(), - timedRequestTimeoutMs=1000) + ) # Verify RemoveFabric response asserts.assert_equal( response.errorCode, Clusters.OperationalCredentials.Enums.OperationalCredentialsStatusEnum.kSuccess, - 'RemoveFabric failed') + "RemoveFabric failed", + ) # Step 6: Put device in commissioning mode self.step(6) @@ -125,9 +129,10 @@ async def test_TC_CGEN_2_9(self): # Step 7: Commission without TC acknowledgements self.step(7) - commissioner.SetTCRequired(False) commissioner.SetSkipCommissioningComplete(True) self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + self.matter_test_config.tc_version_to_simulate = None + self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() # Step 8: Verify CommissioningComplete fails @@ -136,13 +141,14 @@ async def test_TC_CGEN_2_9(self): nodeid=self.dut_node_id, endpoint=ROOT_ENDPOINT_ID, payload=Clusters.GeneralCommissioning.Commands.CommissioningComplete(), - timedRequestTimeoutMs=1000) + ) # Verify CommissioningComplete fails with correct error asserts.assert_equal( response.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kTCAcknowledgementsNotReceived, - 'Expected TCAcknowledgementsNotReceived error after fabric removal') + "Expected TCAcknowledgementsNotReceived error after fabric removal", + ) if __name__ == "__main__": From 28565c111c721375cb35011ae43a18c6ba22186e Mon Sep 17 00:00:00 2001 From: James Swan Date: Wed, 15 Jan 2025 23:17:19 +0000 Subject: [PATCH 08/23] --- scripts/build/builders/host.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build/builders/host.py b/scripts/build/builders/host.py index 4df8719def5596..0d6d99a5f00e71 100644 --- a/scripts/build/builders/host.py +++ b/scripts/build/builders/host.py @@ -282,8 +282,8 @@ def OutputNames(self): yield 'water-leak-detector-app' yield 'water-leak-detector-app.map' elif self == HostApp.TERMS_AND_CONDITIONS: - yield 'terms-and-conditions-app' - yield 'terms-and-conditions-app.map' + yield 'chip-terms-and-conditions-app' + yield 'chip-terms-and-conditions-app.map' else: raise Exception('Unknown app type: %r' % self) From 451e82c45da21d13daf333549181569267be7cf3 Mon Sep 17 00:00:00 2001 From: James Swan Date: Tue, 21 Jan 2025 23:46:53 +0000 Subject: [PATCH 09/23] feat(testing): Add PICS guard for Terms & Conditions test steps - Wrap test steps in PICS guard checks for "CGEN.S" and "CGEN.S.F00(TC)" - Ensure test steps only execute when Terms & Conditions feature flag is enabled - Maintain test logic while adding conditional execution based on PICS support --- .../tests/suites/certification/ci-pics-values | 9 ++- src/python_testing/TC_CGEN_2_10.py | 22 +++++- src/python_testing/TC_CGEN_2_11.py | 33 +++++++- src/python_testing/TC_CGEN_2_5.py | 34 ++++++++- src/python_testing/TC_CGEN_2_6.py | 11 +++ src/python_testing/TC_CGEN_2_7.py | 33 +++++++- src/python_testing/TC_CGEN_2_8.py | 42 ++++++++-- src/python_testing/TC_CGEN_2_9.py | 76 ++++++++++++++----- 8 files changed, 221 insertions(+), 39 deletions(-) diff --git a/src/app/tests/suites/certification/ci-pics-values b/src/app/tests/suites/certification/ci-pics-values index 1f4f1f66e906c3..c8498bcd03ce76 100644 --- a/src/app/tests/suites/certification/ci-pics-values +++ b/src/app/tests/suites/certification/ci-pics-values @@ -729,6 +729,7 @@ SWTCH.C.AO-READ=0 SWTCH.C.AO-WRITE=0 # General Commissioning Cluster +CGEN.C=1 CGEN.S=1 CGEN.S.A0000=1 CGEN.S.A0001=1 @@ -742,7 +743,13 @@ CGEN.S.C03.Tx=1 CGEN.S.C04.Rsp=1 CGEN.S.C05.Tx=1 -CGEN.C=1 +#Feature +CGEN.S.F00(TC)=1 + +#PIXIT +PIXIT.CGEN.FailsafeExpiryLengthSeconds=0 +PIXIT.CGEN.RequiredTCAcknowledgements=1 +PIXIT.CGEN.TCRevision=1 # LAUNDRY WASHER MODE CLUSTER LWM.S=1 diff --git a/src/python_testing/TC_CGEN_2_10.py b/src/python_testing/TC_CGEN_2_10.py index ce5ac7b01199d7..0eb08aeb3d5834 100644 --- a/src/python_testing/TC_CGEN_2_10.py +++ b/src/python_testing/TC_CGEN_2_10.py @@ -26,7 +26,8 @@ # --custom-flow 2 # --capabilities 6 # script-args: -# --commissioning-method on-network +# --PICS src/app/tests/suites/certification/ci-pics-values +# --in-test-commissioning-method on-network # --tc-version-to-simulate 1 # --tc-user-response-to-simulate 1 # --qr-code MT:-24J0AFN00KA0648G00 @@ -46,8 +47,13 @@ class TC_CGEN_2_10(MatterBaseTest): def desc_TC_CGEN_2_10(self) -> str: return "[TC-CGEN-2.10] Verification that required terms can't be unset from TCAcknowledgements with SetTCAcknowledgements [DUT as Server]" + def pics_TC_CGEN_2_10(self) -> list[str]: + """ This function returns a list of PICS for this test case that must be True for the test to be run""" + return ["CGEN.S", "CGEN.S.F00(TC)"] + def steps_TC_CGEN_2_10(self) -> list[TestStep]: return [ + TestStep(0, description="", expectation="", is_commissioning=False), TestStep(1, "TH reads from the DUT the attribute TCAcceptedVersion. Store the value as acceptedVersion."), TestStep(2, "TH reads from the DUT the attribute TCAcknowledgements. Store the value as userAcknowledgements."), TestStep(3, "TH Sends the SetTCAcknowledgements command to the DUT with the fields set as follows:\n* TCVersion: 0\n* TCUserResponse: 65535"), @@ -61,8 +67,22 @@ def steps_TC_CGEN_2_10(self) -> list[TestStep]: @async_test_body async def test_TC_CGEN_2_10(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + + self.step(0) + if not self.pics_guard(self.check_pics("CGEN.S.F00(TC)")): + self.skip_all_remaining_steps(1) + return + + # Step 1: Begin commissioning with PASE and failsafe + commissioner.SetSkipCommissioningComplete(True) + self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method + self.matter_test_config.tc_version_to_simulate = None + self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() + # await self.commission_devices() + # self.skip_all_remaining_steps(1) + # return # Step 1: Read TCAcceptedVersion self.step(1) response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion)]) diff --git a/src/python_testing/TC_CGEN_2_11.py b/src/python_testing/TC_CGEN_2_11.py index 7ec275f1a59ea3..fdb5d8e13b9292 100644 --- a/src/python_testing/TC_CGEN_2_11.py +++ b/src/python_testing/TC_CGEN_2_11.py @@ -26,9 +26,11 @@ # --custom-flow 2 # --capabilities 6 # script-args: +# --PICS src/app/tests/suites/certification/ci-pics-values # --in-test-commissioning-method on-network -# --tc-version-to-simulate 1 -# --tc-user-response-to-simulate 1 +# --int-arg PIXIT.CGEN.FailsafeExpiryLengthSeconds:900 +# --int-arg PIXIT.CGEN.RequiredTCAcknowledgements:1 +# --int-arg PIXIT.CGEN.TCRevision:1 # --qr-code MT:-24J0AFN00KA0648G00 # --trace-to json:log # factoryreset: True @@ -46,8 +48,13 @@ class TC_CGEN_2_11(MatterBaseTest): def desc_TC_CGEN_2_11(self) -> str: return "[TC-CGEN-2.11] Verification that TCAcknowledgements and TCAcceptedVersion can be updated after being commissioned [DUT as Server]" + def pics_TC_CGEN_2_11(self) -> list[str]: + """ This function returns a list of PICS for this test case that must be True for the test to be run""" + return ["CGEN.S", "CGEN.S.F00(TC)"] + def steps_TC_CGEN_2_11(self) -> list[TestStep]: return [ + TestStep(0, description="", expectation="", is_commissioning=False), TestStep(1, "TH begins commissioning the DUT and performs the following steps in order:\n* Security setup using PASE\n* Setup fail-safe timer, with ExpiryLengthSeconds field set to PIXIT.CGEN.FailsafeExpiryLengthSeconds and the Breadcrumb value as 1\n* Configure information- UTC time, regulatory, etc."), TestStep(2, "TH sends SetTCAcknowledgements to DUT with the following values:\n* TCVersion: PIXIT.CGEN.TCRevision\n* TCUserResponse: PIXIT.CGEN.RequiredTCAcknowledgements"), TestStep(3, "TH sends CommissioningComplete to DUT."), @@ -60,8 +67,14 @@ def steps_TC_CGEN_2_11(self) -> list[TestStep]: @async_test_body async def test_TC_CGEN_2_11(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller - tc_version_to_simulate: int = self.matter_test_config.tc_version_to_simulate - tc_user_response_to_simulate: int = self.matter_test_config.tc_user_response_to_simulate + failsafe_expiry_length_seconds = self.matter_test_config.global_test_params['PIXIT.CGEN.FailsafeExpiryLengthSeconds'] + tc_version_to_simulate = self.matter_test_config.global_test_params['PIXIT.CGEN.TCRevision'] + tc_user_response_to_simulate = self.matter_test_config.global_test_params['PIXIT.CGEN.RequiredTCAcknowledgements'] + + self.step(0) + if not self.pics_guard(self.check_pics("CGEN.S.F00(TC)")): + self.skip_all_remaining_steps(1) + return # Step 1: Begin commissioning with PASE and failsafe self.step(1) @@ -71,6 +84,18 @@ async def test_TC_CGEN_2_11(self): self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.ArmFailSafe( + expiryLengthSeconds=failsafe_expiry_length_seconds, breadcrumb=1), + ) + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + "ArmFailSafeResponse error code is not OK.", + ) + # Step 2: Send initial SetTCAcknowledgements self.step(2) response = await commissioner.SendCommand( diff --git a/src/python_testing/TC_CGEN_2_5.py b/src/python_testing/TC_CGEN_2_5.py index 9e2991f5989746..bbcd266aad38aa 100644 --- a/src/python_testing/TC_CGEN_2_5.py +++ b/src/python_testing/TC_CGEN_2_5.py @@ -26,9 +26,11 @@ # --custom-flow 2 # --capabilities 6 # script-args: +# --PICS src/app/tests/suites/certification/ci-pics-values # --in-test-commissioning-method on-network -# --tc-version-to-simulate 1 -# --tc-user-response-to-simulate 1 +# --int-arg PIXIT.CGEN.FailsafeExpiryLengthSeconds:900 +# --int-arg PIXIT.CGEN.RequiredTCAcknowledgements:1 +# --int-arg PIXIT.CGEN.TCRevision:1 # --qr-code MT:-24J0AFN00KA0648G00 # --trace-to json:log # factoryreset: True @@ -47,8 +49,13 @@ class TC_CGEN_2_5(MatterBaseTest): def desc_TC_CGEN_2_5(self) -> str: return "[TC-CGEN-2.5] Verification for SetTCAcknowledgements [DUT as Server]" + def pics_TC_CGEN_2_5(self) -> list[str]: + """ This function returns a list of PICS for this test case that must be True for the test to be run""" + return ["CGEN.S", "CGEN.S.F00(TC)"] + def steps_TC_CGEN_2_5(self) -> list[TestStep]: return [ + TestStep(0, description="", expectation="", is_commissioning=False), TestStep(1, "TH begins commissioning the DUT and performs the following steps in order:\n* Security setup using PASE\n* Setup fail-safe timer, with ExpiryLengthSeconds field set to PIXIT.CGEN.FailsafeExpiryLengthSeconds and the Breadcrumb value as 1\n* Configure information- UTC time, regulatory, etc."), TestStep(2, "TH reads TCAcknowledgementsRequired attribute from the DUT"), TestStep(3, "TH reads TCUpdateDeadline attribute from the DUT"), @@ -66,8 +73,15 @@ def steps_TC_CGEN_2_5(self) -> list[TestStep]: @async_test_body async def test_TC_CGEN_2_5(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller - tc_version_to_simulate: int = self.matter_test_config.tc_version_to_simulate - tc_user_response_to_simulate: int = self.matter_test_config.tc_user_response_to_simulate + + failsafe_expiry_length_seconds = self.matter_test_config.global_test_params['PIXIT.CGEN.FailsafeExpiryLengthSeconds'] + tc_version_to_simulate = self.matter_test_config.global_test_params['PIXIT.CGEN.TCRevision'] + tc_user_response_to_simulate = self.matter_test_config.global_test_params['PIXIT.CGEN.RequiredTCAcknowledgements'] + + self.step(0) + if not self.pics_guard(self.check_pics("CGEN.S.F00(TC)")): + self.skip_all_remaining_steps(1) + return # Step 1: Begin commissioning with PASE and failsafe self.step(1) @@ -77,6 +91,18 @@ async def test_TC_CGEN_2_5(self): self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.ArmFailSafe( + expiryLengthSeconds=failsafe_expiry_length_seconds, breadcrumb=1), + ) + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + "ArmFailSafeResponse error code is not OK.", + ) + # Step 2: Read TCAcknowledgementsRequired self.step(2) response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgementsRequired)]) diff --git a/src/python_testing/TC_CGEN_2_6.py b/src/python_testing/TC_CGEN_2_6.py index 188e8d0dafe42b..e68c1a46524217 100644 --- a/src/python_testing/TC_CGEN_2_6.py +++ b/src/python_testing/TC_CGEN_2_6.py @@ -26,6 +26,7 @@ # --custom-flow 2 # --capabilities 6 # script-args: +# --PICS src/app/tests/suites/certification/ci-pics-values # --in-test-commissioning-method on-network # --qr-code MT:-24J0AFN00KA0648G00 # --trace-to json:log @@ -44,8 +45,13 @@ class TC_CGEN_2_6(MatterBaseTest): def desc_TC_CGEN_2_6(self) -> str: return "[TC-CGEN-2.6] Verification for CommissioningComplete no terms accepted when required [DUT as Server]" + def pics_TC_CGEN_2_6(self) -> list[str]: + """ This function returns a list of PICS for this test case that must be True for the test to be run""" + return ["CGEN.S", "CGEN.S.F00(TC)"] + def steps_TC_CGEN_2_6(self) -> list[TestStep]: return [ + TestStep(0, description="", expectation="", is_commissioning=False), TestStep(1, "TH starts commissioning the DUT. It performs all commissioning steps from 'Device discovery and establish commissioning channel' to 'Security setup using CASE', except for TC configuration with SetTCAcknowledgements."), TestStep(2, "TH sends CommissioningComplete to DUT."), ] @@ -54,6 +60,11 @@ def steps_TC_CGEN_2_6(self) -> list[TestStep]: async def test_TC_CGEN_2_6(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + self.step(0) + if not self.pics_guard(self.check_pics("CGEN.S.F00(TC)")): + self.skip_all_remaining_steps(1) + return + # Step 1: Commission device without setting TC acknowledgements self.step(1) # Don't set TCs for the next commissioning and skip CommissioningComplete so we can manually call CommissioningComplete to check the response error code diff --git a/src/python_testing/TC_CGEN_2_7.py b/src/python_testing/TC_CGEN_2_7.py index b037055436d1e4..9cc4db41a90bf2 100644 --- a/src/python_testing/TC_CGEN_2_7.py +++ b/src/python_testing/TC_CGEN_2_7.py @@ -26,9 +26,11 @@ # --custom-flow 2 # --capabilities 6 # script-args: +# --PICS src/app/tests/suites/certification/ci-pics-values # --in-test-commissioning-method on-network -# --tc-version-to-simulate 1 -# --tc-user-response-to-simulate 1 +# --int-arg PIXIT.CGEN.FailsafeExpiryLengthSeconds:900 +# --int-arg PIXIT.CGEN.RequiredTCAcknowledgements:1 +# --int-arg PIXIT.CGEN.TCRevision:1 # --qr-code MT:-24J0AFN00KA0648G00 # --trace-to json:log # factoryreset: True @@ -46,8 +48,13 @@ class TC_CGEN_2_7(MatterBaseTest): def desc_TC_CGEN_2_7(self) -> str: return "[TC-CGEN-2.7] Verification for CommissioningComplete when SetTCAcknowledgements provides invalid terms [DUT as Server]" + def pics_TC_CGEN_2_7(self) -> list[str]: + """ This function returns a list of PICS for this test case that must be True for the test to be run""" + return ["CGEN.S", "CGEN.S.F00(TC)"] + def steps_TC_CGEN_2_7(self) -> list[TestStep]: return [ + TestStep(0, description="", expectation="", is_commissioning=False), TestStep(1, "TH begins commissioning the DUT and performs the following steps in order:\n* Security setup using PASE\n* Setup fail-safe timer, with ExpiryLengthSeconds field set to PIXIT.CGEN.FailsafeExpiryLengthSeconds and the Breadcrumb value as 1\n* Configure information- UTC time, regulatory, etc."), TestStep(2, "TH reads from the DUT the attribute TCMinRequiredVersion. Store the value as minVersion."), TestStep(3, "TH sends SetTCAcknowledgements to DUT with the following values:\n* TCVersion: minVersion\n* TCUserResponse: 0"), @@ -60,8 +67,14 @@ def steps_TC_CGEN_2_7(self) -> list[TestStep]: @async_test_body async def test_TC_CGEN_2_7(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller - tc_version_to_simulate: int = self.matter_test_config.tc_version_to_simulate - tc_user_response_to_simulate: int = self.matter_test_config.tc_user_response_to_simulate + failsafe_expiry_length_seconds = self.matter_test_config.global_test_params['PIXIT.CGEN.FailsafeExpiryLengthSeconds'] + tc_version_to_simulate = self.matter_test_config.global_test_params['PIXIT.CGEN.TCRevision'] + tc_user_response_to_simulate = self.matter_test_config.global_test_params['PIXIT.CGEN.RequiredTCAcknowledgements'] + + self.step(0) + if not self.pics_guard(self.check_pics("CGEN.S.F00(TC)")): + self.skip_all_remaining_steps(1) + return # Step 1: Begin commissioning with PASE and failsafe self.step(1) @@ -71,6 +84,18 @@ async def test_TC_CGEN_2_7(self): self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.ArmFailSafe( + expiryLengthSeconds=failsafe_expiry_length_seconds, breadcrumb=1), + ) + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + "ArmFailSafeResponse error code is not OK.", + ) + # Step 2: Read TCMinRequiredVersion self.step(2) response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion)]) diff --git a/src/python_testing/TC_CGEN_2_8.py b/src/python_testing/TC_CGEN_2_8.py index aa1b11ba9c5842..0f7b3289ea6ca5 100644 --- a/src/python_testing/TC_CGEN_2_8.py +++ b/src/python_testing/TC_CGEN_2_8.py @@ -26,9 +26,11 @@ # --custom-flow 2 # --capabilities 6 # script-args: +# --PICS src/app/tests/suites/certification/ci-pics-values # --in-test-commissioning-method on-network -# --tc-version-to-simulate 1 -# --tc-user-response-to-simulate 1 +# --int-arg PIXIT.CGEN.FailsafeExpiryLengthSeconds:900 +# --int-arg PIXIT.CGEN.RequiredTCAcknowledgements:1 +# --int-arg PIXIT.CGEN.TCRevision:1 # --qr-code MT:-24J0AFN00KA0648G00 # --trace-to json:log # factoryreset: True @@ -46,8 +48,13 @@ class TC_CGEN_2_8(MatterBaseTest): def desc_TC_CGEN_2_8(self) -> str: return "[TC-CGEN-2.8] Verification that TCAcknowledgements is reset after Factory Reset [DUT as Server]" + def pics_TC_CGEN_2_8(self) -> list[str]: + """ This function returns a list of PICS for this test case that must be True for the test to be run""" + return ["CGEN.S", "CGEN.S.F00(TC)"] + def steps_TC_CGEN_2_8(self) -> list[TestStep]: return [ + TestStep(0, description="", expectation="", is_commissioning=False), TestStep(1, "TH begins commissioning the DUT and performs the following steps in order:\n* Security setup using PASE\n* Setup fail-safe timer, with ExpiryLengthSeconds field set to PIXIT.CGEN.FailsafeExpiryLengthSeconds and the Breadcrumb value as 1\n* Configure information- UTC time, regulatory, etc."), TestStep(2, "TH sends SetTCAcknowledgements to DUT with the following values:\n* TCVersion: PIXIT.CGEN.TCRevision\n* TCUserResponse: PIXIT.CGEN.RequiredTCAcknowledgements"), TestStep(3, "TH continues commissioning steps with the DUT and performs steps 'Operation CSR exchange' through 'Security setup using CASE'"), @@ -61,10 +68,16 @@ def steps_TC_CGEN_2_8(self) -> list[TestStep]: @async_test_body async def test_TC_CGEN_2_8(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller - tc_version_to_simulate: int = self.matter_test_config.tc_version_to_simulate - tc_user_response_to_simulate: int = self.matter_test_config.tc_user_response_to_simulate + failsafe_expiry_length_seconds = self.matter_test_config.global_test_params['PIXIT.CGEN.FailsafeExpiryLengthSeconds'] + tc_version_to_simulate = self.matter_test_config.global_test_params['PIXIT.CGEN.TCRevision'] + tc_user_response_to_simulate = self.matter_test_config.global_test_params['PIXIT.CGEN.RequiredTCAcknowledgements'] + + self.step(0) + if not self.pics_guard(self.check_pics("CGEN.S.F00(TC)")): + self.skip_all_remaining_steps(1) + return - # Steps 1-4: Initial commissioning with TC acknowledgements + # Step 1: Begin commissioning with PASE and failsafe self.step(1) commissioner.SetSkipCommissioningComplete(True) self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method @@ -72,6 +85,18 @@ async def test_TC_CGEN_2_8(self): self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.ArmFailSafe( + expiryLengthSeconds=failsafe_expiry_length_seconds, breadcrumb=1), + ) + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + "ArmFailSafeResponse error code is not OK.", + ) + # Step 2: Send SetTCAcknowledgements self.step(2) response = await commissioner.SendCommand( @@ -107,14 +132,17 @@ async def test_TC_CGEN_2_8(self): # Step 5: Factory reset is handled by test runner configuration self.step(5) - # Step 6: Put device in commissioning mode + # Step 6: Put device in commissioning mode (requiring user input, so skip in CI) self.step(6) + if not self.check_pics('PICS_USER_PROMPT'): + self.skip_all_remaining_steps(7) + return + self.wait_for_user_input(prompt_msg="Set the DUT into commissioning mode") # Step 7: Commission without TC acknowledgements self.step(7) commissioner.SetSkipCommissioningComplete(True) - self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method self.matter_test_config.tc_version_to_simulate = None self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() diff --git a/src/python_testing/TC_CGEN_2_9.py b/src/python_testing/TC_CGEN_2_9.py index 2362e2f9c6df36..7b9b0977b3e4a4 100644 --- a/src/python_testing/TC_CGEN_2_9.py +++ b/src/python_testing/TC_CGEN_2_9.py @@ -26,9 +26,11 @@ # --custom-flow 2 # --capabilities 6 # script-args: +# --PICS src/app/tests/suites/certification/ci-pics-values # --in-test-commissioning-method on-network -# --tc-version-to-simulate 1 -# --tc-user-response-to-simulate 1 +# --int-arg PIXIT.CGEN.FailsafeExpiryLengthSeconds:900 +# --int-arg PIXIT.CGEN.RequiredTCAcknowledgements:1 +# --int-arg PIXIT.CGEN.TCRevision:1 # --qr-code MT:-24J0AFN00KA0648G00 # --trace-to json:log # factoryreset: True @@ -43,11 +45,39 @@ class TC_CGEN_2_9(MatterBaseTest): + + async def remove_commissioner_fabric(self): + commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller + + fabrics: list[Clusters.OperationalCredentials.Structs.FabricDescriptorStruct] = await self.read_single_attribute( + dev_ctrl=commissioner, + node_id=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + attribute=Clusters.OperationalCredentials.Attributes.Fabrics) + + # Re-order the list of fabrics so that the test harness admin fabric is removed last + commissioner_fabric = next((fabric for fabric in fabrics if fabric.fabricIndex == commissioner.fabricId), None) + fabrics.remove(commissioner_fabric) + fabrics.append(commissioner_fabric) + + for fabric in fabrics: + response: Clusters.OperationalCredentials.Commands.NOCResponse = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.OperationalCredentials.Commands.RemoveFabric(fabric.fabricIndex), + ) + asserts.assert_equal(response.statusCode, Clusters.OperationalCredentials.Enums.NodeOperationalCertStatusEnum.kOk) + def desc_TC_CGEN_2_9(self) -> str: return "[TC-CGEN-2.9] Verification that TCAcknowledgements is reset after all fabrics removed [DUT as Server]" + def pics_TC_CGEN_2_9(self) -> list[str]: + """ This function returns a list of PICS for this test case that must be True for the test to be run""" + return ["CGEN.S", "CGEN.S.F00(TC)"] + def steps_TC_CGEN_2_9(self) -> list[TestStep]: return [ + TestStep(0, description="", expectation="", is_commissioning=False), TestStep(1, "TH begins commissioning the DUT and performs the following steps in order:\n* Security setup using PASE\n* Setup fail-safe timer, with ExpiryLengthSeconds field set to PIXIT.CGEN.FailsafeExpiryLengthSeconds and the Breadcrumb value as 1\n* Configure information- UTC time, regulatory, etc."), TestStep(2, "TH sends SetTCAcknowledgements to DUT with the following values:\n* TCVersion: PIXIT.CGEN.TCRevision\n* TCUserResponse: PIXIT.CGEN.RequiredTCAcknowledgements"), TestStep(3, "TH continues commissioning with the DUT and performs the steps from 'Operation CSR exchange' through 'Security setup using CASE'"), @@ -61,8 +91,14 @@ def steps_TC_CGEN_2_9(self) -> list[TestStep]: @async_test_body async def test_TC_CGEN_2_9(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller - tc_version_to_simulate: int = self.matter_test_config.tc_version_to_simulate - tc_user_response_to_simulate: int = self.matter_test_config.tc_user_response_to_simulate + failsafe_expiry_length_seconds = self.matter_test_config.global_test_params['PIXIT.CGEN.FailsafeExpiryLengthSeconds'] + tc_version_to_simulate = self.matter_test_config.global_test_params['PIXIT.CGEN.TCRevision'] + tc_user_response_to_simulate = self.matter_test_config.global_test_params['PIXIT.CGEN.RequiredTCAcknowledgements'] + + self.step(0) + if not self.pics_guard(self.check_pics("CGEN.S.F00(TC)")): + self.skip_all_remaining_steps(1) + return # Step 1: Begin commissioning with PASE and failsafe self.step(1) @@ -72,6 +108,18 @@ async def test_TC_CGEN_2_9(self): self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() + response = await commissioner.SendCommand( + nodeid=self.dut_node_id, + endpoint=ROOT_ENDPOINT_ID, + payload=Clusters.GeneralCommissioning.Commands.ArmFailSafe( + expiryLengthSeconds=failsafe_expiry_length_seconds, breadcrumb=1), + ) + asserts.assert_equal( + response.errorCode, + Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + "ArmFailSafeResponse error code is not OK.", + ) + # Step 2: Send SetTCAcknowledgements self.step(2) response = await commissioner.SendCommand( @@ -110,27 +158,19 @@ async def test_TC_CGEN_2_9(self): # Step 5: Remove all fabrics self.step(5) - response = await commissioner.SendCommand( - nodeid=self.dut_node_id, - endpoint=ROOT_ENDPOINT_ID, - payload=Clusters.OperationalCredentials.Commands.RemoveFabric(), - ) + await self.remove_commissioner_fabric() - # Verify RemoveFabric response - asserts.assert_equal( - response.errorCode, - Clusters.OperationalCredentials.Enums.OperationalCredentialsStatusEnum.kSuccess, - "RemoveFabric failed", - ) - - # Step 6: Put device in commissioning mode + # Step 6: Put device in commissioning mode (requiring user input, so skip in CI) self.step(6) + if not self.check_pics('PICS_USER_PROMPT'): + self.skip_all_remaining_steps(7) + return + self.wait_for_user_input(prompt_msg="Set the DUT into commissioning mode") # Step 7: Commission without TC acknowledgements self.step(7) commissioner.SetSkipCommissioningComplete(True) - self.matter_test_config.commissioning_method = self.matter_test_config.in_test_commissioning_method self.matter_test_config.tc_version_to_simulate = None self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() From ed7f70fb16fab0648b53b6c786f12f64d332e5d1 Mon Sep 17 00:00:00 2001 From: James Swan Date: Wed, 22 Jan 2025 18:38:26 +0000 Subject: [PATCH 10/23] Added PICS and PIXIT definitions to src/app/tests/suites/certification/PICS.yaml --- src/app/tests/suites/certification/PICS.yaml | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/app/tests/suites/certification/PICS.yaml b/src/app/tests/suites/certification/PICS.yaml index e2111925952c02..0645554ca034fb 100644 --- a/src/app/tests/suites/certification/PICS.yaml +++ b/src/app/tests/suites/certification/PICS.yaml @@ -3632,6 +3632,27 @@ PICS: CommissioningCompleteResponse command?" id: CGEN.S.C05.Tx + # + # server / features + # + - label: + "Does the device implement the General Commissioning cluster's terms + and conditions feature?" + id: CGEN.S.F00(TC) + + - label: + "The device's failsafe expiration limit." + id: PIXIT.CGEN.FailsafeExpiryLengthSeconds + + - label: + "The device's required terms and conditions acknowledgements." + id: PIXIT.CGEN.RequiredTCAcknowledgements + + - label: + "The device's required minimum terms and conditions revision." + id: PIXIT.CGEN.TCRevision + + # General Diagnostics Cluster Test Plan - label: "Does the device implement the General Diagnostics cluster as a From 9c51e2b3f0fa0146e4ddd88e014a45a4a73324ea Mon Sep 17 00:00:00 2001 From: James Swan Date: Wed, 22 Jan 2025 18:42:39 +0000 Subject: [PATCH 11/23] --- src/app/tests/suites/certification/PICS.yaml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/app/tests/suites/certification/PICS.yaml b/src/app/tests/suites/certification/PICS.yaml index 0645554ca034fb..47fc43d7f285c4 100644 --- a/src/app/tests/suites/certification/PICS.yaml +++ b/src/app/tests/suites/certification/PICS.yaml @@ -3640,19 +3640,15 @@ PICS: and conditions feature?" id: CGEN.S.F00(TC) - - label: - "The device's failsafe expiration limit." + - label: "The device's failsafe expiration limit." id: PIXIT.CGEN.FailsafeExpiryLengthSeconds - - label: - "The device's required terms and conditions acknowledgements." + - label: "The device's required terms and conditions acknowledgements." id: PIXIT.CGEN.RequiredTCAcknowledgements - - label: - "The device's required minimum terms and conditions revision." + - label: "The device's required minimum terms and conditions revision." id: PIXIT.CGEN.TCRevision - # General Diagnostics Cluster Test Plan - label: "Does the device implement the General Diagnostics cluster as a From a7af4a55cdcc48d11828c6164fab82c873c1185a Mon Sep 17 00:00:00 2001 From: James Swan Date: Wed, 22 Jan 2025 23:21:15 +0000 Subject: [PATCH 12/23] From be17d16f4932c4f7e801fe09c221f09be1f2525b Mon Sep 17 00:00:00 2001 From: James Swan Date: Thu, 23 Jan 2025 00:26:25 +0000 Subject: [PATCH 13/23] refactor: Extract commission_devices functionality into reusable methods Move commissioning logic from CommissionDeviceTest class into standalone functions to improve code reusability. Introduce CommissioningInfo dataclass to encapsulate commissioning parameters and add commission_device/ commission_devices helper functions. The changes: - Move SetupPayloadInfo dataclass to module level - Add new CommissioningInfo dataclass for commissioning parameters - Extract commission_device and commission_devices as standalone async functions - Add commission_devices method to MatterBaseTest class - Maintain backward compatibility with existing usage in CommissionDeviceTest --- .../chip/testing/matter_testing.py | 195 ++++++++++-------- 1 file changed, 112 insertions(+), 83 deletions(-) diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py index 799b950882142a..3ad07fb66af579 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2022 Project CHIP Authors +# Copyright (c) 2022-2025 Project CHIP Authors # All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -221,6 +221,101 @@ def get_wait_seconds_from_set_time(set_time_matter_us: int, wait_seconds: int): return wait_seconds - seconds_passed + +@dataclass +class SetupPayloadInfo: + filter_type: discovery.FilterType = discovery.FilterType.LONG_DISCRIMINATOR + filter_value: int = 0 + passcode: int = 0 + + +@dataclass +class CommissioningInfo: + commissionee_ip_address_just_for_testing: Optional[str] = None + commissioning_method: Optional[str] = None + thread_operational_dataset: Optional[str] = None + wifi_passphrase: Optional[str] = None + wifi_ssid: Optional[str] = None + # Accepted Terms and Conditions if used + tc_version_to_simulate: int = None + tc_user_response_to_simulate: int = None + + +async def commission_device( + dev_ctrl: ChipDeviceCtrl.ChipDeviceController, node_id: int, info: SetupPayloadInfo, commissioning_info: CommissioningInfo +) -> bool: + if commissioning_info.tc_version_to_simulate is not None and commissioning_info.tc_user_response_to_simulate is not None: + logging.debug( + f"Setting TC Acknowledgements to version {commissioning_info.tc_version_to_simulate} with user response {commissioning_info.tc_user_response_to_simulate}." + ) + dev_ctrl.SetTCAcknowledgements(commissioning_info.tc_version_to_simulate, commissioning_info.tc_user_response_to_simulate) + + if commissioning_info.commissioning_method == "on-network": + try: + await dev_ctrl.CommissionOnNetwork( + nodeId=node_id, setupPinCode=info.passcode, filterType=info.filter_type, filter=info.filter_value + ) + return True + except ChipStackError as e: + logging.error("Commissioning failed: %s" % e) + return False + elif commissioning_info.commissioning_method == "ble-wifi": + try: + await dev_ctrl.CommissionWiFi( + info.filter_value, + info.passcode, + node_id, + commissioning_info.wifi_ssid, + commissioning_info.wifi_passphrase, + isShortDiscriminator=(info.filter_type == DiscoveryFilterType.SHORT_DISCRIMINATOR), + ) + return True + except ChipStackError as e: + logging.error("Commissioning failed: %s" % e) + return False + elif commissioning_info.commissioning_method == "ble-thread": + try: + await dev_ctrl.CommissionThread( + info.filter_value, + info.passcode, + node_id, + commissioning_info.thread_operational_dataset, + isShortDiscriminator=(info.filter_type == DiscoveryFilterType.SHORT_DISCRIMINATOR), + ) + return True + except ChipStackError as e: + logging.error("Commissioning failed: %s" % e) + return False + elif commissioning_info.commissioning_method == "on-network-ip": + try: + logging.warning("==== USING A DIRECT IP COMMISSIONING METHOD NOT SUPPORTED IN THE LONG TERM ====") + await dev_ctrl.CommissionIP( + ipaddr=commissioning_info.commissionee_ip_address_just_for_testing, + setupPinCode=info.passcode, + nodeid=node_id, + ) + return True + except ChipStackError as e: + logging.error("Commissioning failed: %s" % e) + return False + else: + raise ValueError("Invalid commissioning method %s!" % commissioning_info.commissioning_method) + + +async def commission_devices( + dev_ctrl: ChipDeviceCtrl.ChipDeviceController, + dut_node_ids: List[int], + setup_payloads: List[SetupPayloadInfo], + commissioning_info: CommissioningInfo, +) -> bool: + commissioned = [] + for node_id, setup_payload in zip(dut_node_ids, setup_payloads): + logging.info(f"Commissioning method: {commissioning_info.commissioning_method}") + commissioned.append(await commission_device(dev_ctrl, node_id, setup_payload, commissioning_info)) + + return all(commissioned) + + class SimpleEventCallback: def __init__(self, name: str, expected_cluster_id: int, expected_event_id: int, output_queue: queue.SimpleQueue): self._name = name @@ -851,13 +946,6 @@ def manual_code(self): self.custom_flow, self.capabilities, self.version) -@dataclass -class SetupPayloadInfo: - filter_type: discovery.FilterType = discovery.FilterType.LONG_DISCRIMINATOR - filter_value: int = 0 - passcode: int = 0 - - class MatterStackState: def __init__(self, config: MatterTestConfig): self._logger = logger @@ -1212,6 +1300,22 @@ def check_pics(self, pics_key: str) -> bool: @property def is_pics_sdk_ci_only(self) -> bool: return self.check_pics('PICS_SDK_CI_ONLY') + + async def commission_devices(self) -> bool: + dev_ctrl: ChipDeviceCtrl.ChipDeviceController = self.default_controller + dut_node_ids: List[int] = self.matter_test_config.dut_node_ids + setup_payloads: List[SetupPayloadInfo] = self.get_setup_payload_info() + commissioning_info: CommissioningInfo = CommissioningInfo( + commissionee_ip_address_just_for_testing=self.matter_test_config.commissionee_ip_address_just_for_testing, + commissioning_method=self.matter_test_config.commissioning_method, + thread_operational_dataset=self.matter_test_config.thread_operational_dataset, + wifi_passphrase=self.matter_test_config.wifi_passphrase, + wifi_ssid=self.matter_test_config.wifi_ssid, + tc_version_to_simulate=self.matter_test_config.tc_version_to_simulate, + tc_user_response_to_simulate=self.matter_test_config.tc_user_response_to_simulate, + ) + + return await commission_devices(dev_ctrl, dut_node_ids, setup_payloads, commissioning_info) async def open_commissioning_window(self, dev_ctrl: Optional[ChipDeviceCtrl.ChipDeviceController] = None, node_id: Optional[int] = None, timeout: int = 900) -> CustomCommissioningParameters: rnd_discriminator = random.randint(0, 4095) @@ -2394,81 +2498,6 @@ def test_run_commissioning(self): if not self.event_loop.run_until_complete(self.commission_devices()): raise signals.TestAbortAll("Failed to commission node(s)") - async def commission_devices(self) -> bool: - conf = self.matter_test_config - - commissioned = [] - setup_payloads = self.get_setup_payload_info() - for node_id, setup_payload in zip(conf.dut_node_ids, setup_payloads): - logging.info(f"Starting commissioning for root index {conf.root_of_trust_index}, " - f"fabric ID 0x{conf.fabric_id:016X}, node ID 0x{node_id:016X}") - logging.info(f"Commissioning method: {conf.commissioning_method}") - commissioned.append(await self.commission_device(node_id, setup_payload)) - - return all(commissioned) - - async def commission_device(self, node_id: int, info: SetupPayloadInfo) -> bool: - dev_ctrl = self.default_controller - conf = self.matter_test_config - - if conf.tc_version_to_simulate is not None and conf.tc_user_response_to_simulate is not None: - logging.debug( - f"Setting TC Acknowledgements to version {conf.tc_version_to_simulate} with user response {conf.tc_user_response_to_simulate}.") - dev_ctrl.SetTCAcknowledgements(conf.tc_version_to_simulate, conf.tc_user_response_to_simulate) - - if conf.commissioning_method == "on-network": - try: - await dev_ctrl.CommissionOnNetwork( - nodeId=node_id, - setupPinCode=info.passcode, - filterType=info.filter_type, - filter=info.filter_value - ) - return True - except ChipStackError as e: - logging.error("Commissioning failed: %s" % e) - return False - elif conf.commissioning_method == "ble-wifi": - try: - await dev_ctrl.CommissionWiFi( - info.filter_value, - info.passcode, - node_id, - conf.wifi_ssid, - conf.wifi_passphrase, - isShortDiscriminator=(info.filter_type == DiscoveryFilterType.SHORT_DISCRIMINATOR) - ) - return True - except ChipStackError as e: - logging.error("Commissioning failed: %s" % e) - return False - elif conf.commissioning_method == "ble-thread": - try: - await dev_ctrl.CommissionThread( - info.filter_value, - info.passcode, - node_id, - conf.thread_operational_dataset, - isShortDiscriminator=(info.filter_type == DiscoveryFilterType.SHORT_DISCRIMINATOR) - ) - return True - except ChipStackError as e: - logging.error("Commissioning failed: %s" % e) - return False - elif conf.commissioning_method == "on-network-ip": - try: - logging.warning("==== USING A DIRECT IP COMMISSIONING METHOD NOT SUPPORTED IN THE LONG TERM ====") - await dev_ctrl.CommissionIP( - ipaddr=conf.commissionee_ip_address_just_for_testing, - setupPinCode=info.passcode, - nodeid=node_id, - ) - return True - except ChipStackError as e: - logging.error("Commissioning failed: %s" % e) - return False - else: - raise ValueError("Invalid commissioning method %s!" % conf.commissioning_method) def default_matter_test_main(): From 8abdba34d30957c5514a3ddb33f34f8525ce42a5 Mon Sep 17 00:00:00 2001 From: James Swan Date: Thu, 23 Jan 2025 00:41:35 +0000 Subject: [PATCH 14/23] From 2ab69be4d35b6e793507ce6e1b174c6f0822dd36 Mon Sep 17 00:00:00 2001 From: James Swan Date: Thu, 23 Jan 2025 00:44:37 +0000 Subject: [PATCH 15/23] From 009e8131e6317bf77302436970a9d4b250142607 Mon Sep 17 00:00:00 2001 From: James Swan Date: Thu, 23 Jan 2025 18:43:02 +0000 Subject: [PATCH 16/23] --- .../chip/testing/matter_testing.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py index 3ad07fb66af579..dac0ed9822065b 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py @@ -221,7 +221,6 @@ def get_wait_seconds_from_set_time(set_time_matter_us: int, wait_seconds: int): return wait_seconds - seconds_passed - @dataclass class SetupPayloadInfo: filter_type: discovery.FilterType = discovery.FilterType.LONG_DISCRIMINATOR @@ -1300,7 +1299,7 @@ def check_pics(self, pics_key: str) -> bool: @property def is_pics_sdk_ci_only(self) -> bool: return self.check_pics('PICS_SDK_CI_ONLY') - + async def commission_devices(self) -> bool: dev_ctrl: ChipDeviceCtrl.ChipDeviceController = self.default_controller dut_node_ids: List[int] = self.matter_test_config.dut_node_ids @@ -2499,7 +2498,6 @@ def test_run_commissioning(self): raise signals.TestAbortAll("Failed to commission node(s)") - def default_matter_test_main(): """Execute the test class in a test module. This is the default entry point for running a test script file directly. From e7e9a9278efd5bd2d9836fbe8f5ce7e8a4f34bf3 Mon Sep 17 00:00:00 2001 From: James Swan Date: Thu, 23 Jan 2025 20:47:19 +0000 Subject: [PATCH 17/23] Addressed PR comments --- src/python_testing/TC_CGEN_2_10.py | 3 --- src/python_testing/TC_CGEN_2_5.py | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/python_testing/TC_CGEN_2_10.py b/src/python_testing/TC_CGEN_2_10.py index 0eb08aeb3d5834..32d42e1ae88fa4 100644 --- a/src/python_testing/TC_CGEN_2_10.py +++ b/src/python_testing/TC_CGEN_2_10.py @@ -80,9 +80,6 @@ async def test_TC_CGEN_2_10(self): self.matter_test_config.tc_user_response_to_simulate = None await self.commission_devices() - # await self.commission_devices() - # self.skip_all_remaining_steps(1) - # return # Step 1: Read TCAcceptedVersion self.step(1) response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion)]) diff --git a/src/python_testing/TC_CGEN_2_5.py b/src/python_testing/TC_CGEN_2_5.py index bbcd266aad38aa..5837a8f5021eea 100644 --- a/src/python_testing/TC_CGEN_2_5.py +++ b/src/python_testing/TC_CGEN_2_5.py @@ -66,7 +66,7 @@ def steps_TC_CGEN_2_5(self) -> list[TestStep]: TestStep(8, "TH sends CommissioningComplete to DUT."), TestStep(9, "TH reads from the DUT the attribute TCAcceptedVersion."), TestStep(10, "TH reads from the DUT the attribute TCAcknowledgements."), - TestStep(11, "TH reads from the DUT the attribute."), + TestStep(11, "TH reads from the DUT the attribute TCMinRequiredVersion."), TestStep(12, "TH reads from the DUT the attribute TCAcknowledgementsRequired."), ] From 2d8722d46793dad99b64cc8101d2c12c03f18aaf Mon Sep 17 00:00:00 2001 From: James Swan Date: Fri, 24 Jan 2025 00:27:14 +0000 Subject: [PATCH 18/23] --- src/python_testing/TC_CGEN_2_10.py | 1 - src/python_testing/TC_CGEN_2_11.py | 1 - src/python_testing/TC_CGEN_2_5.py | 1 - src/python_testing/TC_CGEN_2_6.py | 1 - src/python_testing/TC_CGEN_2_7.py | 1 - src/python_testing/TC_CGEN_2_8.py | 1 - src/python_testing/TC_CGEN_2_9.py | 1 - 7 files changed, 7 deletions(-) diff --git a/src/python_testing/TC_CGEN_2_10.py b/src/python_testing/TC_CGEN_2_10.py index 32d42e1ae88fa4..97e78222346ca8 100644 --- a/src/python_testing/TC_CGEN_2_10.py +++ b/src/python_testing/TC_CGEN_2_10.py @@ -20,7 +20,6 @@ # run1: # app: ${TERMS_AND_CONDITIONS_APP} # app-args: > -# --KVS kvs1 # --tc-min-required-version 1 # --tc-required-acknowledgements 1 # --custom-flow 2 diff --git a/src/python_testing/TC_CGEN_2_11.py b/src/python_testing/TC_CGEN_2_11.py index fdb5d8e13b9292..e8a57937d3ee83 100644 --- a/src/python_testing/TC_CGEN_2_11.py +++ b/src/python_testing/TC_CGEN_2_11.py @@ -20,7 +20,6 @@ # run1: # app: ${TERMS_AND_CONDITIONS_APP} # app-args: > -# --KVS kvs1 # --tc-min-required-version 1 # --tc-required-acknowledgements 1 # --custom-flow 2 diff --git a/src/python_testing/TC_CGEN_2_5.py b/src/python_testing/TC_CGEN_2_5.py index 5837a8f5021eea..136b478b28bea9 100644 --- a/src/python_testing/TC_CGEN_2_5.py +++ b/src/python_testing/TC_CGEN_2_5.py @@ -20,7 +20,6 @@ # run1: # app: ${TERMS_AND_CONDITIONS_APP} # app-args: > -# --KVS kvs1 # --tc-min-required-version 1 # --tc-required-acknowledgements 1 # --custom-flow 2 diff --git a/src/python_testing/TC_CGEN_2_6.py b/src/python_testing/TC_CGEN_2_6.py index e68c1a46524217..fd83f1a79adaa1 100644 --- a/src/python_testing/TC_CGEN_2_6.py +++ b/src/python_testing/TC_CGEN_2_6.py @@ -20,7 +20,6 @@ # run1: # app: ${TERMS_AND_CONDITIONS_APP} # app-args: > -# --KVS kvs1 # --tc-min-required-version 1 # --tc-required-acknowledgements 1 # --custom-flow 2 diff --git a/src/python_testing/TC_CGEN_2_7.py b/src/python_testing/TC_CGEN_2_7.py index 9cc4db41a90bf2..17ae9c908b136a 100644 --- a/src/python_testing/TC_CGEN_2_7.py +++ b/src/python_testing/TC_CGEN_2_7.py @@ -20,7 +20,6 @@ # run1: # app: ${TERMS_AND_CONDITIONS_APP} # app-args: > -# --KVS kvs1 # --tc-min-required-version 1 # --tc-required-acknowledgements 1 # --custom-flow 2 diff --git a/src/python_testing/TC_CGEN_2_8.py b/src/python_testing/TC_CGEN_2_8.py index 0f7b3289ea6ca5..c20036dbe87f5f 100644 --- a/src/python_testing/TC_CGEN_2_8.py +++ b/src/python_testing/TC_CGEN_2_8.py @@ -20,7 +20,6 @@ # run1: # app: ${TERMS_AND_CONDITIONS_APP} # app-args: > -# --KVS kvs1 # --tc-min-required-version 1 # --tc-required-acknowledgements 1 # --custom-flow 2 diff --git a/src/python_testing/TC_CGEN_2_9.py b/src/python_testing/TC_CGEN_2_9.py index 7b9b0977b3e4a4..18f64586fc03f4 100644 --- a/src/python_testing/TC_CGEN_2_9.py +++ b/src/python_testing/TC_CGEN_2_9.py @@ -20,7 +20,6 @@ # run1: # app: ${TERMS_AND_CONDITIONS_APP} # app-args: > -# --KVS kvs1 # --tc-min-required-version 1 # --tc-required-acknowledgements 1 # --custom-flow 2 From 6cfe31e4994c3c4905c487b8c7c6c9571e6e6eb1 Mon Sep 17 00:00:00 2001 From: James Swan Date: Wed, 5 Feb 2025 00:31:46 +0000 Subject: [PATCH 19/23] Improve test assertions and manual testing steps - Use Matter-specific type assertions in TC_CGEN_2_5 - Update TC_CGEN_2_8 manual testing flow and prompts --- src/python_testing/TC_CGEN_2_5.py | 7 ++++--- src/python_testing/TC_CGEN_2_8.py | 13 +++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/python_testing/TC_CGEN_2_5.py b/src/python_testing/TC_CGEN_2_5.py index 136b478b28bea9..f7d8e3e0d8a21b 100644 --- a/src/python_testing/TC_CGEN_2_5.py +++ b/src/python_testing/TC_CGEN_2_5.py @@ -40,6 +40,7 @@ from chip import ChipDeviceCtrl from chip.clusters.Attribute import ValueDecodeFailure from chip.commissioning import ROOT_ENDPOINT_ID +from chip.testing import matter_asserts from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main from mobly import asserts @@ -120,7 +121,7 @@ async def test_TC_CGEN_2_5(self): if isinstance(tc_update_deadline, ValueDecodeFailure): asserts.assert_is_none(tc_update_deadline.TLVValue) else: - asserts.assert_less(tc_update_deadline, 2**32, "TCUpdateDeadline exceeds uint32 range") + matter_asserts.assert_valid_uint32(tc_update_deadline, "TCUpdateDeadline exceeds uint32 range") # Step 4: Verify TC feature flag in FeatureMap self.step(4) @@ -129,7 +130,7 @@ async def test_TC_CGEN_2_5(self): attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.FeatureMap)], ) feature_map = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.FeatureMap] - asserts.assert_equal(feature_map & 0x1, 0x1, "TC feature flag is not set.") + asserts.assert_equal(feature_map & Clusters.GeneralCommissioning.Bitmaps.Feature.kTermsAndConditions, Clusters.GeneralCommissioning.Bitmaps.Feature.kTermsAndConditions, "TC feature flag is not set.") # Step 5: Send SetTCAcknowledgements self.step(5) @@ -184,7 +185,7 @@ async def test_TC_CGEN_2_5(self): self.step(11) response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion)]) min_required_version = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCMinRequiredVersion] - asserts.assert_is_instance(min_required_version, int, "TCMinRequiredVersion is not a uint16 type.") + matter_asserts.assert_valid_uint16(min_required_version, "TCMinRequiredVersion is not a uint16 type.") # Step 12: Verify TCAcknowledgementsRequired is False again self.step(12) diff --git a/src/python_testing/TC_CGEN_2_8.py b/src/python_testing/TC_CGEN_2_8.py index c20036dbe87f5f..18364c2d769cf1 100644 --- a/src/python_testing/TC_CGEN_2_8.py +++ b/src/python_testing/TC_CGEN_2_8.py @@ -128,16 +128,17 @@ async def test_TC_CGEN_2_8(self): "First CommissioningComplete failed", ) - # Step 5: Factory reset is handled by test runner configuration + # Step 5: Factory reset is handled by test operator self.step(5) - - # Step 6: Put device in commissioning mode (requiring user input, so skip in CI) - self.step(6) if not self.check_pics('PICS_USER_PROMPT'): - self.skip_all_remaining_steps(7) + self.skip_all_remaining_steps(6) return - self.wait_for_user_input(prompt_msg="Set the DUT into commissioning mode") + self.wait_for_user_input(prompt_msg="Manually trigger factory reset on the DUT, then continue") + + # Step 6: Put device in commissioning mode (requiring user input, so skip in CI) + self.step(6) + self.wait_for_user_input(prompt_msg="Manually set the DUT into commissioning mode, then continue") # Step 7: Commission without TC acknowledgements self.step(7) From 5ca1f54e319f1fb9dd589a11818888e6dc191707 Mon Sep 17 00:00:00 2001 From: James Swan Date: Fri, 7 Feb 2025 22:31:22 +0000 Subject: [PATCH 20/23] restyle --- src/python_testing/TC_CGEN_2_5.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/python_testing/TC_CGEN_2_5.py b/src/python_testing/TC_CGEN_2_5.py index f7d8e3e0d8a21b..5730de70e54da1 100644 --- a/src/python_testing/TC_CGEN_2_5.py +++ b/src/python_testing/TC_CGEN_2_5.py @@ -130,7 +130,8 @@ async def test_TC_CGEN_2_5(self): attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.FeatureMap)], ) feature_map = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.FeatureMap] - asserts.assert_equal(feature_map & Clusters.GeneralCommissioning.Bitmaps.Feature.kTermsAndConditions, Clusters.GeneralCommissioning.Bitmaps.Feature.kTermsAndConditions, "TC feature flag is not set.") + asserts.assert_equal(feature_map & Clusters.GeneralCommissioning.Bitmaps.Feature.kTermsAndConditions, + Clusters.GeneralCommissioning.Bitmaps.Feature.kTermsAndConditions, "TC feature flag is not set.") # Step 5: Send SetTCAcknowledgements self.step(5) From a69971639ab1dd37530496409e3254c2466ae85e Mon Sep 17 00:00:00 2001 From: James Swan Date: Fri, 7 Feb 2025 23:42:52 +0000 Subject: [PATCH 21/23] refactor: simplify CGEN feature identifier from CGEN.S.F00(TC) to CGEN.S.F00 - Update PICS.yaml and ci-pics-values to use simplified feature ID - Update Python test files to use new feature identifier - Improve error messaging when commissioning feature check fails - Affected test files: TC_CGEN_2_5 through TC_CGEN_2_11 --- src/app/tests/suites/certification/PICS.yaml | 2 +- src/app/tests/suites/certification/ci-pics-values | 2 +- src/python_testing/TC_CGEN_2_10.py | 6 +++--- src/python_testing/TC_CGEN_2_11.py | 6 +++--- src/python_testing/TC_CGEN_2_5.py | 6 +++--- src/python_testing/TC_CGEN_2_6.py | 6 +++--- src/python_testing/TC_CGEN_2_7.py | 6 +++--- src/python_testing/TC_CGEN_2_8.py | 6 +++--- src/python_testing/TC_CGEN_2_9.py | 6 +++--- 9 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/app/tests/suites/certification/PICS.yaml b/src/app/tests/suites/certification/PICS.yaml index 47fc43d7f285c4..4e10d5f49640fd 100644 --- a/src/app/tests/suites/certification/PICS.yaml +++ b/src/app/tests/suites/certification/PICS.yaml @@ -3638,7 +3638,7 @@ PICS: - label: "Does the device implement the General Commissioning cluster's terms and conditions feature?" - id: CGEN.S.F00(TC) + id: CGEN.S.F00 - label: "The device's failsafe expiration limit." id: PIXIT.CGEN.FailsafeExpiryLengthSeconds diff --git a/src/app/tests/suites/certification/ci-pics-values b/src/app/tests/suites/certification/ci-pics-values index c8498bcd03ce76..258b61e42f2df3 100644 --- a/src/app/tests/suites/certification/ci-pics-values +++ b/src/app/tests/suites/certification/ci-pics-values @@ -744,7 +744,7 @@ CGEN.S.C04.Rsp=1 CGEN.S.C05.Tx=1 #Feature -CGEN.S.F00(TC)=1 +CGEN.S.F00=1 #PIXIT PIXIT.CGEN.FailsafeExpiryLengthSeconds=0 diff --git a/src/python_testing/TC_CGEN_2_10.py b/src/python_testing/TC_CGEN_2_10.py index 97e78222346ca8..4e094148e3d0d1 100644 --- a/src/python_testing/TC_CGEN_2_10.py +++ b/src/python_testing/TC_CGEN_2_10.py @@ -48,7 +48,7 @@ def desc_TC_CGEN_2_10(self) -> str: def pics_TC_CGEN_2_10(self) -> list[str]: """ This function returns a list of PICS for this test case that must be True for the test to be run""" - return ["CGEN.S", "CGEN.S.F00(TC)"] + return ["CGEN.S", "CGEN.S.F00"] def steps_TC_CGEN_2_10(self) -> list[TestStep]: return [ @@ -68,8 +68,8 @@ async def test_TC_CGEN_2_10(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller self.step(0) - if not self.pics_guard(self.check_pics("CGEN.S.F00(TC)")): - self.skip_all_remaining_steps(1) + if not self.check_pics("CGEN.S.F00"): + asserts.skip('Root endpoint does not support the [commissioning] feature under test') return # Step 1: Begin commissioning with PASE and failsafe diff --git a/src/python_testing/TC_CGEN_2_11.py b/src/python_testing/TC_CGEN_2_11.py index e8a57937d3ee83..dc600135fad1ef 100644 --- a/src/python_testing/TC_CGEN_2_11.py +++ b/src/python_testing/TC_CGEN_2_11.py @@ -49,7 +49,7 @@ def desc_TC_CGEN_2_11(self) -> str: def pics_TC_CGEN_2_11(self) -> list[str]: """ This function returns a list of PICS for this test case that must be True for the test to be run""" - return ["CGEN.S", "CGEN.S.F00(TC)"] + return ["CGEN.S", "CGEN.S.F00"] def steps_TC_CGEN_2_11(self) -> list[TestStep]: return [ @@ -71,8 +71,8 @@ async def test_TC_CGEN_2_11(self): tc_user_response_to_simulate = self.matter_test_config.global_test_params['PIXIT.CGEN.RequiredTCAcknowledgements'] self.step(0) - if not self.pics_guard(self.check_pics("CGEN.S.F00(TC)")): - self.skip_all_remaining_steps(1) + if not self.check_pics("CGEN.S.F00"): + asserts.skip('Root endpoint does not support the [commissioning] feature under test') return # Step 1: Begin commissioning with PASE and failsafe diff --git a/src/python_testing/TC_CGEN_2_5.py b/src/python_testing/TC_CGEN_2_5.py index 5730de70e54da1..5b0b6a276e56e6 100644 --- a/src/python_testing/TC_CGEN_2_5.py +++ b/src/python_testing/TC_CGEN_2_5.py @@ -51,7 +51,7 @@ def desc_TC_CGEN_2_5(self) -> str: def pics_TC_CGEN_2_5(self) -> list[str]: """ This function returns a list of PICS for this test case that must be True for the test to be run""" - return ["CGEN.S", "CGEN.S.F00(TC)"] + return ["CGEN.S", "CGEN.S.F00"] def steps_TC_CGEN_2_5(self) -> list[TestStep]: return [ @@ -79,8 +79,8 @@ async def test_TC_CGEN_2_5(self): tc_user_response_to_simulate = self.matter_test_config.global_test_params['PIXIT.CGEN.RequiredTCAcknowledgements'] self.step(0) - if not self.pics_guard(self.check_pics("CGEN.S.F00(TC)")): - self.skip_all_remaining_steps(1) + if not self.check_pics("CGEN.S.F00"): + asserts.skip('Root endpoint does not support the [commissioning] feature under test') return # Step 1: Begin commissioning with PASE and failsafe diff --git a/src/python_testing/TC_CGEN_2_6.py b/src/python_testing/TC_CGEN_2_6.py index fd83f1a79adaa1..07017842d59df1 100644 --- a/src/python_testing/TC_CGEN_2_6.py +++ b/src/python_testing/TC_CGEN_2_6.py @@ -46,7 +46,7 @@ def desc_TC_CGEN_2_6(self) -> str: def pics_TC_CGEN_2_6(self) -> list[str]: """ This function returns a list of PICS for this test case that must be True for the test to be run""" - return ["CGEN.S", "CGEN.S.F00(TC)"] + return ["CGEN.S", "CGEN.S.F00"] def steps_TC_CGEN_2_6(self) -> list[TestStep]: return [ @@ -60,8 +60,8 @@ async def test_TC_CGEN_2_6(self): commissioner: ChipDeviceCtrl.ChipDeviceController = self.default_controller self.step(0) - if not self.pics_guard(self.check_pics("CGEN.S.F00(TC)")): - self.skip_all_remaining_steps(1) + if not self.check_pics("CGEN.S.F00"): + asserts.skip('Root endpoint does not support the [commissioning] feature under test') return # Step 1: Commission device without setting TC acknowledgements diff --git a/src/python_testing/TC_CGEN_2_7.py b/src/python_testing/TC_CGEN_2_7.py index 17ae9c908b136a..95a15b8cbd8229 100644 --- a/src/python_testing/TC_CGEN_2_7.py +++ b/src/python_testing/TC_CGEN_2_7.py @@ -49,7 +49,7 @@ def desc_TC_CGEN_2_7(self) -> str: def pics_TC_CGEN_2_7(self) -> list[str]: """ This function returns a list of PICS for this test case that must be True for the test to be run""" - return ["CGEN.S", "CGEN.S.F00(TC)"] + return ["CGEN.S", "CGEN.S.F00"] def steps_TC_CGEN_2_7(self) -> list[TestStep]: return [ @@ -71,8 +71,8 @@ async def test_TC_CGEN_2_7(self): tc_user_response_to_simulate = self.matter_test_config.global_test_params['PIXIT.CGEN.RequiredTCAcknowledgements'] self.step(0) - if not self.pics_guard(self.check_pics("CGEN.S.F00(TC)")): - self.skip_all_remaining_steps(1) + if not self.check_pics("CGEN.S.F00"): + asserts.skip('Root endpoint does not support the [commissioning] feature under test') return # Step 1: Begin commissioning with PASE and failsafe diff --git a/src/python_testing/TC_CGEN_2_8.py b/src/python_testing/TC_CGEN_2_8.py index 18364c2d769cf1..1b885452d21d8d 100644 --- a/src/python_testing/TC_CGEN_2_8.py +++ b/src/python_testing/TC_CGEN_2_8.py @@ -49,7 +49,7 @@ def desc_TC_CGEN_2_8(self) -> str: def pics_TC_CGEN_2_8(self) -> list[str]: """ This function returns a list of PICS for this test case that must be True for the test to be run""" - return ["CGEN.S", "CGEN.S.F00(TC)"] + return ["CGEN.S", "CGEN.S.F00"] def steps_TC_CGEN_2_8(self) -> list[TestStep]: return [ @@ -72,8 +72,8 @@ async def test_TC_CGEN_2_8(self): tc_user_response_to_simulate = self.matter_test_config.global_test_params['PIXIT.CGEN.RequiredTCAcknowledgements'] self.step(0) - if not self.pics_guard(self.check_pics("CGEN.S.F00(TC)")): - self.skip_all_remaining_steps(1) + if not self.check_pics("CGEN.S.F00"): + asserts.skip('Root endpoint does not support the [commissioning] feature under test') return # Step 1: Begin commissioning with PASE and failsafe diff --git a/src/python_testing/TC_CGEN_2_9.py b/src/python_testing/TC_CGEN_2_9.py index 18f64586fc03f4..03521e5dd89b38 100644 --- a/src/python_testing/TC_CGEN_2_9.py +++ b/src/python_testing/TC_CGEN_2_9.py @@ -72,7 +72,7 @@ def desc_TC_CGEN_2_9(self) -> str: def pics_TC_CGEN_2_9(self) -> list[str]: """ This function returns a list of PICS for this test case that must be True for the test to be run""" - return ["CGEN.S", "CGEN.S.F00(TC)"] + return ["CGEN.S", "CGEN.S.F00"] def steps_TC_CGEN_2_9(self) -> list[TestStep]: return [ @@ -95,8 +95,8 @@ async def test_TC_CGEN_2_9(self): tc_user_response_to_simulate = self.matter_test_config.global_test_params['PIXIT.CGEN.RequiredTCAcknowledgements'] self.step(0) - if not self.pics_guard(self.check_pics("CGEN.S.F00(TC)")): - self.skip_all_remaining_steps(1) + if not self.check_pics("CGEN.S.F00"): + asserts.skip('Root endpoint does not support the [commissioning] feature under test') return # Step 1: Begin commissioning with PASE and failsafe From 4c25eb0092983afa2d64a67bc7c4f780480188e8 Mon Sep 17 00:00:00 2001 From: James Swan Date: Sat, 8 Feb 2025 00:00:18 +0000 Subject: [PATCH 22/23] Update TC_CGEN_2_5 to use Nullable type for TCUpdateDeadline validation --- src/python_testing/TC_CGEN_2_5.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/python_testing/TC_CGEN_2_5.py b/src/python_testing/TC_CGEN_2_5.py index 5b0b6a276e56e6..7a55dcf35b7d73 100644 --- a/src/python_testing/TC_CGEN_2_5.py +++ b/src/python_testing/TC_CGEN_2_5.py @@ -38,7 +38,7 @@ import chip.clusters as Clusters from chip import ChipDeviceCtrl -from chip.clusters.Attribute import ValueDecodeFailure +from chip.clusters.Types import Nullable from chip.commissioning import ROOT_ENDPOINT_ID from chip.testing import matter_asserts from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main @@ -117,10 +117,8 @@ async def test_TC_CGEN_2_5(self): ) tc_update_deadline = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCUpdateDeadline] - # Validate the value is of type Optional[uint32], e.g. either None or within the 32-bit range. - if isinstance(tc_update_deadline, ValueDecodeFailure): - asserts.assert_is_none(tc_update_deadline.TLVValue) - else: + # Validate the value is of type Optional[uint32], e.g. either Nullable or within the 32-bit range. + if not isinstance(tc_update_deadline, Nullable): matter_asserts.assert_valid_uint32(tc_update_deadline, "TCUpdateDeadline exceeds uint32 range") # Step 4: Verify TC feature flag in FeatureMap From 00acce5fc3ef880109fd0338a07a2c501643b8a7 Mon Sep 17 00:00:00 2001 From: James Swan Date: Sat, 8 Feb 2025 01:28:50 +0000 Subject: [PATCH 23/23] Add type validation for TCAcceptedVersion and TCAcknowledgements --- src/python_testing/TC_CGEN_2_5.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/python_testing/TC_CGEN_2_5.py b/src/python_testing/TC_CGEN_2_5.py index 7a55dcf35b7d73..f6d6043958b005 100644 --- a/src/python_testing/TC_CGEN_2_5.py +++ b/src/python_testing/TC_CGEN_2_5.py @@ -173,12 +173,14 @@ async def test_TC_CGEN_2_5(self): response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion)]) accepted_version = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcceptedVersion] asserts.assert_equal(accepted_version, tc_version_to_simulate, "TCAcceptedVersion does not match expected value.") + matter_asserts.assert_valid_uint16(accepted_version, "TCAcceptedVersion is not a uint16 type.") # Step 10: Verify TCAcknowledgements self.step(10) response = await commissioner.ReadAttribute(nodeid=self.dut_node_id, attributes=[(ROOT_ENDPOINT_ID, Clusters.GeneralCommissioning.Attributes.TCAcknowledgements)]) acknowledgements = response[ROOT_ENDPOINT_ID][Clusters.GeneralCommissioning][Clusters.GeneralCommissioning.Attributes.TCAcknowledgements] asserts.assert_equal(acknowledgements, tc_user_response_to_simulate, "TCAcknowledgements does not match expected value.") + matter_asserts.assert_valid_uint16(accepted_version, "TCAcknowledgements is not a map16 type.") # Step 11: Verify TCMinRequiredVersion self.step(11)