diff --git a/.flake8 b/.flake8 index 1bdb5a695d3159..7accafbde7efe2 100644 --- a/.flake8 +++ b/.flake8 @@ -33,17 +33,14 @@ exclude = third_party scripts/build/builders/imx.py scripts/build/builders/infineon.py scripts/build/builders/nrf.py - scripts/build/test.py scripts/codegen.py scripts/codepregen.py scripts/error_table.py scripts/examples/gn_to_cmakelists.py - scripts/examples/tests/test.py scripts/flashing/bouffalolab_firmware_utils.py scripts/flashing/cyw30739_firmware_utils.py scripts/flashing/nrfconnect_firmware_utils.py scripts/gen_chip_version.py - scripts/gen_test_driver.py scripts/helpers/bloat_check.py scripts/pregenerate/using_codegen.py scripts/pregenerate/using_zap.py @@ -60,16 +57,7 @@ exclude = third_party scripts/py_matter_yamltests/test_yaml_parser.py scripts/run-clang-tidy-on-compile-commands.py scripts/setup/nrfconnect/update_ncs.py - scripts/tests/chiptest/__init__.py - scripts/tests/chiptest/runner.py - scripts/tests/chiptest/test_definition.py scripts/tests/chiptest/yamltest_with_chip_repl_tester.py - scripts/tests/java/base.py - scripts/tests/java/commissioning_test.py - scripts/tests/java/discover_test.py - scripts/tests/run_java_test.py - scripts/tests/run_python_test.py - scripts/tests/run_test_suite.py scripts/tools/check_zcl_file_sync.py scripts/tools/convert_ini.py scripts/tools/generate_esp32_chip_factory_bin.py @@ -82,12 +70,10 @@ exclude = third_party scripts/tools/telink/mfg_tool.py scripts/tools/zap/generate.py scripts/tools/zap/prune_outputs.py - scripts/tools/zap/test_generate.py scripts/tools/zap/version_update.py scripts/tools/zap/zap_download.py scripts/tools/zap_convert_all.py src/app/ota_image_tool.py - src/app/tests/suites/certification/information.py src/app/zap_cluster_list.py src/controller/python/build-chip-wheel.py src/controller/python/chip-device-ctrl.py @@ -117,23 +103,7 @@ exclude = third_party src/controller/python/chip/yaml/__init__.py src/controller/python/chip/yaml/format_converter.py src/controller/python/chip/yaml/runner.py - src/controller/python/test/test_scripts/base.py - src/controller/python/test/test_scripts/cluster_objects.py - src/controller/python/test/test_scripts/mobile-device-test.py - src/controller/python/test/test_scripts/network_commissioning.py - src/controller/python/test/unit_tests/test_cluster_objects.py - src/controller/python/test/unit_tests/test_tlv.py src/lib/asn1/gen_asn1oid.py src/pybindings/pycontroller/build-chip-wheel.py src/pybindings/pycontroller/pychip/__init__.py - src/python_testing/TC_ACE_1_3.py - src/python_testing/TC_ACE_1_4.py - src/python_testing/TC_CGEN_2_4.py - src/python_testing/TC_DA_1_7.py - src/python_testing/TC_RR_1_1.py - src/python_testing/TC_SC_3_6.py - src/python_testing/TC_TestEventTrigger.py - src/python_testing/hello_test.py - src/python_testing/matter_testing_support.py src/setup_payload/python/generate_setup_payload.py - src/setup_payload/tests/run_python_setup_payload_gen_test.py diff --git a/build/chip/java/tests/test.py b/build/chip/java/tests/test.py index a67c40079b1a59..1c90f51e04e9df 100755 --- a/build/chip/java/tests/test.py +++ b/build/chip/java/tests/test.py @@ -18,7 +18,6 @@ import json import os -import subprocess import unittest from os import path diff --git a/scripts/build/test.py b/scripts/build/test.py index 8cf88b0571c44e..4156a898f153d7 100644 --- a/scripts/build/test.py +++ b/scripts/build/test.py @@ -26,8 +26,8 @@ def build_expected_output(source: str, root: str, out: str) -> List[str]: with open(os.path.join(SCRIPT_ROOT, source), 'rt') as f: - for l in f.readlines(): - yield l.replace("{root}", root).replace("{out}", out) + for line in f.readlines(): + yield line.replace("{root}", root).replace("{out}", out) def build_actual_output(root: str, out: str, args: List[str]) -> List[str]: @@ -57,7 +57,7 @@ def build_actual_output(root: str, out: str, args: List[str]) -> List[str]: '--out-prefix', out, ] + args, stdout=subprocess.PIPE, check=True, encoding='UTF-8', env=runenv) - result = [l + '\n' for l in retval.stdout.split('\n')] + result = [line + '\n' for line in retval.stdout.split('\n')] # ensure a single terminating newline: easier to edit since autoformat # often strips ending double newlines on text files @@ -73,22 +73,22 @@ def assertCommandOutput(self, expected_file: str, args: List[str]): ROOT = '/TEST/BUILD/ROOT' OUT = '/OUTPUT/DIR' - expected = [l for l in build_expected_output(expected_file, ROOT, OUT)] - actual = [l for l in build_actual_output(ROOT, OUT, args)] + expected = [line for line in build_expected_output(expected_file, ROOT, OUT)] + actual = [line for line in build_actual_output(ROOT, OUT, args)] diffs = [line for line in difflib.unified_diff(expected, actual)] if diffs: reference = os.path.basename(expected_file) + '.actual' with open(reference, 'wt') as fo: - for l in build_actual_output(ROOT, OUT, args): - fo.write(l.replace(ROOT, '{root}').replace(OUT, '{out}')) + for line in build_actual_output(ROOT, OUT, args): + fo.write(line.replace(ROOT, '{root}').replace(OUT, '{out}')) msg = "DIFFERENCE between expected and generated output in %s\n" % expected_file msg += "Expected file can be found in %s" % reference - for l in diffs: - msg += ("\n " + l.replace(ROOT, - '{root}').replace(OUT, '{out}').strip()) + for line in diffs: + msg += ("\n " + line.replace(ROOT, + '{root}').replace(OUT, '{out}').strip()) self.fail(msg) @unittest.skipUnless(sys.platform == 'linux', 'Build on linux test') diff --git a/scripts/examples/tests/test.py b/scripts/examples/tests/test.py index 2430e27ccd854e..4a4b537e27a655 100644 --- a/scripts/examples/tests/test.py +++ b/scripts/examples/tests/test.py @@ -27,9 +27,9 @@ def build_expected_output(root: str, out: str) -> List[str]: - with open(os.path.join(SCRIPT_ROOT, 'expected_test_cmakelists.txt'), 'rt') as f: - for l in f.readlines(): - yield l.replace("{root}", root).replace("{out}", out) + with open(os.path.join(SCRIPT_ROOT, 'expected_test_cmakelists.txt'), 'rt') as file: + for line in file.readlines(): + yield line.replace("{root}", root).replace("{out}", out) def build_actual_output(root: str, out: str) -> List[str]: @@ -37,14 +37,14 @@ def build_actual_output(root: str, out: str) -> List[str]: binary = os.path.join(SCRIPT_ROOT, '../gn_to_cmakelists.py') project = os.path.join(SCRIPT_ROOT, "test_project.json") cmake = os.path.join(SCRIPT_ROOT, "../../../out/CMakeLists.txt") - retval = subprocess.run([ + subprocess.run([ binary, project, ], stdout=subprocess.PIPE, check=True, encoding='UTF-8', ) with open(cmake, 'rt') as f: - for l in f.readlines(): - yield l + for line in f.readlines(): + yield line def main(): @@ -54,15 +54,15 @@ def main(): ROOT = '/TEST/BUILD/ROOT' OUT = '/OUTPUT/DIR' - expected = [l for l in build_expected_output(ROOT, OUT)] - actual = [l for l in build_actual_output(ROOT, OUT)] + expected = [line for line in build_expected_output(ROOT, OUT)] + actual = [line for line in build_actual_output(ROOT, OUT)] diffs = [line for line in difflib.unified_diff(expected, actual)] if diffs: logging.error("DIFFERENCE between expected and generated output") - for l in diffs: - logging.warning(" " + l.strip()) + for line in diffs: + logging.warning(" " + line.strip()) sys.exit(1) diff --git a/scripts/gen_test_driver.py b/scripts/gen_test_driver.py index 9ef28a833f1c57..8bf03bf05d2c84 100644 --- a/scripts/gen_test_driver.py +++ b/scripts/gen_test_driver.py @@ -1,4 +1,3 @@ - #!/usr/bin/env python # Copyright (c) 2020 Project CHIP Authors @@ -74,8 +73,8 @@ def main(argv): TEST_SUITE_RE = re.compile(r'\s*CHIP_REGISTER_TEST_SUITE\(([^)]*)\)') with open(options.input_file, 'r') as input_file: - for l in input_file.readlines(): - match = TEST_SUITE_RE.match(l) + for line in input_file.readlines(): + match = TEST_SUITE_RE.match(line) if not match: continue diff --git a/scripts/tests/chiptest/__init__.py b/scripts/tests/chiptest/__init__.py index fbfc79cf39b212..55e125c29bac19 100644 --- a/scripts/tests/chiptest/__init__.py +++ b/scripts/tests/chiptest/__init__.py @@ -22,7 +22,7 @@ from typing import Iterator, Set from . import linux, runner -from .test_definition import ApplicationPaths, TestDefinition, TestRunTime, TestTag, TestTarget +from .test_definition import ApplicationPaths, TestDefinition, TestTag, TestTarget _DEFAULT_CHIP_ROOT = os.path.abspath( os.path.join(os.path.dirname(__file__), "..", "..", "..")) @@ -149,7 +149,13 @@ def _AllYamlTests(): def target_for_name(name: str): - if name.startswith("TV_") or name.startswith("Test_TC_MC_") or name.startswith("Test_TC_LOWPOWER_") or name.startswith("Test_TC_KEYPADINPUT_") or name.startswith("Test_TC_APPLAUNCHER_") or name.startswith("Test_TC_MEDIAINPUT_") or name.startswith("Test_TC_WAKEONLAN_") or name.startswith("Test_TC_CHANNEL_") or name.startswith("Test_TC_MEDIAPLAYBACK_") or name.startswith("Test_TC_AUDIOOUTPUT_") or name.startswith("Test_TC_TGTNAV_") or name.startswith("Test_TC_APBSC_") or name.startswith("Test_TC_CONTENTLAUNCHER_") or name.startswith("Test_TC_ALOGIN_"): + if (name.startswith("TV_") or name.startswith("Test_TC_MC_") or + name.startswith("Test_TC_LOWPOWER_") or name.startswith("Test_TC_KEYPADINPUT_") or + name.startswith("Test_TC_APPLAUNCHER_") or name.startswith("Test_TC_MEDIAINPUT_") or + name.startswith("Test_TC_WAKEONLAN_") or name.startswith("Test_TC_CHANNEL_") or + name.startswith("Test_TC_MEDIAPLAYBACK_") or name.startswith("Test_TC_AUDIOOUTPUT_") or + name.startswith("Test_TC_TGTNAV_") or name.startswith("Test_TC_APBSC_") or + name.startswith("Test_TC_CONTENTLAUNCHER_") or name.startswith("Test_TC_ALOGIN_")): return TestTarget.TV if name.startswith("DL_") or name.startswith("Test_TC_DRLK_"): return TestTarget.LOCK diff --git a/scripts/tests/chiptest/runner.py b/scripts/tests/chiptest/runner.py index 71cf0c7d5e433f..d2f3d96503210e 100644 --- a/scripts/tests/chiptest/runner.py +++ b/scripts/tests/chiptest/runner.py @@ -56,8 +56,8 @@ def CapturedLogContains(self, txt: str, index=0): return False, len(self.captured_logs) def FindLastMatchingLine(self, matcher): - for l in reversed(self.captured_logs): - match = re.match(matcher, l) + for line in reversed(self.captured_logs): + match = re.match(matcher, line) if match: return match return None diff --git a/scripts/tests/chiptest/test_definition.py b/scripts/tests/chiptest/test_definition.py index b9842647105ab5..bbce2428b619a9 100644 --- a/scripts/tests/chiptest/test_definition.py +++ b/scripts/tests/chiptest/test_definition.py @@ -15,14 +15,12 @@ import logging import os -import sys import threading import time import typing from dataclasses import dataclass, field from datetime import datetime from enum import Enum, auto -from random import randrange TEST_NODE_ID = '0x12344321' @@ -94,7 +92,7 @@ def wait(self, timeout=None): if self.killed: return 0 # If the App was never started, wait cannot be called on the process - if self.process == None: + if self.process is None: time.sleep(0.1) continue code = self.process.wait(timeout) @@ -169,7 +167,8 @@ class ApplicationPaths: chip_tool_with_python_cmd: typing.List[str] def items(self): - return [self.chip_tool, self.all_clusters_app, self.lock_app, self.ota_provider_app, self.ota_requestor_app, self.tv_app, self.bridge_app, self.chip_repl_yaml_tester_cmd, self.chip_tool_with_python_cmd] + return [self.chip_tool, self.all_clusters_app, self.lock_app, self.ota_provider_app, self.ota_requestor_app, + self.tv_app, self.bridge_app, self.chip_repl_yaml_tester_cmd, self.chip_tool_with_python_cmd] @dataclass @@ -253,7 +252,8 @@ def tags_str(self) -> str: """Get a human readable list of tags applied to this test""" return ", ".join([t.to_s() for t in self.tags]) - def Run(self, runner, apps_register, paths: ApplicationPaths, pics_file: str, timeout_seconds: typing.Optional[int], dry_run=False, test_runtime: TestRunTime = TestRunTime.CHIP_TOOL_BUILTIN): + def Run(self, runner, apps_register, paths: ApplicationPaths, pics_file: str, + timeout_seconds: typing.Optional[int], dry_run=False, test_runtime: TestRunTime = TestRunTime.CHIP_TOOL_BUILTIN): """ Executes the given test case using the provided runner for execution. """ diff --git a/scripts/tests/java/base.py b/scripts/tests/java/base.py index ce0e04bbccceb7..f849c08d352f39 100755 --- a/scripts/tests/java/base.py +++ b/scripts/tests/java/base.py @@ -17,11 +17,8 @@ # limitations under the License. # -import asyncio import datetime # Commissioning test. -import logging -import os import queue import subprocess import sys @@ -39,7 +36,7 @@ def EnqueueLogOutput(fp, tag, q): try: timestamp = float(line[1:18].decode()) line = line[19:] - except Exception as ex: + except Exception: pass sys.stdout.buffer.write( (f"[{datetime.datetime.fromtimestamp(timestamp).isoformat(sep=' ')}]").encode() + tag + line) diff --git a/scripts/tests/java/commissioning_test.py b/scripts/tests/java/commissioning_test.py index c306afada822ce..138c9efa49065a 100755 --- a/scripts/tests/java/commissioning_test.py +++ b/scripts/tests/java/commissioning_test.py @@ -18,12 +18,9 @@ # import argparse -import asyncio import logging -import os import queue import subprocess -import sys import threading import typing @@ -46,7 +43,8 @@ def __init__(self, thread_list: typing.List[threading.Thread], queue: queue.Queu parser.add_argument('-s', '--setup-payload', dest='setup_payload', help="Setup Payload (manual pairing code or QR code content)") parser.add_argument('-c', '--setup-pin-code', dest='setup_pin_code', - help="Setup PIN code which can be used for password-authenticated session establishment (PASE) with the Commissionee") + help=("Setup PIN code which can be used for password-authenticated " + "session establishment (PASE) with the Commissionee")) parser.add_argument('-n', '--nodeid', help="The Node ID issued to the device", default='1') parser.add_argument('-d', '--discriminator', help="Discriminator of the device", default='3840') parser.add_argument('-u', '--paa-trust-store-path', dest='paa_trust_store_path', diff --git a/scripts/tests/java/discover_test.py b/scripts/tests/java/discover_test.py index 80c18d6c30e301..ed9fea7bc03c8a 100755 --- a/scripts/tests/java/discover_test.py +++ b/scripts/tests/java/discover_test.py @@ -18,12 +18,9 @@ # import argparse -import asyncio import logging -import os import queue import subprocess -import sys import threading import typing diff --git a/scripts/tests/run_java_test.py b/scripts/tests/run_java_test.py index 12d7f7c7b6c3cf..9205c3fec49322 100755 --- a/scripts/tests/run_java_test.py +++ b/scripts/tests/run_java_test.py @@ -16,8 +16,6 @@ import logging import os -import pathlib -import pty import queue import re import shlex @@ -34,12 +32,18 @@ @click.command() -@click.option("--app", type=click.Path(exists=True), default=None, help='Path to local application to use, omit to use external apps.') -@click.option("--app-args", type=str, default='', help='The extra arguments passed to the device.') -@click.option("--tool-path", type=click.Path(exists=True), default=None, help='Path to java-matter-controller.') -@click.option("--tool-cluster", type=str, default='pairing', help='The cluster name passed to the java-matter-controller.') -@click.option("--tool-args", type=str, default='', help='The arguments passed to the java-matter-controller.') -@click.option("--factoryreset", is_flag=True, help='Remove app configs (/tmp/chip*) before running the tests.') +@click.option("--app", type=click.Path(exists=True), default=None, + help='Path to local application to use, omit to use external apps.') +@click.option("--app-args", type=str, default='', + help='The extra arguments passed to the device.') +@click.option("--tool-path", type=click.Path(exists=True), default=None, + help='Path to java-matter-controller.') +@click.option("--tool-cluster", type=str, default='pairing', + help='The cluster name passed to the java-matter-controller.') +@click.option("--tool-args", type=str, default='', + help='The arguments passed to the java-matter-controller.') +@click.option("--factoryreset", is_flag=True, + help='Remove app configs (/tmp/chip*) before running the tests.') def main(app: str, app_args: str, tool_path: str, tool_cluster: str, tool_args: str, factoryreset: bool): logging.info("Execute: {script_command}") diff --git a/scripts/tests/run_python_test.py b/scripts/tests/run_python_test.py index 4318ee1221da35..87f6044c2a35f0 100755 --- a/scripts/tests/run_python_test.py +++ b/scripts/tests/run_python_test.py @@ -44,7 +44,7 @@ def EnqueueLogOutput(fp, tag, q): try: timestamp = float(line[1:18].decode()) line = line[19:] - except Exception as ex: + except Exception: pass sys.stdout.buffer.write( (f"[{datetime.datetime.fromtimestamp(timestamp).isoformat(sep=' ')}]").encode() + tag + line) @@ -67,12 +67,23 @@ def DumpProgramOutputToQueue(thread_list: typing.List[threading.Thread], tag: st @click.command() -@click.option("--app", type=click.Path(exists=True), default=None, help='Path to local application to use, omit to use external apps.') -@click.option("--factoryreset", is_flag=True, help='Remove app config and repl configs (/tmp/chip* and /tmp/repl*) before running the tests.') -@click.option("--app-args", type=str, default='', help='The extra arguments passed to the device.') -@click.option("--script", type=click.Path(exists=True), default=os.path.join(DEFAULT_CHIP_ROOT, 'src', 'controller', 'python', 'test', 'test_scripts', 'mobile-device-test.py'), help='Test script to use.') -@click.option("--script-args", type=str, default='', help='Path to the test script to use, omit to use the default test script (mobile-device-test.py).') -@click.option("--script-gdb", is_flag=True, help='Run script through gdb') +@click.option("--app", type=click.Path(exists=True), default=None, + help='Path to local application to use, omit to use external apps.') +@click.option("--factoryreset", is_flag=True, + help='Remove app config and repl configs (/tmp/chip* and /tmp/repl*) before running the tests.') +@click.option("--app-args", type=str, default='', + help='The extra arguments passed to the device.') +@click.option("--script", type=click.Path(exists=True), default=os.path.join(DEFAULT_CHIP_ROOT, + 'src', + 'controller', + 'python', + 'test', + 'test_scripts', + 'mobile-device-test.py'), help='Test script to use.') +@click.option("--script-args", type=str, default='', + help='Path to the test script to use, omit to use the default test script (mobile-device-test.py).') +@click.option("--script-gdb", is_flag=True, + help='Run script through gdb') def main(app: str, factoryreset: bool, app_args: str, script: str, script_args: str, script_gdb: bool): if factoryreset: # Remove native app config @@ -123,10 +134,12 @@ def main(app: str, factoryreset: bool, app_args: str, script: str, script_args: if script_gdb: # - # When running through Popen, we need to preserve some space-delimited args to GDB as a single logical argument. To do that, let's use '|' as a placeholder - # for the space character so that the initial split will not tokenize them, and then replace that with the space char there-after. + # When running through Popen, we need to preserve some space-delimited args to GDB as a single logical argument. + # To do that, let's use '|' as a placeholder for the space character so that the initial split will not tokenize them, + # and then replace that with the space char there-after. # - script_command = "gdb -batch -return-child-result -q -ex run -ex thread|apply|all|bt --args python3".split() + script_command + script_command = ("gdb -batch -return-child-result -q -ex run -ex " + "thread|apply|all|bt --args python3".split() + script_command) else: script_command = "/usr/bin/env python3".split() + script_command diff --git a/scripts/tests/run_test_suite.py b/scripts/tests/run_test_suite.py index 357148da8a35b5..d0ff275a1d4b55 100755 --- a/scripts/tests/run_test_suite.py +++ b/scripts/tests/run_test_suite.py @@ -52,7 +52,6 @@ def FindBinaryPath(name: str): else: del cache[name] - start = time.time() for path in Path(DEFAULT_CHIP_ROOT).rglob(name): if not path.is_file(): continue @@ -289,7 +288,8 @@ def cmd_list(context): type=int, help='If provided, fail if a test runs for longer than this time') @click.pass_context -def cmd_run(context, iterations, all_clusters_app, lock_app, ota_provider_app, ota_requestor_app, tv_app, bridge_app, chip_repl_yaml_tester, chip_tool_with_python, pics_file, keep_going, test_timeout_seconds): +def cmd_run(context, iterations, all_clusters_app, lock_app, ota_provider_app, ota_requestor_app, + tv_app, bridge_app, chip_repl_yaml_tester, chip_tool_with_python, pics_file, keep_going, test_timeout_seconds): runner = chiptest.runner.Runner() if all_clusters_app is None: diff --git a/scripts/tools/zap/test_generate.py b/scripts/tools/zap/test_generate.py index f6ea2ab3d5abfb..ff7ea2c20e74c2 100755 --- a/scripts/tools/zap/test_generate.py +++ b/scripts/tools/zap/test_generate.py @@ -14,7 +14,6 @@ # limitations under the License. import glob -import logging import os import shutil import subprocess @@ -116,7 +115,7 @@ def run_test_cases(self, checker: unittest.TestCase): try: subprocess.check_call(["diff", actual, expected]) - except: + except subprocess.CalledProcessError: if self.context.regenerate_golden: print( f"Copying updated golden image from {actual} to {expected}") diff --git a/src/app/tests/suites/certification/information.py b/src/app/tests/suites/certification/information.py index 1efda20315df66..bf5bbaa418bd30 100755 --- a/src/app/tests/suites/certification/information.py +++ b/src/app/tests/suites/certification/information.py @@ -55,7 +55,6 @@ def checkPythonVersion(): def parseTestPlans(filepath): tests_names = [] tests_statuses = [] - rv = [] for name, test_plan in parseYaml(filepath)['Test Plans'].items(): for section, tests in test_plan['tests'].items(): @@ -81,12 +80,12 @@ def parseTestPlan(filepath): for test_definition in parseYaml(filepath)['tests']: if 'disabled' in test_definition: - if is_pending_test == False: + if is_pending_test is False: return TestStatus.partial else: is_pending_test = False - if is_pending_test == True: + if is_pending_test is True: return TestStatus.pending return TestStatus.complete diff --git a/src/controller/python/test/test_scripts/base.py b/src/controller/python/test/test_scripts/base.py index 3188e310848ae7..9542210bfa9b15 100644 --- a/src/controller/python/test/test_scripts/base.py +++ b/src/controller/python/test/test_scripts/base.py @@ -27,7 +27,6 @@ import threading import time from dataclasses import dataclass -from inspect import Attribute from typing import Any import chip.CertificateAuthority @@ -38,7 +37,7 @@ import chip.interaction_model as IM import chip.native from chip import ChipDeviceCtrl -from chip.ChipStack import * +from chip.ChipStack import ChipStack from chip.utils import CommissioningBuildingBlocks logger = logging.getLogger('PythonMatterControllerTEST') @@ -226,7 +225,7 @@ def TestDiscovery(self, discriminator: int): chip.discovery.FilterType.LONG_DISCRIMINATOR, discriminator, stopOnFirst=True, timeoutSecond=3) if not res: self.logger.info( - f"Device not found") + "Device not found") return False self.logger.info(f"Found device {res[0]}") return res[0] @@ -241,15 +240,20 @@ def CreateNewFabricController(self): return True async def TestRevokeCommissioningWindow(self, ip: str, setuppin: int, nodeid: int): - await self.devCtrl.SendCommand(nodeid, 0, Clusters.AdministratorCommissioning.Commands.OpenBasicCommissioningWindow(180), timedRequestTimeoutMs=10000) + await self.devCtrl.SendCommand( + nodeid, 0, Clusters.AdministratorCommissioning.Commands.OpenBasicCommissioningWindow(180), timedRequestTimeoutMs=10000) if not self.TestPaseOnly(ip=ip, setuppin=setuppin, nodeid=nodeid, devCtrl=self.devCtrl2): return False - await self.devCtrl2.SendCommand(nodeid, 0, Clusters.GeneralCommissioning.Commands.ArmFailSafe(expiryLengthSeconds=180, breadcrumb=0)) + await self.devCtrl2.SendCommand( + nodeid, 0, Clusters.GeneralCommissioning.Commands.ArmFailSafe(expiryLengthSeconds=180, breadcrumb=0)) - await self.devCtrl.SendCommand(nodeid, 0, Clusters.AdministratorCommissioning.Commands.RevokeCommissioning(), timedRequestTimeoutMs=10000) - await self.devCtrl.SendCommand(nodeid, 0, Clusters.AdministratorCommissioning.Commands.OpenBasicCommissioningWindow(180), timedRequestTimeoutMs=10000) - await self.devCtrl.SendCommand(nodeid, 0, Clusters.AdministratorCommissioning.Commands.RevokeCommissioning(), timedRequestTimeoutMs=10000) + await self.devCtrl.SendCommand( + nodeid, 0, Clusters.AdministratorCommissioning.Commands.RevokeCommissioning(), timedRequestTimeoutMs=10000) + await self.devCtrl.SendCommand( + nodeid, 0, Clusters.AdministratorCommissioning.Commands.OpenBasicCommissioningWindow(180), timedRequestTimeoutMs=10000) + await self.devCtrl.SendCommand( + nodeid, 0, Clusters.AdministratorCommissioning.Commands.RevokeCommissioning(), timedRequestTimeoutMs=10000) return True def TestEnhancedCommissioningWindow(self, ip: str, nodeid: int): @@ -354,17 +358,24 @@ def TestFailsafe(self, nodeid: int): self.logger.info( "Attempting to open basic commissioning window - this should fail since the failsafe is armed") try: - res = asyncio.run(self.devCtrl.SendCommand( - nodeid, 0, Clusters.AdministratorCommissioning.Commands.OpenBasicCommissioningWindow(180), timedRequestTimeoutMs=10000)) + asyncio.run(self.devCtrl.SendCommand( + nodeid, + 0, + Clusters.AdministratorCommissioning.Commands.OpenBasicCommissioningWindow(180), + timedRequestTimeoutMs=10000 + )) # we actually want the exception here because we want to see a failure, so return False here self.logger.error( 'Incorrectly succeeded in opening basic commissioning window') return False - except Exception as ex: + except Exception: pass - # TODO: pipe through the commissioning window opener so we can test enhanced properly. The pake verifier is just garbage because none of of the functions to calculate - # it or serialize it are available right now. However, this command should fail BEFORE that becomes an issue. + # TODO: + ''' Pipe through the commissioning window opener so we can test enhanced properly. + The pake verifier is just garbage because none of of the functions to calculate + it or serialize it are available right now. However, this command should fail BEFORE that becomes an issue. + ''' discriminator = 1111 salt = secrets.token_bytes(16) iterations = 2000 @@ -373,13 +384,19 @@ def TestFailsafe(self, nodeid: int): self.logger.info( "Attempting to open enhanced commissioning window - this should fail since the failsafe is armed") try: - res = asyncio.run(self.devCtrl.SendCommand(nodeid, 0, Clusters.AdministratorCommissioning.Commands.OpenCommissioningWindow( - commissioningTimeout=180, PAKEPasscodeVerifier=verifier, discriminator=discriminator, iterations=iterations, salt=salt), timedRequestTimeoutMs=10000)) + asyncio.run(self.devCtrl.SendCommand( + nodeid, 0, Clusters.AdministratorCommissioning.Commands.OpenCommissioningWindow( + commissioningTimeout=180, + PAKEPasscodeVerifier=verifier, + discriminator=discriminator, + iterations=iterations, + salt=salt), timedRequestTimeoutMs=10000)) + # we actually want the exception here because we want to see a failure, so return False here self.logger.error( 'Incorrectly succeeded in opening enhanced commissioning window') return False - except Exception as ex: + except Exception: pass self.logger.info("Disarming failsafe on CASE connection") @@ -393,9 +410,14 @@ def TestFailsafe(self, nodeid: int): self.logger.info( "Opening Commissioning Window - this should succeed since the failsafe was just disarmed") try: - res = asyncio.run(self.devCtrl.SendCommand( - nodeid, 0, Clusters.AdministratorCommissioning.Commands.OpenBasicCommissioningWindow(180), timedRequestTimeoutMs=10000)) - except Exception as ex: + asyncio.run( + self.devCtrl.SendCommand( + nodeid, + 0, + Clusters.AdministratorCommissioning.Commands.OpenBasicCommissioningWindow(180), + timedRequestTimeoutMs=10000 + )) + except Exception: self.logger.error( 'Failed to open commissioning window after disarming failsafe') return False @@ -416,7 +438,12 @@ async def TestControllerCATValues(self, nodeid: int): ''' This tests controllers using CAT Values ''' # Allocate a new controller instance with a CAT tag. - newControllers = await CommissioningBuildingBlocks.CreateControllersOnFabric(fabricAdmin=self.fabricAdmin, adminDevCtrl=self.devCtrl, controllerNodeIds=[300], targetNodeId=nodeid, privilege=None, catTags=[0x0001_0001]) + newControllers = await CommissioningBuildingBlocks.CreateControllersOnFabric( + fabricAdmin=self.fabricAdmin, + adminDevCtrl=self.devCtrl, + controllerNodeIds=[300], + targetNodeId=nodeid, + privilege=None, catTags=[0x0001_0001]) # Read out an attribute using the new controller. It has no privileges, so this should fail with an UnsupportedAccess error. res = await newControllers[0].ReadAttribute(nodeid=nodeid, attributes=[(0, Clusters.AccessControl.Attributes.Acl)]) @@ -425,16 +452,27 @@ async def TestControllerCATValues(self, nodeid: int): return False # Grant the new controller privilege by adding the CAT tag to the subject. - await CommissioningBuildingBlocks.GrantPrivilege(adminCtrl=self.devCtrl, grantedCtrl=newControllers[0], privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, targetNodeId=nodeid, targetCatTags=[0x0001_0001]) + await CommissioningBuildingBlocks.GrantPrivilege( + adminCtrl=self.devCtrl, + grantedCtrl=newControllers[0], + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, + targetNodeId=nodeid, targetCatTags=[0x0001_0001]) # Read out the attribute again - this time, it should succeed. res = await newControllers[0].ReadAttribute(nodeid=nodeid, attributes=[(0, Clusters.AccessControl.Attributes.Acl)]) - if (type(res[0][Clusters.AccessControl][Clusters.AccessControl.Attributes.Acl][0]) != Clusters.AccessControl.Structs.AccessControlEntryStruct): + if (type(res[0][ + Clusters.AccessControl][ + Clusters.AccessControl.Attributes.Acl][0]) != Clusters.AccessControl.Structs.AccessControlEntryStruct): self.logger.error(f"2: Received something other than data:{res}") return False # Reset the privilege back to pre-test. - await CommissioningBuildingBlocks.GrantPrivilege(adminCtrl=self.devCtrl, grantedCtrl=newControllers[0], privilege=None, targetNodeId=nodeid) + await CommissioningBuildingBlocks.GrantPrivilege( + adminCtrl=self.devCtrl, + grantedCtrl=newControllers[0], + privilege=None, + targetNodeId=nodeid + ) newControllers[0].Shutdown() @@ -445,7 +483,13 @@ async def TestMultiControllerFabric(self, nodeid: int): ''' # Create two new controllers on the same fabric with no privilege on the target node. - newControllers = await CommissioningBuildingBlocks.CreateControllersOnFabric(fabricAdmin=self.fabricAdmin, adminDevCtrl=self.devCtrl, controllerNodeIds=[100, 200], targetNodeId=nodeid, privilege=None) + newControllers = await CommissioningBuildingBlocks.CreateControllersOnFabric( + fabricAdmin=self.fabricAdmin, + adminDevCtrl=self.devCtrl, + controllerNodeIds=[100, 200], + targetNodeId=nodeid, + privilege=None + ) # # Read out the ACL list from one of the newly minted controllers which has no access. This should return an IM error. @@ -460,12 +504,15 @@ async def TestMultiControllerFabric(self, nodeid: int): # Doing this ensures that we're not somehow aliasing the CASE sessions. # res = await self.devCtrl.ReadAttribute(nodeid=nodeid, attributes=[(0, Clusters.AccessControl.Attributes.Acl)]) - if (type(res[0][Clusters.AccessControl][Clusters.AccessControl.Attributes.Acl][0]) != Clusters.AccessControl.Structs.AccessControlEntryStruct): + if (type(res[0][ + Clusters.AccessControl][ + Clusters.AccessControl.Attributes.Acl][0]) != Clusters.AccessControl.Structs.AccessControlEntryStruct): self.logger.error(f"2: Received something other than data:{res}") return False # - # Re-do the previous read from the unprivileged controller just to do an ABA test to prove we haven't switched the CASE sessions + # Re-do the previous read from the unprivileged controller + # just to do an ABA test to prove we haven't switched the CASE sessions # under-neath. # res = await newControllers[0].ReadAttribute(nodeid=nodeid, attributes=[(0, Clusters.AccessControl.Attributes.Acl)]) @@ -476,25 +523,43 @@ async def TestMultiControllerFabric(self, nodeid: int): # # Grant the new controller admin privileges. Reading out the ACL cluster should now yield data. # - await CommissioningBuildingBlocks.GrantPrivilege(adminCtrl=self.devCtrl, grantedCtrl=newControllers[0], privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, targetNodeId=nodeid) + await CommissioningBuildingBlocks.GrantPrivilege( + adminCtrl=self.devCtrl, + grantedCtrl=newControllers[0], + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, + targetNodeId=nodeid + ) res = await newControllers[0].ReadAttribute(nodeid=nodeid, attributes=[(0, Clusters.AccessControl.Attributes.Acl)]) - if (type(res[0][Clusters.AccessControl][Clusters.AccessControl.Attributes.Acl][0]) != Clusters.AccessControl.Structs.AccessControlEntryStruct): + if (type(res[0][ + Clusters.AccessControl][ + Clusters.AccessControl.Attributes.Acl][0]) != Clusters.AccessControl.Structs.AccessControlEntryStruct): self.logger.error(f"4: Received something other than data:{res}") return False # # Grant the second new controller admin privileges as well. Reading out the ACL cluster should now yield data. # - await CommissioningBuildingBlocks.GrantPrivilege(adminCtrl=self.devCtrl, grantedCtrl=newControllers[1], privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, targetNodeId=nodeid) + await CommissioningBuildingBlocks.GrantPrivilege( + adminCtrl=self.devCtrl, + grantedCtrl=newControllers[1], + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, + targetNodeId=nodeid + ) res = await newControllers[1].ReadAttribute(nodeid=nodeid, attributes=[(0, Clusters.AccessControl.Attributes.Acl)]) - if (type(res[0][Clusters.AccessControl][Clusters.AccessControl.Attributes.Acl][0]) != Clusters.AccessControl.Structs.AccessControlEntryStruct): + if (type(res[0][ + Clusters.AccessControl][ + Clusters.AccessControl.Attributes.Acl][0]) != Clusters.AccessControl.Structs.AccessControlEntryStruct): self.logger.error(f"5: Received something other than data:{res}") return False # # Grant the second new controller just view privilege. Reading out the ACL cluster should return no data. # - await CommissioningBuildingBlocks.GrantPrivilege(adminCtrl=self.devCtrl, grantedCtrl=newControllers[1], privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, targetNodeId=nodeid) + await CommissioningBuildingBlocks.GrantPrivilege( + adminCtrl=self.devCtrl, + grantedCtrl=newControllers[1], + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + targetNodeId=nodeid) res = await newControllers[1].ReadAttribute(nodeid=nodeid, attributes=[(0, Clusters.AccessControl.Attributes.Acl)]) if (res[0][Clusters.AccessControl][Clusters.AccessControl.Attributes.Acl].Reason.status != IM.Status.UnsupportedAccess): self.logger.error(f"6: Received data5 instead of an error:{res}") @@ -503,8 +568,13 @@ async def TestMultiControllerFabric(self, nodeid: int): # # Read the Basic cluster from the 2nd controller. This is possible with just view privileges. # - res = await newControllers[1].ReadAttribute(nodeid=nodeid, attributes=[(0, Clusters.BasicInformation.Attributes.ClusterRevision)]) - if (type(res[0][Clusters.BasicInformation][Clusters.BasicInformation.Attributes.ClusterRevision]) != Clusters.BasicInformation.Attributes.ClusterRevision.attribute_type.Type): + res = await newControllers[1].ReadAttribute(nodeid=nodeid, + attributes=[(0, Clusters.BasicInformation.Attributes.ClusterRevision)]) + if (type( + res[0][ + Clusters.BasicInformation][ + Clusters.BasicInformation.Attributes.ClusterRevision] + ) != Clusters.BasicInformation.Attributes.ClusterRevision.attribute_type.Type): self.logger.error(f"7: Received something other than data:{res}") return False @@ -554,9 +624,16 @@ async def TestAddUpdateRemoveFabric(self, nodeid: int): # TODO Read using old node ID and expect that it fails. - currentFabricIndexResponse = await tempDevCtrl.ReadAttribute(newNodeIdForUpdateNoc, [(Clusters.OperationalCredentials.Attributes.CurrentFabricIndex)]) - updatedNOCFabricIndex = currentFabricIndexResponse[0][Clusters.OperationalCredentials][Clusters.OperationalCredentials.Attributes.CurrentFabricIndex] - removeFabricResponse = await tempDevCtrl.SendCommand(newNodeIdForUpdateNoc, 0, Clusters.OperationalCredentials.Commands.RemoveFabric(updatedNOCFabricIndex)) + currentFabricIndexResponse = await tempDevCtrl.ReadAttribute( + newNodeIdForUpdateNoc, + [(Clusters.OperationalCredentials.Attributes.CurrentFabricIndex)] + ) + updatedNOCFabricIndex = currentFabricIndexResponse[0][Clusters.OperationalCredentials][ + Clusters.OperationalCredentials.Attributes.CurrentFabricIndex] + # Remove Fabric Response + await tempDevCtrl.SendCommand( + newNodeIdForUpdateNoc, 0, + Clusters.OperationalCredentials.Commands.RemoveFabric(updatedNOCFabricIndex)) if startOfTestFabricCount != await self._GetCommissonedFabricCount(nodeid): self.logger.error("Expected fabric count to be the same at the end of test as when it started") @@ -621,7 +698,8 @@ def OnValueChange(path: Attribute.TypedAttributePath, transaction: Attribute.Sub sub.Shutdown() if sawValueChange is False: - self.logger.error("Didn't see value change in time, likely because sub got terminated due to unexpected session eviction!") + self.logger.error( + "Didn't see value change in time, likely because sub got terminated due to unexpected session eviction!") return False # @@ -682,7 +760,12 @@ def OnValueChange(path: Attribute.TypedAttributePath, transaction: Attribute.Sub async def TestMultiFabric(self, ip: str, setuppin: int, nodeid: int): self.logger.info("Opening Commissioning Window") - await self.devCtrl.SendCommand(nodeid, 0, Clusters.AdministratorCommissioning.Commands.OpenBasicCommissioningWindow(180), timedRequestTimeoutMs=10000) + await self.devCtrl.SendCommand( + nodeid, + 0, + Clusters.AdministratorCommissioning.Commands.OpenBasicCommissioningWindow(180), + timedRequestTimeoutMs=10000 + ) self.logger.info("Creating 2nd Fabric Admin") self.fabricAdmin2 = self.certificateAuthority.NewFabricAdmin(vendorId=0xFFF1, fabricId=2) @@ -730,8 +813,16 @@ async def TestMultiFabric(self, ip: str, setuppin: int, nodeid: int): self.logger.error("Got back invalid nocList") return False - data1 = await self.devCtrl.ReadAttribute(nodeid, [(Clusters.OperationalCredentials.Attributes.CurrentFabricIndex)], fabricFiltered=False) - data2 = await self.devCtrl2.ReadAttribute(nodeid, [(Clusters.OperationalCredentials.Attributes.CurrentFabricIndex)], fabricFiltered=False) + data1 = await self.devCtrl.ReadAttribute( + nodeid, + [(Clusters.OperationalCredentials.Attributes.CurrentFabricIndex)], + fabricFiltered=False + ) + data2 = await self.devCtrl2.ReadAttribute( + nodeid, + [(Clusters.OperationalCredentials.Attributes.CurrentFabricIndex)], + fabricFiltered=False + ) # Read out current fabric from each fabric, and both should be different. self.currentFabric1 = data1[0][Clusters.OperationalCredentials][ @@ -863,12 +954,14 @@ def CompareUnfilteredData(accessingFabric, otherFabric, expectedData): if (item != expectedDefaultData): raise AssertionError("Got back mismatched data") - data = await self.devCtrl.ReadAttribute(nodeid, [(1, Clusters.UnitTesting.Attributes.ListFabricScoped)], fabricFiltered=False) + data = await self.devCtrl.ReadAttribute(nodeid, + [(1, Clusters.UnitTesting.Attributes.ListFabricScoped)], fabricFiltered=False) readListDataFabric = data[1][Clusters.UnitTesting][Clusters.UnitTesting.Attributes.ListFabricScoped] CompareUnfilteredData(self.currentFabric1, self.currentFabric2, expectedDataFabric1) - data = await self.devCtrl2.ReadAttribute(nodeid, [(1, Clusters.UnitTesting.Attributes.ListFabricScoped)], fabricFiltered=False) + data = await self.devCtrl2.ReadAttribute(nodeid, + [(1, Clusters.UnitTesting.Attributes.ListFabricScoped)], fabricFiltered=False) readListDataFabric = data[1][Clusters.UnitTesting][Clusters.UnitTesting.Attributes.ListFabricScoped] CompareUnfilteredData(self.currentFabric2, self.currentFabric1, expectedDataFabric2) @@ -928,7 +1021,11 @@ async def OnResubscriptionSucceeded(transaction): async with cv: cv.notify() - subscription = await self.devCtrl.ReadAttribute(nodeid, [(Clusters.BasicInformation.Attributes.ClusterRevision)], reportInterval=(0, 5)) + subscription = await self.devCtrl.ReadAttribute( + nodeid, + [(Clusters.BasicInformation.Attributes.ClusterRevision)], + reportInterval=(0, 5) + ) # # Register async callbacks that will fire when a re-sub is attempted or succeeds. @@ -1029,14 +1126,14 @@ def TestResolve(self, nodeid): while not addr: addr = self.devCtrl.GetAddressAndPort(nodeid) if time.time() - start > 10: - self.logger.exception(f"Timeout waiting for address...") + self.logger.exception("Timeout waiting for address...") break if not addr: time.sleep(0.2) if not addr: - self.logger.exception(f"Addr is missing...") + self.logger.exception("Addr is missing...") return False self.logger.info(f"Resolved address: {addr[0]}:{addr[1]}") return True @@ -1165,21 +1262,23 @@ def run(self): # is really wrong and bail out here with some information. if not updateCv.wait(10.0): self.logger.error( - f"Failed to receive subscription update") + "Failed to receive subscription update") break - # thread changes 5 times, and sleeps for 3 seconds in between. Add an additional 3 seconds of slack. Timeout is in seconds. + # thread changes 5 times, and sleeps for 3 seconds in between. + # Add an additional 3 seconds of slack. Timeout is in seconds. changeThread.join(18.0) # - # Clean-up by shutting down the sub. Otherwise, we're going to get callbacks through OnValueChange on what will soon become an invalid + # Clean-up by shutting down the sub. Otherwise, we're going to get callbacks through + # OnValueChange on what will soon become an invalid # execution context above. # subscription.Shutdown() if changeThread.is_alive(): # Thread join timed out - self.logger.error(f"Failed to join change thread") + self.logger.error("Failed to join change thread") return False return True if receivedUpdate == 5 else False @@ -1213,7 +1312,7 @@ def TestFabricScopedCommandDuringPase(self, nodeid: int): ''' status = None try: - response = asyncio.run(self.devCtrl.SendCommand( + asyncio.run(self.devCtrl.SendCommand( nodeid, 0, Clusters.OperationalCredentials.Commands.UpdateFabricLabel("roboto"))) except IM.InteractionModelError as ex: status = ex.status diff --git a/src/controller/python/test/test_scripts/cluster_objects.py b/src/controller/python/test/test_scripts/cluster_objects.py index 59b55a6a13bf86..80210bb8af32d8 100644 --- a/src/controller/python/test/test_scripts/cluster_objects.py +++ b/src/controller/python/test/test_scripts/cluster_objects.py @@ -57,7 +57,8 @@ def VerifyDecodeSuccess(values): f"Ignoring attribute decode failure for path {endpoint}/{attribute}") else: raise AssertionError( - f"Cannot decode value for path {endpoint}/{attribute}, got error: '{str(v.Reason)}', raw TLV data: '{v.TLVValue}'") + f"Cannot decode value for path {endpoint}/{attribute}, " + f"got error: '{str(v.Reason)}', raw TLV data: '{v.TLVValue}'") for endpoint in values: for cluster in values[endpoint]: @@ -104,7 +105,7 @@ async def TestCommandRoundTripWithBadEndpoint(cls, devCtrl): req = Clusters.OnOff.Commands.On() try: await devCtrl.SendCommand(nodeid=NODE_ID, endpoint=233, payload=req) - raise ValueError(f"Failure expected") + raise ValueError("Failure expected") except chip.interaction_model.InteractionModelError as ex: logger.info(f"Recevied {ex} from server.") return @@ -156,11 +157,16 @@ async def TestWriteRequest(cls, devCtrl): raise AssertionError("Write returned unexpected result.") logger.info("2: Write chunked list") - res = await devCtrl.WriteAttribute(nodeid=NODE_ID, - attributes=[(1, Clusters.UnitTesting.Attributes.ListLongOctetString([b"0123456789abcdef" * 32] * 5))]) + res = await devCtrl.WriteAttribute( + nodeid=NODE_ID, + attributes=[ + (1, Clusters.UnitTesting.Attributes.ListLongOctetString([b"0123456789abcdef" * 32] * 5)) + ] + ) expectedRes = [ AttributeStatus(Path=AttributePath( - EndpointId=1, Attribute=Clusters.UnitTesting.Attributes.ListLongOctetString), Status=chip.interaction_model.Status.Success), + EndpointId=1, + Attribute=Clusters.UnitTesting.Attributes.ListLongOctetString), Status=chip.interaction_model.Status.Success), ] logger.info(f"Received WriteResponse: {res}") @@ -198,15 +204,19 @@ def subUpdate(path: TypedAttributePath, transaction: SubscriptionTransaction): @ base.test_case async def TestSubscribeZeroMinInterval(cls, devCtrl): ''' - This validates receiving subscription reports for two attributes at a time in quick succession after issuing a command that results in attribute side-effects. - Specifically, it relies on the fact that the second attribute is changed in a different execution context than the first. This ensures that we pick-up the first - attribute change and generate a notification, and validating that shortly after that, we generate a second report for the second change. - - This is done using subscriptions with a min reporting interval of 0 to ensure timely notification of the above. An On() command is sent to the OnOff cluster + This validates receiving subscription reports for two attributes at a time in quick succession after + issuing a command that results in attribute side-effects. Specifically, it relies on the fact that the second attribute + is changed in a different execution context than the first. This ensures that we pick-up the first + attribute change and generate a notification, and validating that shortly after that, + we generate a second report for the second change. + + This is done using subscriptions with a min reporting interval of 0 to ensure timely notification of the above. + An On() command is sent to the OnOff cluster which should simultaneously set the state to On as well as set the level to 254. ''' logger.info("Test Subscription With MinInterval of 0") - sub = await devCtrl.ReadAttribute(nodeid=NODE_ID, attributes=[Clusters.OnOff, Clusters.LevelControl], reportInterval=(0, 60)) + sub = await devCtrl.ReadAttribute(nodeid=NODE_ID, + attributes=[Clusters.OnOff, Clusters.LevelControl], reportInterval=(0, 60)) data = sub.GetAttributes() logger.info("Sending off command") @@ -297,17 +307,21 @@ async def TestReadAttributeRequests(cls, devCtrl): if res[1][Clusters.UnitTesting][Clusters.UnitTesting.Attributes.ListLongOctetString] != [b'0123456789abcdef' * 32] * 4: raise AssertionError("Unexpected read result") - logger.info("*: Getting current fabric index") - res = await devCtrl.ReadAttribute(nodeid=NODE_ID, attributes=[(0, Clusters.OperationalCredentials.Attributes.CurrentFabricIndex)]) - fabricIndex = res[0][Clusters.OperationalCredentials][Clusters.OperationalCredentials.Attributes.CurrentFabricIndex] - # Note: ListFabricScoped is an empty list for now. We should re-enable this test after we make it return expected data. + # logger.info("*: Getting current fabric index") + # res = await devCtrl.ReadAttribute(nodeid=NODE_ID, + # attributes=[(0, Clusters.OperationalCredentials.Attributes.CurrentFabricIndex)]) + # fabricIndex = res[0][Clusters.OperationalCredentials][Clusters.OperationalCredentials.Attributes.CurrentFabricIndex] + # # logger.info("8: Read without fabric filter") - # res = await devCtrl.ReadAttribute(nodeid=NODE_ID, attributes=[(1, Clusters.UnitTesting.Attributes.ListFabricScoped)], fabricFiltered=False) + # res = await devCtrl.ReadAttribute(nodeid=NODE_ID, + # attributes=[(1, Clusters.UnitTesting.Attributes.ListFabricScoped)], + # fabricFiltered=False) # if len(res[1][Clusters.UnitTesting][Clusters.UnitTesting.Attributes.ListFabricScoped]) == 1: # raise AssertionError("Expect more elements in the response") # logger.info("9: Read with fabric filter") - # res = await devCtrl.ReadAttribute(nodeid=NODE_ID, attributes=[(1, Clusters.UnitTesting.Attributes.ListFabricScoped)], fabricFiltered=True) + # res = await devCtrl.ReadAttribute(nodeid=NODE_ID, + # attributes=[(1, Clusters.UnitTesting.Attributes.ListFabricScoped)], fabricFiltered=True) # if len(res[1][Clusters.UnitTesting][Clusters.UnitTesting.Attributes.ListFabricScoped]) != 1: # raise AssertionError("Expect exact one element in the response") # if res[1][Clusters.UnitTesting][Clusters.UnitTesting.Attributes.ListFabricScoped][0].fabricIndex != fabricIndex: @@ -317,9 +331,12 @@ async def TestReadAttributeRequests(cls, devCtrl): @ classmethod async def _TriggerEvent(cls, devCtrl): # We trigger sending an event a couple of times just to be safe. - await devCtrl.SendCommand(nodeid=NODE_ID, endpoint=1, payload=Clusters.UnitTesting.Commands.TestEmitTestEventRequest()) - await devCtrl.SendCommand(nodeid=NODE_ID, endpoint=1, payload=Clusters.UnitTesting.Commands.TestEmitTestEventRequest()) - return await devCtrl.SendCommand(nodeid=NODE_ID, endpoint=1, payload=Clusters.UnitTesting.Commands.TestEmitTestEventRequest()) + await devCtrl.SendCommand(nodeid=NODE_ID, + endpoint=1, payload=Clusters.UnitTesting.Commands.TestEmitTestEventRequest()) + await devCtrl.SendCommand(nodeid=NODE_ID, + endpoint=1, payload=Clusters.UnitTesting.Commands.TestEmitTestEventRequest()) + return await devCtrl.SendCommand(nodeid=NODE_ID, + endpoint=1, payload=Clusters.UnitTesting.Commands.TestEmitTestEventRequest()) @ classmethod async def _RetryForContent(cls, request, until, retryCount=10, intervalSeconds=1): @@ -351,20 +368,30 @@ def validate_got_expected_event(events): return False return True - await cls._RetryForContent(request=lambda: devCtrl.ReadEvent(nodeid=NODE_ID, events=req, eventNumberFilter=current_event_filter), until=validate_got_expected_event) + await cls._RetryForContent(request=lambda: devCtrl.ReadEvent( + nodeid=NODE_ID, + events=req, + eventNumberFilter=current_event_filter + ), until=validate_got_expected_event) def validate_got_no_event(events): return len(events) == 0 - await cls._RetryForContent(request=lambda: devCtrl.ReadEvent(nodeid=NODE_ID, events=req, eventNumberFilter=(current_event_filter + 1)), until=validate_got_no_event) + await cls._RetryForContent(request=lambda: devCtrl.ReadEvent( + nodeid=NODE_ID, + events=req, + eventNumberFilter=(current_event_filter + 1) + ), until=validate_got_no_event) @ classmethod @ base.test_case async def TestGenerateUndefinedFabricScopedEventRequests(cls, devCtrl): logger.info("Running TestGenerateUndefinedFabricScopedEventRequests") try: - res = await devCtrl.SendCommand(nodeid=NODE_ID, endpoint=1, payload=Clusters.UnitTesting.Commands.TestEmitTestFabricScopedEventRequest(arg1=0)) - raise ValueError(f"Unexpected Failure") + res = await devCtrl.SendCommand(nodeid=NODE_ID, + endpoint=1, + payload=Clusters.UnitTesting.Commands.TestEmitTestFabricScopedEventRequest(arg1=0)) + raise ValueError("Unexpected Failure") except chip.interaction_model.InteractionModelError as ex: logger.info(f"Recevied {ex} from server.") res = await devCtrl.ReadEvent(nodeid=NODE_ID, events=[ @@ -518,13 +545,15 @@ async def TestReadWriteAttributeRequestsWithVersion(cls, devCtrl): req = [ (0, Clusters.BasicInformation.Attributes.VendorName), ] - res = await devCtrl.ReadAttribute(nodeid=NODE_ID, attributes=req, dataVersionFilters=[(0, Clusters.BasicInformation, data_version)]) + res = await devCtrl.ReadAttribute(nodeid=NODE_ID, + attributes=req, dataVersionFilters=[(0, Clusters.BasicInformation, data_version)]) VerifyDecodeSuccess(res) new_data_version = res[0][Clusters.BasicInformation][DataVersion] if (data_version + 1) != new_data_version: raise AssertionError("Version mistmatch happens.") - res = await devCtrl.ReadAttribute(nodeid=NODE_ID, attributes=req, dataVersionFilters=[(0, Clusters.BasicInformation, new_data_version)]) + res = await devCtrl.ReadAttribute(nodeid=NODE_ID, + attributes=req, dataVersionFilters=[(0, Clusters.BasicInformation, new_data_version)]) VerifyDecodeSuccess(res) res = await devCtrl.WriteAttribute(nodeid=NODE_ID, @@ -590,7 +619,10 @@ def eventPathPossibilities(): logging.info( f"{testCount}: Reading mixed Attributes({attributes[0]}) Events({events[0]})") await cls._TriggerEvent(devCtrl) - res = await cls._RetryForContent(request=lambda: devCtrl.Read(nodeid=NODE_ID, attributes=attributes[1], events=events[1]), until=lambda res: res != 0) + res = await cls._RetryForContent(request=lambda: devCtrl.Read( + nodeid=NODE_ID, + attributes=attributes[1], + events=events[1]), until=lambda res: res != 0) VerifyDecodeSuccess(res.attributes) @ classmethod diff --git a/src/controller/python/test/test_scripts/mobile-device-test.py b/src/controller/python/test/test_scripts/mobile-device-test.py index e602194f29efbf..09f13ccb444843 100755 --- a/src/controller/python/test/test_scripts/mobile-device-test.py +++ b/src/controller/python/test/test_scripts/mobile-device-test.py @@ -195,19 +195,59 @@ def do_tests(controller_nodeid, device_nodeid, address, timeout, discriminator, @click.command() -@click.option("--controller-nodeid", default=TEST_CONTROLLER_NODE_ID, type=int, help="NodeId of the controller.") -@click.option("--device-nodeid", default=TEST_DEVICE_NODE_ID, type=int, help="NodeId of the device.") -@click.option("--address", "-a", default='', type=str, help="Skip commissionee discovery, commission the device with the IP directly.") -@click.option("--timeout", "-t", default=240, type=int, help="The program will return with timeout after specified seconds.") -@click.option("--discriminator", default=TEST_DISCRIMINATOR, type=int, help="Discriminator of the device.") -@click.option("--setup-pin", default=TEST_SETUPPIN, type=int, help="Setup pincode of the device.") -@click.option('--enable-test', default=['all'], type=str, multiple=True, help='The tests to be executed. By default, all tests will be executed, use this option to run a specific set of tests. Use --print-test-list for a list of appliable tests.') -@click.option('--disable-test', default=[], type=str, multiple=True, help='The tests to be excluded from the set of enabled tests. Use --print-test-list for a list of appliable tests.') -@click.option('--log-level', default='WARN', type=click.Choice(['ERROR', 'WARN', 'INFO', 'DEBUG']), help="The log level of the test.") -@click.option('--log-format', default=None, type=str, help="Override logging format") -@click.option('--print-test-list', is_flag=True, help="Print a list of test cases and test sets that can be toggled via --enable-test and --disable-test, then exit") -@click.option('--paa-trust-store-path', default='', type=str, help="Path that contains valid and trusted PAA Root Certificates.") -def run(controller_nodeid, device_nodeid, address, timeout, discriminator, setup_pin, enable_test, disable_test, log_level, log_format, print_test_list, paa_trust_store_path): +@click.option("--controller-nodeid", + default=TEST_CONTROLLER_NODE_ID, + type=int, + help="NodeId of the controller.") +@click.option("--device-nodeid", + default=TEST_DEVICE_NODE_ID, + type=int, + help="NodeId of the device.") +@click.option("--address", "-a", + default='', + type=str, + help="Skip commissionee discovery, commission the device with the IP directly.") +@click.option("--timeout", "-t", + default=240, + type=int, + help="The program will return with timeout after specified seconds.") +@click.option("--discriminator", + default=TEST_DISCRIMINATOR, + type=int, + help="Discriminator of the device.") +@click.option("--setup-pin", + default=TEST_SETUPPIN, + type=int, + help="Setup pincode of the device.") +@click.option('--enable-test', + default=['all'], + type=str, + multiple=True, + help='The tests to be executed. By default, all tests will be executed, use this option to run a ' + 'specific set of tests. Use --print-test-list for a list of appliable tests.') +@click.option('--disable-test', + default=[], + type=str, + multiple=True, + help='The tests to be excluded from the set of enabled tests. Use --print-test-list for a list of ' + 'appliable tests.') +@click.option('--log-level', + default='WARN', + type=click.Choice(['ERROR', 'WARN', 'INFO', 'DEBUG']), + help="The log level of the test.") +@click.option('--log-format', + default=None, + type=str, + help="Override logging format") +@click.option('--print-test-list', + is_flag=True, + help="Print a list of test cases and test sets that can be toggled via --enable-test and --disable-test, then exit") +@click.option('--paa-trust-store-path', + default='', + type=str, + help="Path that contains valid and trusted PAA Root Certificates.") +def run(controller_nodeid, device_nodeid, address, timeout, discriminator, setup_pin, enable_test, disable_test, log_level, + log_format, print_test_list, paa_trust_store_path): coloredlogs.install(level=log_level, fmt=log_format, logger=logger) if print_test_list: diff --git a/src/controller/python/test/test_scripts/network_commissioning.py b/src/controller/python/test/test_scripts/network_commissioning.py index 64c5510c4e9624..f21e3b4603564e 100644 --- a/src/controller/python/test/test_scripts/network_commissioning.py +++ b/src/controller/python/test/test_scripts/network_commissioning.py @@ -58,11 +58,16 @@ def __init__(self, devCtrl, nodeid): self._last_breadcrumb = random.randint(1, 1 << 48) async def must_verify_breadcrumb(self): - res = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[(0, Clusters.GeneralCommissioning.Attributes.Breadcrumb)], returnClusterObject=True) + res = await self._devCtrl.ReadAttribute( + nodeid=self._nodeid, + attributes=[(0, Clusters.GeneralCommissioning.Attributes.Breadcrumb)], + returnClusterObject=True + ) if self._last_breadcrumb is not None: if self._last_breadcrumb != res[0][Clusters.GeneralCommissioning].breadcrumb: raise AssertionError( - f"Breadcrumb attribute mismatch! Expect {self._last_breadcrumb} got {res[0][Clusters.GeneralCommissioning].breadcrumb}") + f"Breadcrumb attribute mismatch! Expect {self._last_breadcrumb} " + f"got {res[0][Clusters.GeneralCommissioning].breadcrumb}") def with_breadcrumb(self) -> int: self._last_breadcrumb += 1 @@ -78,9 +83,13 @@ def log_interface_basic_info(self, values): f"The feature map of this endpoint is {values.featureMap}.") async def readLastNetworkingStateAttributes(self, endpointId): - res = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[(endpointId, Clusters.NetworkCommissioning.Attributes.LastConnectErrorValue), - (endpointId, Clusters.NetworkCommissioning.Attributes.LastNetworkID), - (endpointId, Clusters.NetworkCommissioning.Attributes.LastNetworkingStatus)], returnClusterObject=True) + res = await self._devCtrl.ReadAttribute( + nodeid=self._nodeid, + attributes=[(endpointId, Clusters.NetworkCommissioning.Attributes.LastConnectErrorValue), + (endpointId, Clusters.NetworkCommissioning.Attributes.LastNetworkID), + (endpointId, Clusters.NetworkCommissioning.Attributes.LastNetworkingStatus)], + returnClusterObject=True + ) values = res[endpointId][Clusters.NetworkCommissioning] logger.info(f"Got values: {values}") return values @@ -91,7 +100,7 @@ async def test_negative(self, endpointId): try: logger.info( - f"1. Send ConnectNetwork command with a illegal network id") + "1. Send ConnectNetwork command with a illegal network id") req = Clusters.NetworkCommissioning.Commands.ConnectNetwork( networkID=b'0' * 254, breadcrumb=0) res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=endpointId, payload=req) @@ -99,10 +108,10 @@ async def test_negative(self, endpointId): except chip.interaction_model.InteractionModelError as ex: logger.info(f"Received {ex} from server.") - logger.info(f"Finished negative test cases.") + logger.info("Finished negative test cases.") async def test_wifi(self, endpointId): - logger.info(f"Get basic information of the endpoint") + logger.info("Get basic information of the endpoint") res = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[ (endpointId, Clusters.NetworkCommissioning.Attributes.ConnectMaxTimeSeconds), @@ -115,7 +124,7 @@ async def test_wifi(self, endpointId): returnClusterObject=True) self.log_interface_basic_info( res[endpointId][Clusters.NetworkCommissioning]) - logger.info(f"Finished getting basic information of the endpoint") + logger.info("Finished getting basic information of the endpoint") if res[endpointId][Clusters.NetworkCommissioning].acceptedCommandList != [ Clusters.NetworkCommissioning.Commands.ScanNetworks.command_id, @@ -123,45 +132,54 @@ async def test_wifi(self, endpointId): Clusters.NetworkCommissioning.Commands.RemoveNetwork.command_id, Clusters.NetworkCommissioning.Commands.ConnectNetwork.command_id, Clusters.NetworkCommissioning.Commands.ReorderNetwork.command_id]: - raise AssertionError(f"Unexpected accepted command list for Thread interface") + raise AssertionError("Unexpected accepted command list for Thread interface") if res[endpointId][Clusters.NetworkCommissioning].generatedCommandList != [ Clusters.NetworkCommissioning.Commands.ScanNetworksResponse.command_id, Clusters.NetworkCommissioning.Commands.NetworkConfigResponse.command_id, Clusters.NetworkCommissioning.Commands.ConnectNetworkResponse.command_id]: - raise AssertionError(f"Unexpected generated command list for Thread interface") + raise AssertionError("Unexpected generated command list for Thread interface") # Read Last* attributes - logger.info(f"Read Last* attributes") + logger.info("Read Last* attributes") res = await self.readLastNetworkingStateAttributes(endpointId=endpointId) if (res.lastNetworkID != NullValue) or (res.lastNetworkingStatus != NullValue) or (res.lastConnectErrorValue != NullValue): raise AssertionError( - f"LastNetworkID, LastNetworkingStatus and LastConnectErrorValue should be Null") + "LastNetworkID, LastNetworkingStatus and LastConnectErrorValue should be Null") # Scan networks - logger.info(f"Scan networks") + logger.info("Scan networks") req = Clusters.NetworkCommissioning.Commands.ScanNetworks( ssid=b'', breadcrumb=self.with_breadcrumb()) interactionTimeoutMs = self._devCtrl.ComputeRoundTripTimeout(self._nodeid, upperLayerProcessingTimeoutMs=30000) - res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=endpointId, payload=req, interactionTimeoutMs=interactionTimeoutMs) + res = await self._devCtrl.SendCommand( + nodeid=self._nodeid, + endpoint=endpointId, + payload=req, + interactionTimeoutMs=interactionTimeoutMs + ) logger.info(f"Received response: {res}") if res.networkingStatus != Clusters.NetworkCommissioning.Enums.NetworkCommissioningStatus.kSuccess: raise AssertionError(f"Unexpected result: {res.networkingStatus}") await self.must_verify_breadcrumb() # Arm the failsafe before making network config changes - logger.info(f"Arming the failsafe") + logger.info("Arming the failsafe") req = Clusters.GeneralCommissioning.Commands.ArmFailSafe(expiryLengthSeconds=900) res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=endpointId, payload=req) logger.info(f"Received response: {res}") # Remove existing network - logger.info(f"Check network list") - res = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[(endpointId, Clusters.NetworkCommissioning.Attributes.Networks)], returnClusterObject=True) + logger.info("Check network list") + res = await self._devCtrl.ReadAttribute( + nodeid=self._nodeid, + attributes=[(endpointId, Clusters.NetworkCommissioning.Attributes.Networks)], + returnClusterObject=True + ) networkList = res[endpointId][Clusters.NetworkCommissioning].networks logger.info(f"Got network list: {networkList}") if len(networkList) != 0: - logger.info(f"Removing existing network") + logger.info("Removing existing network") req = Clusters.NetworkCommissioning.Commands.RemoveNetwork( networkID=networkList[0].networkID, breadcrumb=self.with_breadcrumb()) res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=endpointId, payload=req) @@ -172,7 +190,7 @@ async def test_wifi(self, endpointId): await self.must_verify_breadcrumb() # Add first network - logger.info(f"Adding first test network") + logger.info("Adding first test network") req = Clusters.NetworkCommissioning.Commands.AddOrUpdateWiFiNetwork( ssid=TEST_WIFI_SSID.encode(), credentials=TEST_WIFI_PASS.encode(), breadcrumb=self.with_breadcrumb()) res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=endpointId, payload=req) @@ -184,8 +202,12 @@ async def test_wifi(self, endpointId): f"Unexpected result: {res.networkIndex} (should be 0)") await self.must_verify_breadcrumb() - logger.info(f"Check network list") - res = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[(endpointId, Clusters.NetworkCommissioning.Attributes.Networks)], returnClusterObject=True) + logger.info("Check network list") + res = await self._devCtrl.ReadAttribute( + nodeid=self._nodeid, + attributes=[(endpointId, Clusters.NetworkCommissioning.Attributes.Networks)], + returnClusterObject=True + ) networkList = res[endpointId][Clusters.NetworkCommissioning].networks logger.info(f"Got network list: {networkList}") if len(networkList) != 1: @@ -195,28 +217,38 @@ async def test_wifi(self, endpointId): raise AssertionError( f"Unexpected result: first network ID should be 'TestSSID' got {networkList[0].networkID}") - logger.info(f"Connect to a network") + logger.info("Connect to a network") req = Clusters.NetworkCommissioning.Commands.ConnectNetwork( networkID=TEST_WIFI_SSID.encode(), breadcrumb=self.with_breadcrumb()) interactionTimeoutMs = self._devCtrl.ComputeRoundTripTimeout(self._nodeid, upperLayerProcessingTimeoutMs=30000) - res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=endpointId, payload=req, interactionTimeoutMs=interactionTimeoutMs) + res = await self._devCtrl.SendCommand( + nodeid=self._nodeid, + endpoint=endpointId, + payload=req, + interactionTimeoutMs=interactionTimeoutMs + ) logger.info(f"Got response: {res}") if res.networkingStatus != Clusters.NetworkCommissioning.Enums.NetworkCommissioningStatus.kSuccess: raise AssertionError(f"Unexpected result: {res.networkingStatus}") - logger.info(f"Device connected to a network.") + logger.info("Device connected to a network.") await self.must_verify_breadcrumb() # Disarm the failsafe - logger.info(f"Disarming the failsafe") + logger.info("Disarming the failsafe") req = Clusters.GeneralCommissioning.Commands.CommissioningComplete() res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=endpointId, payload=req) logger.info(f"Received response: {res}") - # Note: On Linux, when connecting to a connected network, it will return immediately, however, it will try a reconnect. This will make the below attribute read return false negative values. + # Note: On Linux, when connecting to a connected network, it will return immediately, however, it will try a reconnect. + # This will make the below attribute read return false negative values. await asyncio.sleep(5) - logger.info(f"Check network is connected") - res = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[(endpointId, Clusters.NetworkCommissioning.Attributes.Networks)], returnClusterObject=True) + logger.info("Check network is connected") + res = await self._devCtrl.ReadAttribute( + nodeid=self._nodeid, + attributes=[(endpointId, Clusters.NetworkCommissioning.Attributes.Networks)], + returnClusterObject=True + ) networkList = res[endpointId][Clusters.NetworkCommissioning].networks logger.info(f"Got network list: {networkList}") if len(networkList) != 1: @@ -227,17 +259,18 @@ async def test_wifi(self, endpointId): f"Unexpected result: first network ID should be 'TestSSID' got {networkList[0].networkID}") if not networkList[0].connected: raise AssertionError( - f"Unexpected result: network is not marked as connected") + "Unexpected result: network is not marked as connected") # Verify Last* attributes - logger.info(f"Read Last* attributes") + logger.info("Read Last* attributes") res = await self.readLastNetworkingStateAttributes(endpointId=endpointId) if (res.lastNetworkID == NullValue) or (res.lastNetworkingStatus == NullValue) or (res.lastConnectErrorValue != NullValue): raise AssertionError( - f"LastNetworkID, LastNetworkingStatus should not be Null, LastConnectErrorValue should be Null for a successful network provision.") + "LastNetworkID, LastNetworkingStatus should not be Null, " + "LastConnectErrorValue should be Null for a successful network provision.") async def test_thread(self, endpointId): - logger.info(f"Get basic information of the endpoint") + logger.info("Get basic information of the endpoint") res = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[ (endpointId, Clusters.NetworkCommissioning.Attributes.ConnectMaxTimeSeconds), @@ -257,47 +290,54 @@ async def test_thread(self, endpointId): Clusters.NetworkCommissioning.Commands.RemoveNetwork.command_id, Clusters.NetworkCommissioning.Commands.ConnectNetwork.command_id, Clusters.NetworkCommissioning.Commands.ReorderNetwork.command_id]: - raise AssertionError(f"Unexpected accepted command list for Thread interface") + raise AssertionError("Unexpected accepted command list for Thread interface") if res[endpointId][Clusters.NetworkCommissioning].generatedCommandList != [ Clusters.NetworkCommissioning.Commands.ScanNetworksResponse.command_id, Clusters.NetworkCommissioning.Commands.NetworkConfigResponse.command_id, Clusters.NetworkCommissioning.Commands.ConnectNetworkResponse.command_id]: - raise AssertionError(f"Unexpected generated command list for Thread interface") + raise AssertionError("Unexpected generated command list for Thread interface") - logger.info(f"Finished getting basic information of the endpoint") + logger.info("Finished getting basic information of the endpoint") # Read Last* attributes - logger.info(f"Read Last* attributes") + logger.info("Read Last* attributes") res = await self.readLastNetworkingStateAttributes(endpointId=endpointId) if (res.lastNetworkID != NullValue) or (res.lastNetworkingStatus != NullValue) or (res.lastConnectErrorValue != NullValue): raise AssertionError( - f"LastNetworkID, LastNetworkingStatus and LastConnectErrorValue should be Null") + "LastNetworkID, LastNetworkingStatus and LastConnectErrorValue should be Null") # Scan networks - logger.info(f"Scan networks") + logger.info("Scan networks") req = Clusters.NetworkCommissioning.Commands.ScanNetworks( ssid=b'', breadcrumb=self.with_breadcrumb()) interactionTimeoutMs = self._devCtrl.ComputeRoundTripTimeout(self._nodeid, upperLayerProcessingTimeoutMs=30000) - res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=endpointId, payload=req, interactionTimeoutMs=interactionTimeoutMs) + res = await self._devCtrl.SendCommand(nodeid=self._nodeid, + endpoint=endpointId, + payload=req, + interactionTimeoutMs=interactionTimeoutMs) logger.info(f"Received response: {res}") if res.networkingStatus != Clusters.NetworkCommissioning.Enums.NetworkCommissioningStatus.kSuccess: raise AssertionError(f"Unexpected result: {res.networkingStatus}") await self.must_verify_breadcrumb() # Arm the failsafe before making network config changes - logger.info(f"Arming the failsafe") + logger.info("Arming the failsafe") req = Clusters.GeneralCommissioning.Commands.ArmFailSafe(expiryLengthSeconds=900) res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=endpointId, payload=req) logger.info(f"Received response: {res}") # Remove existing network - logger.info(f"Check network list") - res = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[(endpointId, Clusters.NetworkCommissioning.Attributes.Networks)], returnClusterObject=True) + logger.info("Check network list") + res = await self._devCtrl.ReadAttribute( + nodeid=self._nodeid, + attributes=[(endpointId, Clusters.NetworkCommissioning.Attributes.Networks)], + returnClusterObject=True + ) networkList = res[endpointId][Clusters.NetworkCommissioning].networks logger.info(f"Got network list: {networkList}") if len(networkList) != 0: - logger.info(f"Removing existing network") + logger.info("Removing existing network") req = Clusters.NetworkCommissioning.Commands.RemoveNetwork( networkID=networkList[0].networkID, breadcrumb=self.with_breadcrumb()) res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=endpointId, payload=req) @@ -308,7 +348,7 @@ async def test_thread(self, endpointId): await self.must_verify_breadcrumb() # Add first network - logger.info(f"Adding first test network") + logger.info("Adding first test network") req = Clusters.NetworkCommissioning.Commands.AddOrUpdateThreadNetwork( operationalDataset=TEST_THREAD_NETWORK_DATASET_TLVS[0], breadcrumb=self.with_breadcrumb()) res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=endpointId, payload=req) @@ -320,8 +360,12 @@ async def test_thread(self, endpointId): f"Unexpected result: {res.networkIndex} (should be 0)") await self.must_verify_breadcrumb() - logger.info(f"Check network list") - res = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[(endpointId, Clusters.NetworkCommissioning.Attributes.Networks)], returnClusterObject=True) + logger.info("Check network list") + res = await self._devCtrl.ReadAttribute( + nodeid=self._nodeid, + attributes=[(endpointId, Clusters.NetworkCommissioning.Attributes.Networks)], + returnClusterObject=True + ) networkList = res[endpointId][Clusters.NetworkCommissioning].networks logger.info(f"Got network list: {networkList}") if len(networkList) != 1: @@ -331,32 +375,40 @@ async def test_thread(self, endpointId): raise AssertionError( f"Unexpected result: first network ID should be {TEST_THREAD_NETWORK_IDS[0]} got {networkList[0].networkID}") - logger.info(f"Connect to a network") + logger.info("Connect to a network") req = Clusters.NetworkCommissioning.Commands.ConnectNetwork( networkID=TEST_THREAD_NETWORK_IDS[0], breadcrumb=self.with_breadcrumb()) interactionTimeoutMs = self._devCtrl.ComputeRoundTripTimeout(self._nodeid, upperLayerProcessingTimeoutMs=30000) - res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=endpointId, payload=req, interactionTimeoutMs=interactionTimeoutMs) + res = await self._devCtrl.SendCommand(nodeid=self._nodeid, + endpoint=endpointId, + payload=req, + interactionTimeoutMs=interactionTimeoutMs) logger.info(f"Got response: {res}") if res.networkingStatus != Clusters.NetworkCommissioning.Enums.NetworkCommissioningStatus.kSuccess: raise AssertionError(f"Unexpected result: {res.networkingStatus}") - logger.info(f"Device connected to a network.") + logger.info("Device connected to a network.") await self.must_verify_breadcrumb() # Disarm the failsafe - logger.info(f"Disarming the failsafe") + logger.info("Disarming the failsafe") req = Clusters.GeneralCommissioning.Commands.CommissioningComplete() res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=endpointId, payload=req) logger.info(f"Received response: {res}") # Verify Last* attributes - logger.info(f"Read Last* attributes") + logger.info("Read Last* attributes") res = await self.readLastNetworkingStateAttributes(endpointId=endpointId) if (res.lastNetworkID == NullValue) or (res.lastNetworkingStatus == NullValue) or (res.lastConnectErrorValue != NullValue): raise AssertionError( - f"LastNetworkID, LastNetworkingStatus should not be Null, LastConnectErrorValue should be Null for a successful network provision.") - - logger.info(f"Check network list") - res = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[(endpointId, Clusters.NetworkCommissioning.Attributes.Networks)], returnClusterObject=True) + "LastNetworkID, LastNetworkingStatus should not be Null, " + "LastConnectErrorValue should be Null for a successful network provision.") + + logger.info("Check network list") + res = await self._devCtrl.ReadAttribute( + nodeid=self._nodeid, + attributes=[(endpointId, Clusters.NetworkCommissioning.Attributes.Networks)], + returnClusterObject=True + ) networkList = res[endpointId][Clusters.NetworkCommissioning].networks logger.info(f"Got network list: {networkList}") if len(networkList) != 1: @@ -367,16 +419,24 @@ async def test_thread(self, endpointId): f"Unexpected result: first network ID should be {TEST_THREAD_NETWORK_IDS[0]} got {networkList[0].networkID}") if not networkList[0].connected: raise AssertionError( - f"Unexpected result: network is not marked as connected") + "Unexpected result: network is not marked as connected") @base.test_case async def Test(self): - clusters = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[(Clusters.Descriptor.Attributes.ServerList)], returnClusterObject=True) + clusters = await self._devCtrl.ReadAttribute( + nodeid=self._nodeid, + attributes=[(Clusters.Descriptor.Attributes.ServerList)], + returnClusterObject=True + ) if Clusters.NetworkCommissioning.id not in clusters[0][Clusters.Descriptor].serverList: logger.info( - f"Network commissioning cluster {endpoint} is not enabled on this device.") + "Network commissioning cluster is not enabled on this device.") return - endpoints = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[(Clusters.NetworkCommissioning.Attributes.FeatureMap)], returnClusterObject=True) + endpoints = await self._devCtrl.ReadAttribute( + nodeid=self._nodeid, + attributes=[(Clusters.NetworkCommissioning.Attributes.FeatureMap)], + returnClusterObject=True + ) logger.info(endpoints) for endpoint, obj in endpoints.items(): clus = obj[Clusters.NetworkCommissioning] @@ -398,5 +458,5 @@ async def run(self): try: await self.Test() return True - except Exception as ex: + except Exception: return False diff --git a/src/controller/python/test/unit_tests/test_cluster_objects.py b/src/controller/python/test/unit_tests/test_cluster_objects.py index 926bc0f32d1b99..13b12db185270e 100644 --- a/src/controller/python/test/unit_tests/test_cluster_objects.py +++ b/src/controller/python/test/unit_tests/test_cluster_objects.py @@ -27,7 +27,9 @@ def _encode_attribute_and_then_decode_to_native(data, type: ClusterObjects.Clust return TLVReader(type.ToTLV(None, data)).get()['Any'] -def _encode_from_native_and_then_decode(data, cls: typing.Union[ClusterObjects.ClusterObject, ClusterObjects.ClusterAttributeDescriptor]): +def _encode_from_native_and_then_decode(data, + cls: typing.Union[ClusterObjects.ClusterObject, + ClusterObjects.ClusterAttributeDescriptor]): tlv = TLVWriter() tlv.put(None, data) return cls.FromTLV(bytes(tlv.encoding)) diff --git a/src/controller/python/test/unit_tests/test_tlv.py b/src/controller/python/test/unit_tests/test_tlv.py index ad37b53c190a69..74d7aefe0f07cc 100644 --- a/src/controller/python/test/unit_tests/test_tlv.py +++ b/src/controller/python/test/unit_tests/test_tlv.py @@ -149,9 +149,11 @@ def test_uint(self): def test_structure(self): test_cases = [ - (b'\x15\x36\x01\x15\x35\x01\x26\x00\xBF\xA2\x55\x16\x37\x01\x24\x02\x00\x24\x03\x28\x24\x04\x00\x18\x24\x02\x01\x18\x18\x18\x18', + (b'\x15\x36\x01\x15\x35\x01\x26\x00\xBF\xA2\x55\x16\x37\x01\x24' + b'\x02\x00\x24\x03\x28\x24\x04\x00\x18\x24\x02\x01\x18\x18\x18\x18', {1: [{1: {0: 374710975, 1: [0, 40, 0], 2: 1}}]}), - (b'\x156\x01\x155\x01&\x00\xBF\xA2U\x167\x01$\x02\x00$\x03($\x04\x01\x18,\x02\x18Nordic Semiconductor ASA\x18\x18\x18\x18', + (b'\x156\x01\x155\x01&\x00\xBF\xA2U\x167\x01$\x02\x00$\x03($\x04\x01' + b'\x18,\x02\x18Nordic Semiconductor ASA\x18\x18\x18\x18', {1: [{1: {0: 374710975, 1: [0, 40, 1], 2: 'Nordic Semiconductor ASA'}}]}), (b"\0256\001\0255\001&\000\031\346x\2077\001$\002\001$\003\006$\004\000\030(\002\030\030\030\030", {1: [{1: {0: 2272847385, 1: [1, 6, 0], 2: False}}]}) diff --git a/src/python_testing/TC_ACE_1_3.py b/src/python_testing/TC_ACE_1_3.py index dd3639d7c0b476..2d81b78230fe5f 100644 --- a/src/python_testing/TC_ACE_1_3.py +++ b/src/python_testing/TC_ACE_1_3.py @@ -18,7 +18,7 @@ import logging import chip.clusters as Clusters -from chip.interaction_model import InteractionModelError, Status +from chip.interaction_model import Status from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main from mobly import asserts @@ -43,7 +43,8 @@ async def read_descriptor_expect_success(self, th): async def read_descriptor_expect_unsupported_access(self, th): cluster = Clusters.Objects.Descriptor attribute = Clusters.Descriptor.Attributes.DeviceTypeList - await self.read_single_attribute_expect_error(dev_ctrl=th, endpoint=0, cluster=cluster, attribute=attribute, error=Status.UnsupportedAccess) + await self.read_single_attribute_expect_error( + dev_ctrl=th, endpoint=0, cluster=cluster, attribute=attribute, error=Status.UnsupportedAccess) @async_test_body async def test_TC_ACE_1_3(self): @@ -60,6 +61,8 @@ async def test_TC_ACE_1_3(self): self.print_step(1, "Commissioning, already done") TH0 = self.default_controller + # _ = TH0 Hack for flake8 F841 local variable 'TH0' is assigned to but never used + _ = TH0 fabric_admin = self.certificate_authority_manager.activeCaList[0].adminList[0] TH0_nodeid = self.matter_test_config.controller_node_id @@ -78,14 +81,16 @@ async def test_TC_ACE_1_3(self): catTags=[cat1v1, cat2v2]) self.print_step(2, "TH0 writes ACL all view on PIXIT.ACE.TESTENDPOINT") - TH0_admin_acl = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[TH0_nodeid], - targets=[Clusters.AccessControl.Structs.Target(endpoint=0, cluster=0x001f)]) - all_view = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[], - targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) + TH0_admin_acl = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[TH0_nodeid], + targets=[Clusters.AccessControl.Structs.Target(endpoint=0, cluster=0x001f)]) + all_view = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[], + targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) acl = [TH0_admin_acl, all_view] await self.write_acl(acl) @@ -99,10 +104,11 @@ async def test_TC_ACE_1_3(self): await self.read_descriptor_expect_success(TH3) self.print_step(6, "TH0 writes ACL TH1 view on EP0") - th1_view = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[TH1_nodeid], - targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) + th1_view = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[TH1_nodeid], + targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) acl = [TH0_admin_acl, th1_view] await self.write_acl(acl) self.print_step(7, "TH1 reads EP0 descriptor - expect SUCCESS") @@ -115,10 +121,11 @@ async def test_TC_ACE_1_3(self): await self.read_descriptor_expect_unsupported_access(TH3) self.print_step(10, "TH0 writes ACL TH2 view on EP0") - th2_view = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[TH2_nodeid], - targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) + th2_view = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[TH2_nodeid], + targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) acl = [TH0_admin_acl, th2_view] await self.write_acl(acl) @@ -132,10 +139,11 @@ async def test_TC_ACE_1_3(self): await self.read_descriptor_expect_unsupported_access(TH3) self.print_step(14, "TH0 writes ACL TH3 view on EP0") - th3_view = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[TH3_nodeid], - targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) + th3_view = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[TH3_nodeid], + targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) acl = [TH0_admin_acl, th3_view] await self.write_acl(acl) @@ -149,10 +157,11 @@ async def test_TC_ACE_1_3(self): await self.read_descriptor_expect_success(TH3) self.print_step(18, "TH0 writes ACL TH1 TH2 view on EP0") - th12_view = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[TH1_nodeid, TH2_nodeid], - targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) + th12_view = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[TH1_nodeid, TH2_nodeid], + targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) acl = [TH0_admin_acl, th12_view] await self.write_acl(acl) @@ -166,10 +175,11 @@ async def test_TC_ACE_1_3(self): await self.read_descriptor_expect_unsupported_access(TH3) self.print_step(22, "TH0 writes ACL TH1 TH3 view on EP0") - th13_view = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[TH1_nodeid, TH3_nodeid], - targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) + th13_view = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[TH1_nodeid, TH3_nodeid], + targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) acl = [TH0_admin_acl, th13_view] await self.write_acl(acl) @@ -183,10 +193,11 @@ async def test_TC_ACE_1_3(self): await self.read_descriptor_expect_success(TH3) self.print_step(26, "TH0 writes ACL TH2 TH3 view on EP0") - th23_view = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[TH2_nodeid, TH3_nodeid], - targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) + th23_view = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[TH2_nodeid, TH3_nodeid], + targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) acl = [TH0_admin_acl, th23_view] await self.write_acl(acl) @@ -200,10 +211,11 @@ async def test_TC_ACE_1_3(self): await self.read_descriptor_expect_success(TH3) self.print_step(30, "TH0 writes ACL TH1 TH2 TH3 view on EP0") - th123_view = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[TH1_nodeid, TH2_nodeid, TH3_nodeid], - targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) + th123_view = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[TH1_nodeid, TH2_nodeid, TH3_nodeid], + targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) acl = [TH0_admin_acl, th123_view] await self.write_acl(acl) @@ -217,10 +229,11 @@ async def test_TC_ACE_1_3(self): await self.read_descriptor_expect_success(TH3) self.print_step(34, "TH0 writes ACL cat1v1 view on EP0") - cat1v1_view = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[acl_subject(cat1v1)], - targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) + cat1v1_view = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[acl_subject(cat1v1)], + targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) acl = [TH0_admin_acl, cat1v1_view] await self.write_acl(acl) @@ -234,10 +247,11 @@ async def test_TC_ACE_1_3(self): await self.read_descriptor_expect_success(TH3) self.print_step(38, "TH0 writes ACL cat1v2 view on EP0") - cat1v2_view = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[acl_subject(cat1v2)], - targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) + cat1v2_view = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[acl_subject(cat1v2)], + targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) acl = [TH0_admin_acl, cat1v2_view] await self.write_acl(acl) @@ -252,10 +266,11 @@ async def test_TC_ACE_1_3(self): await self.read_descriptor_expect_unsupported_access(TH3) self.print_step(42, "TH0 writes ACL cat1v3 view on EP0") - cat1v3_view = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[acl_subject(cat1v3)], - targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) + cat1v3_view = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[acl_subject(cat1v3)], + targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) acl = [TH0_admin_acl, cat1v3_view] await self.write_acl(acl) @@ -270,10 +285,11 @@ async def test_TC_ACE_1_3(self): await self.read_descriptor_expect_unsupported_access(TH3) self.print_step(46, "TH0 writes ACL cat2v1 view on EP0") - cat2v1_view = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[acl_subject(cat2v1)], - targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) + cat2v1_view = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[acl_subject(cat2v1)], + targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) acl = [TH0_admin_acl, cat2v1_view] await self.write_acl(acl) @@ -288,10 +304,11 @@ async def test_TC_ACE_1_3(self): await self.read_descriptor_expect_success(TH3) self.print_step(50, "TH0 writes ACL cat2v2 view on EP0") - cat2v2_view = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[acl_subject(cat2v2)], - targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) + cat2v2_view = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[acl_subject(cat2v2)], + targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) acl = [TH0_admin_acl, cat2v2_view] await self.write_acl(acl) @@ -306,10 +323,11 @@ async def test_TC_ACE_1_3(self): await self.read_descriptor_expect_success(TH3) self.print_step(54, "TH0 writes ACL cat2v3 view on EP0") - cat2v3_view = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[acl_subject(cat2v3)], - targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) + cat2v3_view = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[acl_subject(cat2v3)], + targets=[Clusters.AccessControl.Structs.Target(endpoint=0)]) acl = [TH0_admin_acl, cat2v3_view] await self.write_acl(acl) diff --git a/src/python_testing/TC_ACE_1_4.py b/src/python_testing/TC_ACE_1_4.py index c7e179ef2300ab..8091ee38926b32 100644 --- a/src/python_testing/TC_ACE_1_4.py +++ b/src/python_testing/TC_ACE_1_4.py @@ -15,12 +15,10 @@ # limitations under the License. # -import logging import sys import chip.clusters as Clusters -import chip.clusters.Objects -from chip.interaction_model import InteractionModelError, Status +from chip.interaction_model import Status from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main from mobly import asserts @@ -53,13 +51,15 @@ async def read_descriptor_expect_success(self, endpoint: int) -> None: async def read_descriptor_expect_unsupported_access(self, endpoint: int) -> None: cluster = Clusters.Objects.Descriptor attribute = Clusters.Descriptor.Attributes.DeviceTypeList - await self.read_single_attribute_expect_error(endpoint=endpoint, cluster=cluster, attribute=attribute, error=Status.UnsupportedAccess) + await self.read_single_attribute_expect_error( + endpoint=endpoint, cluster=cluster, attribute=attribute, error=Status.UnsupportedAccess) async def read_appcluster_expect_success(self) -> None: await self.read_single_attribute_check_success(endpoint=self.endpoint, cluster=self.cluster, attribute=self.attribute) async def read_appcluster_expect_unsupported_access(self) -> None: - await self.read_single_attribute_expect_error(endpoint=self.endpoint, cluster=self.cluster, attribute=self.attribute, error=Status.UnsupportedAccess) + await self.read_single_attribute_expect_error( + endpoint=self.endpoint, cluster=self.cluster, attribute=self.attribute, error=Status.UnsupportedAccess) async def read_wildcard_endpoint(self, attribute: object) -> object: return await self.default_controller.ReadAttribute(self.dut_node_id, [(attribute)]) @@ -80,13 +80,17 @@ def check_read_success(self, results: object, endpoint: int, cluster: object, at async def test_TC_ACE_1_4(self): # TODO: Guard these on the PICS asserts.assert_true('PIXIT.ACE.APPENDPOINT' in self.matter_test_config.global_test_params, - "PIXIT.ACE.APPENDPOINT must be included on the command line in the --int-arg flag as PIXIT.ACE.APPENDPOINT:") + "PIXIT.ACE.APPENDPOINT must be included on the command line in " + "the --int-arg flag as PIXIT.ACE.APPENDPOINT:") asserts.assert_true('PIXIT.ACE.APPCLUSTER' in self.matter_test_config.global_test_params, - "PIXIT.ACE.APPCLUSTER must be included on the command line in the --string-arg flag as PIXIT.ACE.APPCLUSTER:") + "PIXIT.ACE.APPCLUSTER must be included on the command line in " + "the --string-arg flag as PIXIT.ACE.APPCLUSTER:") asserts.assert_true('PIXIT.ACE.APPATTRIBUTE' in self.matter_test_config.global_test_params, - "PIXIT.ACE.APPATTRIBUTE must be included on the command line in the --string-arg flag as PIXIT.ACE.APPATTRIBUTE:") + "PIXIT.ACE.APPATTRIBUTE must be included on the command line in " + "the --string-arg flag as PIXIT.ACE.APPATTRIBUTE:") asserts.assert_true('PIXIT.ACE.APPDEVTYPEID' in self.matter_test_config.global_test_params, - "PIXIT.ACE.APPDEVTYPEID must be included on the command line in the --int-arg flag as PIXIT.ACE.APPDEVTYPEID:") + "PIXIT.ACE.APPDEVTYPEID must be included on the command line in " + "the --int-arg flag as PIXIT.ACE.APPDEVTYPEID:") cluster_str = self.matter_test_config.global_test_params['PIXIT.ACE.APPCLUSTER'] attribute_str = self.matter_test_config.global_test_params['PIXIT.ACE.APPATTRIBUTE'] @@ -102,14 +106,16 @@ async def test_TC_ACE_1_4(self): self.print_step(1, "Commissioning, already done") self.print_step(2, "TH1 writes ACL all clusters view on all endpoints") - admin_acl = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[], - targets=[Clusters.AccessControl.Structs.Target(endpoint=0, cluster=Clusters.AccessControl.id)]) - all_view = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=[], - targets=[]) + admin_acl = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[], + targets=[Clusters.AccessControl.Structs.Target(endpoint=0, cluster=Clusters.AccessControl.id)]) + all_view = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=[], + targets=[]) acl = [admin_acl, all_view] await self.write_acl(acl) diff --git a/src/python_testing/TC_CGEN_2_4.py b/src/python_testing/TC_CGEN_2_4.py index ae9f912798b6a2..9240caff0e1afe 100644 --- a/src/python_testing/TC_CGEN_2_4.py +++ b/src/python_testing/TC_CGEN_2_4.py @@ -15,19 +15,13 @@ # limitations under the License. # -import asyncio import logging -import queue import time -from threading import Event import chip.CertificateAuthority import chip.clusters as Clusters import chip.FabricAdmin from chip import ChipDeviceCtrl -from chip.clusters.Attribute import SubscriptionTransaction, TypedAttributePath -from chip.interaction_model import InteractionModelError -from chip.utils import CommissioningBuildingBlocks from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main from mobly import asserts @@ -45,15 +39,18 @@ def OpenCommissioningWindow(self) -> int: logging.exception('Error running OpenCommissioningWindow %s', e) asserts.assert_true(False, 'Failed to open commissioning window') - async def CommissionToStageSendCompleteAndCleanup(self, stage: int, expectedErrorPart: chip.native.ErrorSDKPart, expectedErrCode: int): + async def CommissionToStageSendCompleteAndCleanup( + self, stage: int, expectedErrorPart: chip.native.ErrorSDKPart, expectedErrCode: int): logging.info("-----------------Fail on step {}-------------------------".format(stage)) pin, code = self.OpenCommissioningWindow() self.th2.ResetTestCommissioner() - # This will run the commissioning up to the point where stage x is run and the response is sent before the test commissioner simulates a failure + # This will run the commissioning up to the point where stage x is run and the + # response is sent before the test commissioner simulates a failure self.th2.SetTestCommissionerPrematureCompleteAfter(stage) success, errcode = self.th2.CommissionOnNetwork( - nodeId=self.dut_node_id, setupPinCode=pin, filterType=ChipDeviceCtrl.DiscoveryFilterType.LONG_DISCRIMINATOR, filter=self.matter_test_config.discriminator) + nodeId=self.dut_node_id, setupPinCode=pin, + filterType=ChipDeviceCtrl.DiscoveryFilterType.LONG_DISCRIMINATOR, filter=self.matter_test_config.discriminator) logging.info('Commissioning complete done. Successful? {}, errorcode = {}'.format(success, errcode)) asserts.assert_false(success, 'Commissioning complete did not error as expected') asserts.assert_true(errcode.sdk_part == expectedErrorPart, 'Unexpected error type returned from CommissioningComplete') @@ -92,7 +89,8 @@ async def test_TC_CGEN_2_4(self): logging.info('Step 16 - TH2 fully commissions the DUT') self.th2.ResetTestCommissioner() success, errcode = self.th2.CommissionOnNetwork( - nodeId=self.dut_node_id, setupPinCode=pin, filterType=ChipDeviceCtrl.DiscoveryFilterType.LONG_DISCRIMINATOR, filter=self.matter_test_config.discriminator) + nodeId=self.dut_node_id, setupPinCode=pin, + filterType=ChipDeviceCtrl.DiscoveryFilterType.LONG_DISCRIMINATOR, filter=self.matter_test_config.discriminator) logging.info('Commissioning complete done. Successful? {}, errorcode = {}'.format(success, errcode)) logging.info('Step 17 - TH1 sends an arm failsafe') @@ -109,11 +107,15 @@ async def test_TC_CGEN_2_4(self): newloc = Clusters.GeneralCommissioning.Enums.RegulatoryLocationType.kIndoor else: # TODO: figure out how to use the extender - #newloc = MatterIntEnum.extend_enum_if_value_doesnt_exist(Clusters.GeneralCommissioning.Enums.RegulatoryLocationType, 3) - newlog = cap + # newloc = MatterIntEnum.extend_enum_if_value_doesnt_exist( + # Clusters.GeneralCommissioning.Enums.RegulatoryLocationType, 3) + newloc = cap + + _ = newloc logging.info('Step 19 Send SetRgulatoryConfig with incorrect location') - #cmd = Clusters.GeneralCommissioning.Commands.SetRegulatoryConfig(newRegulatoryConfig=newloc, countryCode="XX", breadcrumb=0) + # cmd = Clusters.GeneralCommissioning.Commands.SetRegulatoryConfig( + # newRegulatoryConfig=newloc, countryCode="XX", breadcrumb=0) # try: # await self.th1.SendCommand(nodeid=self.dut_node_id, endpoint=0, payload=cmd) # except InteractionModelError as ex: diff --git a/src/python_testing/TC_DA_1_7.py b/src/python_testing/TC_DA_1_7.py index b16faccbd339bc..4b4dd66aa65866 100644 --- a/src/python_testing/TC_DA_1_7.py +++ b/src/python_testing/TC_DA_1_7.py @@ -21,7 +21,6 @@ from typing import Optional import chip.clusters as Clusters -from chip.interaction_model import Status from cryptography.exceptions import InvalidSignature from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import ec @@ -79,13 +78,15 @@ async def test_TC_DA_1_7(self): dev_ctrl = self.default_controller logging.info("Step 2: Get PAI of DUT1 with certificate chain request") - result = await dev_ctrl.SendCommand(self.dut_node_id, 0, Clusters.OperationalCredentials.Commands.CertificateChainRequest(2)) + result = await dev_ctrl.SendCommand(self.dut_node_id, 0, + Clusters.OperationalCredentials.Commands.CertificateChainRequest(2)) pai_1 = result.certificate asserts.assert_less_equal(len(pai_1), 600, "PAI cert must be at most 600 bytes") self.record_data({"pai_1": hex_from_bytes(pai_1)}) logging.info("Step 3: Get DAC of DUT1 with certificate chain request") - result = await dev_ctrl.SendCommand(self.dut_node_id, 0, Clusters.OperationalCredentials.Commands.CertificateChainRequest(1)) + result = await dev_ctrl.SendCommand(self.dut_node_id, 0, + Clusters.OperationalCredentials.Commands.CertificateChainRequest(1)) dac_1 = result.certificate asserts.assert_less_equal(len(dac_1), 600, "DAC cert must be at most 600 bytes") self.record_data({"dac_1": hex_from_bytes(dac_1)}) diff --git a/src/python_testing/TC_RR_1_1.py b/src/python_testing/TC_RR_1_1.py index 754b9dbf62a819..4a42498eb0146c 100644 --- a/src/python_testing/TC_RR_1_1.py +++ b/src/python_testing/TC_RR_1_1.py @@ -21,16 +21,9 @@ import queue import random import time -from binascii import hexlify -from threading import Event from typing import Any, Dict, List, Set -import chip.CertificateAuthority import chip.clusters as Clusters -import chip.FabricAdmin -from chip import ChipDeviceCtrl -from chip.clusters.Attribute import AttributeStatus, SubscriptionTransaction, TypedAttributePath -from chip.clusters.Types import NullValue from chip.interaction_model import Status as StatusEnum from chip.utils import CommissioningBuildingBlocks from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main @@ -113,7 +106,10 @@ async def test_TC_RR_1_1(self): # TODO: Shall we also verify SupportedFabrics attribute, and the CapabilityMinima attribute? logging.info("Pre-conditions: validate CapabilityMinima.CaseSessionsPerFabric >= 3") - capability_minima = await self.read_single_attribute(dev_ctrl, node_id=self.dut_node_id, endpoint=0, attribute=Clusters.BasicInformation.Attributes.CapabilityMinima) + capability_minima = await self.read_single_attribute(dev_ctrl, + node_id=self.dut_node_id, + endpoint=0, + attribute=Clusters.BasicInformation.Attributes.CapabilityMinima) asserts.assert_greater_equal(capability_minima.caseSessionsPerFabric, 3) # Step 1: Commission 5 fabrics with maximized NOC chains. 1a and 1b have already been completed at this time. @@ -127,13 +123,21 @@ async def test_TC_RR_1_1(self): client_list.append(dev_ctrl) if num_controllers_per_fabric > 1: - new_controllers = await CommissioningBuildingBlocks.CreateControllersOnFabric(fabricAdmin=dev_ctrl.fabricAdmin, adminDevCtrl=dev_ctrl, controllerNodeIds=node_ids, privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, targetNodeId=self.dut_node_id, catTags=[0x0001_0001]) + new_controllers = await CommissioningBuildingBlocks.CreateControllersOnFabric( + fabricAdmin=dev_ctrl.fabricAdmin, + adminDevCtrl=dev_ctrl, + controllerNodeIds=node_ids, + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, + targetNodeId=self.dut_node_id, catTags=[0x0001_0001] + ) for controller in new_controllers: controller.name = all_names.pop(0) client_list.extend(new_controllers) # Step 1c - Ensure there are no leftover fabrics from another process. - commissioned_fabric_count: int = await self.read_single_attribute(dev_ctrl, node_id=self.dut_node_id, endpoint=0, attribute=Clusters.OperationalCredentials.Attributes.CommissionedFabrics) + commissioned_fabric_count: int = await self.read_single_attribute( + dev_ctrl, node_id=self.dut_node_id, + endpoint=0, attribute=Clusters.OperationalCredentials.Attributes.CommissionedFabrics) # Insert a fabric to self-test the next step. # This is not hidden behind a flag to avoid potential undetected bugs. @@ -144,23 +148,32 @@ async def test_TC_RR_1_1(self): new_admin_ctrl = new_fabric_admin.NewController(nodeId=dev_ctrl.nodeId, catTags=[0x0001_0001]) new_admin_ctrl.name = "THTF" - await CommissioningBuildingBlocks.AddNOCForNewFabricFromExisting(commissionerDevCtrl=dev_ctrl, newFabricDevCtrl=new_admin_ctrl, existingNodeId=self.dut_node_id, newNodeId=self.dut_node_id) + await CommissioningBuildingBlocks.AddNOCForNewFabricFromExisting( + commissionerDevCtrl=dev_ctrl, newFabricDevCtrl=new_admin_ctrl, + existingNodeId=self.dut_node_id, newNodeId=self.dut_node_id) - commissioned_fabric_count = await self.read_single_attribute(dev_ctrl, node_id=self.dut_node_id, endpoint=0, attribute=Clusters.OperationalCredentials.Attributes.CommissionedFabrics) + commissioned_fabric_count = await self.read_single_attribute( + dev_ctrl, node_id=self.dut_node_id, + endpoint=0, attribute=Clusters.OperationalCredentials.Attributes.CommissionedFabrics) asserts.assert_not_equal(commissioned_fabric_count, 1, "TH Error: failed to add fabric for testing TH.") # Step 1c - perform removal. if commissioned_fabric_count > 1: logging.info("Removing extra fabrics from device.") - fabrics: List[Clusters.OperationalCredentials.Structs.FabricDescriptorStruct] = await self.read_single_attribute(dev_ctrl, node_id=self.dut_node_id, endpoint=0, attribute=Clusters.OperationalCredentials.Attributes.Fabrics, fabricFiltered=False) + fabrics: List[Clusters.OperationalCredentials.Structs.FabricDescriptorStruct] = await self.read_single_attribute( + dev_ctrl, node_id=self.dut_node_id, endpoint=0, + attribute=Clusters.OperationalCredentials.Attributes.Fabrics, fabricFiltered=False) for fabric in fabrics: if fabric.fabricID == dev_ctrl.fabricId: continue # This is not the initial client's fabric, so remove it. - await dev_ctrl.SendCommand(self.dut_node_id, 0, Clusters.OperationalCredentials.Commands.RemoveFabric(fabricIndex=fabric.fabricIndex)) + await dev_ctrl.SendCommand( + self.dut_node_id, 0, Clusters.OperationalCredentials.Commands.RemoveFabric(fabricIndex=fabric.fabricIndex)) - commissioned_fabric_count = await self.read_single_attribute(dev_ctrl, node_id=self.dut_node_id, endpoint=0, attribute=Clusters.OperationalCredentials.Attributes.CommissionedFabrics) + commissioned_fabric_count = await self.read_single_attribute( + dev_ctrl, node_id=self.dut_node_id, + endpoint=0, attribute=Clusters.OperationalCredentials.Attributes.CommissionedFabrics) asserts.assert_equal(commissioned_fabric_count, 1, "Failed to remove extra fabrics from DUT.") # Prepare clients for subsequent fabrics (step 1d) @@ -173,11 +186,20 @@ async def test_TC_RR_1_1(self): new_admin_ctrl = new_fabric_admin.NewController(nodeId=dev_ctrl.nodeId, catTags=[0x0001_0001]) new_admin_ctrl.name = all_names.pop(0) client_list.append(new_admin_ctrl) - await CommissioningBuildingBlocks.AddNOCForNewFabricFromExisting(commissionerDevCtrl=dev_ctrl, newFabricDevCtrl=new_admin_ctrl, existingNodeId=self.dut_node_id, newNodeId=self.dut_node_id) + await CommissioningBuildingBlocks.AddNOCForNewFabricFromExisting(commissionerDevCtrl=dev_ctrl, + newFabricDevCtrl=new_admin_ctrl, + existingNodeId=self.dut_node_id, + newNodeId=self.dut_node_id) if num_controllers_per_fabric > 1: - new_controllers = await CommissioningBuildingBlocks.CreateControllersOnFabric(fabricAdmin=new_fabric_admin, adminDevCtrl=new_admin_ctrl, - controllerNodeIds=node_ids, privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, targetNodeId=self.dut_node_id, catTags=[0x0001_0001]) + new_controllers = await CommissioningBuildingBlocks.CreateControllersOnFabric( + fabricAdmin=new_fabric_admin, + adminDevCtrl=new_admin_ctrl, + controllerNodeIds=node_ids, + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, + targetNodeId=self.dut_node_id, + catTags=[0x0001_0001] + ) for controller in new_controllers: controller.name = all_names.pop(0) @@ -186,10 +208,14 @@ async def test_TC_RR_1_1(self): asserts.assert_equal(len(client_list), num_fabrics_to_commission * num_controllers_per_fabric, "Must have the right number of clients") - commissioned_fabric_count = await self.read_single_attribute(dev_ctrl, node_id=self.dut_node_id, endpoint=0, attribute=Clusters.OperationalCredentials.Attributes.CommissionedFabrics) + commissioned_fabric_count = await self.read_single_attribute( + dev_ctrl, node_id=self.dut_node_id, + endpoint=0, attribute=Clusters.OperationalCredentials.Attributes.CommissionedFabrics) asserts.assert_equal(commissioned_fabric_count, num_fabrics_to_commission, "Must have the right number of fabrics commissioned.") - fabric_table: List[Clusters.OperationalCredentials.Structs.FabricDescriptorStruct] = await self.read_single_attribute(dev_ctrl, node_id=self.dut_node_id, endpoint=0, attribute=Clusters.OperationalCredentials.Attributes.Fabrics, fabricFiltered=False) + fabric_table: List[Clusters.OperationalCredentials.Structs.FabricDescriptorStruct] = await self.read_single_attribute( + dev_ctrl, node_id=self.dut_node_id, + endpoint=0, attribute=Clusters.OperationalCredentials.Attributes.Fabrics, fabricFiltered=False) client_by_name = {client.name: client for client in client_list} local_session_id_by_client_name = {client.name: client.GetConnectedDeviceSync( @@ -211,15 +237,22 @@ async def test_TC_RR_1_1(self): await client.SendCommand(self.dut_node_id, 0, Clusters.OperationalCredentials.Commands.UpdateFabricLabel(label)) # Read back - fabric_metadata = await self.read_single_attribute(client, node_id=self.dut_node_id, endpoint=0, attribute=Clusters.OperationalCredentials.Attributes.Fabrics) + fabric_metadata = await self.read_single_attribute(client, + node_id=self.dut_node_id, + endpoint=0, + attribute=Clusters.OperationalCredentials.Attributes.Fabrics) print(fabric_metadata) asserts.assert_equal(fabric_metadata[0].label, label, "Fabrics[x].label must match what was written") # Before subscribing, set the NodeLabel to "Before Subscriptions" logging.info(f"Step 2b: Set BasicInformation.NodeLabel to {BEFORE_LABEL}") - await client_list[0].WriteAttribute(self.dut_node_id, [(0, Clusters.BasicInformation.Attributes.NodeLabel(value=BEFORE_LABEL))]) + await client_list[0].WriteAttribute(self.dut_node_id, + [(0, Clusters.BasicInformation.Attributes.NodeLabel(value=BEFORE_LABEL))]) - node_label = await self.read_single_attribute(client, node_id=self.dut_node_id, endpoint=0, attribute=Clusters.BasicInformation.Attributes.NodeLabel) + node_label = await self.read_single_attribute(client, + node_id=self.dut_node_id, + endpoint=0, + attribute=Clusters.BasicInformation.Attributes.NodeLabel) asserts.assert_equal(node_label, BEFORE_LABEL, "NodeLabel must match what was written") # Step 3: Add 4 Access Control entries on DUT with a list of 4 Subjects and 3 Targets with the following parameters (...) @@ -236,7 +269,8 @@ async def test_TC_RR_1_1(self): await client.WriteAttribute(self.dut_node_id, [(0, Clusters.AccessControl.Attributes.Acl(acl))]) logging.info(f"Step 3b: Validating ACL entry for fabric {fabric.fabricIndex}") - acl_readback = await self.read_single_attribute(client, node_id=self.dut_node_id, endpoint=0, attribute=Clusters.AccessControl.Attributes.Acl) + acl_readback = await self.read_single_attribute( + client, node_id=self.dut_node_id, endpoint=0, attribute=Clusters.AccessControl.Attributes.Acl) fabric_index = 9999 for entry in acl_readback: asserts.assert_equal(entry.fabricIndex, fabric.fabricIndex, "Fabric Index of response entries must match") @@ -264,8 +298,12 @@ async def test_TC_RR_1_1(self): for sub_idx, client in enumerate(client_list): logging.info("Establishing subscription %d/%d from controller node %s" % (sub_idx + 1, len(client_list), client.name)) - sub = await client.ReadAttribute(nodeid=self.dut_node_id, attributes=subscription_contents, - reportInterval=(min_report_interval_sec, max_report_interval_sec), keepSubscriptions=False) + sub = await client.ReadAttribute( + nodeid=self.dut_node_id, + attributes=subscription_contents, + reportInterval=(min_report_interval_sec, max_report_interval_sec), + keepSubscriptions=False + ) self._subscriptions.append(sub) attribute_handler = AttributeChangeAccumulator( @@ -308,7 +346,8 @@ async def test_TC_RR_1_1(self): logging.info( "Step 7: Change attribute with one client, await all attributes changed successfully without loss of subscriptions") await asyncio.sleep(1) - await client_list[0].WriteAttribute(self.dut_node_id, [(0, Clusters.BasicInformation.Attributes.NodeLabel(value=AFTER_LABEL))]) + await client_list[0].WriteAttribute(self.dut_node_id, + [(0, Clusters.BasicInformation.Attributes.NodeLabel(value=AFTER_LABEL))]) all_changes = {client.name: False for client in client_list} @@ -366,11 +405,16 @@ async def test_TC_RR_1_1(self): for sub_idx, client in enumerate(client_list): logging.info("Reading NodeLabel (%d/%d) from controller node %s" % (sub_idx + 1, len(client_list), client.name)) - label_readback = await self.read_single_attribute(client, node_id=self.dut_node_id, endpoint=0, attribute=Clusters.BasicInformation.Attributes.NodeLabel) + label_readback = await self.read_single_attribute(client, + node_id=self.dut_node_id, + endpoint=0, + attribute=Clusters.BasicInformation.Attributes.NodeLabel) asserts.assert_equal(label_readback, AFTER_LABEL) - # On each client, read back the local session id for the CASE session to the DUT and ensure it's the same as that of the session established right at the - # beginning of the test. In tandem with checking that the number of sessions to the DUT is exactly one, this ensures we have not established any new CASE + # On each client, read back the local session id for the CASE session to the DUT and ensure + # it's the same as that of the session established right at the beginning of the test. + # In tandem with checking that the number of sessions to the DUT is exactly one, + # this ensures we have not established any new CASE # sessions in this test. if check_local_session_id_unchanged: logging.info("Step 8b: Validate that the local CASE session ID hasn't changed") @@ -383,7 +427,8 @@ async def test_TC_RR_1_1(self): if (beginning_session_id != end_session_id): logging.error( - f"Test ended with a different session ID created from what we had before for {client.name} (total sessions = {total_sessions})") + f"Test ended with a different session ID created from what we had before for {client.name} " + f"(total sessions = {total_sessions})") num_failed_clients = num_failed_clients + 1 elif (total_sessions != 1): logging.error(f"Test ended with more than 1 session for {client.name}") @@ -406,20 +451,22 @@ async def test_TC_RR_1_1(self): # The test for Step 10 and all of Steps 11 to 14 are only performed if Groups cluster instances are found. if counted_groups_clusters > 0: - indicated_max_groups_per_fabric: int = await self.read_single_attribute(dev_ctrl, - node_id=self.dut_node_id, - endpoint=0, - attribute=Clusters.GroupKeyManagement.Attributes.MaxGroupsPerFabric) + indicated_max_groups_per_fabric: int = await self.read_single_attribute( + dev_ctrl, + node_id=self.dut_node_id, + endpoint=0, + attribute=Clusters.GroupKeyManagement.Attributes.MaxGroupsPerFabric) if indicated_max_groups_per_fabric < 4 * counted_groups_clusters: - asserts.fail(f"Failed Step 10: MaxGroupsPerFabric < 4 * counted_groups_clusters") + asserts.fail("Failed Step 10: MaxGroupsPerFabric < 4 * counted_groups_clusters") # Step 11: Confirm MaxGroupKeysPerFabric meets the minimum requirement of 3. - indicated_max_group_keys_per_fabric: int = await self.read_single_attribute(dev_ctrl, - node_id=self.dut_node_id, - endpoint=0, - attribute=Clusters.GroupKeyManagement.Attributes.MaxGroupKeysPerFabric) + indicated_max_group_keys_per_fabric: int = await self.read_single_attribute( + dev_ctrl, + node_id=self.dut_node_id, + endpoint=0, + attribute=Clusters.GroupKeyManagement.Attributes.MaxGroupKeysPerFabric) if indicated_max_group_keys_per_fabric < 3: - asserts.fail(f"Failed Step 11: MaxGroupKeysPerFabric < 3") + asserts.fail("Failed Step 11: MaxGroupKeysPerFabric < 3") # Create a list of per-fabric clients to use for filling group resources accross all fabrics. fabric_unique_clients: List[Any] = [] @@ -431,7 +478,8 @@ async def test_TC_RR_1_1(self): fabric_unique_clients.append(client_by_name[client_name]) # Step 12: Write and verify indicated_max_group_keys_per_fabric group keys to all fabrics. - group_keys: List[List[Clusters.GroupKeyManagement.Structs.GroupKeySetStruct]] = await self.fill_and_validate_group_key_sets( + group_keys: List[List[ + Clusters.GroupKeyManagement.Structs.GroupKeySetStruct]] = await self.fill_and_validate_group_key_sets( num_fabrics_to_commission, fabric_unique_clients, indicated_max_group_keys_per_fabric) # Step 13: Write and verify indicated_max_groups_per_fabric group/key mappings for all fabrics. @@ -443,11 +491,14 @@ async def test_TC_RR_1_1(self): group_key_idx: int = group_idx % len(group_keys[fabric_list_idx]) group_key_map[fabric_list_idx][group_id] = group_keys[fabric_list_idx][group_key_idx].groupKeySetID - await self.fill_and_validate_group_key_map(num_fabrics_to_commission, fabric_unique_clients, group_key_map, fabric_table) + await self.fill_and_validate_group_key_map( + num_fabrics_to_commission, fabric_unique_clients, group_key_map, fabric_table) # Step 14: Add all the groups to the discovered groups-supporting endpoints and verify GroupTable - group_table_written: List[Dict[int, Clusters.GroupKeyManagement.Structs.GroupInfoMapStruct]] = await self.add_all_groups( - num_fabrics_to_commission, fabric_unique_clients, group_key_map, groups_cluster_endpoints, indicated_max_groups_per_fabric, fabric_table) + group_table_written: List[ + Dict[int, Clusters.GroupKeyManagement.Structs.GroupInfoMapStruct]] = await self.add_all_groups( + num_fabrics_to_commission, fabric_unique_clients, group_key_map, + groups_cluster_endpoints, indicated_max_groups_per_fabric, fabric_table) await self.validate_group_table(num_fabrics_to_commission, fabric_unique_clients, group_table_written, fabric_table) # Read heap watermarks after the test @@ -476,11 +527,15 @@ async def fill_user_label_list(self, dev_ctrl, target_node_id): for cluster in clusters: if cluster == Clusters.UserLabel: logging.info("Step 9a: Filling UserLabel cluster on endpoint %d" % endpoint_id) - statuses = await dev_ctrl.WriteAttribute(target_node_id, [(endpoint_id, Clusters.UserLabel.Attributes.LabelList(labels))]) + statuses = await dev_ctrl.WriteAttribute(target_node_id, + [(endpoint_id, Clusters.UserLabel.Attributes.LabelList(labels))]) asserts.assert_equal(statuses[0].Status, StatusEnum.Success, "Label write must succeed") logging.info("Step 9b: Validate UserLabel cluster contents after write on endpoint %d" % endpoint_id) - read_back_labels = await self.read_single_attribute(dev_ctrl, node_id=target_node_id, endpoint=endpoint_id, attribute=Clusters.UserLabel.Attributes.LabelList) + read_back_labels = await self.read_single_attribute(dev_ctrl, + node_id=target_node_id, + endpoint=endpoint_id, + attribute=Clusters.UserLabel.Attributes.LabelList) print(read_back_labels) asserts.assert_equal(read_back_labels, labels, "LabelList attribute must match what was written") @@ -488,7 +543,8 @@ async def fill_user_label_list(self, dev_ctrl, target_node_id): async def fill_and_validate_group_key_sets(self, fabrics: int, clients: List[Any], - keys_per_fabric: int) -> List[List[Clusters.GroupKeyManagement.Structs.GroupKeySetStruct]]: + keys_per_fabric: int) -> List[List[ + Clusters.GroupKeyManagement.Structs.GroupKeySetStruct]]: # Step 12: Write indicated_max_group_keys_per_fabric group keys to all fabrics. group_keys: List[List[Clusters.GroupKeyManagement.Structs.GroupKeySetStruct]] = [[] for _ in range(fabrics)] for client_idx in range(fabrics): @@ -500,7 +556,8 @@ async def fill_and_validate_group_key_sets(self, logging.info("Step 12: Setting group key on fabric %d at index '%d'" % (client_idx+1, group_key_cluster_idx)) group_keys[client_idx].append(self.build_group_key(client_idx, group_key_cluster_idx, keys_per_fabric)) - await client.SendCommand(self.dut_node_id, 0, Clusters.GroupKeyManagement.Commands.KeySetWrite(group_keys[client_idx][group_key_list_idx])) + await client.SendCommand(self.dut_node_id, 0, Clusters.GroupKeyManagement.Commands.KeySetWrite( + group_keys[client_idx][group_key_list_idx])) # Step 12 verification: After all the key sets were written, read all the information back. for client_idx in range(fabrics): @@ -516,7 +573,8 @@ async def fill_and_validate_group_key_sets(self, ipk_group_key_id: Set[int] = set(read_group_key_ids) - set(known_group_key_ids) asserts.assert_equal(keys_per_fabric, len(read_group_key_ids), - "KeySetReadAllIndicesResponse length does not match the key support indicated: %d." % (keys_per_fabric)) + "KeySetReadAllIndicesResponse length does " + "not match the key support indicated: %d." % (keys_per_fabric)) asserts.assert_equal(len(ipk_group_key_id), 1, "Read more than 1 key ID that did not match written values after IPK (only expected 1 for IPK).") @@ -527,7 +585,8 @@ async def fill_and_validate_group_key_map(self, fabrics: int, clients: List[Any], group_key_map: List[Dict[int, int]], - fabric_table: List[Clusters.OperationalCredentials.Structs.FabricDescriptorStruct]) -> None: + fabric_table: List[ + Clusters.OperationalCredentials.Structs.FabricDescriptorStruct]) -> None: # Step 13: Write and verify indicated_max_groups_per_fabric group/key mappings for all fabrics. mapping_structs: List[List[Clusters.GroupKeyManagement.Structs.GroupKeyMapStruct]] = [[] for _ in range(fabrics)] for client_idx in range(fabrics): @@ -535,12 +594,14 @@ async def fill_and_validate_group_key_map(self, fabric_idx: int = fabric_table[client_idx].fabricIndex for group in group_key_map[client_idx]: - mapping_structs[client_idx].append(Clusters.GroupKeyManagement.Structs.GroupKeyMapStruct(groupId=group, - groupKeySetID=group_key_map[client_idx][group], - fabricIndex=fabric_idx)) + mapping_structs[client_idx].append(Clusters.GroupKeyManagement.Structs.GroupKeyMapStruct( + groupId=group, + groupKeySetID=group_key_map[client_idx][group], + fabricIndex=fabric_idx)) logging.info("Step 13: Setting group key map on fabric %d" % (fabric_idx)) - await client.WriteAttribute(self.dut_node_id, [(0, Clusters.GroupKeyManagement.Attributes.GroupKeyMap(mapping_structs[client_idx]))]) + await client.WriteAttribute( + self.dut_node_id, [(0, Clusters.GroupKeyManagement.Attributes.GroupKeyMap(mapping_structs[client_idx]))]) # Step 13 verification: After all the group key maps were written, read all the information back. for client_idx in range(fabrics): @@ -548,7 +609,8 @@ async def fill_and_validate_group_key_map(self, fabric_idx: int = fabric_table[client_idx].fabricIndex logging.info("Step 13: Reading group key map on fabric %d" % (fabric_idx)) - group_key_map_readback = await self.read_single_attribute(client, node_id=self.dut_node_id, endpoint=0, attribute=Clusters.GroupKeyManagement.Attributes.GroupKeyMap) + group_key_map_readback = await self.read_single_attribute( + client, node_id=self.dut_node_id, endpoint=0, attribute=Clusters.GroupKeyManagement.Attributes.GroupKeyMap) found_entry: int = 0 for read_entry in group_key_map_readback: @@ -570,7 +632,9 @@ async def add_all_groups(self, group_key_map: List[Dict[int, int]], group_endpoints: Dict[int, Any], groups_per_fabric: int, - fabric_table: List[Clusters.OperationalCredentials.Structs.FabricDescriptorStruct]) -> List[Dict[int, Clusters.GroupKeyManagement.Structs.GroupInfoMapStruct]]: + fabric_table: List[ + Clusters.OperationalCredentials.Structs.FabricDescriptorStruct]) -> List[ + Dict[int, Clusters.GroupKeyManagement.Structs.GroupInfoMapStruct]]: # Step 14: Add indicated_max_groups_per_fabric to each fabric through the Groups clusters on supporting endpoints. written_group_table_map: List[Dict[int, Clusters.GroupKeyManagement.Structs.GroupInfoMapStruct]] = [ {} for _ in range(fabrics)] @@ -598,12 +662,13 @@ async def add_all_groups(self, group_name: str = self.random_string(16) if name_supported else "" command: Clusters.Groups.Commands.AddGroup = Clusters.Groups.Commands.AddGroup( groupID=group_id, groupName=group_name) - written_group_table_map[client_idx][group_id] = Clusters.GroupKeyManagement.Structs.GroupInfoMapStruct(groupId=group_id, - groupName=group_name, - fabricIndex=fabric_idx, - endpoints=[endpoint_id]) - add_response: Clusters.Groups.Commands.AddGroupResponse = await client.SendCommand(self.dut_node_id, endpoint_id, command, - responseType=Clusters.Groups.Commands.AddGroupResponse) + written_group_table_map[client_idx][group_id] = Clusters.GroupKeyManagement.Structs.GroupInfoMapStruct( + groupId=group_id, + groupName=group_name, + fabricIndex=fabric_idx, + endpoints=[endpoint_id]) + add_response: Clusters.Groups.Commands.AddGroupResponse = await client.SendCommand( + self.dut_node_id, endpoint_id, command, responseType=Clusters.Groups.Commands.AddGroupResponse) asserts.assert_equal(StatusEnum.Success, add_response.status) asserts.assert_equal(group_id, add_response.groupID) @@ -650,22 +715,34 @@ def build_acl(self): # - Privilege field: Administer (5) # - AuthMode field: CASE (2) # - Subjects field: [0xFFFF_FFFD_0001_0001, 0x2000_0000_0000_0001, 0x2000_0000_0000_0002, 0x2000_0000_0000_0003] - # - Targets field: [{Endpoint: 0}, {Cluster: 0xFFF1_FC00, DeviceType: 0xFFF1_FC30}, {Cluster: 0xFFF1_FC00, DeviceType: 0xFFF1_FC31}] + # - Targets field: [ + # {Endpoint: 0}, + # {Cluster: 0xFFF1_FC00, DeviceType: 0xFFF1_FC30}, + # {Cluster: 0xFFF1_FC00, DeviceType: 0xFFF1_FC31} + # ] # . struct # - Privilege field: Manage (4) # - AuthMode field: CASE (2) # - Subjects field: [0x1000_0000_0000_0001, 0x1000_0000_0000_0002, 0x1000_0000_0000_0003, 0x1000_0000_0000_0004] - # - Targets field: [{Cluster: 0xFFF1_FC00, DeviceType: 0xFFF1_FC20}, {Cluster: 0xFFF1_FC01, DeviceType: 0xFFF1_FC21}, {Cluster: 0xFFF1_FC02, DeviceType: 0xFFF1_FC22}] + # - Targets field: [ + # {Cluster: 0xFFF1_FC00, DeviceType: 0xFFF1_FC20}, + # {Cluster: 0xFFF1_FC01, DeviceType: 0xFFF1_FC21}, + # {Cluster: 0xFFF1_FC02, DeviceType: 0xFFF1_FC22} + # ] # . struct # - Privilege field: Operate (3) # - AuthMode field: CASE (2) # - Subjects field: [0x3000_0000_0000_0001, 0x3000_0000_0000_0002, 0x3000_0000_0000_0003, 0x3000_0000_0000_0004] - # - Targets field: [{Cluster: 0xFFF1_FC40, DeviceType: 0xFFF1_FC20}, {Cluster: 0xFFF1_FC41, DeviceType: 0xFFF1_FC21}, {Cluster: 0xFFF1_FC02, DeviceType: 0xFFF1_FC42}] + # - Targets field: [{Cluster: 0xFFF1_FC40, DeviceType: 0xFFF1_FC20}, + # {Cluster: 0xFFF1_FC41, DeviceType: 0xFFF1_FC21}, + # {Cluster: 0xFFF1_FC02, DeviceType: 0xFFF1_FC42}] # . struct # - Privilege field: View (1) # - AuthMode field: CASE (2) # - Subjects field: [0x4000_0000_0000_0001, 0x4000_0000_0000_0002, 0x4000_0000_0000_0003, 0x4000_0000_0000_0004] - # - Targets field: [{Cluster: 0xFFF1_FC80, DeviceType: 0xFFF1_FC20}, {Cluster: 0xFFF1_FC81, DeviceType: 0xFFF1_FC21}, {Cluster: 0xFFF1_FC82, DeviceType: 0xFFF1_FC22}] + # - Targets field: [{Cluster: 0xFFF1_FC80, DeviceType: 0xFFF1_FC20}, + # {Cluster: 0xFFF1_FC81, DeviceType: 0xFFF1_FC21}, + # {Cluster: 0xFFF1_FC82, DeviceType: 0xFFF1_FC22}] # Administer ACL entry admin_subjects = [0xFFFF_FFFD_0001_0001, 0x2000_0000_0000_0001, 0x2000_0000_0000_0002, 0x2000_0000_0000_0003] @@ -675,10 +752,12 @@ def build_acl(self): Clusters.AccessControl.Structs.Target(cluster=0xFFF1_FC00, deviceType=0xFFF1_BC30), Clusters.AccessControl.Structs.Target(cluster=0xFFF1_FC01, deviceType=0xFFF1_BC31) ] - admin_acl_entry = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=admin_subjects, - targets=admin_targets) + admin_acl_entry = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=admin_subjects, + targets=admin_targets + ) acl.append(admin_acl_entry) # Manage ACL entry @@ -689,10 +768,12 @@ def build_acl(self): Clusters.AccessControl.Structs.Target(cluster=0xFFF1_FC02, deviceType=0xFFF1_BC22) ] - manage_acl_entry = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kManage, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=manage_subjects, - targets=manage_targets) + manage_acl_entry = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kManage, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=manage_subjects, + targets=manage_targets + ) acl.append(manage_acl_entry) # Operate ACL entry @@ -703,10 +784,12 @@ def build_acl(self): Clusters.AccessControl.Structs.Target(cluster=0xFFF1_FC42, deviceType=0xFFF1_BC42) ] - operate_acl_entry = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kOperate, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=operate_subjects, - targets=operate_targets) + operate_acl_entry = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kOperate, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=operate_subjects, + targets=operate_targets + ) acl.append(operate_acl_entry) # View ACL entry @@ -717,15 +800,17 @@ def build_acl(self): Clusters.AccessControl.Structs.Target(cluster=0xFFF1_FC82, deviceType=0xFFF1_BC22) ] - view_acl_entry = Clusters.AccessControl.Structs.AccessControlEntryStruct(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, - authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, - subjects=view_subjects, - targets=view_targets) + view_acl_entry = Clusters.AccessControl.Structs.AccessControlEntryStruct( + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, + authMode=Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase, + subjects=view_subjects, + targets=view_targets) acl.append(view_acl_entry) return acl - def build_group_key(self, fabric_index: int, group_key_index: int, keys_per_fabric: int) -> Clusters.GroupKeyManagement.Structs.GroupKeySetStruct: + def build_group_key(self, fabric_index: int, + group_key_index: int, keys_per_fabric: int) -> Clusters.GroupKeyManagement.Structs.GroupKeySetStruct: asserts.assert_not_equal(group_key_index, 0, "TH Internal Error: IPK key set index (0) should not be re-generated.") # groupKeySetID is definted as uint16 in the Matter specification. @@ -735,14 +820,15 @@ def build_group_key(self, fabric_index: int, group_key_index: int, keys_per_fabr set_id: int = fabric_index*keys_per_fabric + group_key_index asserts.assert_less_equal( set_id, 0xFFFF, "Invalid Key Set ID. This may be a limitation of the test harness, not the device under test.") - return Clusters.GroupKeyManagement.Structs.GroupKeySetStruct(groupKeySetID=set_id, - groupKeySecurityPolicy=Clusters.GroupKeyManagement.Enums.GroupKeySecurityPolicyEnum.kTrustFirst, - epochKey0=self.random_string(16).encode(), - epochStartTime0=(set_id * 4), - epochKey1=self.random_string(16).encode(), - epochStartTime1=(set_id * 4 + 1), - epochKey2=self.random_string(16).encode(), - epochStartTime2=(set_id * 4 + 2)) + return Clusters.GroupKeyManagement.Structs.GroupKeySetStruct( + groupKeySetID=set_id, + groupKeySecurityPolicy=Clusters.GroupKeyManagement.Enums.GroupKeySecurityPolicyEnum.kTrustFirst, + epochKey0=self.random_string(16).encode(), + epochStartTime0=(set_id * 4), + epochKey1=self.random_string(16).encode(), + epochStartTime1=(set_id * 4 + 1), + epochKey2=self.random_string(16).encode(), + epochStartTime2=(set_id * 4 + 2)) async def read_heap_statistics(self, dev_ctrl): diagnostics_contents = [ @@ -759,8 +845,10 @@ async def read_heap_statistics(self, dev_ctrl): for attribute in diagnostics_contents: asserts.assert_true(attribute in swdiag_info[0][Clusters.SoftwareDiagnostics], "Must have read back attribute %s" % (attribute.__name__)) - high_watermark = swdiag_info[0][Clusters.SoftwareDiagnostics][Clusters.SoftwareDiagnostics.Attributes.CurrentHeapHighWatermark] - current_usage = swdiag_info[0][Clusters.SoftwareDiagnostics][Clusters.SoftwareDiagnostics.Attributes.CurrentHeapUsed] + high_watermark = swdiag_info[0][Clusters.SoftwareDiagnostics][ + Clusters.SoftwareDiagnostics.Attributes.CurrentHeapHighWatermark] + current_usage = swdiag_info[0][Clusters.SoftwareDiagnostics][ + Clusters.SoftwareDiagnostics.Attributes.CurrentHeapUsed] return high_watermark, current_usage diff --git a/src/python_testing/TC_SC_3_6.py b/src/python_testing/TC_SC_3_6.py index 55d34baffee24b..a6994cbf288539 100644 --- a/src/python_testing/TC_SC_3_6.py +++ b/src/python_testing/TC_SC_3_6.py @@ -21,9 +21,8 @@ import time from threading import Event -import chip.CertificateAuthority import chip.clusters as Clusters -import chip.FabricAdmin +from chip.clusters import ClusterObjects as ClustersObjects from chip.clusters.Attribute import SubscriptionTransaction, TypedAttributePath from chip.utils import CommissioningBuildingBlocks from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main @@ -36,7 +35,7 @@ class AttributeChangeAccumulator: - def __init__(self, name: str, expected_attribute: Clusters.ClusterAttributeDescriptor, output: queue.Queue): + def __init__(self, name: str, expected_attribute: ClustersObjects.ClusterAttributeDescriptor, output: queue.Queue): self._name = name self._output = output self._expected_attribute = expected_attribute @@ -116,7 +115,12 @@ async def test_TC_SC_3_6(self): logging.info("Pre-conditions: validate CapabilityMinima.CaseSessionsPerFabric >= 3") - capability_minima = await self.read_single_attribute(dev_ctrl, node_id=self.dut_node_id, endpoint=0, attribute=Clusters.BasicInformation.Attributes.CapabilityMinima) + capability_minima = await self.read_single_attribute( + dev_ctrl, + node_id=self.dut_node_id, + endpoint=0, + attribute=Clusters.BasicInformation.Attributes.CapabilityMinima + ) asserts.assert_greater_equal(capability_minima.caseSessionsPerFabric, 3) logging.info("Pre-conditions: use existing fabric to configure new fabrics so that total is %d fabrics" % @@ -130,7 +134,13 @@ async def test_TC_SC_3_6(self): client_list.append(dev_ctrl) if num_controllers_per_fabric > 1: - new_controllers = await CommissioningBuildingBlocks.CreateControllersOnFabric(fabricAdmin=dev_ctrl.fabricAdmin, adminDevCtrl=dev_ctrl, controllerNodeIds=node_ids, privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, targetNodeId=self.dut_node_id) + new_controllers = await CommissioningBuildingBlocks.CreateControllersOnFabric( + fabricAdmin=dev_ctrl.fabricAdmin, + adminDevCtrl=dev_ctrl, + controllerNodeIds=node_ids, + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, + targetNodeId=self.dut_node_id + ) for controller in new_controllers: controller.name = all_names.pop(0) client_list.extend(new_controllers) @@ -144,11 +154,21 @@ async def test_TC_SC_3_6(self): new_admin_ctrl = new_fabric_admin.NewController(nodeId=dev_ctrl.nodeId) new_admin_ctrl.name = all_names.pop(0) client_list.append(new_admin_ctrl) - await CommissioningBuildingBlocks.AddNOCForNewFabricFromExisting(commissionerDevCtrl=dev_ctrl, newFabricDevCtrl=new_admin_ctrl, existingNodeId=self.dut_node_id, newNodeId=self.dut_node_id) + await CommissioningBuildingBlocks.AddNOCForNewFabricFromExisting( + commissionerDevCtrl=dev_ctrl, + newFabricDevCtrl=new_admin_ctrl, + existingNodeId=self.dut_node_id, + newNodeId=self.dut_node_id + ) if num_controllers_per_fabric > 1: - new_controllers = await CommissioningBuildingBlocks.CreateControllersOnFabric(fabricAdmin=new_fabric_admin, adminDevCtrl=new_admin_ctrl, - controllerNodeIds=node_ids, privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, targetNodeId=self.dut_node_id) + new_controllers = await CommissioningBuildingBlocks.CreateControllersOnFabric( + fabricAdmin=new_fabric_admin, + adminDevCtrl=new_admin_ctrl, + controllerNodeIds=node_ids, + privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister, + targetNodeId=self.dut_node_id + ) for controller in new_controllers: controller.name = all_names.pop(0) @@ -159,7 +179,8 @@ async def test_TC_SC_3_6(self): # Before subscribing, set the NodeLabel to "Before Subscriptions" logging.info("Pre-conditions: writing initial value of NodeLabel, so that we can control for change of attribute detection") - await client_list[0].WriteAttribute(self.dut_node_id, [(0, Clusters.BasicInformation.Attributes.NodeLabel(value=BEFORE_LABEL))]) + await client_list[0].WriteAttribute(self.dut_node_id, + [(0, Clusters.BasicInformation.Attributes.NodeLabel(value=BEFORE_LABEL))]) # Subscribe with all clients to NodeLabel attribute sub_handlers = [] @@ -170,8 +191,12 @@ async def test_TC_SC_3_6(self): for sub_idx, client in enumerate(client_list): logging.info("Establishing subscription %d/%d from controller node %s" % (sub_idx + 1, len(client_list), client.name)) - sub = await client.ReadAttribute(nodeid=self.dut_node_id, attributes=[(0, Clusters.BasicInformation.Attributes.NodeLabel)], - reportInterval=(min_report_interval_sec, max_report_interval_sec), keepSubscriptions=False) + sub = await client.ReadAttribute( + nodeid=self.dut_node_id, + attributes=[(0, Clusters.BasicInformation.Attributes.NodeLabel)], + reportInterval=(min_report_interval_sec, max_report_interval_sec), + keepSubscriptions=False + ) self._subscriptions.append(sub) attribute_handler = AttributeChangeAccumulator( @@ -190,7 +215,8 @@ async def test_TC_SC_3_6(self): logging.info( "Step 1 (second part): Change attribute with one client, await all attributes changed within time") await asyncio.sleep(1) - await client_list[0].WriteAttribute(self.dut_node_id, [(0, Clusters.BasicInformation.Attributes.NodeLabel(value=AFTER_LABEL))]) + await client_list[0].WriteAttribute(self.dut_node_id, + [(0, Clusters.BasicInformation.Attributes.NodeLabel(value=AFTER_LABEL))]) all_changes = {client.name: False for client in client_list} diff --git a/src/python_testing/TC_TestEventTrigger.py b/src/python_testing/TC_TestEventTrigger.py index 495baa72aae7d0..a27e2f78760879 100644 --- a/src/python_testing/TC_TestEventTrigger.py +++ b/src/python_testing/TC_TestEventTrigger.py @@ -15,11 +15,8 @@ # limitations under the License. # -import logging -from imaplib import Commands - import chip.clusters as Clusters -from chip.interaction_model import InteractionModelError, Status +from chip.interaction_model import InteractionModelError from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main from mobly import asserts @@ -40,35 +37,78 @@ class TestEventTrigger(MatterBaseTest): @async_test_body async def test_all_zeros_key(self): dev_ctrl = self.default_controller - with asserts.assert_raises_regex(InteractionModelError, "ConstraintError", "All-zero TestEventTrigger key must return ConstraintError"): - await dev_ctrl.SendCommand(self.dut_node_id, endpoint=0, payload=Clusters.GeneralDiagnostics.Commands.TestEventTrigger(enableKey=kAllZerosKey, eventTrigger=kValidEventTrigger)) + with asserts.assert_raises_regex(InteractionModelError, + "ConstraintError", "All-zero TestEventTrigger key must return ConstraintError"): + await dev_ctrl.SendCommand( + self.dut_node_id, + endpoint=0, + payload=Clusters.GeneralDiagnostics.Commands.TestEventTrigger(enableKey=kAllZerosKey, + eventTrigger=kValidEventTrigger) + ) @async_test_body async def test_incorrect_key(self): dev_ctrl = self.default_controller - test_event_triggers_enabled = await self.read_single_attribute(dev_ctrl, self.dut_node_id, endpoint=0, attribute=Clusters.GeneralDiagnostics.Attributes.TestEventTriggersEnabled) + test_event_triggers_enabled = await self.read_single_attribute( + dev_ctrl, + self.dut_node_id, + endpoint=0, + attribute=Clusters.GeneralDiagnostics.Attributes.TestEventTriggersEnabled + ) asserts.assert_true(test_event_triggers_enabled, "This test expects Test Event Triggers are Enabled") - with asserts.assert_raises_regex(InteractionModelError, "ConstraintError", "Bad TestEventTrigger key must return ConstraintError"): - await dev_ctrl.SendCommand(self.dut_node_id, endpoint=0, payload=Clusters.GeneralDiagnostics.Commands.TestEventTrigger(enableKey=kBadKey, eventTrigger=kValidEventTrigger)) + with asserts.assert_raises_regex(InteractionModelError, + "ConstraintError", "Bad TestEventTrigger key must return ConstraintError"): + await dev_ctrl.SendCommand( + self.dut_node_id, + endpoint=0, + payload=Clusters.GeneralDiagnostics.Commands.TestEventTrigger(enableKey=kBadKey, + eventTrigger=kValidEventTrigger) + ) @async_test_body async def test_correct_key_valid_code(self): dev_ctrl = self.default_controller - test_event_triggers_enabled = await self.read_single_attribute(dev_ctrl, self.dut_node_id, endpoint=0, attribute=Clusters.GeneralDiagnostics.Attributes.TestEventTriggersEnabled) + test_event_triggers_enabled = await self.read_single_attribute( + dev_ctrl, + self.dut_node_id, + endpoint=0, + attribute=Clusters.GeneralDiagnostics.Attributes.TestEventTriggersEnabled + ) asserts.assert_true(test_event_triggers_enabled, "This test expects Test Event Triggers are Enabled") # No response to command --> Success yields "None". - asserts.assert_is_none(await dev_ctrl.SendCommand(self.dut_node_id, endpoint=0, payload=Clusters.GeneralDiagnostics.Commands.TestEventTrigger(enableKey=kExpectedKey, eventTrigger=kValidEventTrigger))) + asserts.assert_is_none( + await dev_ctrl.SendCommand( + self.dut_node_id, + endpoint=0, + payload=Clusters.GeneralDiagnostics.Commands.TestEventTrigger(enableKey=kExpectedKey, + eventTrigger=kValidEventTrigger) + ) + ) @async_test_body async def test_correct_key_invalid_code(self): dev_ctrl = self.default_controller - test_event_triggers_enabled = await self.read_single_attribute(dev_ctrl, self.dut_node_id, endpoint=0, attribute=Clusters.GeneralDiagnostics.Attributes.TestEventTriggersEnabled) + test_event_triggers_enabled = await self.read_single_attribute( + dev_ctrl, + self.dut_node_id, + endpoint=0, + attribute=Clusters.GeneralDiagnostics.Attributes.TestEventTriggersEnabled + ) asserts.assert_true(test_event_triggers_enabled, "This test expects Test Event Triggers are Enabled") - with asserts.assert_raises_regex(InteractionModelError, "InvalidCommand", "Unsupported EventTrigger must return InvalidCommand"): - await dev_ctrl.SendCommand(self.dut_node_id, endpoint=0, payload=Clusters.GeneralDiagnostics.Commands.TestEventTrigger(enableKey=kExpectedKey, eventTrigger=kInvalidEventTrigger)) + with asserts.assert_raises_regex(InteractionModelError, + "InvalidCommand", + "Unsupported EventTrigger must return InvalidCommand"): + await dev_ctrl.SendCommand( + self.dut_node_id, + endpoint=0, + payload=Clusters.GeneralDiagnostics.Commands.TestEventTrigger( + enableKey=kExpectedKey, + eventTrigger=kInvalidEventTrigger + ) + ) if __name__ == "__main__": diff --git a/src/python_testing/hello_test.py b/src/python_testing/hello_test.py index 70d4bbf97ddcd8..d7bad4c2dc193d 100644 --- a/src/python_testing/hello_test.py +++ b/src/python_testing/hello_test.py @@ -27,7 +27,12 @@ class HelloTest(MatterBaseTest): @async_test_body async def test_names_as_expected(self): dev_ctrl = self.default_controller - vendor_name = await self.read_single_attribute(dev_ctrl, self.dut_node_id, 0, Clusters.BasicInformation.Attributes.VendorName) + vendor_name = await self.read_single_attribute( + dev_ctrl, + self.dut_node_id, + 0, + Clusters.BasicInformation.Attributes.VendorName + ) logging.info("Found VendorName: %s" % (vendor_name)) asserts.assert_equal(vendor_name, "TEST_VENDOR", "VendorName must be TEST_VENDOR!") @@ -35,7 +40,12 @@ async def test_names_as_expected(self): @async_test_body async def test_failure_on_wrong_endpoint(self): dev_ctrl = self.default_controller - result = await self.read_single_attribute(dev_ctrl, self.dut_node_id, 9999, Clusters.BasicInformation.Attributes.ProductName) + result = await self.read_single_attribute( + dev_ctrl, + self.dut_node_id, + 9999, + Clusters.BasicInformation.Attributes.ProductName + ) asserts.assert_true(isinstance(result, Clusters.Attribute.ValueDecodeFailure), "Should fail to read on endpoint 9999") asserts.assert_equal(result.Reason.status, Status.UnsupportedEndpoint, "Failure reason should be UnsupportedEndpoint") diff --git a/src/python_testing/matter_testing_support.py b/src/python_testing/matter_testing_support.py index 76f1adb72d61b6..46c205ed0b3cc3 100644 --- a/src/python_testing/matter_testing_support.py +++ b/src/python_testing/matter_testing_support.py @@ -40,11 +40,10 @@ import chip.clusters as Clusters import chip.logging import chip.native -from chip.ChipStack import * +from chip.ChipStack import ChipStack from chip.interaction_model import InteractionModelError, Status from chip.storage import PersistentStorage -from chip.utils import CommissioningBuildingBlocks -from mobly import asserts, base_test, logger, signals, utils +from mobly import asserts, base_test, signals, utils from mobly.config_parser import ENV_MOBLY_LOGPATH, TestRunConfig from mobly.test_runner import TestRunner @@ -180,7 +179,9 @@ def _init_stack(self, already_initialized: bool, **kwargs): if already_initialized: self._chip_stack = builtins.chipStack self._logger.warn( - "Re-using existing ChipStack object found in current interpreter: storage path %s will be ignored!" % (self._config.storage_path)) + "Re-using existing ChipStack object found in current interpreter: " + "storage path %s will be ignored!" % (self._config.storage_path) + ) # TODO: Warn that storage will not follow what we set in config else: self._chip_stack = ChipStack(**kwargs) @@ -265,12 +266,15 @@ def certificate_authority_manager(self) -> chip.CertificateAuthority.Certificate def dut_node_id(self) -> int: return self.matter_test_config.dut_node_id - async def read_single_attribute(self, dev_ctrl: ChipDeviceCtrl, node_id: int, endpoint: int, attribute: object, fabricFiltered: bool = True) -> object: + async def read_single_attribute( + self, dev_ctrl: ChipDeviceCtrl, node_id: int, endpoint: int, attribute: object, fabricFiltered: bool = True) -> object: result = await dev_ctrl.ReadAttribute(node_id, [(endpoint, attribute)], fabricFiltered=fabricFiltered) data = result[endpoint] return list(data.values())[0][attribute] - async def read_single_attribute_check_success(self, cluster: object, attribute: object, dev_ctrl: ChipDeviceCtrl = None, node_id: int = None, endpoint: int = 0) -> object: + async def read_single_attribute_check_success( + self, cluster: object, attribute: object, + dev_ctrl: ChipDeviceCtrl = None, node_id: int = None, endpoint: int = 0) -> object: if dev_ctrl is None: dev_ctrl = self.default_controller if node_id is None: @@ -283,7 +287,9 @@ async def read_single_attribute_check_success(self, cluster: object, attribute: asserts.assert_false(isinstance(attr_ret, Clusters.Attribute.ValueDecodeFailure), err_msg) return attr_ret - async def read_single_attribute_expect_error(self, cluster: object, attribute: object, error: Status, dev_ctrl: ChipDeviceCtrl = None, node_id: int = None, endpoint: int = 0) -> object: + async def read_single_attribute_expect_error( + self, cluster: object, attribute: object, + error: Status, dev_ctrl: ChipDeviceCtrl = None, node_id: int = None, endpoint: int = 0) -> object: if dev_ctrl is None: dev_ctrl = self.default_controller if node_id is None: @@ -586,7 +592,8 @@ def parse_matter_test_args(argv: List[str]) -> MatterTestConfig: help='NodeID to use for initial/default controller (default: %d)' % _DEFAULT_CONTROLLER_NODE_ID) basic_group.add_argument('-n', '--dut-node-id', type=int_decimal_or_hex, metavar='NODE_ID', default=_DEFAULT_DUT_NODE_ID, - help='Node ID for primary DUT communication, and NodeID to assign if commissioning (default: %d)' % _DEFAULT_DUT_NODE_ID) + help='Node ID for primary DUT communication, ' + 'and NodeID to assign if commissioning (default: %d)' % _DEFAULT_DUT_NODE_ID) commission_group = parser.add_argument_group(title="Commissioning", description="Arguments to commission a node") @@ -616,9 +623,11 @@ def parse_matter_test_args(argv: List[str]) -> MatterTestConfig: help='Thread operational dataset as a hex string for ble-thread commissioning') commission_group.add_argument('--admin-vendor-id', action="store", type=int_decimal_or_hex, default=_DEFAULT_ADMIN_VENDOR_ID, - metavar="VENDOR_ID", help="VendorID to use during commissioning (default 0x%04X)" % _DEFAULT_ADMIN_VENDOR_ID) + metavar="VENDOR_ID", + help="VendorID to use during commissioning (default 0x%04X)" % _DEFAULT_ADMIN_VENDOR_ID) commission_group.add_argument('--case-admin-subject', action="store", type=int_decimal_or_hex, - metavar="CASE_ADMIN_SUBJECT", help="Set the CASE admin subject to an explicit value (default to commissioner Node ID)") + metavar="CASE_ADMIN_SUBJECT", + help="Set the CASE admin subject to an explicit value (default to commissioner Node ID)") commission_group.add_argument('--commission-only', action="store_true", default=False, help="If true, test exits after commissioning without running subsequent tests") @@ -638,7 +647,8 @@ def parse_matter_test_args(argv: List[str]) -> MatterTestConfig: fabric_group.add_argument('-r', '--root-index', type=root_index, metavar='ROOT_INDEX_OR_NAME', default=_DEFAULT_TRUST_ROOT_INDEX, - help='Root of trust under which to operate/commission for single-fabric basic usage. alpha/beta/gamma are aliases for 1/2/3. Default (%d)' % _DEFAULT_TRUST_ROOT_INDEX) + help='Root of trust under which to operate/commission for single-fabric basic usage. ' + 'alpha/beta/gamma are aliases for 1/2/3. Default (%d)' % _DEFAULT_TRUST_ROOT_INDEX) fabric_group.add_argument('-c', '--chip-tool-credentials-path', type=pathlib.Path, metavar='PATH', @@ -696,14 +706,33 @@ def _commission_device(self) -> bool: # TODO: support by manual code and QR if conf.commissioning_method == "on-network": - return dev_ctrl.CommissionOnNetwork(nodeId=conf.dut_node_id, setupPinCode=conf.setup_passcode, filterType=DiscoveryFilterType.LONG_DISCRIMINATOR, filter=conf.discriminator) + return dev_ctrl.CommissionOnNetwork( + nodeId=conf.dut_node_id, + setupPinCode=conf.setup_passcode, + filterType=DiscoveryFilterType.LONG_DISCRIMINATOR, + filter=conf.discriminator + ) elif conf.commissioning_method == "ble-wifi": - return dev_ctrl.CommissionWiFi(conf.discriminator, conf.setup_passcode, conf.dut_node_id, conf.wifi_ssid, conf.wifi_passphrase) + return dev_ctrl.CommissionWiFi( + conf.discriminator, + conf.setup_passcode, + conf.dut_node_id, + conf.wifi_ssid, + conf.wifi_passphrase + ) elif conf.commissioning_method == "ble-thread": - return dev_ctrl.CommissionThread(conf.discriminator, conf.setup_passcode, conf.dut_node_id, conf.thread_operational_dataset) + return dev_ctrl.CommissionThread( + conf.discriminator, + conf.setup_passcode, + conf.dut_node_id, + conf.thread_operational_dataset + ) elif conf.commissioning_method == "on-network-ip": logging.warning("==== USING A DIRECT IP COMMISSIONING METHOD NOT SUPPORTED IN THE LONG TERM ====") - return dev_ctrl.CommissionIP(ipaddr=conf.commissionee_ip_address_just_for_testing, setupPinCode=conf.setup_passcode, nodeid=conf.dut_node_id) + return dev_ctrl.CommissionIP( + ipaddr=conf.commissionee_ip_address_just_for_testing, + setupPinCode=conf.setup_passcode, nodeid=conf.dut_node_id + ) else: raise ValueError("Invalid commissioning method %s!" % conf.commissioning_method) @@ -751,8 +780,11 @@ def default_matter_test_main(argv=None, **kwargs): # TODO: Steer to right FabricAdmin! # TODO: If CASE Admin Subject is a CAT tag range, then make sure to issue NOC with that CAT tag - default_controller = stack.certificate_authorities[0].adminList[0].NewController(nodeId=matter_test_config.controller_node_id, - paaTrustStorePath=str(matter_test_config.paa_trust_store_path), catTags=matter_test_config.controller_cat_tags) + default_controller = stack.certificate_authorities[0].adminList[0].NewController( + nodeId=matter_test_config.controller_node_id, + paaTrustStorePath=str(matter_test_config.paa_trust_store_path), + catTags=matter_test_config.controller_cat_tags + ) test_config.user_params["default_controller"] = stash_globally(default_controller) test_config.user_params["matter_test_config"] = stash_globally(matter_test_config) diff --git a/src/setup_payload/tests/run_python_setup_payload_gen_test.py b/src/setup_payload/tests/run_python_setup_payload_gen_test.py index ae8b3a14e53ca3..b52000c1a6fd98 100644 --- a/src/setup_payload/tests/run_python_setup_payload_gen_test.py +++ b/src/setup_payload/tests/run_python_setup_payload_gen_test.py @@ -15,14 +15,13 @@ # limitations under the License. import os -import random import re import subprocess import sys CHIP_TOPDIR = os.path.dirname(os.path.realpath(__file__))[:-len(os.path.join('src', 'setup_payload', 'tests'))] sys.path.insert(0, os.path.join(CHIP_TOPDIR, 'src', 'setup_payload', 'python')) -from generate_setup_payload import INVALID_PASSCODES, CommissioningFlow, SetupPayload # noqa: E402 +from generate_setup_payload import CommissioningFlow, SetupPayload # noqa: E402 def payload_param_dict(): diff --git a/src/tools/chip-cert/gen_com_dut_test_vectors.py b/src/tools/chip-cert/gen_com_dut_test_vectors.py index bdbc7ca4cdd8ab..d8f22aa2c7093c 100755 --- a/src/tools/chip-cert/gen_com_dut_test_vectors.py +++ b/src/tools/chip-cert/gen_com_dut_test_vectors.py @@ -123,7 +123,8 @@ class CertType(Enum): "is_success_case": 'false', }, { - "description": "Certificate Basic Constraint extension PathLen field presence is wrong (present for DAC not present for PAI)", + "description": "Certificate Basic Constraint extension PathLen field presence is wrong " + "(present for DAC not present for PAI)", "test_folder": 'ext_basic_pathlen_presence_wrong', "error_flag": 'ext-basic-pathlen-presence-wrong', "is_success_case": 'false', @@ -165,7 +166,8 @@ class CertType(Enum): "is_success_case": 'false', }, { - "description": "Certificate Key Usage extension diginalSignature field is wrong (not present for DAC and present for PAI, which is OK as optional)", + "description": "Certificate Key Usage extension diginalSignature field is wrong " + "(not present for DAC and present for PAI, which is OK as optional)", "test_folder": 'ext_key_usage_dig_sig_wrong', "error_flag": 'ext-key-usage-dig-sig', "is_success_case": 'false', @@ -229,7 +231,8 @@ class CertType(Enum): "is_success_case": 'true', }, { - "description": 'Fallback VID and PID encoding example from spec: valid example showing that order or separators are not considered at all for the overall validity of the embedded fields', + "description": 'Fallback VID and PID encoding example from spec: valid example showing that ' + 'order or separators are not considered at all for the overall validity of the embedded fields', "common_name": 'Mpid:00B1,ACME Matter Devel DAC 5CDA9899,Mvid:FFF1', "test_folder": 'vidpid_fallback_encoding_03', "is_success_case": 'true', @@ -241,31 +244,36 @@ class CertType(Enum): "is_success_case": 'true', }, { - "description": 'Fallback VID and PID encoding example from spec: valid, but highly discouraged, since embedding of substrings within other substrings may be confusing to human readers', + "description": 'Fallback VID and PID encoding example from spec: valid, but highly discouraged, ' + 'since embedding of substrings within other substrings may be confusing to human readers', "common_name": 'Mvid:FFF1ACME Matter Devel DAC 5CDAMpid:00B19899', "test_folder": 'vidpid_fallback_encoding_05', "is_success_case": 'true', }, { - "description": 'Fallback VID and PID encoding example from spec: invalid, since substring following Mvid: is not exactly 4 uppercase hexadecimal digits', + "description": 'Fallback VID and PID encoding example from spec: invalid, ' + 'since substring following Mvid: is not exactly 4 uppercase hexadecimal digits', "common_name": 'ACME Matter Devel DAC 5CDA9899 Mvid:FF1 Mpid:00B1', "test_folder": 'vidpid_fallback_encoding_06', "is_success_case": 'false', }, { - "description": 'Fallback VID and PID encoding example from spec: invalid, since substring following Mvid: is not exactly 4 uppercase hexadecimal digits', + "description": 'Fallback VID and PID encoding example from spec: invalid, ' + 'since substring following Mvid: is not exactly 4 uppercase hexadecimal digits', "common_name": 'ACME Matter Devel DAC 5CDA9899 Mvid:fff1 Mpid:00B1', "test_folder": 'vidpid_fallback_encoding_07', "is_success_case": 'false', }, { - "description": 'Fallback VID and PID encoding example from spec: invalid, since substring following Mpid: is not exactly 4 uppercase hexadecimal digits', + "description": 'Fallback VID and PID encoding example from spec: invalid, ' + 'since substring following Mpid: is not exactly 4 uppercase hexadecimal digits', "common_name": 'ACME Matter Devel DAC 5CDA9899 Mvid:FFF1 Mpid:B1', "test_folder": 'vidpid_fallback_encoding_08', "is_success_case": 'false', }, { - "description": 'Fallback VID and PID encoding example from spec: invalid, since substring following Mpid: is not exactly 4 uppercase hexadecimal digits', + "description": 'Fallback VID and PID encoding example from spec: invalid, ' + 'since substring following Mpid: is not exactly 4 uppercase hexadecimal digits', "common_name": 'ACME Matter Devel DAC 5CDA9899 Mpid: Mvid:FFF1', "test_folder": 'vidpid_fallback_encoding_09', "is_success_case": 'false', @@ -303,7 +311,8 @@ class CertType(Enum): }, # Examples with both fallback encoding in the common name and using Matter specific OIDs { - "description": 'Mix of Fallback and Matter OID encoding for VID and PID: valid, Matter OIDs are used and wrong values in the common-name are ignored', + "description": 'Mix of Fallback and Matter OID encoding for VID and PID: valid, ' + 'Matter OIDs are used and wrong values in the common-name are ignored', "common_name": 'ACME Matter Devel DAC 5CDA9899 Mvid:FFF2 Mpid:00B2', "vid": 0xFFF1, "pid": 0x00B1, @@ -311,7 +320,8 @@ class CertType(Enum): "is_success_case": 'true', }, { - "description": 'Mix of Fallback and Matter OID encoding for VID and PID: wrong, Correct values encoded in the common-name are ignored', + "description": 'Mix of Fallback and Matter OID encoding for VID and PID: wrong, ' + 'Correct values encoded in the common-name are ignored', "common_name": 'ACME Matter Devel DAC 5CDA9899 Mvid:FFF1 Mpid:00B1', "vid": 0xFFF2, "pid": 0x00B2, @@ -319,7 +329,8 @@ class CertType(Enum): "is_success_case": 'false', }, { - "description": 'Mix of Fallback and Matter OID encoding for VID and PID: invalid, PID is using Matter OID then VID must also use Matter OID', + "description": 'Mix of Fallback and Matter OID encoding for VID and PID: invalid, ' + 'PID is using Matter OID then VID must also use Matter OID', "common_name": 'Mvid:FFF1', "pid": 0x00B1, "test_folder": 'vidpid_fallback_encoding_17', @@ -413,7 +424,8 @@ class CertType(Enum): "is_success_case": 'false', }, { - "description": "The device_type_id field doesn't match the device_type_id value in the DCL entries associated with the VID and PID.", + "description": "The device_type_id field doesn't match the device_type_id value in the DCL entries " + "associated with the VID and PID.", "test_folder": 'device_type_id_mismatch', "error_flag": 'device-type-id-mismatch', "is_success_case": 'false', @@ -467,13 +479,15 @@ class CertType(Enum): "is_success_case": 'false', }, { - "description": 'The version_number field matches the VID and PID used in a DeviceSoftwareVersionModel entry in the DCL matching the certification record associated with the product presenting this CD.', + "description": 'The version_number field matches the VID and PID used in a DeviceSoftwareVersionModel ' + 'entry in the DCL matching the certification record associated with the product presenting this CD.', "test_folder": 'version_number_match', "error_flag": 'no-error', "is_success_case": 'true', }, { - "description": "The version_number field doesn't match the VID and PID used in a DeviceSoftwareVersionModel entry in the DCL matching the certification record associated with the product presenting this CD.", + "description": "The version_number field doesn't match the VID and PID used in a DeviceSoftwareVersionModel " + "entry in the DCL matching the certification record associated with the product presenting this CD.", "test_folder": 'version_number_wrong', "error_flag": 'version-number-wrong', "is_success_case": 'false', @@ -509,19 +523,22 @@ class CertType(Enum): "is_success_case": 'false', }, { - "description": 'The dac_origin_vendor_id and dac_origin_product_id fields present and contain the VID and PID values that match the VID and PID found in the DAC Subject DN.', + "description": 'The dac_origin_vendor_id and dac_origin_product_id fields present and contain ' + 'the VID and PID values that match the VID and PID found in the DAC Subject DN.', "test_folder": 'dac_origin_vid_pid_present_match', "error_flag": 'dac-origin-vid-pid-present', "is_success_case": 'true', }, { - "description": "The dac_origin_vendor_id and dac_origin_product_id fields present and the VID value doesn't match the VID found in the DAC Subject DN.", + "description": "The dac_origin_vendor_id and dac_origin_product_id fields present and the VID value " + "doesn't match the VID found in the DAC Subject DN.", "test_folder": 'dac_origin_vid_pid_present_vid_mismatch', "error_flag": 'dac-origin-vid-mismatch', "is_success_case": 'false', }, { - "description": "The dac_origin_vendor_id and dac_origin_product_id fields present and the PID value doesn't match the PID found in the DAC Subject DN.", + "description": "The dac_origin_vendor_id and dac_origin_product_id fields present and the PID value " + "doesn't match the PID found in the DAC Subject DN.", "test_folder": 'dac_origin_vid_pid_present_pid_mismatch', "error_flag": 'dac-origin-pid-mismatch', "is_success_case": 'false', @@ -663,7 +680,8 @@ def __init__(self, cert_type: CertType, paa_path, test_case_out_dir): class DevCertBuilder: - def __init__(self, cert_type: CertType, error_type: str, paa_path: str, test_case_out_dir: str, chip_cert: str, vid: int, pid: int, custom_cn_attribute: str, valid_from: str): + def __init__(self, cert_type: CertType, error_type: str, paa_path: str, test_case_out_dir: str, chip_cert: str, vid: int, + pid: int, custom_cn_attribute: str, valid_from: str): self.vid = vid self.pid = pid self.cert_type = cert_type @@ -710,8 +728,9 @@ def make_certs_and_keys(self) -> None: else: return - cmd = self.chipcert + ' gen-att-cert ' + type_flag + error_type_flag + ' -c "' + subject_name + '" -C ' + self.signer.cert_pem + ' -K ' + \ - self.signer.key_pem + vid_flag + pid_flag + validity_flags + ' -o ' + self.own.cert_pem + ' -O ' + self.own.key_pem + cmd = self.chipcert + ' gen-att-cert ' + type_flag + error_type_flag + ' -c "' + subject_name + '" -C ' + \ + self.signer.cert_pem + ' -K ' + self.signer.key_pem + vid_flag + pid_flag + \ + validity_flags + ' -o ' + self.own.cert_pem + ' -O ' + self.own.key_pem subprocess.run(cmd, shell=True) cmd = 'openssl x509 -inform pem -in ' + self.own.cert_pem + \ ' -out ' + self.own.cert_der + ' -outform DER' @@ -762,7 +781,11 @@ def generate_test_case_vector_json(test_case_out_dir: str, test_cert: str, test_ json_dict["description"] = test_cert.upper() + " Test Vector: " + test_case["description"] if "is_success_case" in test_case: # These test cases are expected to fail when error injected in DAC but expected to pass when error injected in PAI - if (test_cert == 'pai') and (test_case["test_folder"] in ['ext_basic_pathlen0', 'vidpid_fallback_encoding_08', 'vidpid_fallback_encoding_09', 'ext_key_usage_dig_sig_wrong']): + if (test_cert == 'pai') and (test_case["test_folder"] in ['ext_basic_pathlen0', + 'vidpid_fallback_encoding_08', + 'vidpid_fallback_encoding_09', + 'ext_key_usage_dig_sig_wrong' + ]): json_dict["is_success_case"] = "true" else: json_dict["is_success_case"] = test_case["is_success_case"] @@ -944,13 +967,18 @@ def main(): if test_case["error_flag"] == 'dac-origin-pid-present' or test_case["error_flag"] == 'dac-origin-vid-pid-present': dac_origin_flag += ' -r 0x{:X}'.format(pid) - if test_case["error_flag"] == 'authorized-paa-list-count0' or test_case["error_flag"] == 'authorized-paa-list-count1-valid' or test_case["error_flag"] == 'authorized-paa-list-count2-valid' or test_case["error_flag"] == 'authorized-paa-list-count3-invalid' or test_case["error_flag"] == 'authorized-paa-list-count10-valid' or test_case["error_flag"] == 'authorized-paa-list-count10-invalid': + if test_case["error_flag"] == 'authorized-paa-list-count0' or test_case["error_flag"] == 'authorized-paa-list-count1-valid'\ + or test_case["error_flag"] == 'authorized-paa-list-count2-valid'\ + or test_case["error_flag"] == 'authorized-paa-list-count3-invalid'\ + or test_case["error_flag"] == 'authorized-paa-list-count10-valid'\ + or test_case["error_flag"] == 'authorized-paa-list-count10-invalid': authorized_paa_flag = ' -a ' + args.paapath + 'Cert.pem' else: authorized_paa_flag = '' - cmd = chipcert + ' gen-cd -I -E ' + test_case["error_flag"] + ' -K ' + cd_key + ' -C ' + cd_cert + ' -O ' + test_case_out_dir + '/cd.der' + \ - ' -f 1 ' + vid_flag + pid_flag + dac_origin_flag + authorized_paa_flag + ' -d 0x1234 -c "ZIG20141ZB330001-24" -l 0 -i 0 -n 9876 -t 0' + cmd = chipcert + ' gen-cd -I -E ' + test_case["error_flag"] + ' -K ' + cd_key + ' -C ' + cd_cert + ' -O ' + \ + test_case_out_dir + '/cd.der' + ' -f 1 ' + vid_flag + pid_flag + dac_origin_flag + authorized_paa_flag + \ + ' -d 0x1234 -c "ZIG20141ZB330001-24" -l 0 -i 0 -n 9876 -t 0' subprocess.run(cmd, shell=True) # Generate Test Case Data Container in JSON Format diff --git a/src/tools/chip-cert/gen_op_cert_test_vectors.py b/src/tools/chip-cert/gen_op_cert_test_vectors.py index d1a074f1bed234..4f1e2d39565b7d 100755 --- a/src/tools/chip-cert/gen_op_cert_test_vectors.py +++ b/src/tools/chip-cert/gen_op_cert_test_vectors.py @@ -376,7 +376,8 @@ class CertFormat(Enum): "is_get_cert_type_expected_to_fail": False, }, { - "description": "Certificate Key Usage extension diginalSignature field is wrong (not present for NOC and present for ICAC/RCAC)", + "description": "Certificate Key Usage extension diginalSignature field is wrong " + "(not present for NOC and present for ICAC/RCAC)", "test_name": 'Ext-KeyUsage-DigSig-Wrong', "error_flag": 'ext-key-usage-dig-sig', "is_chip_to_x509_expected_to_fail": False, @@ -512,7 +513,8 @@ def __init__(self, cert_type: CertType, cert_form: CertFormat, test_case_out_dir class OpCertBuilder: - def __init__(self, cert_type: CertType, cert_form: CertFormat, signer_cert: str, signer_key: str, error_type: str, test_name: str, test_case_out_dir: str, chip_cert: str): + def __init__(self, cert_type: CertType, cert_form: CertFormat, signer_cert: str, signer_key: str, error_type: str, + test_name: str, test_case_out_dir: str, chip_cert: str): self.cert_type = cert_type self.cert_form = cert_form self.error_type = error_type @@ -616,7 +618,8 @@ def main(): for test_case in DER_CERT_ERROR_TEST_CASES: for cert_type in [CertType.NOC, CertType.ICAC, CertType.RCAC]: # The following error cases are applicable only for NOC - if (test_case["error_flag"] == 'subject-node-id-invalid' or test_case["error_flag"] == 'ext-basic-pathlen-presence-wrong') and cert_type != CertType.NOC: + if (test_case["error_flag"] == 'subject-node-id-invalid' or + test_case["error_flag"] == 'ext-basic-pathlen-presence-wrong') and cert_type != CertType.NOC: break if cert_type == CertType.NOC: @@ -658,7 +661,8 @@ def main(): break # The following error cases are applicable only for NOC - if (test_case["error_flag"] == 'subject-node-id-invalid' or test_case["error_flag"] == 'subject-fabric-id-missing') and cert_type != CertType.NOC: + if (test_case["error_flag"] == 'subject-node-id-invalid' + or test_case["error_flag"] == 'subject-fabric-id-missing') and cert_type != CertType.NOC: break if cert_type == CertType.NOC: @@ -685,7 +689,8 @@ def main(): if test_case["is_validate_chip_rcac_expected_to_fail"]: c_validate_chip_rcac_error_cases += builder.add_cert_to_error_cases() validate_chip_rcac_error_cases_count += 1 - if test_case["is_get_cert_type_expected_to_fail"] and not (test_case["error_flag"] == 'subject-cat-twice' and cert_type == CertType.NOC): + if test_case["is_get_cert_type_expected_to_fail"] and not (test_case["error_flag"] == 'subject-cat-twice' + and cert_type == CertType.NOC): c_get_cert_type_error_cases += builder.add_cert_to_error_cases() get_cert_type_error_cases_count += 1