diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index b8ab010a1dfe5f..00000000000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,2 +0,0 @@ -# Current reviewers-XXX teams, who review everything for approval. -* @reviewers-amazon @reviewers-apple @reviewers-comcast @reviewers-google @reviewers-lg @reviewers-nordic @reviewers-samsung @reviewers-silabs @reviewers-tcl diff --git a/.github/workflows/darwin.yaml b/.github/workflows/darwin.yaml index 9eeac9118ef9d3..4c25026840e5d1 100644 --- a/.github/workflows/darwin.yaml +++ b/.github/workflows/darwin.yaml @@ -111,8 +111,7 @@ jobs: working-directory: src/darwin/Framework run: | mkdir -p /tmp/darwin/framework-tests - echo "This is a simple log" > /tmp/darwin/framework-tests/end_user_support_log.txt - ../../../out/debug/all-clusters-app/chip-all-clusters-app --interface-id -1 --end_user_support_log /tmp/darwin/framework-tests/end_user_support_log.txt > >(tee /tmp/darwin/framework-tests/all-cluster-app.log) 2> >(tee /tmp/darwin/framework-tests/all-cluster-app-err.log >&2) & + ../../../out/debug/all-clusters-app/chip-all-clusters-app --interface-id -1 > >(tee /tmp/darwin/framework-tests/all-cluster-app.log) 2> >(tee /tmp/darwin/framework-tests/all-cluster-app-err.log >&2) & export TEST_RUNNER_ASAN_OPTIONS=__CURRENT_VALUE__:detect_stack_use_after_return=1 diff --git a/.github/workflows/docker_img.yaml b/.github/workflows/docker_img.yaml index 05594606a610c7..8921a55cb2b9e0 100644 --- a/.github/workflows/docker_img.yaml +++ b/.github/workflows/docker_img.yaml @@ -101,7 +101,7 @@ jobs: # ApplyLayer exit status 1 stdout: stderr: write /opt/fsl-imx-xwayland/5.15-kirkstone/sysroots/armv8a-poky-linux/opt/ltp/testcases/bin/fanotify15: no space left on device # - "-imx" - "-java" - - "-k32w" + - "-nxp" - "-nrf-platform" - "-telink" - "-ti" diff --git a/.github/workflows/examples-nxp.yaml b/.github/workflows/examples-nxp.yaml index 40d2e338858da4..13023b6bb06d42 100644 --- a/.github/workflows/examples-nxp.yaml +++ b/.github/workflows/examples-nxp.yaml @@ -39,7 +39,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-k32w:80 + image: ghcr.io/project-chip/chip-build-nxp:80 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.pullapprove.yml b/.pullapprove.yml index 5be3f21a28a327..83d7b70b34eb65 100644 --- a/.pullapprove.yml +++ b/.pullapprove.yml @@ -84,7 +84,7 @@ groups: reviewers: teams: [reviewers-amazon] reviews: - request: 10 + request: 0 # Do not auto-add shared-reviewers-apple: type: optional conditions: @@ -92,7 +92,7 @@ groups: reviewers: teams: [reviewers-apple] reviews: - request: 10 + request: 0 # Do not auto-add shared-reviewers-bosch: type: optional conditions: @@ -100,7 +100,7 @@ groups: reviewers: teams: [reviewers-bosch] reviews: - request: 10 + request: 0 # Do not auto-add shared-reviewers-comcast: type: optional conditions: @@ -108,7 +108,7 @@ groups: reviewers: teams: [reviewers-comcast] reviews: - request: 10 + request: 0 # Do not auto-add shared-reviewers-dyson: type: optional conditions: @@ -116,7 +116,7 @@ groups: reviewers: teams: [reviewers-dyson] reviews: - request: 10 + request: 0 # Do not auto-add shared-reviewers-espressif: type: optional conditions: @@ -124,7 +124,7 @@ groups: reviewers: teams: [reviewers-espressif] reviews: - request: 10 + request: 0 # Do not auto-add shared-reviewers-google: type: optional conditions: @@ -132,7 +132,7 @@ groups: reviewers: teams: [reviewers-google] reviews: - request: 10 + request: 0 # Do not auto-add shared-reviewers-grundfos: type: optional conditions: @@ -140,7 +140,7 @@ groups: reviewers: teams: [reviewers-grundfos] reviews: - request: 10 + request: 0 # Do not auto-add shared-reviewers-irobot: type: optional conditions: @@ -148,7 +148,7 @@ groups: reviewers: teams: [reviewers-irobot] reviews: - request: 10 + request: 0 # Do not auto-add shared-reviewers-lg: type: optional conditions: @@ -156,7 +156,7 @@ groups: reviewers: teams: [reviewers-lg] reviews: - request: 10 + request: 0 # Do not auto-add shared-reviewers-logitech: type: optional conditions: @@ -172,7 +172,7 @@ groups: reviewers: teams: [reviewers-nordic] reviews: - request: 10 + request: 0 # Do not auto-add shared-reviewers-nxp: type: optional conditions: @@ -180,7 +180,7 @@ groups: reviewers: teams: [reviewers-nxp] reviews: - request: 10 + request: 0 # Do not auto-add shared-reviewers-samsung: type: optional conditions: @@ -188,7 +188,7 @@ groups: reviewers: teams: [reviewers-samsung] reviews: - request: 10 + request: 0 # Do not auto-add shared-reviewers-eve: type: optional conditions: @@ -196,7 +196,7 @@ groups: reviewers: teams: [reviewers-eve] reviews: - request: 10 + request: 0 # Do not auto-add # shared-reviewers-signify disabled for now, because the reviewers-signify # team is empty and pullapprove seems to mis-handle that badly and treats # _all_ reviewers as being in this group. @@ -210,7 +210,7 @@ groups: # reviewers: # teams: [reviewers-signify] # reviews: - # request: 10 + # request: 0 # Do not auto-add shared-reviewers-silabs: type: optional conditions: @@ -218,7 +218,7 @@ groups: reviewers: teams: [reviewers-silabs] reviews: - request: 10 + request: 0 # Do not auto-add shared-reviewers-somfy: type: optional conditions: @@ -226,7 +226,7 @@ groups: reviewers: teams: [reviewers-somfy] reviews: - request: 10 + request: 0 # Do not auto-add shared-reviewers-tcl: type: optional conditions: @@ -234,7 +234,7 @@ groups: reviewers: teams: [reviewers-tcl] reviews: - request: 10 + request: 0 # Do not auto-add shared-reviewers-qorvo: type: optional conditions: @@ -242,7 +242,7 @@ groups: reviewers: teams: [reviewers-qorvo] reviews: - request: 10 + request: 0 # Do not auto-add ############################################################ # Base Required Reviewers diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 00000000000000..970981cefcc33a --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,71 @@ +/src/platform/ASR/ @tx2rx +asr/ @tx2rx +chip-build-asr/ @tx2rx + +/src/platform/Ameba/ @pankore +ameba/ @pankore +chip-build-ameba/ @pankore + +/src/platform/Beken/ @zhengyaohan + +*.mm @project-chip/reviewers-apple +darwin/ @project-chip/reviewers-apple +/src/darwin/ @project-chip/reviewers-apple +/src/platform/Darwin/ @project-chip/reviewers-apple +/examples/darwin-framework-tool/ @project-chip/reviewers-apple + +/src/platform/ESP32/ @project-chip/reviewers-espressif +esp32/ @project-chip/reviewers-espressif +chip-build-esp32/ @project-chip/reviewers-espressif +chip-build-esp32-qemu/ @project-chip/reviewers-espressif + +/src/platform/Infineon/ @ifyall +infineon/ @ifyall +chip-build-infineon/ @ifyall + +/src/platform/NuttX/ @zhhyu7 +chip-build-nuttx/ @zhhyu7 + +/src/platform/Tizen/ @arkq +tizen/ @arkq +chip-build-tizen/ @arkq +chip-build-tizen-qemu/ @arkq + +*.java @project-chip/reviewers-google +*.kt @project-chip/reviewers-google +android/ @project-chip/reviewers-google +/src/examples/chef/ @project-chip/reviewers-google +/integrations/appengine/ @project-chip/reviewers-google +/integrations/cloudbuild/ @project-chip/reviewers-google +/integrations/compute_engine/ @project-chip/reviewers-google +chip-build-java/ @project-chip/reviewers-google +chip-build-android/ @project-chip/reviewers-google + +/src/platform/bouffalolab/ @wy-hh +chip-build-bouffalolab/ @wy-hh + +cc13xx_26xx/ @s-jain2022 +cc32xx/ @s-jain2022 + +/src/platform/mt793x/ @pakls +nrfconnect/ @project-chip/reviewers-nordic +chip-build-nrf-platform/ @project-chip/reviewers-nordic +Zephyr/ @project-chip/reviewers-nordic @project-chip/reviewers-nxp @s07641069 + + +nxp/ @project-chip/reviewers-nxp +chip-build-nxp/ @project-chip/reviewers-nxp +chip-build-nxp-zephyr/ @project-chip/reviewers-nxp +chip-build-k32w/ @project-chip/reviewers-nxp + +qpg/ @dvdm-qorvo + +silabs/ @project-chip/reviewers-silabs +chip-build-efr32/ @project-chip/reviewers-silabs + +stm32/ @STYoannZamaron + +telink/ @s07641069 +chip-build-telink/ @s07641069 + +webos/ @joonhaengHeo diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 2e2ebe606f089f..0310e2a365eb66 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn @@ -24,10 +24,40 @@ if (current_os == "mac" || current_os == "ios") { import("${build_root}/config/mac/mac_sdk.gni") } +# To use different sanitizer options, use `gn args .` in the out folder and +# use settings like: +# +# is_clang=true +# is_debug=true +# optimize_for_size=false +# is_asan=true +# is_sanitize_fatal=false +# + declare_args() { # Enable -Werror. This can be disabled if using a different compiler # with unfixed or unsupported wanings. treat_warnings_as_errors = true + + # Enable Thread sanitizer + is_tsan = false + + # Enable memory sanitizer + is_msan = false + + # enable undefined behavior sanitizer + is_ubsan = false + + # Exit on sanitize error. Generally standard libraries may get errors + # so not stopping on the first error is often useful + is_sanitize_fatal = true + + # Enable or disable Runtime Type Information (RTTI). + # Defaults true on darwin because Darwin.framework uses it. + enable_rtti = current_os == "mac" || current_os == "ios" + + # Enable or disable support for C++ exceptions. + enable_exceptions = false } if (current_cpu == "arm" || current_cpu == "arm64") { @@ -397,21 +427,6 @@ config("runtime_default") { # is_sanitize_fatal=false # -declare_args() { - # Enable Thread sanitizer - is_tsan = false - - # Enable memory sanitizer - is_msan = false - - # enable undefined behavior sanitizer - is_ubsan = false - - # Exit on sanitize error. Generally standard libraries may get errors - # so not stopping on the first error is often useful - is_sanitize_fatal = true -} - config("sanitize_address") { defines = [] cflags = [ @@ -452,10 +467,14 @@ config("sanitize_undefined_behavior") { "-fsanitize=unsigned-integer-overflow", "-fsanitize=implicit-conversion", "-fsanitize=nullability", - "-fno-sanitize=vptr,function", ] } + #According to the LLVM UBSan documentation, sanitizing vptr is incompatible with the -fno-rtti flag. + if (!enable_rtti) { + cflags += [ "-fno-sanitize=vptr" ] + } + ldflags = cflags } @@ -522,15 +541,6 @@ config("coverage_default") { } } -declare_args() { - # Enable or disable Runtime Type Information (RTTI). - # Defaults true on darwin because Darwin.framework uses it. - enable_rtti = current_os == "mac" || current_os == "ios" - - # Enable or disable support for C++ exceptions. - enable_exceptions = false -} - config("no_rtti") { cflags_cc = [ "-fno-rtti" ] } diff --git a/docs/guides/BUILDING.md b/docs/guides/BUILDING.md index 0cbd2fc3c64920..6fc46950465fb9 100644 --- a/docs/guides/BUILDING.md +++ b/docs/guides/BUILDING.md @@ -401,7 +401,11 @@ Tests will be located in: `chip_pw_fuzztest` is the name of the toolchain used. - Details on How To Run Fuzz Tests in - [Running FuzzTests](https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/fuzz_testing.md) + [Running FuzzTests](https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/fuzz_testing.md#running-fuzztests) + +FAQ: In the event of a build failure related to missing files or dependencies +for pw_fuzzer, check the +[FuzzTest FAQ](https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/fuzz_testing.md#FAQ) ## Build custom configuration diff --git a/docs/testing/fuzz_testing.md b/docs/testing/fuzz_testing.md index 7660e18032ef9a..68f08f4885c48e 100644 --- a/docs/testing/fuzz_testing.md +++ b/docs/testing/fuzz_testing.md @@ -256,6 +256,25 @@ $ ./fuzz-chip-cert-pw --fuzz=ChipCert.DecodeChipCertFuzzer ``` +### FAQ + +#### What revision should the FuzzTest and Abseil submodules be for running `pw_fuzzer` with FuzzTest? + +- Google FuzzTest is integrated into Matter using `pw_fuzzer`, which has + several dependencies. These dependencies are listed here: + [Step 0: Set up FuzzTest for your project](https://pigweed.dev/pw_fuzzer/guides/fuzztest.html#step-0-set-up-fuzztest-for-your-project). +- Matter integrates these dependencies as submodules, including Google + FuzzTest and Abseil. +- Since FuzzTest and Abseil only support the `bazel` and `CMake` build systems + and do not support GN, Pigweed maintainers use a script to generate GN files + for these dependencies. +- the revision of FuzzTest and Abseil submodules in Matter should match or at + least be as new as the specific version (SHA1) used when generating these GN + files. +- You can find the version used for the generated GN files here: + [FuzzTest Version](https://pigweed.dev/third_party/fuzztest/#version) and + [Abseil Version](https://pigweed.dev/third_party/abseil-cpp/#version). + #### TO ADD: - More Information on Test Fixtures (After issues are resolved) diff --git a/docs/testing/python.md b/docs/testing/python.md index c631550b040082..9c2edcfc85caf0 100644 --- a/docs/testing/python.md +++ b/docs/testing/python.md @@ -644,74 +644,70 @@ single command. Example to compile all prerequisites and then running all python tests: -``` +```shell ./scripts/tests/local.py build # will compile python in out/pyenv and ALL application prerequisites ./scripts/tests/local.py python-tests # Runs all python tests that are runnable in CI ``` ## Defining the CI test arguments -Below is the format of the structured environment definition comments: +Arguments required to run a test can be defined in the comment block at the top +of the test script. The section with the arguments should be placed between the +`# === BEGIN CI TEST ARGUMENTS ===` and `# === END CI TEST ARGUMENTS ===` +markers. Arguments should be structured as a valid YAML dictionary with a root +key `test-runner-runs`, followed by the run identifier, and then the parameters +for that run, e.g.: -``` +```python # See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments # for details about the block below. # # === BEGIN CI TEST ARGUMENTS === -# test-runner-runs: -# test-runner-run//app: ${TYPE_OF_APP} -# test-runner-run//factoryreset: -# test-runner-run//quiet: -# test-runner-run//app-args: -# test-runner-run//script-args: +# test-runner-runs: +# run1: +# app: ${TYPE_OF_APP} +# factoryreset: +# quiet: +# app-args: +# script-args: # === END CI TEST ARGUMENTS === ``` -NOTE: The `=== BEGIN CI TEST ARGUMENTS ===` and `=== END CI TEST ARGUMENTS ===` -markers must be present. - ### Description of Parameters -- `test-runner-runs`: Specifies the identifier for the run. This can be any - unique identifier. - - - Example: `run1` - -- `test-runner-run//app`: Indicates the application to be used - in the test. Different app types as needed could be referenced from section - [name: Generate an argument environment file ] of the file +- `app`: Indicates the application to be used in the test. Different app types + as needed could be referenced from section [name: Generate an argument + environment file ] of the file [.github/workflows/tests.yaml](https://github.com/project-chip/connectedhomeip/blob/master/.github/workflows/tests.yaml) - - Example: `${TYPE_OF_APP}` + - Example: `${TYPE_OF_APP}` -- `test-runner-run//factoryreset`: Determines whether a - factory reset should be performed before the test. +- `factoryreset`: Determines whether a factory reset should be performed + before the test. - - Example: `True` + - Example: `true` -- `test-runner-run//quiet`: Sets the verbosity level of the - test run. When set to True, the test run will be quieter. +- `quiet`: Sets the verbosity level of the test run. When set to True, the + test run will be quieter. - - Example: `True` + - Example: `true` -- `test-runner-run//app-args`: Specifies the arguments to be - passed to the application during the test. +- `app-args`: Specifies the arguments to be passed to the application during + the test. - Example: `--discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json` -- `test-runner-run//script-args`: Specifies the arguments to - be passed to the test script. +- `script-args`: Specifies the arguments to be passed to the test script. - Example: `--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto` -- `test-runner-run//script-start-delay`: Specifies the number - of seconds to wait before starting the test script. This parameter can be - used to allow the application to initialize itself properly before the test - script will try to commission it (e.g. in case if the application needs to - be commissioned to some other controller first). By default, the delay is 0 - seconds. +- `script-start-delay`: Specifies the number of seconds to wait before + starting the test script. This parameter can be used to allow the + application to initialize itself properly before the test script will try to + commission it (e.g. in case if the application needs to be commissioned to + some other controller first). By default, the delay is 0 seconds. - Example: `10` diff --git a/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp b/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp index 94345600cf53fd..59bccf11faa481 100644 --- a/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp @@ -1,7 +1,6 @@ #include #include -using namespace std; using namespace chip; using namespace chip::app::Clusters; using namespace chip::app::Clusters::ModeSelect; diff --git a/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp b/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp index 6019006c2a2868..5ed8a0c40f5e89 100644 --- a/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp @@ -19,7 +19,6 @@ #include #include -using namespace std; using namespace chip; using namespace chip::app::Clusters; using namespace chip::app::Clusters::TemperatureControl; diff --git a/examples/chef/common/clusters/audio-output/AudioOutputManager.cpp b/examples/chef/common/clusters/audio-output/AudioOutputManager.cpp index 06a123a6549679..65df8db9ff0bb2 100644 --- a/examples/chef/common/clusters/audio-output/AudioOutputManager.cpp +++ b/examples/chef/common/clusters/audio-output/AudioOutputManager.cpp @@ -20,7 +20,6 @@ #ifdef MATTER_DM_PLUGIN_AUDIO_OUTPUT_SERVER #include "AudioOutputManager.h" -using namespace std; using namespace chip::app; using namespace chip::app::Clusters::AudioOutput; using chip::app::AttributeValueEncoder; diff --git a/examples/chef/common/clusters/media-input/MediaInputManager.cpp b/examples/chef/common/clusters/media-input/MediaInputManager.cpp index 53cc22cd65cce8..4d11d9934ae8ab 100644 --- a/examples/chef/common/clusters/media-input/MediaInputManager.cpp +++ b/examples/chef/common/clusters/media-input/MediaInputManager.cpp @@ -22,7 +22,6 @@ #ifdef MATTER_DM_PLUGIN_MEDIA_INPUT_SERVER #include "MediaInputManager.h" -using namespace std; using namespace chip; using namespace chip::app::Clusters::MediaInput; using Protocols::InteractionModel::Status; diff --git a/examples/chef/common/clusters/media-playback/MediaPlaybackManager.cpp b/examples/chef/common/clusters/media-playback/MediaPlaybackManager.cpp index db3af119c5b286..cf8bcda33cd757 100644 --- a/examples/chef/common/clusters/media-playback/MediaPlaybackManager.cpp +++ b/examples/chef/common/clusters/media-playback/MediaPlaybackManager.cpp @@ -22,7 +22,6 @@ #ifdef MATTER_DM_PLUGIN_MEDIA_PLAYBACK_SERVER #include "MediaPlaybackManager.h" -using namespace std; using namespace chip; using namespace chip::app; using namespace chip::app::DataModel; diff --git a/examples/chef/common/clusters/target-navigator/TargetNavigatorManager.cpp b/examples/chef/common/clusters/target-navigator/TargetNavigatorManager.cpp index be20f92f53a8fe..1f2dcdedb048e6 100644 --- a/examples/chef/common/clusters/target-navigator/TargetNavigatorManager.cpp +++ b/examples/chef/common/clusters/target-navigator/TargetNavigatorManager.cpp @@ -23,7 +23,6 @@ #include #include -using namespace std; using namespace chip::app; using namespace chip::app::Clusters::TargetNavigator; diff --git a/examples/chip-tool/commands/discover/Commands.h b/examples/chip-tool/commands/discover/Commands.h index d308d4ab75b430..d70191f8bc8245 100644 --- a/examples/chip-tool/commands/discover/Commands.h +++ b/examples/chip-tool/commands/discover/Commands.h @@ -84,6 +84,7 @@ void registerCommandsDiscover(Commands & commands, CredentialIssuerCommands * cr make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), }; diff --git a/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.cpp b/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.cpp index ad5e7feaf7f948..35d833e5ad678a 100644 --- a/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.cpp +++ b/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.cpp @@ -122,3 +122,11 @@ CHIP_ERROR DiscoverCommissionableByDeviceTypeCommand::RunCommand() chip::Dnssd::DiscoveryFilter filter(chip::Dnssd::DiscoveryFilterType::kDeviceType, mDeviceType); return mCommissioner->DiscoverCommissionableNodes(filter); } + +CHIP_ERROR DiscoverCommissionableByInstanceNameCommand::RunCommand() +{ + mCommissioner = &CurrentCommissioner(); + mCommissioner->RegisterDeviceDiscoveryDelegate(this); + chip::Dnssd::DiscoveryFilter filter(chip::Dnssd::DiscoveryFilterType::kInstanceName, mInstanceName); + return mCommissioner->DiscoverCommissionableNodes(filter); +} diff --git a/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.h b/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.h index d1fec307eac19e..2ba81b6404efc8 100644 --- a/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.h +++ b/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.h @@ -159,3 +159,19 @@ class DiscoverCommissionableByDeviceTypeCommand : public DiscoverCommissionables // TODO: possibly 32-bit - see spec issue #3226 uint16_t mDeviceType; }; + +class DiscoverCommissionableByInstanceNameCommand : public DiscoverCommissionablesCommandBase +{ +public: + DiscoverCommissionableByInstanceNameCommand(CredentialIssuerCommands * credsIssuerConfig) : + DiscoverCommissionablesCommandBase("find-commissionable-by-instance-name", credsIssuerConfig) + { + AddArgument("value", &mInstanceName); + } + + /////////// CHIPCommand Interface ///////// + CHIP_ERROR RunCommand() override; + +private: + char * mInstanceName; +}; diff --git a/examples/contact-sensor-app/nxp/k32w0/BUILD.gn b/examples/contact-sensor-app/nxp/k32w0/BUILD.gn index c51b8787ea2922..f032603d00457b 100644 --- a/examples/contact-sensor-app/nxp/k32w0/BUILD.gn +++ b/examples/contact-sensor-app/nxp/k32w0/BUILD.gn @@ -199,12 +199,17 @@ action("binsign") { output_name = "bignsign.log" outputs = [ "${root_build_dir}/${output_name}" ] + args = [ + "--sdk-root", + rebase_path(k32w0_sdk_root), + ] + if (chip_simple_hash_verification == 1) { - args = [ "--simple-hash" ] + args += [ "--simple-hash" ] } if (chip_enable_ota_requestor) { - args = [ "--ota-enabled" ] + args += [ "--ota-enabled" ] } } diff --git a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter index c4f74c662191ad..aeb4a47927f771 100644 --- a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter +++ b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter @@ -2015,6 +2015,7 @@ endpoint 0 { ram attribute userActiveModeTriggerHint default = 4096; ram attribute userActiveModeTriggerInstruction default = "Push setup button for Active Mode"; ram attribute operatingMode default = 0; + callback attribute maximumCheckInBackOff; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; diff --git a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap index 31c3577edca1a3..f2e73f974cc087 100644 --- a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap +++ b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap @@ -3726,6 +3726,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "MaximumCheckInBackOff", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "GeneratedCommandList", "code": 65528, diff --git a/examples/lighting-app/nxp/k32w0/BUILD.gn b/examples/lighting-app/nxp/k32w0/BUILD.gn index a63a5967c3948b..65a62229a7f9cd 100644 --- a/examples/lighting-app/nxp/k32w0/BUILD.gn +++ b/examples/lighting-app/nxp/k32w0/BUILD.gn @@ -180,12 +180,17 @@ action("binsign") { output_name = "bignsign.log" outputs = [ "${root_build_dir}/${output_name}" ] + args = [ + "--sdk-root", + rebase_path(k32w0_sdk_root), + ] + if (chip_simple_hash_verification == 1) { - args = [ "--simple-hash" ] + args += [ "--simple-hash" ] } if (chip_enable_ota_requestor) { - args = [ "--ota-enabled" ] + args += [ "--ota-enabled" ] } } diff --git a/examples/placeholder/linux/static-supported-modes-manager.cpp b/examples/placeholder/linux/static-supported-modes-manager.cpp index 94345600cf53fd..59bccf11faa481 100644 --- a/examples/placeholder/linux/static-supported-modes-manager.cpp +++ b/examples/placeholder/linux/static-supported-modes-manager.cpp @@ -1,7 +1,6 @@ #include #include -using namespace std; using namespace chip; using namespace chip::app::Clusters; using namespace chip::app::Clusters::ModeSelect; diff --git a/examples/placeholder/linux/static-supported-temperature-levels.cpp b/examples/placeholder/linux/static-supported-temperature-levels.cpp index de8933fdf649ea..4b65317e8cc58f 100644 --- a/examples/placeholder/linux/static-supported-temperature-levels.cpp +++ b/examples/placeholder/linux/static-supported-temperature-levels.cpp @@ -19,7 +19,6 @@ #include #include -using namespace std; using namespace chip; using namespace chip::app::Clusters; using namespace chip::app::Clusters::TemperatureControl; diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index 074f078af003b4..a2e341efbe7a0f 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -679,16 +679,16 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl) ApplicationShutdown(); -#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE - ShutdownCommissioner(); -#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE - #if defined(ENABLE_CHIP_SHELL) shellThread.join(); #endif Server::GetInstance().Shutdown(); +#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE + ShutdownCommissioner(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE + #if ENABLE_TRACING tracing_setup.StopTracing(); #endif diff --git a/examples/platform/nxp/mcxw71_k32w1/button/ButtonManager.cpp b/examples/platform/nxp/mcxw71_k32w1/button/ButtonManager.cpp index 8bc61eeba64e72..c94e6e44fe71b6 100644 --- a/examples/platform/nxp/mcxw71_k32w1/button/ButtonManager.cpp +++ b/examples/platform/nxp/mcxw71_k32w1/button/ButtonManager.cpp @@ -52,10 +52,6 @@ ButtonManager ButtonManager::sInstance; TimerHandle_t resetTimer; -#if (CHIP_CONFIG_ENABLE_ICD_LIT && CHIP_CONFIG_ENABLE_ICD_DSLS) -static bool sitModeRequested; -#endif // CHIP_CONFIG_ENABLE_ICD_LIT && CHIP_CONFIG_ENABLE_ICD_DSLS - CHIP_ERROR ButtonManager::Init() { resetTimer = xTimerCreate("FnTmr", 1, false, (void *) this, [](TimerHandle_t xTimer) { @@ -65,10 +61,6 @@ CHIP_ERROR ButtonManager::Init() }); VerifyOrReturnError(resetTimer != NULL, APP_ERROR_CREATE_TIMER_FAILED); -#if (CHIP_CONFIG_ENABLE_ICD_LIT && CHIP_CONFIG_ENABLE_ICD_DSLS) - static bool sitModeRequested; -#endif // CHIP_CONFIG_ENABLE_ICD_LIT && CHIP_CONFIG_ENABLE_ICD_DSLS - return CHIP_NO_ERROR; } @@ -208,6 +200,9 @@ void ButtonManager::BleHandler(const AppEvent & event) #if (CHIP_CONFIG_ENABLE_ICD_LIT && CHIP_CONFIG_ENABLE_ICD_DSLS) void ButtonManager::DSLSActionEventHandler(const AppEvent & event) { + + static bool sitModeRequested = false; + if (chip::DeviceLayer::ConfigurationMgr().IsFullyProvisioned()) { if (!sitModeRequested) diff --git a/examples/platform/nxp/mcxw71_k32w1/button/ButtonManager.h b/examples/platform/nxp/mcxw71_k32w1/button/ButtonManager.h index 7f4f6cf81d94d3..4ed6553d10d495 100644 --- a/examples/platform/nxp/mcxw71_k32w1/button/ButtonManager.h +++ b/examples/platform/nxp/mcxw71_k32w1/button/ButtonManager.h @@ -25,6 +25,7 @@ #include "fsl_component_button.h" +#include #include // Application-defined error codes in the CHIP_ERROR space. @@ -87,12 +88,14 @@ class ButtonManager */ static void ResetActionEventHandler(const AppEvent & event); +#if (CHIP_CONFIG_ENABLE_ICD_LIT && CHIP_CONFIG_ENABLE_ICD_DSLS) /** * @brief This callback schedules a DSLS LIT action (Dynamic SIT LIT Support). * * It is used when the app requests SIT mode (check spec, "Runtime Operating Mode Switching") */ static void DSLSActionEventHandler(const AppEvent & event); +#endif /* CHIP_CONFIG_ENABLE_ICD_LIT && CHIP_CONFIG_ENABLE_ICD_DSLS */ /** * @brief This callback performs a factory reset. diff --git a/examples/platform/silabs/MatterConfig.cpp b/examples/platform/silabs/MatterConfig.cpp index b3c672dc2cc21b..20f73ab6811e58 100644 --- a/examples/platform/silabs/MatterConfig.cpp +++ b/examples/platform/silabs/MatterConfig.cpp @@ -230,13 +230,14 @@ CHIP_ERROR SilabsMatterConfig::InitMatter(const char * appName) ReturnErrorOnFailure(PlatformMgr().InitChipStack()); + chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName(appName); + // Provision Manager Silabs::Provision::Manager & provision = Silabs::Provision::Manager::GetInstance(); ReturnErrorOnFailure(provision.Init()); SetDeviceInstanceInfoProvider(&provision.GetStorage()); SetCommissionableDataProvider(&provision.GetStorage()); - - chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName(appName); + ChipLogProgress(DeviceLayer, "Provision mode %s", provision.IsProvisionRequired() ? "ENABLED" : "disabled"); #if CHIP_ENABLE_OPENTHREAD ReturnErrorOnFailure(InitOpenThread()); diff --git a/examples/refrigerator-app/refrigerator-common/src/static-supported-temperature-levels.cpp b/examples/refrigerator-app/refrigerator-common/src/static-supported-temperature-levels.cpp index 8678e5f3d009d0..a7198c0cf0a3b6 100644 --- a/examples/refrigerator-app/refrigerator-common/src/static-supported-temperature-levels.cpp +++ b/examples/refrigerator-app/refrigerator-common/src/static-supported-temperature-levels.cpp @@ -19,7 +19,6 @@ #include #include -using namespace std; using namespace chip; using namespace chip::app::Clusters; using namespace chip::app::Clusters::TemperatureControl; diff --git a/examples/tv-app/android/include/account-login/AccountLoginManager.cpp b/examples/tv-app/android/include/account-login/AccountLoginManager.cpp index 2aa0b313b0eda1..a7e9c9fd627c1a 100644 --- a/examples/tv-app/android/include/account-login/AccountLoginManager.cpp +++ b/examples/tv-app/android/include/account-login/AccountLoginManager.cpp @@ -23,7 +23,6 @@ #include #include -using namespace std; using namespace chip::app::Clusters; using namespace chip::app::Clusters::AccountLogin; using Status = chip::Protocols::InteractionModel::Status; @@ -31,12 +30,12 @@ using Status = chip::Protocols::InteractionModel::Status; namespace { const auto loginTempAccountIdentifierFieldId = - to_string(chip::to_underlying(AccountLogin::Commands::Login::Fields::kTempAccountIdentifier)); -const auto loginSetupPINFieldId = to_string(chip::to_underlying(AccountLogin::Commands::Login::Fields::kSetupPIN)); -const auto loginNodeFieldId = to_string(chip::to_underlying(AccountLogin::Commands::Login::Fields::kNode)); -const auto logoutNodeFieldId = to_string(chip::to_underlying(AccountLogin::Commands::Logout::Fields::kNode)); + std::to_string(chip::to_underlying(AccountLogin::Commands::Login::Fields::kTempAccountIdentifier)); +const auto loginSetupPINFieldId = std::to_string(chip::to_underlying(AccountLogin::Commands::Login::Fields::kSetupPIN)); +const auto loginNodeFieldId = std::to_string(chip::to_underlying(AccountLogin::Commands::Login::Fields::kNode)); +const auto logoutNodeFieldId = std::to_string(chip::to_underlying(AccountLogin::Commands::Logout::Fields::kNode)); -string charSpanToString(const CharSpan & charSpan) +std::string charSpanToString(const CharSpan & charSpan) { return { charSpan.data(), charSpan.size() }; } @@ -45,12 +44,12 @@ std::string serializeLoginCommand(AccountLogin::Commands::Login::Type cmd) { return R"({")" + loginTempAccountIdentifierFieldId + R"(":")" + charSpanToString(cmd.tempAccountIdentifier) + R"(",)" + R"(")" + loginSetupPINFieldId + R"(":")" + charSpanToString(cmd.setupPIN) + R"(",)" + R"(")" + loginNodeFieldId + R"(":")" + - to_string(cmd.node.Value()) + R"("})"; + std::to_string(cmd.node.Value()) + R"("})"; } std::string serializeLogoutCommand(AccountLogin::Commands::Logout::Type cmd) { - return R"({")" + logoutNodeFieldId + R"(":")" + to_string(cmd.node.Value()) + R"("})"; + return R"({")" + logoutNodeFieldId + R"(":")" + std::to_string(cmd.node.Value()) + R"("})"; } } // namespace @@ -128,7 +127,7 @@ bool AccountLoginManager::HandleLogout(const chip::Optional & node void AccountLoginManager::HandleGetSetupPin(CommandResponseHelper & helper, const CharSpan & tempAccountIdentifier) { - string tempAccountIdentifierString(tempAccountIdentifier.data(), tempAccountIdentifier.size()); + std::string tempAccountIdentifierString(tempAccountIdentifier.data(), tempAccountIdentifier.size()); GetSetupPINResponse response; ChipLogProgress(Zcl, "temporary account id: %s returning pin: %s", tempAccountIdentifierString.c_str(), mSetupPin); @@ -144,7 +143,7 @@ void AccountLoginManager::GetSetupPin(char * setupPin, size_t setupPinSize, cons // Other methods in this class do not need to be changed beecause those will get routed to java layer // upstream. ChipLogProgress(DeviceLayer, "AccountLoginManager::GetSetupPin called for endpoint %d", mEndpointId); - string tempAccountIdentifierString(tempAccountIdentifier.data(), tempAccountIdentifier.size()); + std::string tempAccountIdentifierString(tempAccountIdentifier.data(), tempAccountIdentifier.size()); if (mCommandDelegate == nullptr) { // For the dummy content apps to work. diff --git a/examples/tv-app/android/include/application-basic/ApplicationBasicManager.cpp b/examples/tv-app/android/include/application-basic/ApplicationBasicManager.cpp index d94177155f4fde..80e11460bd88e3 100644 --- a/examples/tv-app/android/include/application-basic/ApplicationBasicManager.cpp +++ b/examples/tv-app/android/include/application-basic/ApplicationBasicManager.cpp @@ -18,7 +18,6 @@ #include "ApplicationBasicManager.h" -using namespace std; using namespace chip::app; using namespace chip::app::Clusters::ApplicationBasic; diff --git a/examples/tv-app/android/include/audio-output/AudioOutputManager.cpp b/examples/tv-app/android/include/audio-output/AudioOutputManager.cpp index 1b8a6a36c84912..77a1e2111b44be 100644 --- a/examples/tv-app/android/include/audio-output/AudioOutputManager.cpp +++ b/examples/tv-app/android/include/audio-output/AudioOutputManager.cpp @@ -18,7 +18,6 @@ #include "AudioOutputManager.h" -using namespace std; using namespace chip::app; using namespace chip::app::Clusters::AudioOutput; diff --git a/examples/tv-app/android/include/content-app-observer/ContentAppObserver.cpp b/examples/tv-app/android/include/content-app-observer/ContentAppObserver.cpp index 7145ba24305f21..158da869c07b67 100644 --- a/examples/tv-app/android/include/content-app-observer/ContentAppObserver.cpp +++ b/examples/tv-app/android/include/content-app-observer/ContentAppObserver.cpp @@ -20,7 +20,6 @@ #include #include -using namespace std; using namespace chip; using namespace chip::app::Clusters::ContentAppObserver; diff --git a/examples/tv-app/android/include/content-control/ContentController.cpp b/examples/tv-app/android/include/content-control/ContentController.cpp index edf2550c489d62..4883d4f78086e8 100644 --- a/examples/tv-app/android/include/content-control/ContentController.cpp +++ b/examples/tv-app/android/include/content-control/ContentController.cpp @@ -19,7 +19,6 @@ #include #include -using namespace std; using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::app::DataModel; diff --git a/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.cpp b/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.cpp index 671daab4b239c4..ab98213f068ac3 100644 --- a/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.cpp +++ b/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.cpp @@ -24,7 +24,6 @@ #include #include -using namespace std; using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::app::DataModel; @@ -32,7 +31,8 @@ using namespace chip::app::Clusters::ContentLauncher; using ContentAppAttributeDelegate = chip::AppPlatform::ContentAppAttributeDelegate; AppContentLauncherManager::AppContentLauncherManager(ContentAppAttributeDelegate * attributeDelegate, - list acceptHeaderList, uint32_t supportedStreamingProtocols) : + std::list acceptHeaderList, + uint32_t supportedStreamingProtocols) : mAttributeDelegate(attributeDelegate) { mAcceptHeaderList = acceptHeaderList; @@ -46,7 +46,7 @@ void AppContentLauncherManager::HandleLaunchContent(CommandResponseHelper -using namespace std; using namespace chip; using namespace chip::app; using namespace chip::app::DataModel; @@ -204,7 +203,7 @@ uint64_t AppMediaPlaybackManager::HandleMediaRequestGetAttribute(chip::Attribute Json::Value value; if (reader.parse(resStr, value)) { - std::string attrId = to_string(attributeId); + std::string attrId = std::to_string(attributeId); ChipLogProgress(Zcl, "AppMediaPlaybackManager::HandleMediaRequestGetAttribute response parsing done. reading attr %s", attrId.c_str()); if (!value[attrId].empty() && value[attrId].isUInt()) @@ -250,14 +249,14 @@ CHIP_ERROR AppMediaPlaybackManager::HandleGetSampledPosition(AttributeValueEncod Json::Value value; if (reader.parse(resStr, value)) { - std::string attrId = to_string(chip::app::Clusters::MediaPlayback::Attributes::SampledPosition::Id); + std::string attrId = std::to_string(chip::app::Clusters::MediaPlayback::Attributes::SampledPosition::Id); ChipLogProgress(Zcl, "AppContentLauncherManager::HandleGetSampledPosition response parsing done. reading attr %s", attrId.c_str()); if (!value[attrId].empty() && value[attrId].isObject()) { - std::string updatedAt = to_string( + std::string updatedAt = std::to_string( static_cast(chip::app::Clusters::MediaPlayback::Structs::PlaybackPositionStruct::Fields::kUpdatedAt)); - std::string position = to_string( + std::string position = std::to_string( static_cast(chip::app::Clusters::MediaPlayback::Structs::PlaybackPositionStruct::Fields::kPosition)); if (!value[attrId][updatedAt].empty() && !value[attrId][position].empty() && value[attrId][updatedAt].isUInt() && value[attrId][position].isUInt()) diff --git a/examples/tv-app/android/include/messages/MessagesManager.cpp b/examples/tv-app/android/include/messages/MessagesManager.cpp index 00848c67312751..a4fdaa53291394 100644 --- a/examples/tv-app/android/include/messages/MessagesManager.cpp +++ b/examples/tv-app/android/include/messages/MessagesManager.cpp @@ -17,7 +17,6 @@ #include "MessagesManager.h" -using namespace std; using namespace chip::app; using namespace chip::app::Clusters::Messages; diff --git a/examples/tv-app/android/include/target-navigator/TargetNavigatorManager.cpp b/examples/tv-app/android/include/target-navigator/TargetNavigatorManager.cpp index fe7884227880df..3b84a050d3e51a 100644 --- a/examples/tv-app/android/include/target-navigator/TargetNavigatorManager.cpp +++ b/examples/tv-app/android/include/target-navigator/TargetNavigatorManager.cpp @@ -23,7 +23,6 @@ #include #include -using namespace std; using namespace chip::app; using namespace chip::app::Clusters::TargetNavigator; using ContentAppAttributeDelegate = chip::AppPlatform::ContentAppAttributeDelegate; @@ -53,16 +52,16 @@ CHIP_ERROR TargetNavigatorManager::HandleGetTargetList(AttributeValueEncoder & a Json::Value value; if (reader.parse(resStr, value)) { - std::string attrId = to_string(chip::app::Clusters::TargetNavigator::Attributes::TargetList::Id); + std::string attrId = std::to_string(chip::app::Clusters::TargetNavigator::Attributes::TargetList::Id); ChipLogProgress(Zcl, "TargetNavigatorManager::HandleNavigateTarget response parsing done. reading attr %s", attrId.c_str()); if (value[attrId].isArray()) { return aEncoder.EncodeList([&](const auto & encoder) -> CHIP_ERROR { int i = 0; - std::string targetId = to_string(static_cast( + std::string targetId = std::to_string(static_cast( chip::app::Clusters::TargetNavigator::Structs::TargetInfoStruct::Fields::kIdentifier)); - std::string targetName = to_string( + std::string targetName = std::to_string( static_cast(chip::app::Clusters::TargetNavigator::Structs::TargetInfoStruct::Fields::kName)); for (Json::Value & entry : value[attrId]) { @@ -118,7 +117,7 @@ uint8_t TargetNavigatorManager::HandleGetCurrentTarget() Json::Value value; if (reader.parse(resStr, value)) { - std::string attrId = to_string(chip::app::Clusters::TargetNavigator::Attributes::CurrentTarget::Id); + std::string attrId = std::to_string(chip::app::Clusters::TargetNavigator::Attributes::CurrentTarget::Id); ChipLogProgress(Zcl, "TargetNavigatorManager::HandleGetCurrentTarget response parsing done. reading attr %s", attrId.c_str()); if (value[attrId].isUInt() && value[attrId].asUInt() < 256) diff --git a/examples/tv-app/android/java/ContentLauncherManager.cpp b/examples/tv-app/android/java/ContentLauncherManager.cpp index 9aacc2d6e56b22..b1c3a8cac64a4b 100644 --- a/examples/tv-app/android/java/ContentLauncherManager.cpp +++ b/examples/tv-app/android/java/ContentLauncherManager.cpp @@ -27,7 +27,6 @@ #include #include -using namespace std; using namespace chip; using namespace chip::app::DataModel; using namespace chip::app::Clusters::ContentLauncher; diff --git a/examples/tv-app/android/java/application-launcher/ApplicationLauncherManager.cpp b/examples/tv-app/android/java/application-launcher/ApplicationLauncherManager.cpp index 8ee91292a5e76a..9267a086c64c56 100644 --- a/examples/tv-app/android/java/application-launcher/ApplicationLauncherManager.cpp +++ b/examples/tv-app/android/java/application-launcher/ApplicationLauncherManager.cpp @@ -27,7 +27,6 @@ #include #include -using namespace std; using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::app::Clusters::ApplicationLauncher; diff --git a/examples/tv-app/tv-common/clusters/account-login/AccountLoginManager.cpp b/examples/tv-app/tv-common/clusters/account-login/AccountLoginManager.cpp index 9264553c14d002..21c96255ea6f37 100644 --- a/examples/tv-app/tv-common/clusters/account-login/AccountLoginManager.cpp +++ b/examples/tv-app/tv-common/clusters/account-login/AccountLoginManager.cpp @@ -21,7 +21,6 @@ #include #include -using namespace std; using namespace chip::app::Clusters::AccountLogin; AccountLoginManager::AccountLoginManager(const char * setupPin) @@ -32,8 +31,8 @@ AccountLoginManager::AccountLoginManager(const char * setupPin) bool AccountLoginManager::HandleLogin(const CharSpan & tempAccountIdentifier, const CharSpan & setupPin, const chip::Optional & nodeId) { - string tempAccountIdentifierString(tempAccountIdentifier.data(), tempAccountIdentifier.size()); - string setupPinString(setupPin.data(), setupPin.size()); + std::string tempAccountIdentifierString(tempAccountIdentifier.data(), tempAccountIdentifier.size()); + std::string setupPinString(setupPin.data(), setupPin.size()); ChipLogProgress(Zcl, "temporary account id: %s", tempAccountIdentifierString.c_str()); ChipLogProgress(Zcl, "setup pin %s", setupPinString.c_str()); @@ -57,7 +56,7 @@ bool AccountLoginManager::HandleLogout(const chip::Optional & node void AccountLoginManager::HandleGetSetupPin(CommandResponseHelper & helper, const CharSpan & tempAccountIdentifier) { - string tempAccountIdentifierString(tempAccountIdentifier.data(), tempAccountIdentifier.size()); + std::string tempAccountIdentifierString(tempAccountIdentifier.data(), tempAccountIdentifier.size()); GetSetupPINResponse response; ChipLogProgress(Zcl, "temporary account id: %s returning pin: %s", tempAccountIdentifierString.c_str(), mSetupPin); diff --git a/examples/tv-app/tv-common/clusters/application-basic/ApplicationBasicManager.cpp b/examples/tv-app/tv-common/clusters/application-basic/ApplicationBasicManager.cpp index d94177155f4fde..80e11460bd88e3 100644 --- a/examples/tv-app/tv-common/clusters/application-basic/ApplicationBasicManager.cpp +++ b/examples/tv-app/tv-common/clusters/application-basic/ApplicationBasicManager.cpp @@ -18,7 +18,6 @@ #include "ApplicationBasicManager.h" -using namespace std; using namespace chip::app; using namespace chip::app::Clusters::ApplicationBasic; diff --git a/examples/tv-app/tv-common/clusters/application-launcher/ApplicationLauncherManager.cpp b/examples/tv-app/tv-common/clusters/application-launcher/ApplicationLauncherManager.cpp index c915856f48fd4d..3a4960970f06ba 100644 --- a/examples/tv-app/tv-common/clusters/application-launcher/ApplicationLauncherManager.cpp +++ b/examples/tv-app/tv-common/clusters/application-launcher/ApplicationLauncherManager.cpp @@ -18,7 +18,6 @@ #include "ApplicationLauncherManager.h" -using namespace std; using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::app::Clusters::ApplicationLauncher; diff --git a/examples/tv-app/tv-common/clusters/audio-output/AudioOutputManager.cpp b/examples/tv-app/tv-common/clusters/audio-output/AudioOutputManager.cpp index 1b8a6a36c84912..77a1e2111b44be 100644 --- a/examples/tv-app/tv-common/clusters/audio-output/AudioOutputManager.cpp +++ b/examples/tv-app/tv-common/clusters/audio-output/AudioOutputManager.cpp @@ -18,7 +18,6 @@ #include "AudioOutputManager.h" -using namespace std; using namespace chip::app; using namespace chip::app::Clusters::AudioOutput; diff --git a/examples/tv-app/tv-common/clusters/content-app-observer/ContentAppObserver.cpp b/examples/tv-app/tv-common/clusters/content-app-observer/ContentAppObserver.cpp index a6010a54b0a0f5..9c42fe3f11a525 100644 --- a/examples/tv-app/tv-common/clusters/content-app-observer/ContentAppObserver.cpp +++ b/examples/tv-app/tv-common/clusters/content-app-observer/ContentAppObserver.cpp @@ -20,7 +20,6 @@ #include #include -using namespace std; using namespace chip; using namespace chip::app::Clusters::ContentAppObserver; diff --git a/examples/tv-app/tv-common/clusters/content-control/ContentController.cpp b/examples/tv-app/tv-common/clusters/content-control/ContentController.cpp index 19317a71b7cfaf..352b204bab65cb 100644 --- a/examples/tv-app/tv-common/clusters/content-control/ContentController.cpp +++ b/examples/tv-app/tv-common/clusters/content-control/ContentController.cpp @@ -19,7 +19,6 @@ #include #include -using namespace std; using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::app::DataModel; diff --git a/examples/tv-app/tv-common/clusters/content-launcher/ContentLauncherManager.cpp b/examples/tv-app/tv-common/clusters/content-launcher/ContentLauncherManager.cpp index f0519619c2052a..74dd6de8c8071a 100644 --- a/examples/tv-app/tv-common/clusters/content-launcher/ContentLauncherManager.cpp +++ b/examples/tv-app/tv-common/clusters/content-launcher/ContentLauncherManager.cpp @@ -23,13 +23,12 @@ #include #include -using namespace std; using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::app::DataModel; using namespace chip::app::Clusters::ContentLauncher; -ContentLauncherManager::ContentLauncherManager(list acceptHeaderList, uint32_t supportedStreamingProtocols) +ContentLauncherManager::ContentLauncherManager(std::list acceptHeaderList, uint32_t supportedStreamingProtocols) { mAcceptHeaderList = acceptHeaderList; mSupportedStreamingProtocols = supportedStreamingProtocols; @@ -103,7 +102,7 @@ void ContentLauncherManager::HandleLaunchContent(CommandResponseHelper -using namespace std; using namespace chip; using namespace chip::app::Clusters::MediaInput; @@ -76,8 +75,8 @@ bool MediaInputManager::HandleShowInputStatus() ChipLogProgress(Zcl, " MediaInputManager::HandleShowInputStatus()"); for (auto const & inputInfo : this->mInputs) { - string name(inputInfo.name.data(), inputInfo.name.size()); - string desc(inputInfo.description.data(), inputInfo.description.size()); + std::string name(inputInfo.name.data(), inputInfo.name.size()); + std::string desc(inputInfo.description.data(), inputInfo.description.size()); ChipLogProgress(Zcl, " [%d] type=%d selected=%d name=%s desc=%s", inputInfo.index, static_cast(inputInfo.inputType), (mCurrentInput == inputInfo.index ? 1 : 0), name.c_str(), desc.c_str()); diff --git a/examples/tv-app/tv-common/clusters/media-playback/MediaPlaybackManager.cpp b/examples/tv-app/tv-common/clusters/media-playback/MediaPlaybackManager.cpp index 0e79c6b2a3e9a3..91159021842e75 100644 --- a/examples/tv-app/tv-common/clusters/media-playback/MediaPlaybackManager.cpp +++ b/examples/tv-app/tv-common/clusters/media-playback/MediaPlaybackManager.cpp @@ -21,7 +21,6 @@ #include -using namespace std; using namespace chip::app::DataModel; using namespace chip::app::Clusters::MediaPlayback; using namespace chip::Uint8; diff --git a/examples/tv-app/tv-common/clusters/messages/MessagesManager.cpp b/examples/tv-app/tv-common/clusters/messages/MessagesManager.cpp index 681cd56d6647fa..181c37ca0c3d5a 100644 --- a/examples/tv-app/tv-common/clusters/messages/MessagesManager.cpp +++ b/examples/tv-app/tv-common/clusters/messages/MessagesManager.cpp @@ -21,7 +21,6 @@ #include #include -using namespace std; using namespace chip; using namespace chip::app; using namespace chip::app::Clusters::Messages; diff --git a/examples/tv-app/tv-common/clusters/target-navigator/TargetNavigatorManager.cpp b/examples/tv-app/tv-common/clusters/target-navigator/TargetNavigatorManager.cpp index dced0371fb9f39..03932528e57b0d 100644 --- a/examples/tv-app/tv-common/clusters/target-navigator/TargetNavigatorManager.cpp +++ b/examples/tv-app/tv-common/clusters/target-navigator/TargetNavigatorManager.cpp @@ -21,7 +21,6 @@ #include -using namespace std; using namespace chip::app; using namespace chip::app::Clusters::TargetNavigator; diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java index 5db9a3560749b5..fc3ba6cd1da90a 100644 --- a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java +++ b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java @@ -54,7 +54,9 @@ public class ConnectionExampleFragment extends Fragment { private final CastingPlayer targetCastingPlayer; private final boolean useCommissionerGeneratedPasscode; private TextView connectionFragmentStatusTextView; + private TextView commissionerDeclarationErrorTextView; private Button connectionFragmentNextButton; + private AlertDialog passcodeDialog; public ConnectionExampleFragment( CastingPlayer targetCastingPlayer, boolean useCommissionerGeneratedPasscode) { @@ -100,6 +102,8 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { Log.i(TAG, "onViewCreated()"); connectionFragmentStatusTextView = getView().findViewById(R.id.connectionFragmentStatusText); + commissionerDeclarationErrorTextView = + getView().findViewById(R.id.commissionerDeclarationErrorTextView); if (useCommissionerGeneratedPasscode) { connectionFragmentStatusTextView.setText( "Verifying or establishing connection with Casting Player with device name: " @@ -190,32 +194,52 @@ public void handle(MatterError err) { }, null); - // CommissionerDeclaration is only needed for the CastingPlayer/Commissioner-Generated - // passcode commissioning flow. - if (useCommissionerGeneratedPasscode) { - connectionCallbacks.onCommissionerDeclaration = - new MatterCallback() { - @Override - public void handle(CommissionerDeclaration cd) { - Log.i(TAG, "CastingPlayer CommissionerDeclaration message received: "); - cd.logDetail(); - - getActivity() - .runOnUiThread( - () -> { - connectionFragmentStatusTextView.setText( - "CommissionerDeclaration message received from Casting Player: \n\n"); - if (cd.getCommissionerPasscode()) { - - displayPasscodeInputDialog(getActivity()); + // The CommissionerDeclaration callback is optional and only needed for the + // CastingPlayer/Commissioner-Generated + // passcode commissioning flow. However, if we want to know when the + // CastingPlayer/Commissioner user + // has cancelled the connection attempt when using the Client/Commissionee generated + // passcode flow, then we + // need to implement this callback. + connectionCallbacks.onCommissionerDeclaration = + new MatterCallback() { + @Override + public void handle(CommissionerDeclaration cd) { + Log.i(TAG, "CastingPlayer CommissionerDeclaration message received: "); + cd.logDetail(); + + getActivity() + .runOnUiThread( + () -> { + connectionFragmentStatusTextView.setText( + "CommissionerDeclaration message received from Casting Player: \n\n"); + if (cd.getCommissionerPasscode()) { + + displayPasscodeInputDialog(getActivity()); + connectionFragmentStatusTextView.setText( + "CommissionerDeclaration message received from Casting Player: A passcode is now displayed for the user by the Casting Player. \n\n"); + } + if (cd.getCancelPasscode()) { + if (useCommissionerGeneratedPasscode) { connectionFragmentStatusTextView.setText( - "CommissionerDeclaration message received from Casting Player: A passcode is now displayed for the user by the Casting Player. \n\n"); + "CastingPlayer/Commissioner-Generated passcode connection attempt cancelled by the CastingPlayer/Commissioner user. \n\nRoute back to exit. \n\n"); + } else { + connectionFragmentStatusTextView.setText( + "Connection attempt cancelled by the CastingPlayer/Commissioner user. \n\nRoute back to exit. \n\n"); } - }); - } - }; - } + if (passcodeDialog != null && passcodeDialog.isShowing()) { + passcodeDialog.dismiss(); + } + } + if (cd.getErrorCode() != CommissionerDeclaration.CdError.noError) { + commissionerDeclarationErrorTextView.setText( + "CommissionerDeclaration error from CastingPlayer: " + + cd.getErrorCode().getDescription()); + } + }); + } + }; MatterError err = targetCastingPlayer.verifyOrEstablishConnection( @@ -331,7 +355,7 @@ public void onClick(DialogInterface dialog, int which) { TAG, "displayPasscodeInputDialog() user cancelled the CastingPlayer/Commissioner-Generated Passcode input dialog. Calling stopConnecting()"); connectionFragmentStatusTextView.setText( - "Connection attempt with Casting Player cancelled by the user, route back to exit. \n\n"); + "Connection attempt with Casting Player cancelled by the Casting Client/Commissionee user. \n\nRoute back to exit. \n\n"); MatterError err = targetCastingPlayer.stopConnecting(); if (err.hasError()) { MatterError finalErr = err; @@ -348,9 +372,9 @@ public void onClick(DialogInterface dialog, int which) { }); builder.setView(dialogView); - AlertDialog alertDialog = builder.create(); - alertDialog.show(); - alertDialog + passcodeDialog = builder.create(); // Store the dialog instance in the passcodeDialog variable + passcodeDialog.show(); + passcodeDialog .getWindow() .setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/support/CommissionerDeclaration.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/support/CommissionerDeclaration.java index 82213a3a69517d..401c948d04a2a2 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/support/CommissionerDeclaration.java +++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/support/CommissionerDeclaration.java @@ -22,39 +22,62 @@ public class CommissionerDeclaration { static final String TAG = CommissionerDeclaration.class.getSimpleName(); - /** The allowed values for the ErrorCode field are the following */ + /** + * The allowed values for the ErrorCode field are the following. Indicates errors incurred during + * commissioning. + */ public enum CdError { - kNoError(0), - kCommissionableDiscoveryFailed(1), - kPaseConnectionFailed(2), - kPaseAuthFailed(3), - kDacValidationFailed(4), - kAlreadyOnFabric(5), - kOperationalDiscoveryFailed(6), - kCaseConnectionFailed(7), - kCaseAuthFailed(8), - kConfigurationFailed(9), - kBindingConfigurationFailed(10), - kCommissionerPasscodeNotSupported(11), - kInvalidIdentificationDeclarationParams(12), - kAppInstallConsentPending(13), - kAppInstalling(14), - kAppInstallFailed(15), - kAppInstalledRetryNeeded(16), - kCommissionerPasscodeDisabled(17), - kUnexpectedCommissionerPasscodeReady(18); + noError(0, "No error"), + commissionableDiscoveryFailed(1, "Commissionable Node discovery failed"), + paseConnectionFailed(2, "PASE connection failed"), + paseAuthFailed(3, "PASE authentication failed (bad Passcode)"), + dacValidationFailed(4, "DAC validation failed"), + alreadyOnFabric(5, "Already on fabric"), + operationalDiscoveryFailed(6, "Operational Node discovery failed"), + caseConnectionFailed(7, "CASE connection failed"), + caseAuthFailed(8, "CASE authentication failed"), + configurationFailed(9, "Configuration failed"), + bindingConfigurationFailed(10, "Binding Configuration failed"), + commissionerPasscodeNotSupported(11, "Commissioner Passcode not supported"), + invalidIdentificationDeclarationParams(12, "Invalid UDC Identification Declaration parameters"), + appInstallConsentPending(13, "App Install Consent Pending"), + appInstalling(14, "App Installing"), + appInstallFailed(15, "App Install Failed"), + appInstalledRetryNeeded(16, "App Installed, Retry Needed"), + commissionerPasscodeDisabled(17, "Commissioner Passcode disabled"), + unexpectedCommissionerPasscodeReady(18, "Unexpected Commissioner Passcode ready"); + private final int value; + private final String description; - CdError(int value) { + private CdError(int value, String description) { this.value = value; + this.description = description; + } + + private static String getDefaultDescription(int value) { + for (CdError error : CdError.values()) { + if (error.value == value) { + return error.name(); + } + } + return "Unknown Error"; + } + + CdError(int value) { + this(value, getDefaultDescription(value)); } public int getValue() { return value; } + + public String getDescription() { + return description; + } } /** Feature: All - Indicates errors incurred during commissioning. */ - private CdError errorCode = CdError.kNoError; + private CdError errorCode = CdError.noError; /** * Feature: Coordinate PIN Dialogs - When NoPasscode field set to true, and the Commissioner * determines that a Passcode code will be needed for commissioning. @@ -81,6 +104,11 @@ public int getValue() { * also displays a QR code. */ private boolean qRCodeDisplayed = false; + /** + * Feature: Commissioner-Generated Passcode - Flag to indicate when the CastingplAYER/Commissioner + * user has decided to exit the commissioning process. + */ + private boolean cancelPasscode = false; public CommissionerDeclaration( int errorCode, @@ -88,13 +116,15 @@ public CommissionerDeclaration( boolean noAppsFound, boolean passcodeDialogDisplayed, boolean commissionerPasscode, - boolean qRCodeDisplayed) { + boolean qRCodeDisplayed, + boolean cancelPasscode) { this.errorCode = CdError.values()[errorCode]; this.needsPasscode = needsPasscode; this.noAppsFound = noAppsFound; this.passcodeDialogDisplayed = passcodeDialogDisplayed; this.commissionerPasscode = commissionerPasscode; this.qRCodeDisplayed = qRCodeDisplayed; + this.cancelPasscode = cancelPasscode; } public void setErrorCode(CdError errorCode) { @@ -145,6 +175,10 @@ public boolean getQRCodeDisplayed() { return this.qRCodeDisplayed; } + public boolean getCancelPasscode() { + return this.cancelPasscode; + } + @Override public String toString() { return "CommissionerDeclaration::errorCode: " @@ -163,7 +197,10 @@ public String toString() { + commissionerPasscode + "\n" + "CommissionerDeclaration::qRCodeDisplayed: " - + qRCodeDisplayed; + + qRCodeDisplayed + + "\n" + + "CommissionerDeclaration::cancelPasscode: " + + cancelPasscode; } public void logDetail() { diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/Converters-JNI.cpp b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/Converters-JNI.cpp index 69f70c47d1762e..5b002f392ab4c5 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/Converters-JNI.cpp +++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/Converters-JNI.cpp @@ -528,7 +528,7 @@ convertCommissionerDeclarationFromCppToJava(const chip::Protocols::UserDirectedC jCommissionerDeclarationClass); VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr); - jmethodID jCommissionerDeclarationConstructor = env->GetMethodID(jCommissionerDeclarationClass, "", "(IZZZZZ)V"); + jmethodID jCommissionerDeclarationConstructor = env->GetMethodID(jCommissionerDeclarationClass, "", "(IZZZZZZ)V"); if (jCommissionerDeclarationConstructor == nullptr) { ChipLogError(AppServer, @@ -539,7 +539,8 @@ convertCommissionerDeclarationFromCppToJava(const chip::Protocols::UserDirectedC return env->NewObject(jCommissionerDeclarationClass, jCommissionerDeclarationConstructor, static_cast(cppCd.GetErrorCode()), cppCd.GetNeedsPasscode(), cppCd.GetNoAppsFound(), - cppCd.GetPasscodeDialogDisplayed(), cppCd.GetCommissionerPasscode(), cppCd.GetQRCodeDisplayed()); + cppCd.GetPasscodeDialogDisplayed(), cppCd.GetCommissionerPasscode(), cppCd.GetQRCodeDisplayed(), + cppCd.GetCancelPasscode()); } }; // namespace support diff --git a/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_connection_example.xml b/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_connection_example.xml index 9c2cf867326175..1e6862268a6d60 100644 --- a/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_connection_example.xml +++ b/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_connection_example.xml @@ -28,6 +28,16 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/matter_connection_next_button_text" /> + + diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommissionerDeclaration.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommissionerDeclaration.h index 85bc465c667ab8..f81d032feb3be1 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommissionerDeclaration.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommissionerDeclaration.h @@ -25,27 +25,29 @@ */ @interface MCCommissionerDeclaration : NSObject -/** The allowed values for the ErrorCode field are the following */ +/** The allowed values for the ErrorCode field are the following. Indicates errors incurred + * during commissioning. + */ typedef NS_ENUM(NSInteger, CdError) { - kNoError = 0, - kCommissionableDiscoveryFailed = 1, - kPaseConnectionFailed = 2, - kPaseAuthFailed = 3, - kDacValidationFailed = 4, - kAlreadyOnFabric = 5, - kOperationalDiscoveryFailed = 6, - kCaseConnectionFailed = 7, - kCaseAuthFailed = 8, - kConfigurationFailed = 9, - kBindingConfigurationFailed = 10, - kCommissionerPasscodeNotSupported = 11, - kInvalidIdentificationDeclarationParams = 12, - kAppInstallConsentPending = 13, - kAppInstalling = 14, - kAppInstallFailed = 15, - kAppInstalledRetryNeeded = 16, - kCommissionerPasscodeDisabled = 17, - kUnexpectedCommissionerPasscodeReady = 18 + noError = 0, + commissionableDiscoveryFailed = 1, + paseConnectionFailed = 2, + paseAuthFailed = 3, + dacValidationFailed = 4, + alreadyOnFabric = 5, + operationalDiscoveryFailed = 6, + caseConnectionFailed = 7, + caseAuthFailed = 8, + configurationFailed = 9, + bindingConfigurationFailed = 10, + commissionerPasscodeNotSupported = 11, + invalidIdentificationDeclarationParams = 12, + appInstallConsentPending = 13, + appInstalling = 14, + appInstallFailed = 15, + appInstalledRetryNeeded = 16, + commissionerPasscodeDisabled = 17, + unexpectedCommissionerPasscodeReady = 18 }; /** Feature: All - Indicates errors incurred during commissioning. */ @@ -76,13 +78,24 @@ typedef NS_ENUM(NSInteger, CdError) { * also displays a QR code. */ @property (nonatomic, readonly) BOOL qRCodeDisplayed; +/** + * Feature: Commissioner-Generated Passcode - Flag to indicate when the CastingplAYER/Commissioner + * user has decided to exit the commissioning process. + */ +@property (nonatomic, readonly) BOOL cancelPasscode; - (instancetype)initWithOptions:(NSInteger)errorCode needsPasscode:(BOOL)needsPasscode noAppsFound:(BOOL)noAppsFound passcodeDialogDisplayed:(BOOL)passcodeDialogDisplayed commissionerPasscode:(BOOL)commissionerPasscode - qRCodeDisplayed:(BOOL)qRCodeDisplayed; + qRCodeDisplayed:(BOOL)qRCodeDisplayed + cancelPasscode:(BOOL)cancelPasscode; + +/** + * Function to return the error code as a string. + */ +- (NSString *)getErrorCodeString; - (NSString *)description; - (void)logDetail; diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommissionerDeclaration.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommissionerDeclaration.mm index 1663f1626bb1f8..c9388ac0430e82 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommissionerDeclaration.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommissionerDeclaration.mm @@ -36,6 +36,7 @@ - (instancetype _Nonnull)initWithCppCommissionerDeclaration:(std::shared_ptrGetPasscodeDialogDisplayed(); _commissionerPasscode = cppCommissionerDeclaration->GetCommissionerPasscode(); _qRCodeDisplayed = cppCommissionerDeclaration->GetQRCodeDisplayed(); + _cancelPasscode = cppCommissionerDeclaration->GetCancelPasscode(); } return self; } @@ -46,6 +47,7 @@ - (instancetype)initWithOptions:(NSInteger)errorCode passcodeDialogDisplayed:(BOOL)passcodeDialogDisplayed commissionerPasscode:(BOOL)commissionerPasscode qRCodeDisplayed:(BOOL)qRCodeDisplayed + cancelPasscode:(BOOL)cancelPasscode { self = [super init]; if (self) { @@ -55,62 +57,69 @@ - (instancetype)initWithOptions:(NSInteger)errorCode _passcodeDialogDisplayed = passcodeDialogDisplayed; _commissionerPasscode = commissionerPasscode; _qRCodeDisplayed = qRCodeDisplayed; + _cancelPasscode = cancelPasscode; } return self; } - (NSString *)description { - return [NSString stringWithFormat:@"MCCommissionerDeclaration::errorCode: %@\nMCCommissionerDeclaration::needsPasscode: %d\nMCCommissionerDeclaration::noAppsFound: %d\nMCCommissionerDeclaration::passcodeDialogDisplayed: %d\nMCCommissionerDeclaration::commissionerPasscode: %d\nMCCommissionerDeclaration::qRCodeDisplayed: %d", + return [NSString stringWithFormat:@"MCCommissionerDeclaration::errorCode: %@\nMCCommissionerDeclaration::needsPasscode: %d\nMCCommissionerDeclaration::noAppsFound: %d\nMCCommissionerDeclaration::passcodeDialogDisplayed: %d\nMCCommissionerDeclaration::commissionerPasscode: %d\nMCCommissionerDeclaration::qRCodeDisplayed: %d\nMCCommissionerDeclaration::cancelPasscode: %d", [self stringForErrorCode:self.errorCode], self.needsPasscode, self.noAppsFound, self.passcodeDialogDisplayed, self.commissionerPasscode, - self.qRCodeDisplayed]; + self.qRCodeDisplayed, + self.cancelPasscode]; +} + +- (NSString *)getErrorCodeString +{ + return [self stringForErrorCode:self.errorCode]; } - (NSString *)stringForErrorCode:(CdError)errorCode { switch (errorCode) { - case kNoError: - return @"kNoError"; - case kCommissionableDiscoveryFailed: - return @"kCommissionableDiscoveryFailed"; - case kPaseConnectionFailed: - return @"kPaseConnectionFailed"; - case kPaseAuthFailed: - return @"kPaseAuthFailed"; - case kDacValidationFailed: - return @"kDacValidationFailed"; - case kAlreadyOnFabric: - return @"kAlreadyOnFabric"; - case kOperationalDiscoveryFailed: - return @"kOperationalDiscoveryFailed"; - case kCaseConnectionFailed: - return @"kCaseConnectionFailed"; - case kCaseAuthFailed: - return @"kCaseAuthFailed"; - case kConfigurationFailed: - return @"kConfigurationFailed"; - case kBindingConfigurationFailed: - return @"kBindingConfigurationFailed"; - case kCommissionerPasscodeNotSupported: - return @"kCommissionerPasscodeNotSupported"; - case kInvalidIdentificationDeclarationParams: - return @"kInvalidIdentificationDeclarationParams"; - case kAppInstallConsentPending: - return @"kAppInstallConsentPending"; - case kAppInstalling: - return @"kAppInstalling"; - case kAppInstallFailed: - return @"kAppInstallFailed"; - case kAppInstalledRetryNeeded: - return @"kAppInstalledRetryNeeded"; - case kCommissionerPasscodeDisabled: - return @"kCommissionerPasscodeDisabled"; - case kUnexpectedCommissionerPasscodeReady: - return @"kUnexpectedCommissionerPasscodeReady"; + case noError: + return @"noError"; + case commissionableDiscoveryFailed: + return @"commissionableDiscoveryFailed"; + case paseConnectionFailed: + return @"paseConnectionFailed"; + case paseAuthFailed: + return @"paseAuthFailed"; + case dacValidationFailed: + return @"dacValidationFailed"; + case alreadyOnFabric: + return @"alreadyOnFabric"; + case operationalDiscoveryFailed: + return @"operationalDiscoveryFailed"; + case caseConnectionFailed: + return @"caseConnectionFailed"; + case caseAuthFailed: + return @"caseAuthFailed"; + case configurationFailed: + return @"configurationFailed"; + case bindingConfigurationFailed: + return @"bindingConfigurationFailed"; + case commissionerPasscodeNotSupported: + return @"commissionerPasscodeNotSupported"; + case invalidIdentificationDeclarationParams: + return @"invalidIdentificationDeclarationParams"; + case appInstallConsentPending: + return @"appInstallConsentPending"; + case appInstalling: + return @"appInstalling"; + case appInstallFailed: + return @"appInstallFailed"; + case appInstalledRetryNeeded: + return @"appInstalledRetryNeeded"; + case commissionerPasscodeDisabled: + return @"commissionerPasscodeDisabled"; + case unexpectedCommissionerPasscodeReady: + return @"unexpectedCommissionerPasscodeReady"; default: return @"Unknown Error"; } diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleView.swift index 36ac837df1fa77..5760fae84aa28c 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleView.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleView.swift @@ -65,6 +65,13 @@ struct MCConnectionExampleView: View { .padding() } } + Spacer() // Push the error code to the bottom + if let errorCode = viewModel.errorCodeDescription { + + Text("\(errorCode)") + .foregroundColor(.red) + .padding() + } } .navigationTitle("Connecting...") .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .top) diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift index 895b4a58e31d04..815c79fc381589 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift @@ -22,6 +22,8 @@ import UIKit class MCConnectionExampleViewModel: ObservableObject { let Log = Logger(subsystem: "com.matter.casting", category: "MCConnectionExampleViewModel") + + var passcodeAlertController: UIAlertController? // VendorId of the MCEndpoint on the MCCastingPlayer that the MCCastingApp desires to interact with after connection let kDesiredEndpointVendorId: UInt16 = 65521; @@ -38,6 +40,8 @@ class MCConnectionExampleViewModel: ObservableObject { @Published var connectionStatus: String?; + @Published var errorCodeDescription: String? + func connect(selectedCastingPlayer: MCCastingPlayer?, useCommissionerGeneratedPasscode: Bool) { self.Log.info("MCConnectionExampleViewModel.connect() useCommissionerGeneratedPasscode: \(String(describing: useCommissionerGeneratedPasscode))") @@ -63,6 +67,22 @@ class MCConnectionExampleViewModel: ObservableObject { let commissionerDeclarationCallback: (MCCommissionerDeclaration) -> Void = { commissionerDeclarationMessage in DispatchQueue.main.async { self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, recived a message form the MCCastingPlayer:\n\(commissionerDeclarationMessage)") + + // Display CommissionerDeclaration error code if `errorCode` is not `kNoError` + if commissionerDeclarationMessage.errorCode != CdError.noError { + self.errorCodeDescription = "CommissionerDeclaration error from CastingPlayer: \(commissionerDeclarationMessage.getErrorCodeString())" + self.Log.error("MCConnectionExampleViewModel connect() Casting Player/Commissioner Error: \(self.errorCodeDescription ?? "Unknown Error")") + } + + // Check if the passcode dialog should be cancelled + if commissionerDeclarationMessage.cancelPasscode { + self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback. Cancel passcode received. Dismissing the PasscodeInputDialog.") + self.passcodeAlertController?.dismiss(animated: true, completion: nil) + self.connectionStatus = "Connection attempt cancelled by the CastingPlayer/Commissioner user. \n\nRoute back to exit." + return + } + + // Continue with passcode dialog if needed if commissionerDeclarationMessage.commissionerPasscode { self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, calling getTopMostViewController()") if let topViewController = self.getTopMostViewController() { @@ -151,7 +171,7 @@ class MCConnectionExampleViewModel: ObservableObject { targetAppInfo = MCTargetAppInfo(vendorId: kDesiredEndpointVendorId) connectionCallbacks = MCConnectionCallbacks( callbacks: connectionCompleteCallback, - commissionerDeclarationCallback: nil + commissionerDeclarationCallback: commissionerDeclarationCallback ) } @@ -171,6 +191,7 @@ class MCConnectionExampleViewModel: ObservableObject { // Create the alert controller let alertController = UIAlertController(title: "Enter Passcode", message: nil, preferredStyle: .alert) + self.passcodeAlertController = alertController // Add the text field with the default passcode alertController.addTextField { textField in diff --git a/examples/tv-casting-app/tv-casting-common/clusters/content-app-observer/ContentAppObserver.cpp b/examples/tv-casting-app/tv-casting-common/clusters/content-app-observer/ContentAppObserver.cpp index a6010a54b0a0f5..5be511a575a515 100644 --- a/examples/tv-casting-app/tv-casting-common/clusters/content-app-observer/ContentAppObserver.cpp +++ b/examples/tv-casting-app/tv-casting-common/clusters/content-app-observer/ContentAppObserver.cpp @@ -20,7 +20,6 @@ #include #include -using namespace std; using namespace chip; using namespace chip::app::Clusters::ContentAppObserver; @@ -35,8 +34,8 @@ void ContentAppObserverManager::HandleContentAppMessage(chip::app::CommandRespon { ChipLogProgress(Zcl, "ContentAppObserverManager::HandleContentAppMessage"); - string dataString(data.HasValue() ? data.Value().data() : "", data.HasValue() ? data.Value().size() : 0); - string encodingHintString(encodingHint.data(), encodingHint.size()); + std::string dataString(data.HasValue() ? data.Value().data() : "", data.HasValue() ? data.Value().size() : 0); + std::string encodingHintString(encodingHint.data(), encodingHint.size()); ChipLogProgress(Zcl, "ContentAppObserverManager::HandleContentAppMessage TEST CASE hint=%s data=%s ", encodingHintString.c_str(), dataString.c_str()); diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingPlayerDiscovery.cpp b/examples/tv-casting-app/tv-casting-common/core/CastingPlayerDiscovery.cpp index 81d1f78fe1b33a..4dee3550f3e0bb 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayerDiscovery.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayerDiscovery.cpp @@ -25,7 +25,6 @@ namespace core { using namespace chip::System; using namespace chip::Controller; using namespace chip::Dnssd; -using namespace std; CastingPlayerDiscovery * CastingPlayerDiscovery::_castingPlayerDiscovery = nullptr; diff --git a/integrations/docker/images/base/chip-build/version b/integrations/docker/images/base/chip-build/version index 6cfc3e799491d2..9f5456cec09f76 100644 --- a/integrations/docker/images/base/chip-build/version +++ b/integrations/docker/images/base/chip-build/version @@ -1 +1 @@ -80 : [Tizen] Run tests from 9P-shared directory instead of ISO +81 : [Telink] Update Docker image (Zephyr update) diff --git a/integrations/docker/images/stage-2/chip-build-k32w/Dockerfile b/integrations/docker/images/stage-2/chip-build-k32w/Dockerfile deleted file mode 100644 index c4cf71927d59fe..00000000000000 --- a/integrations/docker/images/stage-2/chip-build-k32w/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -ARG VERSION=1 -FROM ghcr.io/project-chip/chip-build:${VERSION} as build -LABEL org.opencontainers.image.source https://github.com/project-chip/connectedhomeip - -RUN set -x \ - && apt-get update \ - && DEBIAN_FRONTEND=noninteractive apt-get install -fy --no-install-recommends \ - unzip \ - wget \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/ \ - && : # last line - -WORKDIR /opt/sdk - -RUN set -x \ - && python3 -m pip install --break-system-packages -U --no-cache-dir west==1.2.0 \ - && : # last line - -RUN set -x \ - && west init -m https://github.com/nxp-mcuxpresso/mcux-sdk --mr "MCUX_2.6.14_K32W0" \ - && west update -o=--depth=1 -n -f smart \ - && chmod +x core/tools/imagetool/sign_images.sh \ - && ln -sf ../rtos core \ - && ln -sf ../middleware core \ - && cp -R examples/* core/boards && rm -rf examples \ - && : # last line - -FROM ghcr.io/project-chip/chip-build:${VERSION} - -COPY --from=build /opt/sdk/ /opt/sdk/ - -ENV NXP_K32W0_SDK_ROOT=/opt/sdk/core diff --git a/integrations/docker/images/stage-2/chip-build-k32w/build.sh b/integrations/docker/images/stage-2/chip-build-k32w/build.sh deleted file mode 120000 index 46b20313461454..00000000000000 --- a/integrations/docker/images/stage-2/chip-build-k32w/build.sh +++ /dev/null @@ -1 +0,0 @@ -../../../build.sh \ No newline at end of file diff --git a/integrations/docker/images/stage-2/chip-build-k32w/run.sh b/integrations/docker/images/stage-2/chip-build-k32w/run.sh deleted file mode 120000 index 9bbfad86d46e50..00000000000000 --- a/integrations/docker/images/stage-2/chip-build-k32w/run.sh +++ /dev/null @@ -1 +0,0 @@ -../../../run.sh \ No newline at end of file diff --git a/integrations/docker/images/stage-2/chip-build-k32w/version b/integrations/docker/images/stage-2/chip-build-k32w/version deleted file mode 120000 index a40ba48b0188a8..00000000000000 --- a/integrations/docker/images/stage-2/chip-build-k32w/version +++ /dev/null @@ -1 +0,0 @@ -../../base/chip-build/version \ No newline at end of file diff --git a/integrations/docker/images/stage-2/chip-build-telink/Dockerfile b/integrations/docker/images/stage-2/chip-build-telink/Dockerfile index 348d6989d57d9f..4311be77edddc4 100644 --- a/integrations/docker/images/stage-2/chip-build-telink/Dockerfile +++ b/integrations/docker/images/stage-2/chip-build-telink/Dockerfile @@ -18,7 +18,7 @@ RUN set -x \ && : # last line # Setup Zephyr -ARG ZEPHYR_REVISION=9ea364fd3b48c97f7cea6d69935f1fa630e30fb7 +ARG ZEPHYR_REVISION=3ed7686a9378de6be1368c912f9a42f998bbfb18 WORKDIR /opt/telink/zephyrproject RUN set -x \ && python3 -m pip install --break-system-packages -U --no-cache-dir west \ diff --git a/scripts/setup/bootstrap.sh b/scripts/setup/bootstrap.sh index ce3ab42dd56c79..f7e733da6b84b4 100644 --- a/scripts/setup/bootstrap.sh +++ b/scripts/setup/bootstrap.sh @@ -141,7 +141,8 @@ _bootstrap_or_activate() { $_CHIP_ROOT/scripts/setup/gen_pigweed_cipd_json.py \ -i $_PIGWEED_CIPD_JSON \ -o $_GENERATED_PIGWEED_CIPD_JSON \ - -e darwin:$_PYTHON_CIPD_JSON + -e darwin:$_PYTHON_CIPD_JSON \ + -e windows:$_PYTHON_CIPD_JSON if test -n "$GITHUB_ACTION"; then tee <"${_PW_ACTUAL_ENVIRONMENT_ROOT}/pip.conf" diff --git a/scripts/setup/environment.json b/scripts/setup/environment.json index fc9ace2b99b11c..09e31468771cd1 100644 --- a/scripts/setup/environment.json +++ b/scripts/setup/environment.json @@ -1,7 +1,6 @@ { "cipd_package_files": [ "third_party/pigweed/repo/pw_env_setup/py/pw_env_setup/cipd_setup/arm.json", - "scripts/setup/python.json", "scripts/setup/zap.json" ], "virtualenv": { diff --git a/scripts/setup/gen_pigweed_cipd_json.py b/scripts/setup/gen_pigweed_cipd_json.py index d1a47fe2cef7be..4fe77aaf09dce4 100755 --- a/scripts/setup/gen_pigweed_cipd_json.py +++ b/scripts/setup/gen_pigweed_cipd_json.py @@ -15,10 +15,15 @@ # limitations under the License. import argparse +import itertools import json +import logging import platform -_LIST_OF_PACKAGES_TO_EXCLUDE = ['fuchsia/third_party/rust/'] +_LIST_OF_PACKAGES_TO_EXCLUDE = { + 'fuchsia/third_party/rust/', + 'infra/3pp/tools/renode', +} def include_package(package: dict) -> bool: @@ -43,12 +48,20 @@ def generate_new_cipd_package_json(input, output, extra): # Extra is a list of platform:json. # Filter it for the given platform and append any resulting packages my_platform = platform.system().lower() - for item in extra: + + logging.info("Loading extra packages for %s", my_platform) + + # Extra chain because extra is a list of lists like: + # [['darwin:path1'], ['windows:path2']] + for item in itertools.chain.from_iterable(extra): inject_platform, path = item.split(':', 1) if inject_platform.lower() != my_platform: + logging.info("Skipping: %s (i.e. %s)", inject_platform.lower(), path) continue + logging.info("Appending: %s for this platform", path) + with open(path) as ins: for package in json.load(ins).get('packages'): new_file_packages.append(package) @@ -57,6 +70,8 @@ def generate_new_cipd_package_json(input, output, extra): with open(output, 'w') as f: json.dump(new_packages, f, indent=2) + logging.debug("PACKAGES:\n%s\n", json.dumps(new_packages, indent=2)) + def main(): parser = argparse.ArgumentParser( @@ -70,10 +85,11 @@ def main(): '--output', '-o', required=True ) parser.add_argument( - '--extra', '-e', nargs='*', default=[], + '--extra', '-e', nargs='*', action="append", default=[], help="Inject extra packages for specific platforms. Format is :" ) + logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO) generate_new_cipd_package_json(**vars(parser.parse_args())) diff --git a/scripts/setup/python.json b/scripts/setup/python.json deleted file mode 100644 index 0df6cc494ab40a..00000000000000 --- a/scripts/setup/python.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "packages": [ - { - "path": "infra/3pp/tools/cpython3/${platform}", - "platforms": ["mac-amd64", "windows-amd64"], - "tags": ["version:2@3.9.5.chromium.19"] - } - ] -} diff --git a/scripts/tests/cirque_tests.sh b/scripts/tests/cirque_tests.sh index a8be290f6c7e2c..b7dcdbcab2ff6a 100755 --- a/scripts/tests/cirque_tests.sh +++ b/scripts/tests/cirque_tests.sh @@ -37,13 +37,17 @@ OT_SIMULATION_CACHE="$CIRQUE_CACHE_PATH/ot-simulation-cmake.tgz" OT_SIMULATION_CACHE_STAMP_FILE="$CIRQUE_CACHE_PATH/ot-simulation.commit" # Append test name here to add more tests for run_all_tests +# +# NOTE: +# "InteractionModelTest" is currently disabled due to it overriding +# internal data model methods (for example it says "CommandExists" for +# paths where endpoint/cluster do not) CIRQUE_TESTS=( "EchoTest" "EchoOverTcpTest" "FailsafeTest" "MobileDeviceTest" "CommissioningTest" - "InteractionModelTest" "IcdWaitForActiveTest" "SplitCommissioningTest" "CommissioningFailureTest" diff --git a/src/app/ClusterStateCache.cpp b/src/app/ClusterStateCache.cpp index 65ab12095bfeba..fdb8e40abac0b7 100644 --- a/src/app/ClusterStateCache.cpp +++ b/src/app/ClusterStateCache.cpp @@ -626,15 +626,7 @@ CHIP_ERROR ClusterStateCacheT::OnUpdateDataVersionFilterLi continue; } - DataVersionFilterIB::Builder & filterIB = aDataVersionFilterIBsBuilder.CreateDataVersionFilter(); - SuccessOrExit(err = aDataVersionFilterIBsBuilder.GetError()); - ClusterPathIB::Builder & filterPath = filterIB.CreatePath(); - SuccessOrExit(err = filterIB.GetError()); - SuccessOrExit(err = filterPath.Endpoint(filter.first.mEndpointId).Cluster(filter.first.mClusterId).EndOfClusterPathIB()); - SuccessOrExit(err = filterIB.DataVersion(filter.first.mDataVersion.Value()).EndOfDataVersionFilterIB()); - ChipLogProgress(DataManagement, "Update DataVersionFilter: Endpoint=%u Cluster=" ChipLogFormatMEI " Version=%" PRIu32, - filter.first.mEndpointId, ChipLogValueMEI(filter.first.mClusterId), filter.first.mDataVersion.Value()); - + SuccessOrExit(err = aDataVersionFilterIBsBuilder.EncodeDataVersionFilterIB(filter.first)); aEncodedDataVersionList = true; } diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp index 6e4c0419e5b68b..e4c90b435902c5 100644 --- a/src/app/InteractionModelEngine.cpp +++ b/src/app/InteractionModelEngine.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -515,7 +516,8 @@ CHIP_ERROR InteractionModelEngine::ParseAttributePaths(const Access::SubjectDesc { ConcreteAttributePath concretePath(paramsList.mValue.mEndpointId, paramsList.mValue.mClusterId, paramsList.mValue.mAttributeId); - if (ConcreteAttributePathExists(concretePath)) + + if (IsExistentAttributePath(concretePath)) { Access::RequestPath requestPath{ .cluster = concretePath.mClusterId, .endpoint = concretePath.mEndpointId, @@ -1584,16 +1586,19 @@ CHIP_ERROR InteractionModelEngine::PushFrontAttributePathList(SingleLinkedListNo return err; } -bool InteractionModelEngine::IsExistingAttributePath(const ConcreteAttributePath & path) +bool InteractionModelEngine::IsExistentAttributePath(const ConcreteAttributePath & path) { #if CHIP_CONFIG_USE_DATA_MODEL_INTERFACE #if CHIP_CONFIG_USE_EMBER_DATA_MODEL - // Ensure that Provider interface and ember are IDENTICAL in attribute location (i.e. "check" mode) - VerifyOrDie(GetDataModelProvider() - ->GetAttributeInfo(ConcreteAttributePath(path.mEndpointId, path.mClusterId, path.mAttributeId)) - .has_value() == emberAfContainsAttribute(path.mEndpointId, path.mClusterId, path.mAttributeId) - ); + bool providerResult = GetDataModelProvider() + ->GetAttributeInfo(ConcreteAttributePath(path.mEndpointId, path.mClusterId, path.mAttributeId)) + .has_value(); + + bool emberResult = emberAfContainsAttribute(path.mEndpointId, path.mClusterId, path.mAttributeId); + + // Ensure that Provider interface and ember are IDENTICAL in attribute location (i.e. "check" mode) + VerifyOrDie(providerResult == emberResult); #endif return GetDataModelProvider() @@ -1615,7 +1620,7 @@ void InteractionModelEngine::RemoveDuplicateConcreteAttributePath(SingleLinkedLi // skip all wildcard paths and invalid concrete attribute if (path1->mValue.IsWildcardPath() || - !IsExistingAttributePath( + !IsExistentAttributePath( ConcreteAttributePath(path1->mValue.mEndpointId, path1->mValue.mClusterId, path1->mValue.mAttributeId))) { prev = path1; @@ -1766,7 +1771,49 @@ void InteractionModelEngine::DispatchCommand(CommandHandlerImpl & apCommandObj, Protocols::InteractionModel::Status InteractionModelEngine::CommandExists(const ConcreteCommandPath & aCommandPath) { +#if CHIP_CONFIG_USE_DATA_MODEL_INTERFACE + auto provider = GetDataModelProvider(); + if (provider->GetAcceptedCommandInfo(aCommandPath).has_value()) + { +#if CHIP_CONFIG_USE_EMBER_DATA_MODEL + VerifyOrDie(ServerClusterCommandExists(aCommandPath) == Protocols::InteractionModel::Status::Success); +#endif + return Protocols::InteractionModel::Status::Success; + } + + // We failed, figure out why ... + // + if (provider->GetClusterInfo(aCommandPath).has_value()) + { +#if CHIP_CONFIG_USE_EMBER_DATA_MODEL + VerifyOrDie(ServerClusterCommandExists(aCommandPath) == Protocols::InteractionModel::Status::UnsupportedCommand); +#endif + return Protocols::InteractionModel::Status::UnsupportedCommand; // cluster exists, so command is invalid + } + + // At this point either cluster or endpoint does not exist. If we find the endpoint, then the cluster + // is invalid + for (EndpointId endpoint = provider->FirstEndpoint(); endpoint != kInvalidEndpointId; + endpoint = provider->NextEndpoint(endpoint)) + { + if (endpoint == aCommandPath.mEndpointId) + { +#if CHIP_CONFIG_USE_EMBER_DATA_MODEL + VerifyOrDie(ServerClusterCommandExists(aCommandPath) == Protocols::InteractionModel::Status::UnsupportedCluster); +#endif + // endpoint exists, so cluster is invalid + return Protocols::InteractionModel::Status::UnsupportedCluster; + } + } + + // endpoint not found +#if CHIP_CONFIG_USE_EMBER_DATA_MODEL + VerifyOrDie(ServerClusterCommandExists(aCommandPath) == Protocols::InteractionModel::Status::UnsupportedEndpoint); +#endif + return Protocols::InteractionModel::Status::UnsupportedEndpoint; +#else return ServerClusterCommandExists(aCommandPath); +#endif } DataModel::Provider * InteractionModelEngine::SetDataModelProvider(DataModel::Provider * model) diff --git a/src/app/InteractionModelEngine.h b/src/app/InteractionModelEngine.h index a51e781dac216e..82af788d685c91 100644 --- a/src/app/InteractionModelEngine.h +++ b/src/app/InteractionModelEngine.h @@ -508,6 +508,7 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, void DispatchCommand(CommandHandlerImpl & apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & apPayload) override; + Protocols::InteractionModel::Status CommandExists(const ConcreteCommandPath & aCommandPath) override; bool HasActiveRead(); @@ -615,7 +616,7 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, /** * Check if the given attribute path is a valid path in the data model provider. */ - bool IsExistingAttributePath(const ConcreteAttributePath & path); + bool IsExistentAttributePath(const ConcreteAttributePath & path); static void ResumeSubscriptionsTimerCallback(System::Layer * apSystemLayer, void * apAppState); diff --git a/src/app/MessageDef/DataVersionFilterIBs.cpp b/src/app/MessageDef/DataVersionFilterIBs.cpp index ca6008975d7992..91b9e63d25fd90 100644 --- a/src/app/MessageDef/DataVersionFilterIBs.cpp +++ b/src/app/MessageDef/DataVersionFilterIBs.cpp @@ -69,6 +69,21 @@ DataVersionFilterIB::Builder & DataVersionFilterIBs::Builder::CreateDataVersionF return mDataVersionFilter; } +CHIP_ERROR DataVersionFilterIBs::Builder::EncodeDataVersionFilterIB(const DataVersionFilter & aFilter) +{ + DataVersionFilterIB::Builder & filterIB = CreateDataVersionFilter(); + ReturnErrorOnFailure(GetError()); + ClusterPathIB::Builder & path = filterIB.CreatePath(); + ReturnErrorOnFailure(filterIB.GetError()); + ReturnErrorOnFailure(path.Endpoint(aFilter.mEndpointId).Cluster(aFilter.mClusterId).EndOfClusterPathIB()); + ReturnErrorOnFailure(filterIB.DataVersion(aFilter.mDataVersion.Value()).EndOfDataVersionFilterIB()); + + ChipLogProgress(DataManagement, "Encoded DataVersionFilter: Endpoint=%u Cluster=" ChipLogFormatMEI " Version=%" PRIu32, + aFilter.mEndpointId, ChipLogValueMEI(aFilter.mClusterId), aFilter.mDataVersion.Value()); + + return CHIP_NO_ERROR; +} + CHIP_ERROR DataVersionFilterIBs::Builder::EndOfDataVersionFilterIBs() { EndOfContainer(); diff --git a/src/app/MessageDef/DataVersionFilterIBs.h b/src/app/MessageDef/DataVersionFilterIBs.h index 199a6686cb011f..bb753006e4dd19 100644 --- a/src/app/MessageDef/DataVersionFilterIBs.h +++ b/src/app/MessageDef/DataVersionFilterIBs.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include #include #include @@ -54,6 +55,16 @@ class Builder : public ArrayBuilder */ DataVersionFilterIB::Builder & GetDataVersionFilter() { return mDataVersionFilter; }; + /** + * Add a DataVersionFilter to the list. This is a convenience method + * that will handle calling CreateDataVersionFilter() and then using the + * result to encode the provided DataVersionFilter. + * + * The passed-in DataVersionFilter is assumed to pass the + * IsValidDataVersionFilter() test. + */ + CHIP_ERROR EncodeDataVersionFilterIB(const DataVersionFilter & aFilter); + /** * @brief Mark the end of this DataVersionFilterIBs * diff --git a/src/app/ReadClient.cpp b/src/app/ReadClient.cpp index 91b8adb0721608..1e9c7e727f409c 100644 --- a/src/app/ReadClient.cpp +++ b/src/app/ReadClient.cpp @@ -433,7 +433,7 @@ CHIP_ERROR ReadClient::BuildDataVersionFilterList(DataVersionFilterIBs::Builder TLV::TLVWriter backup; aDataVersionFilterIBsBuilder.Checkpoint(backup); - CHIP_ERROR err = EncodeDataVersionFilter(aDataVersionFilterIBsBuilder, filter); + CHIP_ERROR err = aDataVersionFilterIBsBuilder.EncodeDataVersionFilterIB(filter); if (err == CHIP_NO_ERROR) { #if CHIP_PROGRESS_LOGGING @@ -464,19 +464,6 @@ CHIP_ERROR ReadClient::BuildDataVersionFilterList(DataVersionFilterIBs::Builder return CHIP_NO_ERROR; } -CHIP_ERROR ReadClient::EncodeDataVersionFilter(DataVersionFilterIBs::Builder & aDataVersionFilterIBsBuilder, - DataVersionFilter const & aFilter) -{ - // Caller has checked aFilter.IsValidDataVersionFilter() - DataVersionFilterIB::Builder & filterIB = aDataVersionFilterIBsBuilder.CreateDataVersionFilter(); - ReturnErrorOnFailure(aDataVersionFilterIBsBuilder.GetError()); - ClusterPathIB::Builder & path = filterIB.CreatePath(); - ReturnErrorOnFailure(filterIB.GetError()); - ReturnErrorOnFailure(path.Endpoint(aFilter.mEndpointId).Cluster(aFilter.mClusterId).EndOfClusterPathIB()); - ReturnErrorOnFailure(filterIB.DataVersion(aFilter.mDataVersion.Value()).EndOfDataVersionFilterIB()); - return CHIP_NO_ERROR; -} - CHIP_ERROR ReadClient::GenerateDataVersionFilterList(DataVersionFilterIBs::Builder & aDataVersionFilterIBsBuilder, const Span & aAttributePaths, const Span & aDataVersionFilters, diff --git a/src/app/ReadClient.h b/src/app/ReadClient.h index 468aba012e07ae..fd27f0afc9e959 100644 --- a/src/app/ReadClient.h +++ b/src/app/ReadClient.h @@ -562,8 +562,6 @@ class ReadClient : public Messaging::ExchangeDelegate CHIP_ERROR BuildDataVersionFilterList(DataVersionFilterIBs::Builder & aDataVersionFilterIBsBuilder, const Span & aAttributePaths, const Span & aDataVersionFilters, bool & aEncodedDataVersionList); - CHIP_ERROR EncodeDataVersionFilter(DataVersionFilterIBs::Builder & aDataVersionFilterIBsBuilder, - DataVersionFilter const & aFilter); CHIP_ERROR ReadICDOperatingModeFromAttributeDataIB(TLV::TLVReader && aReader, PeerType & aType); CHIP_ERROR ProcessAttributeReportIBs(TLV::TLVReader & aAttributeDataIBsReader); CHIP_ERROR ProcessEventReportIBs(TLV::TLVReader & aEventReportIBsReader); diff --git a/src/app/clusters/dishwasher-alarm-server/dishwasher-alarm-server.cpp b/src/app/clusters/dishwasher-alarm-server/dishwasher-alarm-server.cpp index b3c9b8edbccf34..672df0af786d3d 100644 --- a/src/app/clusters/dishwasher-alarm-server/dishwasher-alarm-server.cpp +++ b/src/app/clusters/dishwasher-alarm-server/dishwasher-alarm-server.cpp @@ -33,7 +33,6 @@ using namespace chip::app::Clusters::DishwasherAlarm; using namespace chip::app::Clusters::DishwasherAlarm::Attributes; using namespace chip::DeviceLayer; using chip::Protocols::InteractionModel::Status; -using namespace std; static constexpr size_t kDishwasherAlarmDelegateTableSize = MATTER_DM_DISHWASHER_ALARM_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; diff --git a/src/app/clusters/door-lock-server/door-lock-server.cpp b/src/app/clusters/door-lock-server/door-lock-server.cpp index 43a044d0c4b9ec..d0574958c953aa 100644 --- a/src/app/clusters/door-lock-server/door-lock-server.cpp +++ b/src/app/clusters/door-lock-server/door-lock-server.cpp @@ -4430,16 +4430,19 @@ CHIP_ERROR DoorLockServer::Read(const ConcreteReadAttributePath & aPath, Attribu return ReadAliroSupportedBLEUWBProtocolVersions(aEncoder, delegate); } case AliroBLEAdvertisingVersion::Id: { + VerifyOrReturnError(delegate != nullptr, CHIP_ERROR_INCORRECT_STATE, ChipLogError(Zcl, "Delegate is null")); uint8_t bleAdvertisingVersion = delegate->GetAliroBLEAdvertisingVersion(); ReturnErrorOnFailure(aEncoder.Encode(bleAdvertisingVersion)); return CHIP_NO_ERROR; } case NumberOfAliroCredentialIssuerKeysSupported::Id: { + VerifyOrReturnError(delegate != nullptr, CHIP_ERROR_INCORRECT_STATE, ChipLogError(Zcl, "Delegate is null")); uint16_t numberOfCredentialIssuerKeysSupported = delegate->GetNumberOfAliroCredentialIssuerKeysSupported(); ReturnErrorOnFailure(aEncoder.Encode(numberOfCredentialIssuerKeysSupported)); return CHIP_NO_ERROR; } case NumberOfAliroEndpointKeysSupported::Id: { + VerifyOrReturnError(delegate != nullptr, CHIP_ERROR_INCORRECT_STATE, ChipLogError(Zcl, "Delegate is null")); uint16_t numberOfEndpointKeysSupported = delegate->GetNumberOfAliroEndpointKeysSupported(); ReturnErrorOnFailure(aEncoder.Encode(numberOfEndpointKeysSupported)); return CHIP_NO_ERROR; diff --git a/src/app/clusters/mode-select-server/mode-select-server.cpp b/src/app/clusters/mode-select-server/mode-select-server.cpp index 5f247bb4b2e95d..813d16d965148e 100644 --- a/src/app/clusters/mode-select-server/mode-select-server.cpp +++ b/src/app/clusters/mode-select-server/mode-select-server.cpp @@ -37,7 +37,6 @@ #include #endif // MATTER_DM_PLUGIN_ON_OFF -using namespace std; using namespace chip; using namespace chip::app; using namespace chip::app::Clusters; diff --git a/src/app/clusters/refrigerator-alarm-server/refrigerator-alarm-server.cpp b/src/app/clusters/refrigerator-alarm-server/refrigerator-alarm-server.cpp index 620e113177c1c7..751bd768cdf8ee 100644 --- a/src/app/clusters/refrigerator-alarm-server/refrigerator-alarm-server.cpp +++ b/src/app/clusters/refrigerator-alarm-server/refrigerator-alarm-server.cpp @@ -32,7 +32,6 @@ using namespace chip::app::Clusters::RefrigeratorAlarm::Attributes; using namespace chip::DeviceLayer; using chip::Protocols::InteractionModel::Status; -using namespace std; RefrigeratorAlarmServer RefrigeratorAlarmServer::instance; RefrigeratorAlarmServer & RefrigeratorAlarmServer::Instance() diff --git a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp index b8d885599245a4..6c581ff72a9e19 100644 --- a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp +++ b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp @@ -34,8 +34,6 @@ #include #include -// using namespace std; -using namespace chip; using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::app::Clusters::ResourceMonitoring; diff --git a/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp b/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp index 4d42fc90282104..aa8e2e20d9cc8d 100644 --- a/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp +++ b/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp @@ -17,11 +17,16 @@ #include #include +#include #include +#include +#include #include +#include #include #include #include +#include #include #include @@ -31,6 +36,113 @@ namespace chip { namespace app { namespace { +/// Handles going through callback-based enumeration of generated/accepted commands +/// for CommandHandlerInterface based items. +/// +/// Offers the ability to focus on some operation for finding a given +/// command id: +/// - FindFirst will return the first found element +/// - FindExact finds the element with the given id +/// - FindNext finds the element following the given id +class EnumeratorCommandFinder +{ +public: + using HandlerCallbackFunction = CHIP_ERROR (CommandHandlerInterface::*)(const ConcreteClusterPath &, + CommandHandlerInterface::CommandIdCallback, void *); + + enum class Operation + { + kFindFirst, // Find the first value in the list + kFindExact, // Find the given value + kFindNext // Find the value AFTER this value + }; + + EnumeratorCommandFinder(HandlerCallbackFunction callback) : + mCallback(callback), mOperation(Operation::kFindFirst), mTarget(kInvalidCommandId) + {} + + /// Find the given command ID that matches the given operation/path. + /// + /// If operation is kFindFirst, then path commandID is ignored. Otherwise it is used as a key to + /// kFindExact or kFindNext. + /// + /// Returns: + /// - std::nullopt if no command found using the command handler interface + /// - kInvalidCommandId if the find failed (but command handler interface does provide a list) + /// - valid id if command handler interface usage succeeds + std::optional FindCommandId(Operation operation, const ConcreteCommandPath & path); + + /// Uses FindCommandId to find the given command and loads the command entry data + std::optional FindCommandEntry(Operation operation, const ConcreteCommandPath & path); + +private: + HandlerCallbackFunction mCallback; + Operation mOperation; + CommandId mTarget; + std::optional mFound = std::nullopt; + + Loop HandlerCallback(CommandId id) + { + switch (mOperation) + { + case Operation::kFindFirst: + mFound = id; + return Loop::Break; + case Operation::kFindExact: + if (mTarget == id) + { + mFound = id; // found it + return Loop::Break; + } + break; + case Operation::kFindNext: + if (mTarget == id) + { + // Once we found the ID, get the first + mOperation = Operation::kFindFirst; + } + break; + } + return Loop::Continue; // keep searching + } + + static Loop HandlerCallbackFn(CommandId id, void * context) + { + auto self = static_cast(context); + return self->HandlerCallback(id); + } +}; + +std::optional EnumeratorCommandFinder::FindCommandId(Operation operation, const ConcreteCommandPath & path) +{ + mOperation = operation; + mTarget = path.mCommandId; + + CommandHandlerInterface * interface = + CommandHandlerInterfaceRegistry::Instance().GetCommandHandler(path.mEndpointId, path.mClusterId); + + if (interface == nullptr) + { + return std::nullopt; // no data: no interface + } + + CHIP_ERROR err = (interface->*mCallback)(path, HandlerCallbackFn, this); + if (err == CHIP_ERROR_NOT_IMPLEMENTED) + { + return std::nullopt; // no data provided by the interface + } + + if (err != CHIP_NO_ERROR) + { + // Report the error here since we lose actual error. This generally should NOT be possible as CommandHandlerInterface + // usually returns unimplemented or should just work for our use case (our callback never fails) + ChipLogError(DataManagement, "Enumerate error: %" CHIP_ERROR_FORMAT, err.Format()); + return kInvalidCommandId; + } + + return mFound.value_or(kInvalidCommandId); +} + /// Load the cluster information into the specified destination std::variant LoadClusterInfo(const ConcreteClusterPath & path, const EmberAfCluster & cluster) { @@ -160,6 +272,20 @@ DataModel::CommandEntry CommandEntryFrom(const ConcreteClusterPath & clusterPath return entry; } +std::optional EnumeratorCommandFinder::FindCommandEntry(Operation operation, + const ConcreteCommandPath & path) +{ + + std::optional id = FindCommandId(operation, path); + + if (!id.has_value()) + { + return std::nullopt; + } + + return (*id == kInvalidCommandId) ? DataModel::CommandEntry::kInvalid : CommandEntryFrom(path, *id); +} + const ConcreteCommandPath kInvalidCommandPath(kInvalidEndpointId, kInvalidClusterId, kInvalidCommandId); } // namespace @@ -492,6 +618,15 @@ std::optional CodegenDataModelProvider::GetAttributeIn DataModel::CommandEntry CodegenDataModelProvider::FirstAcceptedCommand(const ConcreteClusterPath & path) { + auto handlerInterfaceValue = EnumeratorCommandFinder(&CommandHandlerInterface::EnumerateAcceptedCommands) + .FindCommandEntry(EnumeratorCommandFinder::Operation::kFindFirst, + ConcreteCommandPath(path.mEndpointId, path.mClusterId, kInvalidCommandId)); + + if (handlerInterfaceValue.has_value()) + { + return *handlerInterfaceValue; + } + const EmberAfCluster * cluster = FindServerCluster(path); VerifyOrReturnValue(cluster != nullptr, DataModel::CommandEntry::kInvalid); @@ -504,6 +639,16 @@ DataModel::CommandEntry CodegenDataModelProvider::FirstAcceptedCommand(const Con DataModel::CommandEntry CodegenDataModelProvider::NextAcceptedCommand(const ConcreteCommandPath & before) { + // TODO: `Next` redirecting to a callback is slow O(n^2). + // see https://github.com/project-chip/connectedhomeip/issues/35790 + auto handlerInterfaceValue = EnumeratorCommandFinder(&CommandHandlerInterface::EnumerateAcceptedCommands) + .FindCommandEntry(EnumeratorCommandFinder::Operation::kFindNext, before); + + if (handlerInterfaceValue.has_value()) + { + return *handlerInterfaceValue; + } + const EmberAfCluster * cluster = FindServerCluster(before); VerifyOrReturnValue(cluster != nullptr, DataModel::CommandEntry::kInvalid); @@ -516,6 +661,14 @@ DataModel::CommandEntry CodegenDataModelProvider::NextAcceptedCommand(const Conc std::optional CodegenDataModelProvider::GetAcceptedCommandInfo(const ConcreteCommandPath & path) { + auto handlerInterfaceValue = EnumeratorCommandFinder(&CommandHandlerInterface::EnumerateAcceptedCommands) + .FindCommandEntry(EnumeratorCommandFinder::Operation::kFindExact, path); + + if (handlerInterfaceValue.has_value()) + { + return handlerInterfaceValue->IsValid() ? std::make_optional(handlerInterfaceValue->info) : std::nullopt; + } + const EmberAfCluster * cluster = FindServerCluster(path); VerifyOrReturnValue(cluster != nullptr, std::nullopt); @@ -526,17 +679,37 @@ std::optional CodegenDataModelProvider::GetAcceptedComma ConcreteCommandPath CodegenDataModelProvider::FirstGeneratedCommand(const ConcreteClusterPath & path) { - const EmberAfCluster * cluster = FindServerCluster(path); + std::optional commandId = + EnumeratorCommandFinder(&CommandHandlerInterface::EnumerateGeneratedCommands) + .FindCommandId(EnumeratorCommandFinder::Operation::kFindFirst, + ConcreteCommandPath(path.mEndpointId, path.mClusterId, kInvalidCommandId)); + if (commandId.has_value()) + { + return *commandId == kInvalidCommandId ? kInvalidCommandPath + : ConcreteCommandPath(path.mEndpointId, path.mClusterId, *commandId); + } + const EmberAfCluster * cluster = FindServerCluster(path); VerifyOrReturnValue(cluster != nullptr, kInvalidCommandPath); - std::optional commandId = mGeneratedCommandsIterator.First(cluster->generatedCommandList); + commandId = mGeneratedCommandsIterator.First(cluster->generatedCommandList); VerifyOrReturnValue(commandId.has_value(), kInvalidCommandPath); return ConcreteCommandPath(path.mEndpointId, path.mClusterId, *commandId); } ConcreteCommandPath CodegenDataModelProvider::NextGeneratedCommand(const ConcreteCommandPath & before) { + // TODO: `Next` redirecting to a callback is slow O(n^2). + // see https://github.com/project-chip/connectedhomeip/issues/35790 + auto nextId = EnumeratorCommandFinder(&CommandHandlerInterface::EnumerateGeneratedCommands) + .FindCommandId(EnumeratorCommandFinder::Operation::kFindNext, before); + + if (nextId.has_value()) + { + return (*nextId == kInvalidCommandId) ? kInvalidCommandPath + : ConcreteCommandPath(before.mEndpointId, before.mClusterId, *nextId); + } + const EmberAfCluster * cluster = FindServerCluster(before); VerifyOrReturnValue(cluster != nullptr, kInvalidCommandPath); diff --git a/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp b/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp index 077376bcb44311..5314684fc6f9a4 100644 --- a/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp +++ b/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp @@ -15,8 +15,6 @@ * limitations under the License. */ -#include - #include #include @@ -30,11 +28,14 @@ #include #include #include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -62,6 +63,8 @@ #include #include +#include + using namespace chip; using namespace chip::Test; using namespace chip::app; @@ -183,6 +186,61 @@ class MockAccessControl : public Access::AccessControl::Delegate, public Access: bool IsDeviceTypeOnEndpoint(DeviceTypeId deviceType, EndpointId endpoint) override { return true; } }; +/// Overrides Enumerate*Commands in the CommandHandlerInterface to allow +/// testing of behaviors when command enumeration is done in the interace. +class CustomListCommandHandler : public CommandHandlerInterface +{ +public: + CustomListCommandHandler(Optional endpointId, ClusterId clusterId) : CommandHandlerInterface(endpointId, clusterId) + { + CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this); + } + ~CustomListCommandHandler() { CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); } + + void InvokeCommand(HandlerContext & handlerContext) override { handlerContext.SetCommandNotHandled(); } + + CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override + { + VerifyOrReturnError(mOverrideAccepted, CHIP_ERROR_NOT_IMPLEMENTED); + + for (auto id : mAccepted) + { + if (callback(id, context) != Loop::Continue) + { + break; + } + } + return CHIP_NO_ERROR; + } + + CHIP_ERROR EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override + { + VerifyOrReturnError(mOverrideGenerated, CHIP_ERROR_NOT_IMPLEMENTED); + + for (auto id : mGenerated) + { + if (callback(id, context) != Loop::Continue) + { + break; + } + } + return CHIP_NO_ERROR; + } + + void SetOverrideAccepted(bool o) { mOverrideAccepted = o; } + void SetOverrideGenerated(bool o) { mOverrideGenerated = o; } + + std::vector & AcceptedVec() { return mAccepted; } + std::vector & GeneratedVec() { return mGenerated; } + +private: + bool mOverrideAccepted = false; + bool mOverrideGenerated = false; + + std::vector mAccepted; + std::vector mGenerated; +}; + class ScopedMockAccessControl { public: @@ -1193,6 +1251,60 @@ TEST(TestCodegenModelViaMocks, IterateOverGeneratedCommands) } } +TEST(TestCodegenModelViaMocks, CommandHandlerInterfaceAcceptedCommands) +{ + + UseMockNodeConfig config(gTestNodeConfig); + CodegenDataModelProviderWithContext model; + + // Command handler interface is capable to override accepted and generated commands. + // Validate that these work + CustomListCommandHandler handler(MakeOptional(kMockEndpoint1), MockClusterId(1)); + + // At this point, without overrides, there should be no accepted/generated commands + EXPECT_FALSE(model.FirstAcceptedCommand(ConcreteClusterPath(kMockEndpoint1, MockClusterId(1))).IsValid()); + EXPECT_FALSE(model.FirstGeneratedCommand(ConcreteClusterPath(kMockEndpoint1, MockClusterId(1))).HasValidIds()); + EXPECT_FALSE(model.GetAcceptedCommandInfo(ConcreteCommandPath(kMockEndpoint1, MockClusterId(1), 1234)).has_value()); + + handler.SetOverrideAccepted(true); + handler.SetOverrideGenerated(true); + + // with overrides, the list is still empty ... + EXPECT_FALSE(model.FirstAcceptedCommand(ConcreteClusterPath(kMockEndpoint1, MockClusterId(1))).IsValid()); + EXPECT_FALSE(model.FirstGeneratedCommand(ConcreteClusterPath(kMockEndpoint1, MockClusterId(1))).HasValidIds()); + EXPECT_FALSE(model.GetAcceptedCommandInfo(ConcreteCommandPath(kMockEndpoint1, MockClusterId(1), 1234)).has_value()); + + // set some overrides + handler.AcceptedVec().push_back(1234); + handler.AcceptedVec().push_back(999); + + handler.GeneratedVec().push_back(33); + + DataModel::CommandEntry entry; + + entry = model.FirstAcceptedCommand(ConcreteClusterPath(kMockEndpoint1, MockClusterId(1))); + EXPECT_TRUE(entry.IsValid()); + EXPECT_EQ(entry.path, ConcreteCommandPath(kMockEndpoint1, MockClusterId(1), 1234)); + + entry = model.NextAcceptedCommand(entry.path); + EXPECT_TRUE(entry.IsValid()); + EXPECT_EQ(entry.path, ConcreteCommandPath(kMockEndpoint1, MockClusterId(1), 999)); + + entry = model.NextAcceptedCommand(entry.path); + EXPECT_FALSE(entry.IsValid()); + + ConcreteCommandPath path = model.FirstGeneratedCommand(ConcreteClusterPath(kMockEndpoint1, MockClusterId(1))); + EXPECT_TRUE(path.HasValidIds()); + EXPECT_EQ(path, ConcreteCommandPath(kMockEndpoint1, MockClusterId(1), 33)); + path = model.NextGeneratedCommand(path); + EXPECT_FALSE(path.HasValidIds()); + + // Command finding should work + EXPECT_TRUE(model.GetAcceptedCommandInfo(ConcreteCommandPath(kMockEndpoint1, MockClusterId(1), 1234)).has_value()); + EXPECT_FALSE(model.GetAcceptedCommandInfo(ConcreteCommandPath(kMockEndpoint1, MockClusterId(1), 88)).has_value()); + EXPECT_FALSE(model.GetAcceptedCommandInfo(ConcreteCommandPath(kMockEndpoint1, MockClusterId(1), 33)).has_value()); +} + TEST(TestCodegenModelViaMocks, EmberAttributeReadAclDeny) { UseMockNodeConfig config(gTestNodeConfig); diff --git a/src/app/tests/TestAclAttribute.cpp b/src/app/tests/TestAclAttribute.cpp index 264137dbfbdd8b..0325760959f5de 100644 --- a/src/app/tests/TestAclAttribute.cpp +++ b/src/app/tests/TestAclAttribute.cpp @@ -41,11 +41,27 @@ #include #include -#include - namespace { using namespace chip; using namespace chip::Access; +using namespace chip::Test; + +const MockNodeConfig & TestMockNodeConfig() +{ + using namespace chip::app; + using namespace chip::app::Clusters::Globals::Attributes; + + // clang-format off + static const MockNodeConfig config({ + MockEndpointConfig(kTestEndpointId, { + MockClusterConfig(kTestClusterId, { + ClusterRevision::Id, FeatureMap::Id, 1, 2 + }), + }), + }); + // clang-format on + return config; +} class TestAccessControlDelegate : public AccessControl::Delegate { @@ -119,10 +135,12 @@ class TestAclAttribute : public Test::AppContext Access::GetAccessControl().Finish(); Access::GetAccessControl().Init(GetTestAccessControlDelegate(), gDeviceTypeResolver); mOldProvider = InteractionModelEngine::GetInstance()->SetDataModelProvider(&TestImCustomDataModel::Instance()); + chip::Test::SetMockNodeConfig(TestMockNodeConfig()); } void TearDown() override { + chip::Test::ResetMockNodeConfig(); AppContext::TearDown(); InteractionModelEngine::GetInstance()->SetDataModelProvider(mOldProvider); } diff --git a/src/app/tests/TestCommandInteraction.cpp b/src/app/tests/TestCommandInteraction.cpp index 34f59edd245ff6..e4465c119d14f8 100644 --- a/src/app/tests/TestCommandInteraction.cpp +++ b/src/app/tests/TestCommandInteraction.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -96,6 +97,33 @@ class SimpleTLVPayload : public app::DataModel::EncodableToTLV } }; +const chip::Test::MockNodeConfig & TestMockNodeConfig() +{ + using namespace chip::app; + using namespace chip::Test; + using namespace chip::app::Clusters::Globals::Attributes; + + // clang-format off + static const MockNodeConfig config({ + MockEndpointConfig(chip::kTestEndpointId, { + MockClusterConfig(Clusters::Identify::Id, { + ClusterRevision::Id, FeatureMap::Id, + }, + {}, // events + { + kTestCommandIdWithData, + kTestCommandIdNoData, + kTestCommandIdCommandSpecificResponse, + kTestCommandIdFillResponseMessage, + }, // accepted commands + {} // generated commands + ), + }), + }); + // clang-format on + return config; +} + } // namespace namespace app { @@ -354,9 +382,42 @@ class MockCommandHandlerCallback : public CommandHandlerImpl::Callback int onFinalCalledTimes = 0; } mockCommandHandlerDelegate; +class TestCommandInteractionModel : public TestImCustomDataModel +{ +public: + static TestCommandInteractionModel * Instance() + { + static TestCommandInteractionModel instance; + return &instance; + } + + TestCommandInteractionModel() {} + + std::optional Invoke(const DataModel::InvokeRequest & request, + chip::TLV::TLVReader & input_arguments, CommandHandler * handler) + { + DispatchSingleClusterCommand(request.path, input_arguments, handler); + return std::nullopt; // handler status is set by the dispatch + } +}; + class TestCommandInteraction : public chip::Test::AppContext { public: + void SetUp() override + { + AppContext::SetUp(); + mOldProvider = InteractionModelEngine::GetInstance()->SetDataModelProvider(TestCommandInteractionModel::Instance()); + chip::Test::SetMockNodeConfig(TestMockNodeConfig()); + } + + void TearDown() override + { + chip::Test::ResetMockNodeConfig(); + InteractionModelEngine::GetInstance()->SetDataModelProvider(mOldProvider); + AppContext::TearDown(); + } + static size_t GetNumActiveCommandResponderObjects() { return chip::app::InteractionModelEngine::GetInstance()->mCommandResponderObjs.Allocated(); @@ -423,6 +484,9 @@ class TestCommandInteraction : public chip::Test::AppContext static void FillCurrentInvokeResponseBuffer(CommandHandlerImpl * apCommandHandler, const ConcreteCommandPath & aRequestCommandPath, uint32_t aSizeToLeaveInBuffer); static void ValidateCommandHandlerEncodeInvokeResponseMessage(bool aNeedStatusCode); + +protected: + chip::app::DataModel::Provider * mOldProvider = nullptr; }; class TestExchangeDelegate : public Messaging::ExchangeDelegate diff --git a/src/app/tests/TestReadInteraction.cpp b/src/app/tests/TestReadInteraction.cpp index e984b3ee081d89..aec74af6082aa2 100644 --- a/src/app/tests/TestReadInteraction.cpp +++ b/src/app/tests/TestReadInteraction.cpp @@ -15,9 +15,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -#include - #include #include #include @@ -51,7 +48,7 @@ uint8_t gDebugEventBuffer[128]; uint8_t gInfoEventBuffer[128]; uint8_t gCritEventBuffer[128]; chip::app::CircularEventBuffer gCircularEventBuffer[3]; -chip::ClusterId kTestClusterId = 6; +chip::ClusterId kTestClusterId = 6; // OnOff, but not used as OnOff directly chip::ClusterId kTestEventClusterId = chip::Test::MockClusterId(1); chip::ClusterId kInvalidTestClusterId = 7; chip::EndpointId kTestEndpointId = 1; @@ -71,6 +68,65 @@ static chip::System::Clock::ClockBase * gRealClock; static chip::app::reporting::ReportSchedulerImpl * gReportScheduler; static bool sUsingSubSync = false; +const chip::Test::MockNodeConfig & TestMockNodeConfig() +{ + using namespace chip::app; + using namespace chip::app::Clusters::Globals::Attributes; + using namespace chip::Test; + + // clang-format off + static const chip::Test::MockNodeConfig config({ + MockEndpointConfig(kTestEndpointId, { + MockClusterConfig(kTestClusterId, { + ClusterRevision::Id, FeatureMap::Id, + 1, + 2, // treated as a list + }), + MockClusterConfig(kInvalidTestClusterId, { + ClusterRevision::Id, FeatureMap::Id, + 1, + }), + }), + MockEndpointConfig(kMockEndpoint1, { + MockClusterConfig(MockClusterId(1), { + ClusterRevision::Id, FeatureMap::Id, + }, { + MockEventId(1), MockEventId(2), + }), + MockClusterConfig(MockClusterId(2), { + ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), + }), + }), + MockEndpointConfig(kMockEndpoint2, { + MockClusterConfig(MockClusterId(1), { + ClusterRevision::Id, FeatureMap::Id, + }), + MockClusterConfig(MockClusterId(2), { + ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), MockAttributeId(2), + }), + MockClusterConfig(MockClusterId(3), { + ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), MockAttributeId(2), MockAttributeId(3), + }), + }), + MockEndpointConfig(chip::Test::kMockEndpoint3, { + MockClusterConfig(MockClusterId(1), { + ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), + }), + MockClusterConfig(MockClusterId(2), { + ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), MockAttributeId(2), MockAttributeId(3), MockAttributeId(4), + }), + MockClusterConfig(MockClusterId(3), { + ClusterRevision::Id, FeatureMap::Id, + }), + MockClusterConfig(MockClusterId(4), { + ClusterRevision::Id, FeatureMap::Id, + }), + }), + }); + // clang-format on + return config; +} + class TestEventGenerator : public chip::app::EventLoggingDelegate { public: @@ -259,7 +315,7 @@ class TestReadInteraction : public chip::Test::AppContext AppContext::TearDownTestSuite(); } - void SetUp() + void SetUp() override { const chip::app::LogStorageResources logStorageResources[] = { { &gDebugEventBuffer[0], sizeof(gDebugEventBuffer), chip::app::PriorityLevel::Debug }, @@ -273,9 +329,11 @@ class TestReadInteraction : public chip::Test::AppContext chip::app::EventManagement::CreateEventManagement(&GetExchangeManager(), ArraySize(logStorageResources), gCircularEventBuffer, logStorageResources, &mEventCounter); mOldProvider = InteractionModelEngine::GetInstance()->SetDataModelProvider(&TestImCustomDataModel::Instance()); + chip::Test::SetMockNodeConfig(TestMockNodeConfig()); } - void TearDown() + void TearDown() override { + chip::Test::ResetMockNodeConfig(); InteractionModelEngine::GetInstance()->SetDataModelProvider(mOldProvider); chip::app::EventManagement::DestroyEventManagement(); AppContext::TearDown(); @@ -2330,6 +2388,10 @@ TEST_F_FROM_FIXTURE(TestReadInteraction, TestSubscribeUrgentWildcardEvent) TEST_F(TestReadInteraction, TestSubscribeWildcard) { + // This test in particular is completely tied to the DefaultMockConfig in the mock + // attribute storage, so reset to that (figuring out chunking location is extra hard to + // maintain) + chip::Test::ResetMockNodeConfig(); Messaging::ReliableMessageMgr * rm = GetExchangeManager().GetReliableMessageMgr(); // Shouldn't have anything in the retransmit table when starting the test. @@ -2368,8 +2430,8 @@ TEST_F(TestReadInteraction, TestSubscribeWildcard) EXPECT_TRUE(delegate.mGotReport); #if CHIP_CONFIG_ENABLE_EVENTLIST_ATTRIBUTE - // Mock attribute storage in src/app/util/mock/attribute-storage.cpp - // has the following items + // Mock attribute storage that is reset and resides in src/app/util/mock/attribute-storage.cpp + // has the following items: // - Endpoint 0xFFFE // - cluster 0xFFF1'FC01 (2 attributes) // - cluster 0xFFF1'FC02 (3 attributes) diff --git a/src/app/tests/TestReportingEngine.cpp b/src/app/tests/TestReportingEngine.cpp index f4f52b83f8bfa7..3a16e43e6481f4 100644 --- a/src/app/tests/TestReportingEngine.cpp +++ b/src/app/tests/TestReportingEngine.cpp @@ -50,6 +50,27 @@ constexpr EndpointId kTestEndpointId = 1; constexpr chip::AttributeId kTestFieldId1 = 1; constexpr chip::AttributeId kTestFieldId2 = 2; +using namespace chip; +using namespace chip::Access; + +const Test::MockNodeConfig & TestMockNodeConfig() +{ + using namespace chip::app; + using namespace chip::app::Clusters::Globals::Attributes; + + // clang-format off + static const Test::MockNodeConfig config({ + Test::MockEndpointConfig(kTestEndpointId, { + Test::MockClusterConfig(kTestClusterId, { + ClusterRevision::Id, FeatureMap::Id, + kTestFieldId1, kTestFieldId2, + }), + }), + }); + // clang-format on + return config; +} + namespace app { namespace reporting { @@ -60,10 +81,12 @@ class TestReportingEngine : public chip::Test::AppContext { chip::Test::AppContext::SetUp(); mOldProvider = InteractionModelEngine::GetInstance()->SetDataModelProvider(&TestImCustomDataModel::Instance()); + chip::Test::SetMockNodeConfig(TestMockNodeConfig()); } void TearDown() override { + chip::Test::ResetMockNodeConfig(); InteractionModelEngine::GetInstance()->SetDataModelProvider(mOldProvider); chip::Test::AppContext::TearDown(); } diff --git a/src/app/tests/integration/chip_im_responder.cpp b/src/app/tests/integration/chip_im_responder.cpp index 86d654b99ff94c..b65710d06894b1 100644 --- a/src/app/tests/integration/chip_im_responder.cpp +++ b/src/app/tests/integration/chip_im_responder.cpp @@ -69,6 +69,21 @@ class TestTLVDataEncoder : public DataModel::EncodableToTLV } // namespace +// TODO: +// The overrides here do NOT provide a consistent data model view: +// This should be overriden with a Mock data model if using direct ember and +// CodegenDataModel OR a custom DataModel::Provider should be written +// +// We cannot just say "every attribut exist, every device on every endpoint exists, +// every data version compare is the same etc.". +// +// The following override implementation need changing: +// - ServerClusterCommandExists - should have a proper data mmodel +// - ConcreteAttributePathExists - cannot say "Yes" on all paths when query for EP/Cluster would fail +// - CheckEventSupportStatus - cannot say yes for invalid endpoints/clusters +// - IsClusterDataVersionEqual returning true on everything is odd +// - IsDeviceTypeOnEndpoint returning true on every value seems odd + Protocols::InteractionModel::Status ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath) { // The Mock cluster catalog -- only have one command on one cluster on one endpoint. diff --git a/src/app/tests/suites/certification/Test_TC_CC_3_2.yaml b/src/app/tests/suites/certification/Test_TC_CC_3_2.yaml index 398ec48f36f4d2..c5628c9d4fe5ae 100644 --- a/src/app/tests/suites/certification/Test_TC_CC_3_2.yaml +++ b/src/app/tests/suites/certification/Test_TC_CC_3_2.yaml @@ -86,58 +86,45 @@ tests: - name: "OptionsOverride" value: 0 - - label: "Wait 10s" + - label: "Wait 5s" PICS: CC.S.F00 cluster: "DelayCommands" command: "WaitForMs" arguments: values: - name: "ms" - value: 10000 + value: 5000 - #Tolerance to be computed from the range - #Start value 200, expected value 250, 200 - 250 = -50, 50 % 15 = 8 , So 250+/-8 We need two range here as 254 is the max value - #242...254...0...4 - #Multiple range not supported in YAML: https://github.com/project-chip/connectedhomeip/issues/23197 - - label: "Step 2c: TH reads CurrentHue attribute from DUT" - PICS: CC.S.F00 && CC.S.A0000 && PICS_SKIP_SAMPLE_APP - verification: | - ./chip-tool colorcontrol read current-hue 1 1 - - After 10 seconds, Verify that CurrentHue attribute value is 250 On TH(chip-tool) Logs and below is the sample log provided for the raspi platform - - [1649662328.012887][8447:8452] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0300 Attribute 0x0000_0000 DataVersion: 4087279986 - [1649662328.012957][8447:8452] CHIP:TOO: Current hue: 250 - [1649662328.013055][8447:8452] CHIP:EM: Sending Standalone Ack for MessageCounter:8634142 on exchange 13871i - (Value can vary) - cluster: "LogCommands" - command: "UserPrompt" - arguments: - values: - - name: "message" - value: "Enter 'y' after success" - - name: "expectedValue" - value: "y" + #Tolerance to be computed from the range (note) + # In 5 seconds, the value will have changed by 25. A 15% tolerance is 1.7, so ~2, and value must be 225 +/- 2 + - label: "Step 2d: TH reads CurrentHue attribute from DUT" + PICS: CC.S.F00 && CC.S.A0000 + command: "readAttribute" + attribute: "CurrentHue" + response: + constraints: + minValue: 223 + maxValue: 227 - - label: "Wait 10s" + - label: "Wait 15s" PICS: CC.S.F00 cluster: "DelayCommands" command: "WaitForMs" arguments: values: - name: "ms" - value: 10000 + value: 15000 - #Tolerance to be computed from the range - #Start value 200, expected value 45, 200 - 45 = 155, 155 % 15 = 23 , So 45+/-23 + # Tolerance to be computed from the range (20*5=100) that hue changed (note that hue reaches max, wraps back to 0 then continues from min value) + # In 20s the value will have changed by 100 and wrapped around to 45. A 15% tolerance is 15, so 30 to 60 - label: "Step 2d: TH reads CurrentHue attribute from DUT" PICS: CC.S.F00 && CC.S.A0000 command: "readAttribute" attribute: "CurrentHue" response: constraints: - minValue: 22 - maxValue: 68 + minValue: 30 + maxValue: 60 - label: "Wait 10s" PICS: CC.S.F00 diff --git a/src/app/tests/suites/certification/Test_TC_DLOG_2_1.yaml b/src/app/tests/suites/certification/Test_TC_DLOG_2_1.yaml index 45111b016974d2..ebc658f16523b7 100644 --- a/src/app/tests/suites/certification/Test_TC_DLOG_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_DLOG_2_1.yaml @@ -34,6 +34,18 @@ tests: Length of TransferFileDesignator is equal to 32 characters Length of TransferFileDesignator is greater than 32 characters To send a message that mismatches the current transfer mode + 1. Execute the below commands in the interactive mode: + ./chip-tool interactive start + 2. Before running the below steps ensure that \tmp folder on the system does not contain the below files. + If they are present please delete these files: + TH_LOG_OK_NORMAL : "Length_1234567.txt" + TH_LOG_OK_FULL_LENGTH : "Length_123456789123456789123.txt" + 3. Use the below command in the all-cluster-app for setting up the diagonistics logs. + ./chip-all-clusters-app --trace_decode 1 --end_user_support_log ~/tmp/end_user_support_log.txt --network_diagnostics_log ~/tmp/nw_log.txt --crash_log ~/tmp/crash_log.txt + The log file content can be set such that the file size can be as follows to obtain different status code from DUT: + 1. end_user_support_log > 1024 bytes + 2. Make sure that nw_log.txt does not exist + 3. crash_log < 1024 bytes disabled: true - label: "Step 1: Commission DUT to TH" @@ -187,7 +199,7 @@ tests: TH_LOG_OK_NORMAL)" PICS: MCORE.BDX.Initiator verification: | - "diagnosticlogs retrieve-logs-request 0 1 1 0 --TransferFileDesignator Length_1234567.txt + diagnosticlogs retrieve-logs-request 0 1 1 0 --TransferFileDesignator Length_1234567.txt On TH(chip-tool), Verify that the DUT sends SendInit message with TransferFileDesignator field set to Length_1234567891234567891 [1707967645.770994][10882:10885] CHIP:ATM: SendInit @@ -219,7 +231,7 @@ tests: by setting Intent field to . NetworkDiag . CrashLogs" PICS: MCORE.BDX.Initiator verification: | - "diagnosticlogs retrieve-logs-request 0 0 1 0 + diagnosticlogs retrieve-logs-request 0 0 1 0 On TH(chip-tool), Verify that the DUT responds with Success(0) status code for the RetrieveLogsResponse command Verify that LogContent field contains at most 1024 bytes @@ -254,7 +266,7 @@ tests: EndUserSupport, RequestedProtocol= BDX)" PICS: MCORE.BDX.Initiator verification: | - "diagnosticlogs retrieve-logs-request 0 1 1 0 + diagnosticlogs retrieve-logs-request 0 1 1 0 On TH(chip-tool), Verify that the DUT responds with INVALID_COMMAND for the RetrieveLogsRequest that was sent without TransferFileDesignator @@ -290,7 +302,7 @@ tests: RequestedProtocol= BDX, TransferFileDesignator = TH_LOG_OK_NORMAL)" PICS: "!MCORE.BDX.Initiator" verification: | - "diagnosticlogs retrieve-logs-request 0 1 1 0 --TransferFileDesignator Length_1234567.txt + diagnosticlogs retrieve-logs-request 0 1 1 0 --TransferFileDesignator Length_1234567.txt On TH(chip-tool), Verify that the DUT responds with Exhausted(1) status code for the RetrieveLogsResponse command with the LogContent field containing at most 1024 bytes @@ -299,14 +311,40 @@ tests: [1707979121.749593][7593:7596] CHIP:TOO: logContent: 31353238303033363031313533353030333730303234303030303234303133653234303230313138333530313331303034373032313533313031316230323330383230323137303630393261383634383836663730643031303730326130383230323038333038323032303430323031303333313064333030623036303936303836343830313635303330343032303133303832303137303036303932613836343838366637306430313037303161303832303136313034383230313564313532343030303132353031663166663336303230353030383030353031383030353032383030353033383030353034383030353035383030353036383030353037383030353038383030353039383030353061383030353062383030353063383030353064383030353065383030353066383030353130383030353131383030353132383030353133383030353134383030353135383030353136383030353137383030353138383030353139383030353161383030353162383030353163383030353164383030353165383030353166383030353230383030353231383030353232383030353233383030353234383030353235383030353236383030353237383030353238383030353239383030353261383030353262383030353263383030353264383030353265383030353266383030353330383030353331383030353332383030353333383030353334383030353335383030353336383030353337383030353338383030353339383030353361383030353362383030353363383030353364383030353365383030353366383030353430383030353431383030353432383030353433383030353434383030353435383030353436383030353437383030353438383030353439383030353461383030353462383030353463383030353464383030353465383030353466383030353530383030353531383030353532383030353533383030353534383030353535383030353536383030353537383030353538383030353539383030353561383030353562383030353563383030353564383030353565383030353566383030353630383030353631383030353632383030353633383031383234303331363263303431333433353334313330333033303330333035333537343333303330333033303330326433303330323430353030323430363030323430373031323430383030313833313763333037613032303130333830313466653334336639353939343737363362363165653435333931333133333834393466653637643865333030623036303936303836343830633733653461363039363038363438303630393630383634383036303936303836343830363039363038363438303630393630383634383036303936303836}" disabled: true + - label: + "Step 11: TH sends RetrieveLogsRequest Command to DUT with Invalid + Intent : RetrieveLogsRequest(Intent = 3, RequestedProtocol= BDX, + TransferFileDesignator = TH_LOG_OK_NORMAL) Repeat this step with + RequestedProtocol as ResponsePayload" + verification: | + diagnosticlogs retrieve-logs-request 3 0 1 0 --TransferFileDesignator Length_1234567.txt + + On TH(chip-tool), Verify that the DUT responds with INVALID_COMMAND for the RetrieveLogsRequest that was sent invalid Intent(3) + + [1707901794.468552][36124:36127] CHIP:DMG: StatusIB = + [1707901794.468560][36124:36127] CHIP:DMG: { + [1707901794.468569][36124:36127] CHIP:DMG: status = 0x85 (INVALID_COMMAND), + [1707901794.468576][36124:36127] CHIP:DMG: }, + [1707901794.468584][36124:36127] CHIP:DMG: + [1707901794.468591][36124:36127] CHIP:DMG: }, + + Repeat this step by setting RequestedProtocol as ResponsePayload : + + diagnosticlogs retrieve-logs-request 3 1 1 0 --TransferFileDesignator Length_1234567.txt + On TH(chip-tool), Verify that the DUT responds with INVALID_COMMAND for the RetrieveLogsRequest that was sent invalid Intent(3) + [1707901794.468552][36124:36127] CHIP:DMG: StatusIB = + [1707901794.468560][36124:36127] CHIP:DMG: { + [1707901794.468569][36124:36127] CHIP:DMG: status = 0x85 (INVALID_COMMAND), + [1707901794.468576][36124:36127] CHIP:DMG: }, + disabled: true + - label: "Step 12: TH sends RetrieveLogsRequest Command to DUT with Invalid RequestedProtocol : RetrieveLogsRequest(Intent = EndUserSupport,RequestedProtocol= 2, TransferFileDesignator = TH_LOG_OK_NORMAL)" - PICS: MCORE.BDX.Initiator verification: | - "diagnosticlogs retrieve-logs-request 0 2 1 0 --TransferFileDesignator Length_1234567.txt + diagnosticlogs retrieve-logs-request 0 2 1 0 --TransferFileDesignator Length_1234567.txt On TH(chip-tool), Verify that the DUT responds with INVALID_COMMAND for the RetrieveLogsRequest that was sent Invalid RequestedProtocol(2) @@ -344,39 +382,14 @@ tests: TransferFileDesignator length : RetrieveLogsRequest(Intent = EndUserSupport,RequestedProtocol= BDX, TransferFileDesignator = TH_LOG_ERROR_EMPTY)" + PICS: MCORE.BDX.Initiator verification: | - "diagnosticlogs retrieve-logs-request 0 1 1 0 --TransferFileDesignator '' - - [1707904517.151453][36678:36681] CHIP:DMG: ICR moving to [ResponseRe] - [1707904517.151489][36678:36681] CHIP:DMG: InvokeResponseMessage = - [1707904517.151501][36678:36681] CHIP:DMG: { - [1707904517.151511][36678:36681] CHIP:DMG: suppressResponse = false, - [1707904517.151522][36678:36681] CHIP:DMG: InvokeResponseIBs = - [1707904517.151541][36678:36681] CHIP:DMG: [ - [1707904517.151548][36678:36681] CHIP:DMG: InvokeResponseIB = - [1707904517.151565][36678:36681] CHIP:DMG: { - [1707904517.151573][36678:36681] CHIP:DMG: CommandStatusIB = - [1707904517.151582][36678:36681] CHIP:DMG: { - [1707904517.151590][36678:36681] CHIP:DMG: CommandPathIB = - [1707904517.151599][36678:36681] CHIP:DMG: { - [1707904517.151613][36678:36681] CHIP:DMG: EndpointId = 0x0, - [1707904517.151627][36678:36681] CHIP:DMG: ClusterId = 0x32, - [1707904517.151640][36678:36681] CHIP:DMG: CommandId = 0x0, - [1707904517.151652][36678:36681] CHIP:DMG: }, - [1707904517.151670][36678:36681] CHIP:DMG: - [1707904517.151681][36678:36681] CHIP:DMG: StatusIB = - [1707904517.151696][36678:36681] CHIP:DMG: { - [1707904517.151708][36678:36681] CHIP:DMG: status = 0x87 (CONSTRAINT_ERROR), - [1707904517.151720][36678:36681] CHIP:DMG: }, - [1707904517.151734][36678:36681] CHIP:DMG: - [1707904517.151745][36678:36681] CHIP:DMG: }, - [1707904517.151763][36678:36681] CHIP:DMG: - [1707904517.151772][36678:36681] CHIP:DMG: }, - [1707904517.151790][36678:36681] CHIP:DMG: - [1707904517.151798][36678:36681] CHIP:DMG: ], - [1707904517.151816][36678:36681] CHIP:DMG: - [1707904517.151824][36678:36681] CHIP:DMG: InteractionModelRevision = 11 - [1707904517.151830][36678:36681] CHIP:DMG: }," + diagnosticlogs retrieve-logs-request 0 1 1 0 --TransferFileDesignator '' + On TH(chip-tool), Verify that DUT sends RetrieveLogsResponse command to TH with Denied(4) status code. + [1719990173.360981][8053:8056] CHIP:TOO: RetrieveLogsResponse: { + [1719990173.361009][8053:8056] CHIP:TOO: status: 4 + [1719990173.361021][8053:8056] CHIP:TOO: logContent: + [1719990173.361030][8053:8056] CHIP:TOO: } disabled: true - label: @@ -385,9 +398,9 @@ tests: EndUserSupport,RequestedProtocol= BDX, TransferFileDesignator = TH_LOG_BAD_LENGTH)" verification: | - "diagnosticlogs retrieve-logs-request 0 1 1 0 --TransferFileDesignator Length_1234567891234567891234567891212345.txt + diagnosticlogs retrieve-logs-request 0 1 1 0 --TransferFileDesignator Length_1234567891234567891234567891212345.txt - On TH(chip-tool), Verify that the DUT responds with CONSTRAINT_ERRORfor the RetrieveLogsRequest that was sent Invalid Invalid TransferFileDesignator length(> 32) + On TH(chip-tool), Verify that the DUT responds with CONSTRAINT_ERROR for the RetrieveLogsRequest that was sent Invalid Invalid TransferFileDesignator length(> 32) [1707904517.151453][36678:36681] CHIP:DMG: ICR moving to [ResponseRe] [1707904517.151489][36678:36681] CHIP:DMG: InvokeResponseMessage = diff --git a/src/app/tests/suites/certification/Test_TC_DRLK_2_4.yaml b/src/app/tests/suites/certification/Test_TC_DRLK_2_4.yaml index bece149e34ed32..a52538964c97f3 100644 --- a/src/app/tests/suites/certification/Test_TC_DRLK_2_4.yaml +++ b/src/app/tests/suites/certification/Test_TC_DRLK_2_4.yaml @@ -33,9 +33,50 @@ tests: - name: "nodeId" value: nodeId - - label: "Create new user" + - label: + "Step 1a: TH writes AutoRelockTime attribute value as 10 seconds on + the DUT" + PICS: DRLK.S.M.AutoRelockTimeAttributeWritable && PICS_SDK_CI_ONLY + command: "writeAttribute" + attribute: "AutoRelockTime" + arguments: + value: 10 + + - label: + "Step 1b: TH writes AutoRelockTime attribute value as 60 seconds on + the DUT" + PICS: DRLK.S.M.AutoRelockTimeAttributeWritable && PICS_SKIP_SAMPLE_APP + command: "writeAttribute" + attribute: "AutoRelockTime" + arguments: + value: 60 + + - label: + "Step 1c: TH writes AutoRelockTime attribute value as 10 seconds on + the DUT" + PICS: PICS_SDK_CI_ONLY && !DRLK.S.M.AutoRelockTimeAttributeWritable + command: "writeAttribute" + attribute: "AutoRelockTime" + arguments: + value: 10 + response: + error: UNSUPPORTED_WRITE + + - label: + "Step 1d: TH writes AutoRelockTime attribute value as 60 seconds on + the DUT" + PICS: PICS_SKIP_SAMPLE_APP && !DRLK.S.M.AutoRelockTimeAttributeWritable + command: "writeAttribute" + attribute: "AutoRelockTime" + arguments: + value: 60 + response: + error: UNSUPPORTED_WRITE + + - label: + "Step 2a: TH sends SetUser Command to DUT with the following values:" command: "SetUser" - PICS: DRLK.S.F08 && DRLK.S.F00 + PICS: DRLK.S.F08 && DRLK.S.C1a.Rsp timedInteractionTimeoutMs: 1000 arguments: values: @@ -54,39 +95,33 @@ tests: - name: "CredentialRule" value: 0 - - label: "Read the user back and verify its fields" - command: "GetUser" - PICS: DRLK.S.F08 && DRLK.S.F00 - arguments: - values: - - name: "UserIndex" - value: 1 + - label: "Step 2b: TH reads MinPINCodeLength attribute from DUT" + PICS: DRLK.S.F00 && DRLK.S.A0018 + command: "readAttribute" + attribute: "MinPINCodeLength" response: - values: - - name: "UserIndex" - value: 1 - - name: "UserName" - value: "xxx" - - name: "UserUniqueID" - value: 6452 - - name: "UserStatus" - value: 1 - - name: "UserType" - value: 0 - - name: "CredentialRule" - value: 0 - - name: "Credentials" - value: [] - - name: "CreatorFabricIndex" - value: 1 - - name: "LastModifiedFabricIndex" - value: 1 - - name: "NextUserIndex" - value: null - - - label: "Create new PIN credential and lock/unlock user" + saveAs: MinPINCodeLengthValue + constraints: + type: int8u + minValue: 0 + maxValue: 255 + + - label: "Step 2c: TH reads MaxPINCodeLength attribute from DUT" + PICS: DRLK.S.F00 && DRLK.S.A0017 + command: "readAttribute" + attribute: "MaxPINCodeLength" + response: + saveAs: MaxPINCodeLengthValue + constraints: + type: int8u + minValue: 0 + maxValue: 255 + - label: + "Step 2d: TH sends SetCredential Command to DUT with the following + fields and CredentialData Length is in an inclusive range of + MaxPINCodeLengthValue to MaxPINCodeLengthValue" command: "SetCredential" - PICS: DRLK.S.F08 && DRLK.S.F00 + PICS: DRLK.S.F00 && DRLK.S.C22.Rsp && DRLK.S.C23.Tx timedInteractionTimeoutMs: 1000 arguments: values: @@ -111,68 +146,8 @@ tests: - name: "NextCredentialIndex" value: 2 - - label: "Verify created PIN credential" - PICS: DRLK.S.F08 && DRLK.S.F00 - command: "GetCredentialStatus" - arguments: - values: - - name: "Credential" - value: { CredentialType: 1, CredentialIndex: 1 } - response: - values: - - name: "CredentialExists" - value: true - - name: "UserIndex" - value: 1 - - name: "CreatorFabricIndex" - value: 1 - - name: "LastModifiedFabricIndex" - value: 1 - - name: "NextCredentialIndex" - value: null - - - label: - "Step 1a: TH writes AutoRelockTime attribute value as 10 seconds on - the DUT" - PICS: DRLK.S.M.AutoRelockTimeAttributeWritable && PICS_SDK_CI_ONLY - command: "writeAttribute" - attribute: "AutoRelockTime" - arguments: - value: 10 - - - label: - "Step 1b: TH writes AutoRelockTime attribute value as 60 seconds on - the DUT" - PICS: DRLK.S.M.AutoRelockTimeAttributeWritable && PICS_SKIP_SAMPLE_APP - command: "writeAttribute" - attribute: "AutoRelockTime" - arguments: - value: 60 - - - label: - "Step 1c: TH writes AutoRelockTime attribute value as 10 seconds on - the DUT" - PICS: PICS_SDK_CI_ONLY && !DRLK.S.M.AutoRelockTimeAttributeWritable - command: "writeAttribute" - attribute: "AutoRelockTime" - arguments: - value: 10 - response: - error: UNSUPPORTED_WRITE - - label: - "Step 1d: TH writes AutoRelockTime attribute value as 60 seconds on - the DUT" - PICS: PICS_SKIP_SAMPLE_APP && !DRLK.S.M.AutoRelockTimeAttributeWritable - command: "writeAttribute" - attribute: "AutoRelockTime" - arguments: - value: 60 - response: - error: UNSUPPORTED_WRITE - - - label: - "Step 2a: TH sends the Unlock with Timeout argument value as 10 + "Step 2e: TH sends the Unlock with Timeout argument value as 10 seconds" PICS: DRLK.S.C03.Rsp && PICS_SDK_CI_ONLY command: "UnlockWithTimeout" @@ -185,7 +160,7 @@ tests: value: "123456" - label: - "Step 2b: TH sends the Unlock with Timeout argument value as 60 + "Step 2f: TH sends the Unlock with Timeout argument value as 60 seconds" PICS: " DRLK.S.F08 && DRLK.S.F00 && DRLK.S.C03.Rsp && PICS_SKIP_SAMPLE_APP " @@ -199,7 +174,7 @@ tests: value: "123456" - label: - "Step 2b: TH sends the Unlock with Timeout argument value as 60 + "Step 2g: TH sends the Unlock with Timeout argument value as 60 seconds" PICS: " (!DRLK.S.F08 || !DRLK.S.F00) && DRLK.S.C03.Rsp && @@ -230,27 +205,30 @@ tests: - name: "ms" value: 70000 - - label: "Step 2c: TH reads LockState attribute" + - label: "Step 2h: TH reads LockState attribute" PICS: DRLK.S.A0000 && DRLK.S.C03.Rsp command: "readAttribute" attribute: "LockState" response: value: 1 - - label: "Cleanup the created user" - command: "ClearUser" - PICS: DRLK.S.F08 && DRLK.S.F00 + - label: + "Step 3a: TH sends ClearCredential Command to DUT with the following + fields:" + PICS: DRLK.S.F00 && DRLK.S.C26.Rsp + command: "ClearCredential" timedInteractionTimeoutMs: 1000 arguments: values: - - name: "UserIndex" - value: 1 + - name: "Credential" + value: { CredentialType: 1, CredentialIndex: 1 } - - label: "Clean the created credential" - PICS: DRLK.S.F08 && DRLK.S.F00 && DRLK.S.C26.Rsp - command: "ClearCredential" + - label: + "Step 3b: TH sends ClearUser Command to DUT with the UserIndex as 1" + command: "ClearUser" + PICS: DRLK.S.F08 && DRLK.S.C1d.Rsp timedInteractionTimeoutMs: 1000 arguments: values: - - name: "Credential" - value: { CredentialType: 1, CredentialIndex: 1 } + - name: "UserIndex" + value: 1 diff --git a/src/app/tests/suites/certification/Test_TC_DRLK_2_5.yaml b/src/app/tests/suites/certification/Test_TC_DRLK_2_5.yaml deleted file mode 100644 index c0c8feb91775cd..00000000000000 --- a/src/app/tests/suites/certification/Test_TC_DRLK_2_5.yaml +++ /dev/null @@ -1,320 +0,0 @@ -# Copyright (c) 2021 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -name: - 111.2.5. [TC-DRLK-2.5] Verification for the following Commands - Set Week - Day Schedule, Get Week Day Schedule , Get Week Day Schedule Response, Clear - Week Day Schedule [DUT-Server] - -PICS: - - DRLK.S - - DRLK.S.F08 - -config: - nodeId: 0x12344321 - cluster: "Door Lock" - endpoint: 1 - -tests: - - label: "Wait for the commissioned device to be retrieved" - cluster: "DelayCommands" - command: "WaitForCommissionee" - arguments: - values: - - name: "nodeId" - value: nodeId - - - label: "Precondition: Create new user" - command: "SetUser" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "OperationType" - value: 0 - - name: "UserIndex" - value: 1 - - name: "UserName" - value: "xxx" - - name: "UserUniqueID" - value: 6452 - - name: "UserStatus" - value: 1 - - name: "UserType" - value: 0 - - name: "CredentialRule" - value: 0 - - - label: "Precondition: Read the user back and verify its fields" - command: "GetUser" - arguments: - values: - - name: "UserIndex" - value: 1 - response: - values: - - name: "UserIndex" - value: 1 - - name: "UserName" - value: "xxx" - - name: "UserUniqueID" - value: 6452 - - name: "UserStatus" - value: 1 - - name: "UserType" - value: 0 - - name: "CredentialRule" - value: 0 - - name: "Credentials" - value: [] - - name: "CreatorFabricIndex" - value: 1 - - name: "LastModifiedFabricIndex" - value: 1 - - name: "NextUserIndex" - value: null - - - label: - "Step 1: TH reads NumberOfWeekDay SchedulesSupportedPerUser attribute - and saves for future use" - PICS: DRLK.S.F04 && DRLK.S.A0014 - command: "readAttribute" - attribute: "NumberOfWeekDaySchedulesSupportedPerUser" - response: - saveAs: NumberOfWeekDaySchedulesSupportedPerUserValue - constraints: - minValue: 0 - maxValue: 255 - - - label: - "Step 2: TH reads NumberOfTotalUsers Supported attribute and saves for - future use" - PICS: DRLK.S.F08 && DRLK.S.A0011 - command: "readAttribute" - attribute: "NumberOfTotalUsersSupported" - response: - saveAs: NumberOfTotalUsersSupportedValue - constraints: - minValue: 0 - maxValue: 65534 - - - label: - "Step 3: TH send Set Week Day Schedule Command to DUT with the - following values : a)WeekDayIndex as 1 b)UserIndex as 1 c)DaysMaskMap - as 2 d)StartHour as 15 e)StartMinute as 45 f)EndHour as 16 g)EndMinute - as 55 " - PICS: DRLK.S.F04 && DRLK.S.C0b.Rsp - command: "SetWeekDaySchedule" - arguments: - values: - - name: "WeekDayIndex" - value: 1 - - name: "UserIndex" - value: 1 - - name: "DaysMask" - value: 2 - - name: "StartHour" - value: 15 - - name: "StartMinute" - value: 45 - - name: "EndHour" - value: 16 - - name: "EndMinute" - value: 55 - - #issue #18591 - - label: - "Step 4: TH send Get Week Day Schedule Command to DUT with - a)WeekDayIndex as 1 b)UserIndex as 1 " - PICS: DRLK.S.F04 && DRLK.S.C0c.Rsp && DRLK.S.C0c.Tx - command: "GetWeekDaySchedule" - arguments: - values: - - name: "WeekDayIndex" - value: 1 - - name: "UserIndex" - value: 1 - response: - values: - - name: "WeekDayIndex" - value: 1 - - name: "UserIndex" - value: 1 - - name: "Status" - value: 0x0 - - name: "DaysMask" - value: 2 - - name: "StartHour" - value: 15 - - name: "StartMinute" - value: 45 - - name: "EndHour" - constraints: - hasValue: true - minValue: 16 - - name: "EndMinute" - constraints: - hasValue: true - minValue: 55 - - - label: - "Step 5: TH send Set Week Day Schedule Command to DUT with the - following values : a)WeekDayIndex as 0 (invalid value) b)UserIndex as - 1 c)DaysMaskMap as 7 (invalid value) d)StartHour as 15 e)StartMinute - as 45 f)EndHour as 16 g)EndMinute as 55" - PICS: DRLK.S.F04 && DRLK.S.C0b.Rsp - command: "SetWeekDaySchedule" - arguments: - values: - - name: "WeekDayIndex" - value: 0 - - name: "UserIndex" - value: 1 - - name: "DaysMask" - value: 7 - - name: "StartHour" - value: 15 - - name: "StartMinute" - value: 45 - - name: "EndHour" - value: 16 - - name: "EndMinute" - value: 55 - response: - error: INVALID_COMMAND - - - label: - "Step 6: TH send Get Week Day Schedule Command to DUT : a)WeekDayIndex - as 0 b)UserIndex as 1 " - PICS: DRLK.S.F04 && DRLK.S.C0c.Rsp && DRLK.S.C0c.Tx - command: "GetWeekDaySchedule" - arguments: - values: - - name: "WeekDayIndex" - value: 0 - - name: "UserIndex" - value: 1 - response: - values: - - name: "WeekDayIndex" - value: 0 - - name: "UserIndex" - value: 1 - - name: "Status" - value: 0x85 - - name: "DaysMask" - constraints: - hasValue: false - - name: "StartHour" - constraints: - hasValue: false - - name: "StartMinute" - constraints: - hasValue: false - - name: "EndHour" - constraints: - hasValue: false - - name: "EndMinute" - constraints: - hasValue: false - - - label: - "Step 7: TH sends Get Week Day Schedule Command to DUT with following - values: a)WeekDayIndex as 1 (index of existing Schedule entry) - b)UserIndex as 2 (index on non-existent User)" - PICS: DRLK.S.F04 && DRLK.S.C0c.Rsp && DRLK.S.C0c.Tx - command: "GetWeekDaySchedule" - arguments: - values: - - name: "WeekDayIndex" - value: 1 - - name: "UserIndex" - value: 2 - response: - values: - - name: "WeekDayIndex" - value: 1 - - name: "UserIndex" - value: 2 - - name: "Status" - value: 0x8B - - name: "DaysMask" - constraints: - hasValue: false - - name: "StartHour" - constraints: - hasValue: false - - name: "StartMinute" - constraints: - hasValue: false - - name: "EndHour" - constraints: - hasValue: false - - name: "EndMinute" - constraints: - hasValue: false - - - label: - "Step 8: TH sends Clear Week Day Schedule Command to DUT with : - a)WeekDayIndex as 1 b)UserIndex as 1" - PICS: DRLK.S.F04 && DRLK.S.C0d.Rsp - command: "ClearWeekDaySchedule" - arguments: - values: - - name: "WeekDayIndex" - value: 1 - - name: "UserIndex" - value: 1 - - - label: - "Step 9: TH sends Get Week Day Schedule Command to DUT with following - values: a)WeekDayIndex as 1 b)UserIndex as 1" - PICS: DRLK.S.F04 && DRLK.S.C0c.Rsp && DRLK.S.C0c.Tx - command: "GetWeekDaySchedule" - arguments: - values: - - name: "WeekDayIndex" - value: 1 - - name: "UserIndex" - value: 1 - response: - values: - - name: "WeekDayIndex" - value: 1 - - name: "UserIndex" - value: 1 - - name: "Status" - value: 0x8B - - name: "DaysMask" - constraints: - hasValue: false - - name: "StartHour" - constraints: - hasValue: false - - name: "StartMinute" - constraints: - hasValue: false - - name: "EndHour" - constraints: - hasValue: false - - name: "EndMinute" - constraints: - hasValue: false - - - label: "Cleanup the created user" - command: "ClearUser" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "UserIndex" - value: 1 diff --git a/src/app/tests/suites/certification/Test_TC_DRLK_2_9.yaml b/src/app/tests/suites/certification/Test_TC_DRLK_2_9.yaml deleted file mode 100644 index 0c0a372b175d7e..00000000000000 --- a/src/app/tests/suites/certification/Test_TC_DRLK_2_9.yaml +++ /dev/null @@ -1,471 +0,0 @@ -# Copyright (c) 2021 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -name: - 111.2.9. [TC-DRLK-2.9] Verification for the following Commands - Set - Credential , Set Credential Response, Get Credential Status, Get Credential - Status Response, Clear Credential [DUT-Server] - -PICS: - - DRLK.S - -config: - nodeId: 0x12344321 - cluster: "Door Lock" - endpoint: 1 - -tests: - - label: "Wait for the commissioned device to be retrieved" - cluster: "DelayCommands" - command: "WaitForCommissionee" - arguments: - values: - - name: "nodeId" - value: nodeId - - - label: "Precondition: Create new user with default parameters" - command: "SetUser" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "OperationType" - value: 0 - - name: "UserIndex" - value: 1 - - name: "UserName" - value: "xxx" - - name: "UserUniqueID" - value: 6452 - - name: "UserStatus" - value: 1 - - name: "UserType" - value: 0 - - name: "CredentialRule" - value: 0 - - - label: "Precondition: Read the user back and verify its fields" - command: "GetUser" - arguments: - values: - - name: "UserIndex" - value: 1 - response: - values: - - name: "UserIndex" - value: 1 - - name: "UserName" - value: "xxx" - - name: "UserUniqueID" - value: 6452 - - name: "UserStatus" - value: 1 - - name: "UserType" - value: 0 - - name: "CredentialRule" - value: 0 - - name: "Credentials" - value: [] - - name: "CreatorFabricIndex" - value: 1 - - name: "LastModifiedFabricIndex" - value: 1 - - name: "NextUserIndex" - value: null - - - label: - "Step 1: TH reads NumberOfTotalUsersSupported attribute and saves for - future use." - PICS: DRLK.S.F08 && DRLK.S.A0011 - command: "readAttribute" - attribute: "NumberOfTotalUsersSupported" - response: - saveAs: NumberOfTotalUsersSupportedValue - constraints: - minValue: 0 - maxValue: 65534 - - - label: - "Step 2: TH sends Set Credential Command to DUT with the following - fields a)OperationType as 0 b)Credential as 1 1 c)CredentialData as - 123456 d)UserIndex as 1 e)UserStatus as null f)UserType as null" - PICS: DRLK.S.F08 && DRLK.S.C22.Rsp && DRLK.S.C23.Tx - command: "SetCredential" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "OperationType" - value: 0 - - name: "Credential" - value: { CredentialType: 1, CredentialIndex: 1 } - - name: "CredentialData" - value: "123456" - - name: "UserIndex" - value: 1 - - name: "UserStatus" - value: null - - name: "UserType" - value: null - response: - values: - - name: "Status" - value: 0 - - name: "UserIndex" - value: null - - name: "NextCredentialIndex" - value: 2 - - - label: - "Step 3: TH sends Get Credential Status Command with a)CredentialType - as 1 b)CredentialIndex as 1" - PICS: DRLK.S.F08 && DRLK.S.C24.Rsp && DRLK.S.C25.Tx - command: "GetCredentialStatus" - arguments: - values: - - name: "Credential" - value: { CredentialType: 1, CredentialIndex: 1 } - response: - values: - - name: "CredentialExists" - constraints: - type: boolean - - name: "UserIndex" - value: 1 - - name: "CreatorFabricIndex" - value: 1 - - name: "LastModifiedFabricIndex" - value: 1 - - name: "NextCredentialIndex" - value: null - - - label: - "Step 4: TH sends Set Credential Command to DUT with the following - fields a)OperationType as 0 b)Credential as 1 2 C)CredentialData as - 4321 D)UserIndex as null e)UserStatus as 5(Invalid value) f)UserType - as 10(Invalid value)" - PICS: DRLK.S.F08 && DRLK.S.C22.Rsp && DRLK.S.C23.Tx - command: "SetCredential" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "OperationType" - value: 0 - - name: "Credential" - value: { CredentialType: 1, CredentialIndex: 2 } - - name: "CredentialData" - value: "4321" - - name: "UserIndex" - value: null - - name: "UserStatus" - value: UserStatusEnum.UnknownEnumValue(5) - - name: "UserType" - value: 10 - response: - values: - - name: "Status" - value: 0x85 - - name: "UserIndex" - value: null - - - label: - "Step 5: TH sends Set Credential Command to DUT with the following - fields a)OperationType as 0 b)Credential as 1 2 d)CredentialData as - 123456 (same as step 2) e)UserIndex as null f)UserStatus as null - g)UserType as null" - PICS: DRLK.S.F08 && DRLK.S.C22.Rsp && DRLK.S.C23.Tx - command: "SetCredential" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "OperationType" - value: 0 - - name: "Credential" - value: { CredentialType: 1, CredentialIndex: 2 } - - name: "CredentialData" - value: "123456" - - name: "UserIndex" - value: null - - name: "UserStatus" - value: null - - name: "UserType" - value: null - response: - values: - - name: "Status" - value: 0x02 - - name: "UserIndex" - value: null - - - label: - "Step 6a: TH sends Set Credential Command to DUT with the following - fields a)OperationType as 0 b)Credential as 1 1 (same as step 2) - c)CredentialData as 123456 d)UserIndex as 1 e)UserStatus as null - f)UserType as null" - PICS: DRLK.S.F08 && DRLK.S.C22.Rsp && DRLK.S.C23.Tx - command: "SetCredential" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "OperationType" - value: 0 - - name: "Credential" - value: { CredentialType: 1, CredentialIndex: 1 } - - name: "CredentialData" - value: "123456" - - name: "UserIndex" - value: 1 - - name: "UserStatus" - value: null - - name: "UserType" - value: null - response: - values: - - name: "Status" - constraints: - anyOf: [0x2, 0x3] - - - label: - "Step 6b: TH sends Set Credential Command to DUT with the following - fields: a)OperationType as 0 b)Credential as 1 1 (same as step 2) - c)CredentialData as 123457 d)UserIndex as 1 e)UserStatus as null - f)UserType as null" - PICS: DRLK.S.F08 && DRLK.S.C22.Rsp && DRLK.S.C23.Tx - command: "SetCredential" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "OperationType" - value: 0 - - name: "Credential" - value: { CredentialType: 1, CredentialIndex: 1 } - - name: "CredentialData" - value: "123457" - - name: "UserIndex" - value: 1 - - name: "UserStatus" - value: null - - name: "UserType" - value: null - response: - values: - - name: "Status" - constraints: - anyOf: [0x2, 0x3] - - - label: - "Step 7: TH sends Set Credential Command to DUT with the following - fields: a)OperationType as 2 b)Credential as 1 3 c)CredentialData as - 1234567 d)UserIndex as 1 e)UserStatus as null f)UserType as null" - PICS: DRLK.S.F08 && DRLK.S.C22.Rsp && DRLK.S.C23.Tx - command: "SetCredential" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "OperationType" - value: 2 - - name: "Credential" - value: { CredentialType: 1, CredentialIndex: 3 } - - name: "CredentialData" - value: "1234567" - - name: "UserIndex" - value: 1 - - name: "UserStatus" - value: null - - name: "UserType" - value: null - response: - values: - - name: "Status" - value: 0x85 - - - label: - "Step 8: TH sends Clear Credential Command to DUT with the following - fields: a)CredentialType as 1 b)CredentialIndex as 1" - PICS: DRLK.S.F08 && DRLK.S.C26.Rsp - command: "ClearCredential" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "Credential" - value: { CredentialType: 1, CredentialIndex: 1 } - - - label: - "Step 9: TH sends Get Credential command to DUT with the following - fields: a)CredentialType as 1 b)CredentialIndex as 1" - PICS: DRLK.S.F08 && DRLK.S.C24.Rsp && DRLK.S.C25.Tx - command: "GetCredentialStatus" - arguments: - values: - - name: "Credential" - value: { CredentialType: 1, CredentialIndex: 1 } - response: - values: - - name: "CredentialExists" - value: false - - name: "UserIndex" - value: null - - name: "CreatorFabricIndex" - value: null - - name: "LastModifiedFabricIndex" - value: null - - name: "NextCredentialIndex" - value: null - - - label: - "Step 10: TH sends Set User Command to DUT with the following values: - a)OperationType as 0 b)UserIndex as 2 c)UserName as xxx d)UserUniqueID - as 6452 e)UserStatus as 1 f)UserType as 0 g)CredentialRule as 0" - PICS: DRLK.S.F08 && DRLK.S.C1a.Rsp - command: "SetUser" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "OperationType" - value: 0 - - name: "UserIndex" - value: 2 - - name: "UserName" - value: "xxx" - - name: "UserUniqueID" - value: "6452" - - name: "UserStatus" - value: 1 - - name: "UserType" - value: 0 - - name: "CredentialRule" - value: 0 - - - label: - "Step 11: TH sends Set Credential Command to DUT with the following - fields: a)OperationType as 0 b)Credential as 1 1 c)CredentialData as - 123456 d)UserIndex as 2 e)UserStatus as null f)UserType as null" - PICS: DRLK.S.F08 && DRLK.S.C22.Rsp && DRLK.S.C23.Tx - command: "SetCredential" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "OperationType" - value: 0 - - name: "Credential" - value: { CredentialType: 1, CredentialIndex: 1 } - - name: "CredentialData" - value: "123456" - - name: "UserIndex" - value: 2 - - name: "UserStatus" - value: null - - name: "UserType" - value: null - response: - values: - - name: "Status" - value: 0 - - name: "UserIndex" - value: null - - - label: - "Step 12a: TH sends Clear Credential Command to DUT with the following - fields: a)CredentialType as 1 b)CredentialIndex as 0xFFFE" - PICS: DRLK.S.F08 && DRLK.S.C26.Rsp - command: "ClearCredential" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "Credential" - value: { CredentialType: 1, CredentialIndex: 65534 } - - - label: - "Step 12b: TH sends Get Credential command to DUT with the following - fields: a)CredentialType as 1 b)CredentialIndex as 0xFFFE" - PICS: DRLK.S.F08 && DRLK.S.C24.Rsp && DRLK.S.C25.Tx - command: "GetCredentialStatus" - arguments: - values: - - name: "Credential" - value: { CredentialType: 1, CredentialIndex: 65534 } - response: - values: - - name: "CredentialExists" - value: false - - name: "UserIndex" - value: null - - name: "CreatorFabricIndex" - value: null - - name: "LastModifiedFabricIndex" - value: null - - name: "NextCredentialIndex" - value: null - - - label: - "Step 13: TH sends Get Credential Status Command with a)CredentialType - as 1 b)CredentialIndex as 1" - PICS: DRLK.S.F08 && DRLK.S.C24.Rsp && DRLK.S.C25.Tx - command: "GetCredentialStatus" - arguments: - values: - - name: "Credential" - value: { CredentialType: 1, CredentialIndex: 1 } - response: - values: - - name: "CredentialExists" - value: false - - name: "UserIndex" - value: null - - name: "CreatorFabricIndex" - value: null - - name: "LastModifiedFabricIndex" - value: null - - name: "NextCredentialIndex" - value: null - - - label: - "Step 14: TH sends Clear Credential Command to DUT with the following - fields: a)CredentialType as 8(Invalid value) b)CredentialIndex as 2" - PICS: DRLK.S.F08 && DRLK.S.C26.Rsp && !DRLK.S.F0d - command: "ClearCredential" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "Credential" - value: { CredentialType: 8, CredentialIndex: 2 } - response: - error: INVALID_COMMAND - - - label: - "Step 14: TH sends Clear Credential Command to DUT with the following - fields: a)CredentialType as 9(Invalid value) b)CredentialIndex as 2" - PICS: DRLK.S.F08 && DRLK.S.C26.Rsp && DRLK.S.F0d - command: "ClearCredential" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "Credential" - value: { CredentialType: 9, CredentialIndex: 2 } - response: - error: INVALID_COMMAND - - - label: "Cleanup the first created user" - command: "ClearUser" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "UserIndex" - value: 1 - - - label: "Cleanup the second created user" - command: "ClearUser" - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "UserIndex" - value: 2 diff --git a/src/app/tests/test-interaction-model-api.cpp b/src/app/tests/test-interaction-model-api.cpp index d24c586efc2e12..5750e098b995f3 100644 --- a/src/app/tests/test-interaction-model-api.cpp +++ b/src/app/tests/test-interaction-model-api.cpp @@ -13,16 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "app/data-model-provider/ActionReturnStatus.h" #include #include #include #include +#include #include #include #include #include +#include #include using namespace chip::app::DataModel; diff --git a/src/app/tests/test-interaction-model-api.h b/src/app/tests/test-interaction-model-api.h index 7b1b1ad335b1e8..3f4bd27cee36c1 100644 --- a/src/app/tests/test-interaction-model-api.h +++ b/src/app/tests/test-interaction-model-api.h @@ -91,7 +91,6 @@ CHIP_ERROR WriteSingleClusterData(const Access::SubjectDescriptor & aSubjectDesc TLV::TLVReader & aReader, WriteHandler * aWriteHandler); const EmberAfAttributeMetadata * GetAttributeMetadata(const ConcreteAttributePath & aConcreteClusterPath); -bool ConcreteAttributePathExists(const ConcreteAttributePath & aPath); Protocols::InteractionModel::Status CheckEventSupportStatus(const ConcreteEventPath & aPath); Protocols::InteractionModel::Status ServerClusterCommandExists(const ConcreteCommandPath & aRequestCommandPath); diff --git a/src/controller/tests/TestServerCommandDispatch.cpp b/src/controller/tests/TestServerCommandDispatch.cpp index 6e2c2c5306ec2a..a09d2537f377bf 100644 --- a/src/controller/tests/TestServerCommandDispatch.cpp +++ b/src/controller/tests/TestServerCommandDispatch.cpp @@ -15,13 +15,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/** - * @file - * This file implements unit tests for CHIP Interaction Model Command Interaction - * - */ - #include #include @@ -30,10 +23,14 @@ #include #include #include +#include +#include #include #include #include #include +#include +#include #include #include #include @@ -129,9 +126,33 @@ CHIP_ERROR TestClusterCommandHandler::EnumerateAcceptedCommands(const ConcreteCl namespace { +class DispatchTestDataModel : public CodegenDataModelProvider +{ +public: + static DispatchTestDataModel & Instance() + { + static DispatchTestDataModel instance; + return instance; + } +}; + class TestServerCommandDispatch : public chip::Test::AppContext { +public: + void SetUp() + { + AppContext::SetUp(); + mOldProvider = InteractionModelEngine::GetInstance()->SetDataModelProvider(&DispatchTestDataModel::Instance()); + } + void TearDown() + { + InteractionModelEngine::GetInstance()->SetDataModelProvider(mOldProvider); + AppContext::TearDown(); + } + protected: + chip::app::DataModel::Provider * mOldProvider = nullptr; + void TestDataResponseHelper(const EmberAfEndpointType * aEndpoint, bool aExpectSuccess); }; diff --git a/src/controller/tests/data_model/DataModelFixtures.cpp b/src/controller/tests/data_model/DataModelFixtures.cpp index 1850bc0799cdc6..e30641fc530532 100644 --- a/src/controller/tests/data_model/DataModelFixtures.cpp +++ b/src/controller/tests/data_model/DataModelFixtures.cpp @@ -17,14 +17,19 @@ */ #include "DataModelFixtures.h" -#include "app/data-model-provider/ActionReturnStatus.h" #include #include #include #include +#include +#include #include #include +#include +#include +#include +#include using namespace chip; using namespace chip::app; @@ -237,11 +242,6 @@ bool IsDeviceTypeOnEndpoint(DeviceTypeId deviceType, EndpointId endpoint) return false; } -bool ConcreteAttributePathExists(const ConcreteAttributePath & aPath) -{ - return true; -} - Protocols::InteractionModel::Status CheckEventSupportStatus(const ConcreteEventPath & aPath) { return Protocols::InteractionModel::Status::Success; @@ -485,7 +485,7 @@ Protocols::InteractionModel::Status ServerClusterCommandExists(const ConcreteCom // Mock cluster catalog, only support commands on one cluster on one endpoint. using Protocols::InteractionModel::Status; - if (aCommandPath.mEndpointId != kTestEndpointId) + if (aCommandPath.mEndpointId != DataModelTests::kTestEndpointId) { return Status::UnsupportedEndpoint; } @@ -665,7 +665,8 @@ ActionReturnStatus CustomDataModel::WriteAttribute(const WriteAttributeRequest & std::optional CustomDataModel::Invoke(const InvokeRequest & request, chip::TLV::TLVReader & input_arguments, CommandHandler * handler) { - return std::make_optional(CHIP_ERROR_NOT_IMPLEMENTED); + DispatchSingleClusterCommand(request.path, input_arguments, handler); + return std::nullopt; // handler status is set by the dispatch } EndpointId CustomDataModel::FirstEndpoint() diff --git a/src/controller/tests/data_model/TestCommands.cpp b/src/controller/tests/data_model/TestCommands.cpp index 4e8b3dd39adb74..c54e458ad81dde 100644 --- a/src/controller/tests/data_model/TestCommands.cpp +++ b/src/controller/tests/data_model/TestCommands.cpp @@ -50,7 +50,50 @@ using namespace chip::Protocols; namespace { -using TestCommands = chip::Test::AppContext; +const chip::Test::MockNodeConfig & TestMockNodeConfig() +{ + using namespace chip::app; + using namespace chip::Test; + using namespace chip::app::Clusters::Globals::Attributes; + + // clang-format off + static const MockNodeConfig config({ + MockEndpointConfig(kTestEndpointId, { + MockClusterConfig(Clusters::UnitTesting::Id, { + ClusterRevision::Id, FeatureMap::Id, + }, + {}, // events + { + Clusters::UnitTesting::Commands::TestSimpleArgumentRequest::Id, + }, // accepted commands + {} // generated commands + ), + }), + }); + // clang-format on + return config; +} + +class TestCommands : public chip::Test::AppContext +{ +public: + void SetUp() override + { + AppContext::SetUp(); + mOldProvider = InteractionModelEngine::GetInstance()->SetDataModelProvider(&CustomDataModel::Instance()); + chip::Test::SetMockNodeConfig(TestMockNodeConfig()); + } + + void TearDown() override + { + chip::Test::ResetMockNodeConfig(); + InteractionModelEngine::GetInstance()->SetDataModelProvider(mOldProvider); + AppContext::TearDown(); + } + +protected: + chip::app::DataModel::Provider * mOldProvider = nullptr; +}; TEST_F(TestCommands, TestDataResponse) { @@ -104,7 +147,8 @@ TEST_F(TestCommands, TestDataResponse) DrainAndServiceIO(); - EXPECT_TRUE(onSuccessWasCalled && !onFailureWasCalled); + EXPECT_TRUE(onSuccessWasCalled); + EXPECT_FALSE(onFailureWasCalled); EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u); } @@ -367,7 +411,7 @@ TEST_F(TestCommands, TestFailureWithClusterStatus) { app::StatusIB status(aError); statusCheck = (status.mStatus == Protocols::InteractionModel::Status::Failure && - status.mClusterStatus.Value() == kTestFailureClusterStatus); + status.mClusterStatus == MakeOptional(kTestFailureClusterStatus)); } onFailureWasCalled = true; }; diff --git a/src/controller/tests/data_model/TestRead.cpp b/src/controller/tests/data_model/TestRead.cpp index c2c2e63689f932..6724e0d589457f 100644 --- a/src/controller/tests/data_model/TestRead.cpp +++ b/src/controller/tests/data_model/TestRead.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,67 @@ using namespace chip::Test; namespace { +const MockNodeConfig & TestMockNodeConfig() +{ + using namespace Clusters::Globals::Attributes; + + // clang-format off + static const MockNodeConfig config({ + MockEndpointConfig(kRootEndpointId, { + MockClusterConfig(Clusters::IcdManagement::Id, { + ClusterRevision::Id, FeatureMap::Id, + Clusters::IcdManagement::Attributes::OperatingMode::Id, + }), + }), + MockEndpointConfig(kTestEndpointId, { + MockClusterConfig(Clusters::UnitTesting::Id, { + ClusterRevision::Id, FeatureMap::Id, + Clusters::UnitTesting::Attributes::Boolean::Id, + Clusters::UnitTesting::Attributes::Int16u::Id, + Clusters::UnitTesting::Attributes::ListFabricScoped::Id, + Clusters::UnitTesting::Attributes::ListStructOctetString::Id, + }), + }), + MockEndpointConfig(kMockEndpoint1, { + MockClusterConfig(MockClusterId(1), { + ClusterRevision::Id, FeatureMap::Id, + }, { + MockEventId(1), MockEventId(2), + }), + MockClusterConfig(MockClusterId(2), { + ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), + }), + }), + MockEndpointConfig(kMockEndpoint2, { + MockClusterConfig(MockClusterId(1), { + ClusterRevision::Id, FeatureMap::Id, + }), + MockClusterConfig(MockClusterId(2), { + ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), MockAttributeId(2), + }), + MockClusterConfig(MockClusterId(3), { + ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), MockAttributeId(2), MockAttributeId(3), + }), + }), + MockEndpointConfig(kMockEndpoint3, { + MockClusterConfig(MockClusterId(1), { + ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), + }), + MockClusterConfig(MockClusterId(2), { + ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), MockAttributeId(2), MockAttributeId(3), MockAttributeId(4), + }), + MockClusterConfig(MockClusterId(3), { + ClusterRevision::Id, FeatureMap::Id, + }), + MockClusterConfig(MockClusterId(4), { + ClusterRevision::Id, FeatureMap::Id, + }), + }), + }); + // clang-format on + return config; +} + class TestRead : public chip::Test::AppContext, public app::ReadHandler::ApplicationCallback { protected: @@ -57,11 +119,13 @@ class TestRead : public chip::Test::AppContext, public app::ReadHandler::Applica { chip::Test::AppContext::SetUp(); mOldProvider = InteractionModelEngine::GetInstance()->SetDataModelProvider(&CustomDataModel::Instance()); + chip::Test::SetMockNodeConfig(TestMockNodeConfig()); } // Performs teardown for each individual test in the test suite void TearDown() override { + chip::Test::ResetMockNodeConfig(); InteractionModelEngine::GetInstance()->SetDataModelProvider(mOldProvider); chip::Test::AppContext::TearDown(); } @@ -3192,6 +3256,7 @@ TEST_F(TestRead, TestSubscribeAttributeDeniedNotExistPath) app::AttributePathParams attributePathParams[1]; readPrepareParams.mpAttributePathParamsList = attributePathParams; readPrepareParams.mAttributePathParamsListSize = ArraySize(attributePathParams); + attributePathParams[0].mEndpointId = kRootEndpointId; // this cluster does NOT exist on the root endpoint attributePathParams[0].mClusterId = app::Clusters::UnitTesting::Id; attributePathParams[0].mAttributeId = app::Clusters::UnitTesting::Attributes::ListStructOctetString::Id; diff --git a/src/darwin/Framework/CHIP/MTRDevice.mm b/src/darwin/Framework/CHIP/MTRDevice.mm index 552c99c7e873b4..a584bd68e06f9f 100644 --- a/src/darwin/Framework/CHIP/MTRDevice.mm +++ b/src/darwin/Framework/CHIP/MTRDevice.mm @@ -295,6 +295,15 @@ - (instancetype)initForSubclassesWithNodeID:(NSNumber *)nodeID controller:(MTRDe return self; } +// For now, implement an initWithNodeID in case some sub-class outside the +// framework called it (by manually declaring it, even though it's not public +// API). Ideally we would not have this thing, since its signature does not +// match the initWithNodeID signatures of our subclasses. +- (instancetype)initWithNodeID:(NSNumber *)nodeID controller:(MTRDeviceController *)controller +{ + return [self initForSubclassesWithNodeID:nodeID controller:controller]; +} + - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:_systemTimeChangeObserverToken]; @@ -305,6 +314,17 @@ - (void)dealloc + (MTRDevice *)deviceWithNodeID:(NSNumber *)nodeID controller:(MTRDeviceController *)controller { + if (nodeID == nil || controller == nil) { + // These are not nullable in our API, but clearly someone is not + // actually turning on the relevant compiler checks (or is doing dynamic + // dispatch with bad values). While we promise to not return nil from + // this method, if the caller is ignoring the nullability API contract, + // there's not much we can do here. + MTR_LOG_ERROR("Can't create device with nodeID: %@, controller: %@", + nodeID, controller); + return nil; + } + return [controller deviceForNodeID:nodeID]; } @@ -432,13 +452,6 @@ - (void)invalidate [_delegates removeAllObjects]; } -- (void)nodeMayBeAdvertisingOperational -{ - assertChipStackLockedByCurrentThread(); - - MTR_LOG("%@ saw new operational advertisement", self); -} - - (BOOL)_delegateExists { os_unfair_lock_assert_owner(&self->_lock); @@ -1050,7 +1063,7 @@ - (void)invokeCommandWithEndpointID:(NSNumber *)endpointID } MTRDeviceDataValueDictionary fieldsDataValue = commandFields; - if (fieldsDataValue[MTRTypeKey] != MTRStructureValueType) { + if (![MTRStructureValueType isEqual:fieldsDataValue[MTRTypeKey]]) { MTR_LOG_ERROR("%@ invokeCommandWithEndpointID passed a commandFields (%@) that is not a structure-typed data-value object", self, commandFields); completion(nil, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_ARGUMENT]); @@ -1141,12 +1154,10 @@ - (void)openCommissioningWindowWithSetupPasscode:(NSNumber *)setupPasscode queue:(dispatch_queue_t)queue completion:(MTRDeviceOpenCommissioningWindowHandler)completion { - auto * baseDevice = [self newBaseDevice]; - [baseDevice openCommissioningWindowWithSetupPasscode:setupPasscode - discriminator:discriminator - duration:duration - queue:queue - completion:completion]; + MTR_ABSTRACT_METHOD(); + dispatch_async(queue, ^{ + completion(nil, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE]); + }); } - (void)openCommissioningWindowWithDiscriminator:(NSNumber *)discriminator @@ -1154,8 +1165,10 @@ - (void)openCommissioningWindowWithDiscriminator:(NSNumber *)discriminator queue:(dispatch_queue_t)queue completion:(MTRDeviceOpenCommissioningWindowHandler)completion { - auto * baseDevice = [self newBaseDevice]; - [baseDevice openCommissioningWindowWithDiscriminator:discriminator duration:duration queue:queue completion:completion]; + MTR_ABSTRACT_METHOD(); + dispatch_async(queue, ^{ + completion(nil, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE]); + }); } - (void)downloadLogOfType:(MTRDiagnosticLogType)type @@ -1163,11 +1176,10 @@ - (void)downloadLogOfType:(MTRDiagnosticLogType)type queue:(dispatch_queue_t)queue completion:(void (^)(NSURL * _Nullable url, NSError * _Nullable error))completion { - auto * baseDevice = [self newBaseDevice]; - [baseDevice downloadLogOfType:type - timeout:timeout - queue:queue - completion:completion]; + MTR_ABSTRACT_METHOD(); + dispatch_async(queue, ^{ + completion(nil, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE]); + }); } #pragma mark - Cache management @@ -1286,11 +1298,6 @@ - (BOOL)deviceCachePrimed return _deviceCachePrimed; } -- (MTRBaseDevice *)newBaseDevice -{ - return [MTRBaseDevice deviceWithNodeID:self.nodeID controller:self.deviceController]; -} - #pragma mark Log Help - (nullable NSNumber *)_informationalNumberAtAttributePath:(MTRAttributePath *)attributePath diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.mm b/src/darwin/Framework/CHIP/MTRDeviceController.mm index d1759e3008eee8..690f0e4ba89cfd 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController.mm @@ -126,7 +126,6 @@ @implementation MTRDeviceController { MTRDeviceControllerDelegateBridge * _deviceControllerDelegateBridge; MTROperationalCredentialsDelegate * _operationalCredentialsDelegate; MTRDeviceAttestationDelegateBridge * _deviceAttestationDelegateBridge; - MTRDeviceControllerFactory * _factory; os_unfair_lock _underlyingDeviceMapLock; MTRCommissionableBrowser * _commissionableBrowser; MTRAttestationTrustStoreBridge * _attestationTrustStoreBridge; @@ -419,7 +418,11 @@ - (MTRBaseDevice *)baseDeviceForNodeID:(NSNumber *)nodeID - (MTRDevice *)_setupDeviceForNodeID:(NSNumber *)nodeID prefetchedClusterData:(NSDictionary *)prefetchedClusterData { MTR_ABSTRACT_METHOD(); - return nil; + // We promise to not return nil from this API... return an MTRDevice + // instance, which will largely not be able to do anything useful. This + // only matters when someone subclasses MTRDeviceController in a weird way, + // then tries to create an MTRDevice from their subclass. + return [[MTRDevice alloc] initForSubclassesWithNodeID:nodeID controller:self]; } - (MTRDevice *)deviceForNodeID:(NSNumber *)nodeID @@ -554,65 +557,14 @@ - (BOOL)checkIsRunning:(NSError * __autoreleasing *)error - (void)getSessionForNode:(chip::NodeId)nodeID completion:(MTRInternalDeviceConnectionCallback)completion { - // Get the corresponding MTRDevice object to determine if the case/subscription pool is to be used - MTRDevice * device = [self deviceForNodeID:@(nodeID)]; - - // In the case that this device is known to use thread, queue this with subscription attempts as well, to - // help with throttling Thread traffic. - if ([device deviceUsesThread]) { - MTRAsyncWorkItem * workItem = [[MTRAsyncWorkItem alloc] initWithQueue:dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0)]; - [workItem setReadyHandler:^(id _Nonnull context, NSInteger retryCount, MTRAsyncWorkCompletionBlock _Nonnull workItemCompletion) { - MTRInternalDeviceConnectionCallback completionWrapper = ^(chip::Messaging::ExchangeManager * _Nullable exchangeManager, - const chip::Optional & session, NSError * _Nullable error, NSNumber * _Nullable retryDelay) { - completion(exchangeManager, session, error, retryDelay); - workItemCompletion(MTRAsyncWorkComplete); - }; - [self directlyGetSessionForNode:nodeID completion:completionWrapper]; - }]; - - [_concurrentSubscriptionPool enqueueWorkItem:workItem descriptionWithFormat:@"device controller getSessionForNode nodeID: 0x%016llX", nodeID]; - } else { - [self directlyGetSessionForNode:nodeID completion:completion]; - } -} - -- (void)directlyGetSessionForNode:(chip::NodeId)nodeID completion:(MTRInternalDeviceConnectionCallback)completion -{ - [self - asyncGetCommissionerOnMatterQueue:^(chip::Controller::DeviceCommissioner * commissioner) { - auto connectionBridge = new MTRDeviceConnectionBridge(completion); - - // MTRDeviceConnectionBridge always delivers errors async via - // completion. - connectionBridge->connect(commissioner, nodeID); - } - errorHandler:^(NSError * error) { - completion(nullptr, chip::NullOptional, error, nil); - }]; + MTR_ABSTRACT_METHOD(); + completion(nullptr, chip::NullOptional, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil); } - (void)getSessionForCommissioneeDevice:(chip::NodeId)deviceID completion:(MTRInternalDeviceConnectionCallback)completion { - [self - asyncGetCommissionerOnMatterQueue:^(chip::Controller::DeviceCommissioner * commissioner) { - chip::CommissioneeDeviceProxy * deviceProxy; - CHIP_ERROR err = commissioner->GetDeviceBeingCommissioned(deviceID, &deviceProxy); - if (err != CHIP_NO_ERROR) { - completion(nullptr, chip::NullOptional, [MTRError errorForCHIPErrorCode:err], nil); - return; - } - - chip::Optional session = deviceProxy->GetSecureSession(); - if (!session.HasValue() || !session.Value()->AsSecureSession()->IsPASESession()) { - completion(nullptr, chip::NullOptional, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil); - return; - } - - completion(deviceProxy->GetExchangeManager(), session, nil, nil); - } - errorHandler:^(NSError * error) { - completion(nullptr, chip::NullOptional, error, nil); - }]; + MTR_ABSTRACT_METHOD(); + completion(nullptr, chip::NullOptional, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil); } - (MTRTransportType)sessionTransportTypeForDevice:(MTRBaseDevice *)device @@ -665,10 +617,8 @@ - (void)asyncGetCommissionerOnMatterQueue:(void (^)(chip::Controller::DeviceComm - (void)asyncDispatchToMatterQueue:(dispatch_block_t)block errorHandler:(nullable MTRDeviceErrorHandler)errorHandler { - auto adapter = ^(chip::Controller::DeviceCommissioner *) { - block(); - }; - [self asyncGetCommissionerOnMatterQueue:adapter errorHandler:errorHandler]; + MTR_ABSTRACT_METHOD(); + errorHandler([MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE]); } - (void)syncRunOnWorkQueue:(SyncWorkQueueBlock)block error:(NSError * __autoreleasing *)error @@ -729,39 +679,16 @@ - (void)invalidateCASESessionForNode:(chip::NodeId)nodeID; [self syncRunOnWorkQueue:block error:nil]; } -- (void)operationalInstanceAdded:(chip::NodeId)nodeID -{ - // Don't use deviceForNodeID here, because we don't want to create the - // device if it does not already exist. - os_unfair_lock_lock(self.deviceMapLock); - MTRDevice * device = [_nodeIDToDeviceMap objectForKey:@(nodeID)]; - os_unfair_lock_unlock(self.deviceMapLock); - - if (device == nil) { - return; - } - - ChipLogProgress(Controller, "Notifying device about node 0x" ChipLogFormatX64 " advertising", ChipLogValueX64(nodeID)); - [device nodeMayBeAdvertisingOperational]; -} - - (void)downloadLogFromNodeWithID:(NSNumber *)nodeID type:(MTRDiagnosticLogType)type timeout:(NSTimeInterval)timeout queue:(dispatch_queue_t)queue completion:(void (^)(NSURL * _Nullable url, NSError * _Nullable error))completion { - [self asyncDispatchToMatterQueue:^() { - [self->_factory downloadLogFromNodeWithID:nodeID - controller:self - type:type - timeout:timeout - queue:queue - completion:completion]; - } - errorHandler:^(NSError * error) { - completion(nil, error); - }]; + MTR_ABSTRACT_METHOD(); + dispatch_async(queue, ^{ + completion(nil, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE]); + }); } - (NSArray *)accessGrantsForClusterPath:(MTRClusterPath *)clusterPath diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm index 4cff8a633105b2..085d0a2c55ca6d 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm @@ -1099,7 +1099,7 @@ - (nullable NSNumber *)neededReadPrivilegeForClusterID:(NSNumber *)clusterID att } - (void)downloadLogFromNodeWithID:(NSNumber *)nodeID - controller:(MTRDeviceController *)controller + controller:(MTRDeviceController_Concrete *)controller type:(MTRDiagnosticLogType)type timeout:(NSTimeInterval)timeout queue:(dispatch_queue_t)queue @@ -1132,7 +1132,7 @@ - (void)operationalInstanceAdded:(chip::PeerId &)operationalID if (compressedFabricId != nil && compressedFabricId.unsignedLongLongValue == operationalID.GetCompressedFabricId()) { ChipLogProgress(Controller, "Notifying controller at fabric index %u about new operational node 0x" ChipLogFormatX64, controller.fabricIndex, ChipLogValueX64(operationalID.GetNodeId())); - [controller operationalInstanceAdded:operationalID.GetNodeId()]; + [controller operationalInstanceAdded:@(operationalID.GetNodeId())]; } // Keep going: more than one controller might match a given compressed diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory_Internal.h b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory_Internal.h index 1642641717cbe8..3ff9d0268703fa 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory_Internal.h +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory_Internal.h @@ -83,7 +83,7 @@ MTR_DIRECT_MEMBERS * Download log of the desired type from the device. */ - (void)downloadLogFromNodeWithID:(NSNumber *)nodeID - controller:(MTRDeviceController *)controller + controller:(MTRDeviceController_Concrete *)controller type:(MTRDiagnosticLogType)type timeout:(NSTimeInterval)timeout queue:(dispatch_queue_t)queue diff --git a/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.h b/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.h index ea71f351c72377..e0820d57e0f88c 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.h +++ b/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.h @@ -17,10 +17,19 @@ #import -#import - +#import +#import +#import +#import +#import +#import + +#import "MTRDeviceConnectionBridge.h" #import "MTRDeviceControllerStartupParams_Internal.h" +#include +#include + NS_ASSUME_NONNULL_BEGIN @interface MTRDeviceController_Concrete : MTRDeviceController @@ -109,6 +118,19 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)clearPendingShutdown; +/** + * Since getSessionForNode now enqueues by the subscription pool for Thread + * devices, MTRDevice_Concrete needs a direct non-queued access because it already + * makes use of the subscription pool. + */ +- (void)directlyGetSessionForNode:(chip::NodeId)nodeID completion:(MTRInternalDeviceConnectionCallback)completion; + +/** + * Notify the controller that a new operational instance with the given node id + * and a compressed fabric id that matches this controller has been observed. + */ +- (void)operationalInstanceAdded:(NSNumber *)nodeID; + @end NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm b/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm index d0cab185e40bf6..cb86c5d2db044f 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm @@ -1633,20 +1633,28 @@ - (void)invalidateCASESessionForNode:(chip::NodeId)nodeID; [self syncRunOnWorkQueue:block error:nil]; } -- (void)operationalInstanceAdded:(chip::NodeId)nodeID +- (void)operationalInstanceAdded:(NSNumber *)nodeID { // Don't use deviceForNodeID here, because we don't want to create the // device if it does not already exist. os_unfair_lock_lock(self.deviceMapLock); - MTRDevice * device = [self.nodeIDToDeviceMap objectForKey:@(nodeID)]; + MTRDevice * device = [self.nodeIDToDeviceMap objectForKey:nodeID]; os_unfair_lock_unlock(self.deviceMapLock); if (device == nil) { return; } - ChipLogProgress(Controller, "Notifying device about node 0x" ChipLogFormatX64 " advertising", ChipLogValueX64(nodeID)); - [device nodeMayBeAdvertisingOperational]; + // TODO: Can we not just assume this isKindOfClass test is true? Would be + // really nice if we had compile-time checking for this somehow... + if (![device isKindOfClass:MTRDevice_Concrete.class]) { + MTR_LOG_ERROR("%@ somehow has %@ instead of MTRDevice_Concrete for node ID 0x%016llX (%llu)", self, device, nodeID.unsignedLongLongValue, nodeID.unsignedLongLongValue); + return; + } + + MTR_LOG("%@ Notifying %@ about its node advertising", self, device); + auto * concreteDevice = static_cast(device); + [concreteDevice nodeMayBeAdvertisingOperational]; } - (void)downloadLogFromNodeWithID:(NSNumber *)nodeID diff --git a/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h b/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h index a052d527b89b86..958e7914b1dd3a 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h +++ b/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h @@ -201,12 +201,6 @@ NS_ASSUME_NONNULL_BEGIN */ - (MTRBaseDevice *)baseDeviceForNodeID:(NSNumber *)nodeID; -/** - * Notify the controller that a new operational instance with the given node id - * and a compressed fabric id that matches this controller has been observed. - */ -- (void)operationalInstanceAdded:(chip::NodeId)nodeID; - /** * Download log of the desired type from the device. */ @@ -243,13 +237,6 @@ NS_ASSUME_NONNULL_BEGIN - (MTRDevice *)_setupDeviceForNodeID:(NSNumber *)nodeID prefetchedClusterData:(nullable NSDictionary *)prefetchedClusterData; - (void)removeDevice:(MTRDevice *)device; -/** - * Since getSessionForNode now enqueues by the subscription pool for Thread - * devices, MTRDevice needs a direct non-queued access because it already - * makes use of the subscription pool. - */ -- (void)directlyGetSessionForNode:(chip::NodeId)nodeID completion:(MTRInternalDeviceConnectionCallback)completion; - @end /** diff --git a/src/darwin/Framework/CHIP/MTRDevice_Concrete.h b/src/darwin/Framework/CHIP/MTRDevice_Concrete.h index 74a9a5788c5b8b..70dac9a362b10d 100644 --- a/src/darwin/Framework/CHIP/MTRDevice_Concrete.h +++ b/src/darwin/Framework/CHIP/MTRDevice_Concrete.h @@ -26,6 +26,11 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithNodeID:(NSNumber *)nodeID controller:(MTRDeviceController_Concrete *)controller; +// Called by controller when a new operational advertisement for what we think +// is this device's identity has been observed. This could have +// false-positives, for example due to compressed fabric id collisions. +- (void)nodeMayBeAdvertisingOperational; + @end NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm index a2dbb2dcbaf35d..5d6e47c8d9d781 100644 --- a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm +++ b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm @@ -2388,7 +2388,7 @@ - (void)_setupSubscriptionWithReason:(NSString *)reason MATTER_LOG_METRIC_BEGIN(kMetricMTRDeviceInitialSubscriptionSetup); // Call directlyGetSessionForNode because the subscription setup already goes through the subscription pool queue - [_deviceController + [[self _concreteController] directlyGetSessionForNode:_nodeID.unsignedLongLongValue completion:^(chip::Messaging::ExchangeManager * _Nullable exchangeManager, const chip::Optional & session, NSError * _Nullable error, @@ -3322,6 +3322,8 @@ - (void)_noteDataVersion:(NSNumber *)dataVersion forClusterPath:(MTRClusterPath _clusterDataToPersist = [NSMutableDictionary dictionary]; } _clusterDataToPersist[clusterPath] = clusterData; + + MTR_LOG("%@ updated DataVersion for %@ to %@", self, clusterPath, dataVersion); } } @@ -4138,6 +4140,14 @@ - (void)controllerResumed [self _ensureSubscriptionForExistingDelegates:@"Controller resumed"]; } +// nullable because technically _deviceController is nullable. +- (nullable MTRDeviceController_Concrete *)_concreteController +{ + // We know our _deviceController is actually an MTRDeviceController_Concrete, since that's what + // gets passed to initWithNodeID. + return static_cast(_deviceController); +} + @end /* BEGIN DRAGONS: Note methods here cannot be renamed, and are used by private callers, do not rename, remove or modify behavior here */ diff --git a/src/darwin/Framework/CHIP/MTRDevice_Internal.h b/src/darwin/Framework/CHIP/MTRDevice_Internal.h index 6aea99eeda1ffb..2cdcd66976099a 100644 --- a/src/darwin/Framework/CHIP/MTRDevice_Internal.h +++ b/src/darwin/Framework/CHIP/MTRDevice_Internal.h @@ -118,7 +118,8 @@ MTR_DIRECT_MEMBERS NSNumber * _nodeID; // Our controller. Declared nullable because our property is, though in - // practice it does not look like we ever set it to nil. + // practice it does not look like we ever set it to nil. If this changes, + // fix _concreteController on MTRDevice_Concrete accordingly. MTRDeviceController * _Nullable _deviceController; } @@ -127,11 +128,6 @@ MTR_DIRECT_MEMBERS // called by controller to clean up and shutdown - (void)invalidate; -// Called by controller when a new operational advertisement for what we think -// is this device's identity has been observed. This could have -// false-positives, for example due to compressed fabric id collisions. -- (void)nodeMayBeAdvertisingOperational; - - (BOOL)_callDelegatesWithBlock:(void (^)(id delegate))block; // Called by MTRDevice_XPC to forward delegate callbacks diff --git a/src/darwin/Framework/CHIP/MTRDevice_XPC.mm b/src/darwin/Framework/CHIP/MTRDevice_XPC.mm index 015736e179c2c4..7806546768b4f2 100644 --- a/src/darwin/Framework/CHIP/MTRDevice_XPC.mm +++ b/src/darwin/Framework/CHIP/MTRDevice_XPC.mm @@ -266,6 +266,7 @@ - (void)_invokeCommandWithEndpointID:(NSNumber *)endpointID // Not Supported via XPC //- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID openCommissioningWindowWithSetupPasscode:(NSNumber *)setupPasscode discriminator:(NSNumber *)discriminator duration:(NSNumber *)duration completion:(MTRDeviceOpenCommissioningWindowHandler)completion; +//- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID openCommissioningWindowWithDiscriminator:(NSNumber *)discriminator duration:(NSNumber *)duration completion:(MTRDeviceOpenCommissioningWindowHandler)completion; // Not Supported via XPC // - (oneway void)downloadLogOfType:(MTRDiagnosticLogType)type nodeID:(NSNumber *)nodeID timeout:(NSTimeInterval)timeout completion:(void (^)(NSURL * _Nullable url, NSError * _Nullable error))completion; diff --git a/src/darwin/Framework/CHIP/MTRDiagnosticLogsDownloader.h b/src/darwin/Framework/CHIP/MTRDiagnosticLogsDownloader.h index da7a780c1237f0..8acc6357729d74 100644 --- a/src/darwin/Framework/CHIP/MTRDiagnosticLogsDownloader.h +++ b/src/darwin/Framework/CHIP/MTRDiagnosticLogsDownloader.h @@ -20,6 +20,8 @@ #import #import +#import "MTRDeviceController_Concrete.h" + namespace chip { namespace bdx { class BDXTransferServerDelegate; @@ -33,14 +35,14 @@ NS_ASSUME_NONNULL_BEGIN // Must be called on Matter queue - (void)downloadLogFromNodeWithID:(NSNumber *)nodeID - controller:(MTRDeviceController *)controller + controller:(MTRDeviceController_Concrete *)controller type:(MTRDiagnosticLogType)type timeout:(NSTimeInterval)timeout queue:(dispatch_queue_t)queue completion:(void (^)(NSURL * _Nullable url, NSError * _Nullable error))completion; // Must be called on Matter queue -- (void)abortDownloadsForController:(MTRDeviceController *)controller; +- (void)abortDownloadsForController:(MTRDeviceController_Concrete *)controller; @end diff --git a/src/darwin/Framework/CHIP/MTRDiagnosticLogsDownloader.mm b/src/darwin/Framework/CHIP/MTRDiagnosticLogsDownloader.mm index fdd8a389f71309..a66bae8ede42e5 100644 --- a/src/darwin/Framework/CHIP/MTRDiagnosticLogsDownloader.mm +++ b/src/darwin/Framework/CHIP/MTRDiagnosticLogsDownloader.mm @@ -86,7 +86,7 @@ - (MTRDownload * _Nullable)add:(MTRDiagnosticLogType)type completion:(void (^)(NSURL * _Nullable url, NSError * _Nullable error))completion done:(void (^)(MTRDownload * finishedDownload))done; -- (void)abortDownloadsForController:(MTRDeviceController *)controller; +- (void)abortDownloadsForController:(MTRDeviceController_Concrete *)controller; @end @@ -195,10 +195,11 @@ - (void)checkInteractionModelResponse:(MTRDiagnosticLogsClusterRetrieveLogsRespo VerifyOrReturn(![status isEqual:@(MTRDiagnosticLogsStatusBusy)], [self failure:[MTRError errorForCHIPErrorCode:CHIP_ERROR_BUSY]]); VerifyOrReturn(![status isEqual:@(MTRDiagnosticLogsStatusDenied)], [self failure:[MTRError errorForCHIPErrorCode:CHIP_ERROR_ACCESS_DENIED]]); + VerifyOrReturn(![status isEqual:@(MTRDiagnosticLogsStatusNoLogs)], [self failure:[MTRError errorForCHIPErrorCode:CHIP_ERROR_NOT_FOUND]]); // If the whole log content fits into the response LogContent field or if there is no log, forward it to the caller // and stop here. - if ([status isEqual:@(MTRDiagnosticLogsStatusExhausted)] || [status isEqual:@(MTRDiagnosticLogsStatusNoLogs)]) { + if ([status isEqual:@(MTRDiagnosticLogsStatusExhausted)]) { NSError * writeError = nil; [self writeToFile:response.logContent error:&writeError]; VerifyOrReturn(nil == writeError, [self failure:writeError]); @@ -354,7 +355,7 @@ - (MTRDownload * _Nullable)add:(MTRDiagnosticLogType)type return download; } -- (void)abortDownloadsForController:(MTRDeviceController *)controller +- (void)abortDownloadsForController:(MTRDeviceController_Concrete *)controller { assertChipStackLockedByCurrentThread(); @@ -408,7 +409,7 @@ - (void)dealloc } - (void)downloadLogFromNodeWithID:(NSNumber *)nodeID - controller:(MTRDeviceController *)controller + controller:(MTRDeviceController_Concrete *)controller type:(MTRDiagnosticLogType)type timeout:(NSTimeInterval)timeout queue:(dispatch_queue_t)queue @@ -462,7 +463,7 @@ - (void)downloadLogFromNodeWithID:(NSNumber *)nodeID } } -- (void)abortDownloadsForController:(MTRDeviceController *)controller; +- (void)abortDownloadsForController:(MTRDeviceController_Concrete *)controller; { assertChipStackLockedByCurrentThread(); diff --git a/src/darwin/Framework/CHIPTests/MTRDeviceTests.m b/src/darwin/Framework/CHIPTests/MTRDeviceTests.m index b8552ce325dc8b..cb2acf2db2ce28 100644 --- a/src/darwin/Framework/CHIPTests/MTRDeviceTests.m +++ b/src/darwin/Framework/CHIPTests/MTRDeviceTests.m @@ -1926,6 +1926,51 @@ - (void)test019_MTRDeviceMultipleCommands }]; [self waitForExpectations:@[ readFabricLabelExpectation ] timeout:kTimeoutInSeconds]; + + // Now test doing the UpdateFabricLabel command but directly via the + // MTRDevice API. + XCTestExpectation * updateLabelExpectation2 = [self expectationWithDescription:@"Fabric label updated a second time"]; + // IMPORTANT: commandFields here uses hardcoded strings, not MTR* constants + // for the strings, to check for places that are doing string equality wrong. + __auto_type * commandFields = @{ + @"type" : @"Structure", + @"value" : @[ + @{ + @"contextTag" : @0, + @"data" : @ { + @"type" : @"UTF8String", + @"value" : @"Test2", + }, + }, + ], + }; + + [device invokeCommandWithEndpointID:@(0) + clusterID:@(MTRClusterIDTypeOperationalCredentialsID) + commandID:@(MTRCommandIDTypeClusterOperationalCredentialsCommandUpdateFabricLabelID) + commandFields:commandFields + expectedValues:nil + expectedValueInterval:nil + queue:queue + completion:^(NSArray *> * _Nullable values, NSError * _Nullable error) { + XCTAssertNil(error); + [updateLabelExpectation2 fulfill]; + }]; + + [self waitForExpectations:@[ updateLabelExpectation2 ] timeout:kTimeoutInSeconds]; + + // And again, make sure our fabric label got updated. + readFabricLabelExpectation = [self expectationWithDescription:@"Read fabric label third time"]; + [baseOpCredsCluster readAttributeFabricsWithParams:nil completion:^(NSArray * _Nullable value, NSError * _Nullable error) { + XCTAssertNil(error); + XCTAssertNotNil(value); + XCTAssertEqual(value.count, 1); + MTROperationalCredentialsClusterFabricDescriptorStruct * entry = value[0]; + XCTAssertEqualObjects(entry.label, @"Test2"); + [readFabricLabelExpectation fulfill]; + }]; + + [self waitForExpectations:@[ readFabricLabelExpectation ] timeout:kTimeoutInSeconds]; } - (void)test020_ReadMultipleAttributes diff --git a/src/darwin/Framework/CHIPTests/MTRXPCListenerSampleTests.m b/src/darwin/Framework/CHIPTests/MTRXPCListenerSampleTests.m index f16775af0f9d95..cd7bfa53b6697d 100644 --- a/src/darwin/Framework/CHIPTests/MTRXPCListenerSampleTests.m +++ b/src/darwin/Framework/CHIPTests/MTRXPCListenerSampleTests.m @@ -23,14 +23,14 @@ #import #import "MTRErrorTestUtils.h" +#import "MTRTestCase+ServerAppRunner.h" +#import "MTRTestCase.h" #import "MTRTestKeys.h" -#import "MTRTestResetCommissioneeHelper.h" #import "MTRTestStorage.h" #import // For INFINITY // system dependencies -#import #import static uint16_t kTestVendorId = 0xFFF1u; @@ -418,7 +418,9 @@ - (void)readAttributeCacheWithController:(id _Nullable)controller static const uint16_t kPairingTimeoutInSeconds = 30; static const uint16_t kTimeoutInSeconds = 3; static const uint64_t kDeviceId = 0x12344321; -static NSString * kOnboardingPayload = @"MT:-24J0AFN00KA0648G00"; +static NSString * kOnboardingPayload = @"MT:Y.K90SO527JA0648G00"; +static NSString * _Nullable sLogContentFilePath; +static NSString * kSimpleLogContent = @"This is a simple log\n"; static const uint16_t kLocalPort = 5541; // This test suite reuses a device object to speed up the test process for CI. @@ -501,25 +503,42 @@ - (BOOL)unitTestShouldSkipExpectedValuesForWrite:(MTRDevice *)device } @end -@interface MTRXPCListenerSampleTests : XCTestCase +@interface MTRXPCListenerSampleTests : MTRTestCase @end static BOOL sStackInitRan = NO; -static BOOL sNeedsStackShutdown = YES; @implementation MTRXPCListenerSampleTests ++ (void)setUp +{ + // Global setup, runs once. + [super setUp]; + + __auto_type * uniqueName = [[NSUUID UUID] UUIDString]; + sLogContentFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:uniqueName]; + [[NSFileManager defaultManager] createFileAtPath:sLogContentFilePath + contents:[kSimpleLogContent dataUsingEncoding:NSUTF8StringEncoding] + attributes:nil]; + BOOL started = [self startAppWithName:@"all-clusters" + arguments:@[ + @"--end_user_support_log", + sLogContentFilePath, + ] + payload:kOnboardingPayload]; + XCTAssertTrue(started); +} + + (void)tearDown { // Global teardown, runs once - if (sNeedsStackShutdown) { - // We don't need to worry about ResetCommissionee. If we get here, - // we're running only one of our test methods (using - // -only-testing:MatterTests/MTROTAProviderTests/testMethodName), since - // we did not run test999_TearDown. - // [self shutdownStack]; + if (sLogContentFilePath != nil) { + [[NSFileManager defaultManager] removeItemAtPath:sLogContentFilePath error:nil]; } + + [self shutdownStack]; + [super tearDown]; } - (void)setUp @@ -591,8 +610,6 @@ - (void)initStack + (void)shutdownStack { - sNeedsStackShutdown = NO; - [mSampleListener stop]; mSampleListener = nil; @@ -1953,7 +1970,7 @@ - (void)test016_DownloadLog NSError * readError; NSString * fileContent = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&readError]; XCTAssertNil(readError); - XCTAssertEqualObjects(fileContent, @"This is a simple log\n"); + XCTAssertEqualObjects(fileContent, kSimpleLogContent); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; @@ -2079,11 +2096,4 @@ - (void)test900_SubscribeClusterStateCache [self waitForExpectations:@[ expectation ] timeout:kTimeoutInSeconds]; } -- (void)test999_TearDown -{ - ResetCommissionee( - [MTRBaseDevice deviceWithNodeID:@(kDeviceId) controller:sController], dispatch_get_main_queue(), self, kTimeoutInSeconds); - [[self class] shutdownStack]; -} - @end diff --git a/src/inet/UDPEndPointImplSockets.cpp b/src/inet/UDPEndPointImplSockets.cpp index 31b16c0f8ec192..ed43dc0ecca8f3 100644 --- a/src/inet/UDPEndPointImplSockets.cpp +++ b/src/inet/UDPEndPointImplSockets.cpp @@ -821,7 +821,7 @@ CHIP_ERROR UDPEndPointImplSockets::IPv6JoinLeaveMulticastGroupImpl(InterfaceId a #if CHIP_SYSTEM_CONFIG_USE_PLATFORM_MULTICAST_API if (sMulticastGroupHandler != nullptr) { - return sMulticastGroupHandler(aInterfaceId, aAddress, MulticastOperation::kJoin); + return sMulticastGroupHandler(aInterfaceId, aAddress, join ? MulticastOperation::kJoin : MulticastOperation::kLeave); } #endif // CHIP_SYSTEM_CONFIG_USE_PLATFORM_MULTICAST_API diff --git a/src/lib/address_resolve/AddressResolve_DefaultImpl.cpp b/src/lib/address_resolve/AddressResolve_DefaultImpl.cpp index 9888c96e721265..2fc4e5a526fb65 100644 --- a/src/lib/address_resolve/AddressResolve_DefaultImpl.cpp +++ b/src/lib/address_resolve/AddressResolve_DefaultImpl.cpp @@ -248,6 +248,10 @@ CHIP_ERROR Resolver::Init(System::Layer * systemLayer) void Resolver::Shutdown() { + // mSystemLayer is set in ::Init, so if it's null that means the resolver + // has not been initialized or has already been shut down. + VerifyOrReturn(mSystemLayer != nullptr); + while (mActiveLookups.begin() != mActiveLookups.end()) { auto current = mActiveLookups.begin(); diff --git a/src/lib/dnssd/Discovery_ImplPlatform.cpp b/src/lib/dnssd/Discovery_ImplPlatform.cpp index 54947cd617bf0e..6f98ac71b34a38 100644 --- a/src/lib/dnssd/Discovery_ImplPlatform.cpp +++ b/src/lib/dnssd/Discovery_ImplPlatform.cpp @@ -43,7 +43,7 @@ static void HandleNodeResolve(void * context, DnssdService * result, const Span< { DiscoveryContext * discoveryContext = static_cast(context); - if (error != CHIP_NO_ERROR) + if (error != CHIP_NO_ERROR && error != CHIP_ERROR_IN_PROGRESS) { discoveryContext->Release(); return; @@ -55,7 +55,13 @@ static void HandleNodeResolve(void * context, DnssdService * result, const Span< nodeData.Get().LogDetail(); discoveryContext->OnNodeDiscovered(nodeData); - discoveryContext->Release(); + + // CHIP_ERROR_IN_PROGRESS indicates that more results are coming, so don't release + // the context yet. + if (error == CHIP_NO_ERROR) + { + discoveryContext->Release(); + } } static void HandleNodeOperationalBrowse(void * context, DnssdService * result, CHIP_ERROR error) diff --git a/src/lib/dnssd/minimal_mdns/tests/FuzzPacketParsingPW.cpp b/src/lib/dnssd/minimal_mdns/tests/FuzzPacketParsingPW.cpp index aec550b26e026a..f49265f598a949 100644 --- a/src/lib/dnssd/minimal_mdns/tests/FuzzPacketParsingPW.cpp +++ b/src/lib/dnssd/minimal_mdns/tests/FuzzPacketParsingPW.cpp @@ -10,7 +10,6 @@ namespace { using namespace fuzztest; -using namespace std; using namespace chip; using namespace mdns::Minimal; @@ -65,16 +64,16 @@ void PacketParserFuzz(const std::vector & bytes) mdns::Minimal::ParsePacket(packet, &delegate); } -FUZZ_TEST(MinimalmDNS, PacketParserFuzz).WithDomains(Arbitrary>()); +FUZZ_TEST(MinimalmDNS, PacketParserFuzz).WithDomains(Arbitrary>()); class TxtRecordAccumulator : public TxtRecordDelegate { public: - using DataType = vector>; + using DataType = std::vector>; void OnRecord(const BytesRange & name, const BytesRange & value) override { - mData.push_back(make_pair(AsString(name), AsString(value))); + mData.push_back(std::make_pair(AsString(name), AsString(value))); } DataType & Data() { return mData; } @@ -83,9 +82,9 @@ class TxtRecordAccumulator : public TxtRecordDelegate private: DataType mData; - static string AsString(const BytesRange & range) + static std::string AsString(const BytesRange & range) { - return string(reinterpret_cast(range.Start()), reinterpret_cast(range.End())); + return std::string(reinterpret_cast(range.Start()), reinterpret_cast(range.End())); } }; @@ -97,7 +96,7 @@ void TxtResponderFuzz(const std::vector & aRecord) auto equal_sign_pos = aRecord.end(); // This test is only giving a set of values, it can be gives more - vector prefixedRecord{ static_cast(aRecord.size()) }; + std::vector prefixedRecord{ static_cast(aRecord.size()) }; prefixedRecord.insert(prefixedRecord.end(), aRecord.begin(), aRecord.end()); @@ -127,6 +126,6 @@ void TxtResponderFuzz(const std::vector & aRecord) } } -FUZZ_TEST(MinimalmDNS, TxtResponderFuzz).WithDomains(Arbitrary>().WithMaxSize(254)); +FUZZ_TEST(MinimalmDNS, TxtResponderFuzz).WithDomains(Arbitrary>().WithMaxSize(254)); } // namespace diff --git a/src/lib/dnssd/minimal_mdns/tests/TestAdvertiser.cpp b/src/lib/dnssd/minimal_mdns/tests/TestAdvertiser.cpp index ea85f74d2be11a..6b626be3631d33 100644 --- a/src/lib/dnssd/minimal_mdns/tests/TestAdvertiser.cpp +++ b/src/lib/dnssd/minimal_mdns/tests/TestAdvertiser.cpp @@ -38,7 +38,6 @@ namespace { -using namespace std; using namespace chip; using namespace chip::Dnssd; using namespace mdns::Minimal; diff --git a/src/lib/dnssd/minimal_mdns/tests/TestRecordData.cpp b/src/lib/dnssd/minimal_mdns/tests/TestRecordData.cpp index dcd48959be01ea..ae9e37e42ad960 100644 --- a/src/lib/dnssd/minimal_mdns/tests/TestRecordData.cpp +++ b/src/lib/dnssd/minimal_mdns/tests/TestRecordData.cpp @@ -26,7 +26,6 @@ namespace { -using namespace std; using namespace chip; using namespace mdns::Minimal; @@ -205,11 +204,11 @@ TEST(TestRecordData, PtrRecordComplexParsing) class TxtRecordAccumulator : public TxtRecordDelegate { public: - using DataType = vector>; + using DataType = std::vector>; void OnRecord(const BytesRange & name, const BytesRange & value) override { - mData.push_back(make_pair(AsString(name), AsString(value))); + mData.push_back(std::make_pair(AsString(name), AsString(value))); } DataType & Data() { return mData; } @@ -218,9 +217,9 @@ class TxtRecordAccumulator : public TxtRecordDelegate private: DataType mData; - static string AsString(const BytesRange & range) + static std::string AsString(const BytesRange & range) { - return string(reinterpret_cast(range.Start()), reinterpret_cast(range.End())); + return std::string(reinterpret_cast(range.Start()), reinterpret_cast(range.End())); } }; @@ -237,9 +236,9 @@ TEST(TestRecordData, TxtRecord) EXPECT_TRUE(ParseTxtRecord(BytesRange(record, record + sizeof(record)), &accumulator)); EXPECT_EQ(accumulator.Data().size(), 4u); - EXPECT_EQ(accumulator.Data()[0], (make_pair("some", ""))); - EXPECT_EQ(accumulator.Data()[1], (make_pair("foo", "bar"))); - EXPECT_EQ(accumulator.Data()[2], (make_pair("x", "y=z"))); - EXPECT_EQ(accumulator.Data()[3], (make_pair("a", ""))); + EXPECT_EQ(accumulator.Data()[0], (std::make_pair("some", ""))); + EXPECT_EQ(accumulator.Data()[1], (std::make_pair("foo", "bar"))); + EXPECT_EQ(accumulator.Data()[2], (std::make_pair("x", "y=z"))); + EXPECT_EQ(accumulator.Data()[3], (std::make_pair("a", ""))); } } // namespace diff --git a/src/lib/dnssd/minimal_mdns/tests/TestResponseSender.cpp b/src/lib/dnssd/minimal_mdns/tests/TestResponseSender.cpp index abfceb52080f13..c08b6c82b84b8c 100644 --- a/src/lib/dnssd/minimal_mdns/tests/TestResponseSender.cpp +++ b/src/lib/dnssd/minimal_mdns/tests/TestResponseSender.cpp @@ -34,7 +34,6 @@ namespace { -using namespace std; using namespace chip; using namespace mdns::Minimal; using namespace mdns::Minimal::test; diff --git a/src/lib/format/tests/FuzzPayloadDecoderPW.cpp b/src/lib/format/tests/FuzzPayloadDecoderPW.cpp index 52b51b308d0c2a..51f925bf2fdf87 100644 --- a/src/lib/format/tests/FuzzPayloadDecoderPW.cpp +++ b/src/lib/format/tests/FuzzPayloadDecoderPW.cpp @@ -59,13 +59,17 @@ void RunDecodeFuzz(const std::vector & bytes, chip::Protocols::Id } } -// This function allows us to fuzz using one of four protocols; by using FuzzTests's `ElementOf` API, we define an +// This function allows us to fuzz using all existing protocols; by using FuzzTests's `ElementOf` API, we define an // input domain by explicitly enumerating the set of values in it More Info: // https://github.com/google/fuzztest/blob/main/doc/domains-reference.md#elementof-domains-element-of auto AnyProtocolID() { + // Adding an Invalid Protocol + static constexpr chip::Protocols::Id InvalidProtocolID(chip::VendorId::Common, 2121); + return ElementOf({ chip::Protocols::SecureChannel::Id, chip::Protocols::InteractionModel::Id, chip::Protocols::BDX::Id, - chip::Protocols::UserDirectedCommissioning::Id }); + chip::Protocols::UserDirectedCommissioning::Id, chip::Protocols::Echo::Id, chip::Protocols::NotSpecified, + InvalidProtocolID }); } FUZZ_TEST(PayloadDecoder, RunDecodeFuzz).WithDomains(Arbitrary>(), AnyProtocolID(), Arbitrary()); diff --git a/src/lib/support/CHIPMemString.h b/src/lib/support/CHIPMemString.h index 3b74acdbcaf195..884c79d63e9bff 100644 --- a/src/lib/support/CHIPMemString.h +++ b/src/lib/support/CHIPMemString.h @@ -121,12 +121,20 @@ inline void CopyString(char (&dest)[N], ByteSpan source) */ inline void CopyString(char * dest, size_t destLength, CharSpan source) { - if (dest && destLength) + if ((dest == nullptr) || (destLength == 0)) { - size_t maxChars = std::min(destLength - 1, source.size()); - memcpy(dest, source.data(), maxChars); - dest[maxChars] = '\0'; + return; // no space to copy anything, not even a null terminator } + + if (source.empty()) + { + *dest = '\0'; // just a null terminator, we are copying empty data + return; + } + + size_t maxChars = std::min(destLength - 1, source.size()); + memcpy(dest, source.data(), maxChars); + dest[maxChars] = '\0'; } /** diff --git a/src/lib/support/TypeTraits.h b/src/lib/support/TypeTraits.h index e8718a223e4294..4d326027a17753 100644 --- a/src/lib/support/TypeTraits.h +++ b/src/lib/support/TypeTraits.h @@ -26,8 +26,17 @@ #include +#if __has_include() // For C++23 and later, include if available +#include // Contains std::to_underlying +#endif + namespace chip { +#if __cplusplus >= 202300L + +using to_underlying = std::to_underlying; + +#else /** * @brief Implemented std::to_underlying introduced in C++23. */ @@ -37,6 +46,7 @@ constexpr std::underlying_type_t to_underlying(T e) static_assert(std::is_enum::value, "to_underlying called to non-enum values."); return static_cast>(e); } +#endif /** * @brief This template is not designed to be used directly. A common pattern to check the presence of a member of a class is: diff --git a/src/messaging/ReliableMessageMgr.cpp b/src/messaging/ReliableMessageMgr.cpp index b7bd96f12e1e00..119adeef876972 100644 --- a/src/messaging/ReliableMessageMgr.cpp +++ b/src/messaging/ReliableMessageMgr.cpp @@ -129,9 +129,18 @@ void ReliableMessageMgr::ExecuteActions() VerifyOrDie(!entry->retainedBuf.IsNull()); + // Don't check whether the session in the exchange is valid, because when the session is released, the retrans entry is + // cleared inside ExchangeContext::OnSessionReleased, so the session must be valid if the entry exists. + auto session = entry->ec->GetSessionHandle(); uint8_t sendCount = entry->sendCount; -#if CHIP_ERROR_LOGGING || CHIP_DETAIL_LOGGING +#if CHIP_ERROR_LOGGING || CHIP_PROGRESS_LOGGING uint32_t messageCounter = entry->retainedBuf.GetMessageCounter(); + auto fabricIndex = session->GetFabricIndex(); + auto destination = kUndefinedNodeId; + if (session->IsSecureSession()) + { + destination = session->AsSecureSession()->GetPeerNodeId(); + } #endif // CHIP_ERROR_LOGGING || CHIP_DETAIL_LOGGING if (sendCount == CHIP_CONFIG_RMP_DEFAULT_MAX_RETRANS) @@ -140,13 +149,11 @@ void ReliableMessageMgr::ExecuteActions() ExchangeHandle ec(entry->ec); ChipLogError(ExchangeManager, - "Failed to Send CHIP MessageCounter:" ChipLogFormatMessageCounter " on exchange " ChipLogFormatExchange - " sendCount: %u max retries: %d", - messageCounter, ChipLogValueExchange(&ec.Get()), sendCount, CHIP_CONFIG_RMP_DEFAULT_MAX_RETRANS); - - // Don't check whether the session in the exchange is valid, because when the session is released, the retrans entry is - // cleared inside ExchangeContext::OnSessionReleased, so the session must be valid if the entry exists. - SessionHandle session = ec->GetSessionHandle(); + "<<%d [E:" ChipLogFormatExchange " S:%u M:" ChipLogFormatMessageCounter + "] (%s) Msg Retransmission to %u:" ChipLogFormatX64 " failure (max retries:%d)", + sendCount + 1, ChipLogValueExchange(&entry->ec.Get()), session->SessionIdForLogging(), messageCounter, + Transport::GetSessionTypeString(session), fabricIndex, ChipLogValueX64(destination), + CHIP_CONFIG_RMP_DEFAULT_MAX_RETRANS); // If the exchange is expecting a response, it will handle sending // this notification once it detects that it has not gotten a @@ -167,10 +174,12 @@ void ReliableMessageMgr::ExecuteActions() } entry->sendCount++; + ChipLogProgress(ExchangeManager, - "Retransmitting MessageCounter:" ChipLogFormatMessageCounter " on exchange " ChipLogFormatExchange - " Send Cnt %d", - messageCounter, ChipLogValueExchange(&entry->ec.Get()), entry->sendCount); + "<<%d [E:" ChipLogFormatExchange " S:%u M:" ChipLogFormatMessageCounter + "] (%s) Msg Retransmission to %u:" ChipLogFormatX64, + entry->sendCount, ChipLogValueExchange(&entry->ec.Get()), session->SessionIdForLogging(), messageCounter, + Transport::GetSessionTypeString(session), fabricIndex, ChipLogValueX64(destination)); MATTER_LOG_METRIC(Tracing::kMetricDeviceRMPRetryCount, entry->sendCount); CalculateNextRetransTime(*entry); @@ -467,22 +476,50 @@ void ReliableMessageMgr::SetAdditionalMRPBackoffTime(const OptionalGetSessionHandle(); // Check if we have received at least one application-level message if (entry.ec->HasReceivedAtLeastOneMessage()) { // If we have received at least one message, assume peer is active and use ActiveRetransTimeout - baseTimeout = entry.ec->GetSessionHandle()->GetRemoteMRPConfig().mActiveRetransTimeout; + baseTimeout = sessionHandle->GetRemoteMRPConfig().mActiveRetransTimeout; } else { // If we haven't received at least one message // Choose active/idle timeout from PeerActiveMode of session per 4.11.2.1. Retransmissions. - baseTimeout = entry.ec->GetSessionHandle()->GetMRPBaseTimeout(); + baseTimeout = sessionHandle->GetMRPBaseTimeout(); } System::Clock::Timeout backoff = ReliableMessageMgr::GetBackoff(baseTimeout, entry.sendCount); entry.nextRetransTime = System::SystemClock().GetMonotonicTimestamp() + backoff; + +#if CHIP_PROGRESS_LOGGING + const auto config = sessionHandle->GetRemoteMRPConfig(); + uint32_t messageCounter = entry.retainedBuf.GetMessageCounter(); + auto fabricIndex = sessionHandle->GetFabricIndex(); + auto destination = kUndefinedNodeId; + bool peerIsActive = false; + + if (sessionHandle->IsSecureSession()) + { + peerIsActive = sessionHandle->AsSecureSession()->IsPeerActive(); + destination = sessionHandle->AsSecureSession()->GetPeerNodeId(); + } + else if (sessionHandle->IsUnauthenticatedSession()) + { + peerIsActive = sessionHandle->AsUnauthenticatedSession()->IsPeerActive(); + } + + ChipLogProgress(ExchangeManager, + "??%d [E:" ChipLogFormatExchange " S:%u M:" ChipLogFormatMessageCounter + "] (%s) Msg Retransmission to %u:" ChipLogFormatX64 " in %" PRIu32 "ms [State:%s II:%" PRIu32 " AI:%" PRIu32 + " AT:%u]", + entry.sendCount + 1, ChipLogValueExchange(&entry.ec.Get()), sessionHandle->SessionIdForLogging(), + messageCounter, Transport::GetSessionTypeString(sessionHandle), fabricIndex, ChipLogValueX64(destination), + backoff.count(), peerIsActive ? "Active" : "Idle", config.mIdleRetransTimeout.count(), + config.mActiveRetransTimeout.count(), config.mActiveThresholdTime.count()); +#endif // CHIP_PROGRESS_LOGGING } #if CHIP_CONFIG_TEST diff --git a/src/platform/Darwin/DnssdContexts.cpp b/src/platform/Darwin/DnssdContexts.cpp index 9d293c089665e2..e6b590d09eb6ec 100644 --- a/src/platform/Darwin/DnssdContexts.cpp +++ b/src/platform/Darwin/DnssdContexts.cpp @@ -564,88 +564,78 @@ void ResolveContext::DispatchSuccess() }; #endif // TARGET_OS_TV - for (auto interfaceIndex : priorityInterfaceIndices) + std::vector interfacesOrder; + for (auto priorityInterfaceIndex : priorityInterfaceIndices) { - if (interfaceIndex == 0) + if (priorityInterfaceIndex == 0) { // Not actually an interface we have, since if_nametoindex // returned 0. continue; } - if (TryReportingResultsForInterfaceIndex(static_cast(interfaceIndex))) + for (auto & interface : interfaces) { - return; + if (interface.second.HasAddresses() && priorityInterfaceIndex == interface.first.interfaceId) + { + interfacesOrder.push_back(interface.first); + } } } for (auto & interface : interfaces) { - if (TryReportingResultsForInterfaceIndex(interface.first.interfaceId, interface.first.hostname, - interface.first.isSRPResult)) + // Skip interfaces that have already been prioritized to avoid duplicate results + auto interfaceKey = std::find(std::begin(interfacesOrder), std::end(interfacesOrder), interface.first); + if (interfaceKey != std::end(interfacesOrder)) { - return; + continue; } - } - ChipLogError(Discovery, "Successfully finalizing resolve for %s without finding any actual IP addresses.", - instanceName.c_str()); -} - -bool ResolveContext::TryReportingResultsForInterfaceIndex(uint32_t interfaceIndex, const std::string & hostname, bool isSRPResult) -{ - InterfaceKey interfaceKey = { interfaceIndex, hostname, isSRPResult }; - auto & interface = interfaces[interfaceKey]; - auto & ips = interface.addresses; + // Some interface may not have any ips, just ignore them. + if (!interface.second.HasAddresses()) + { + continue; + } - // Some interface may not have any ips, just ignore them. - if (ips.size() == 0) - { - return false; + interfacesOrder.push_back(interface.first); } - ChipLogProgress(Discovery, "Mdns: Resolve success on interface %" PRIu32, interfaceIndex); - - auto & service = interface.service; - auto addresses = Span(ips.data(), ips.size()); - if (nullptr == callback) + for (auto & interfaceKey : interfacesOrder) { - auto delegate = static_cast(context); - DiscoveredNodeData nodeData; + auto & interfaceInfo = interfaces[interfaceKey]; + auto & service = interfaceInfo.service; + auto & ips = interfaceInfo.addresses; + auto addresses = Span(ips.data(), ips.size()); - // Check whether mType (service name) exactly matches with operational service name - if (strcmp(service.mType, kOperationalServiceName) == 0) + ChipLogProgress(Discovery, "Mdns: Resolve success on interface %" PRIu32, interfaceKey.interfaceId); + + if (nullptr == callback) { - service.ToDiscoveredOperationalNodeBrowseData(nodeData); + auto delegate = static_cast(context); + DiscoveredNodeData nodeData; + + // Check whether mType (service name) exactly matches with operational service name + if (strcmp(service.mType, kOperationalServiceName) == 0) + { + service.ToDiscoveredOperationalNodeBrowseData(nodeData); + } + else + { + service.ToDiscoveredCommissionNodeData(addresses, nodeData); + } + delegate->OnNodeDiscovered(nodeData); } else { - service.ToDiscoveredCommissionNodeData(addresses, nodeData); + CHIP_ERROR error = &interfaceKey == &interfacesOrder.back() ? CHIP_NO_ERROR : CHIP_ERROR_IN_PROGRESS; + callback(context, &service, addresses, error); } - delegate->OnNodeDiscovered(nodeData); } - else - { - callback(context, &service, addresses, CHIP_NO_ERROR); - } - - return true; -} -bool ResolveContext::TryReportingResultsForInterfaceIndex(uint32_t interfaceIndex) -{ - for (auto & interface : interfaces) - { - if (interface.first.interfaceId == interfaceIndex) - { - if (TryReportingResultsForInterfaceIndex(interface.first.interfaceId, interface.first.hostname, - interface.first.isSRPResult)) - { - return true; - } - } - } - return false; + VerifyOrDo(interfacesOrder.size(), + ChipLogError(Discovery, "Successfully finalizing resolve for %s without finding any actual IP addresses.", + instanceName.c_str())); } void ResolveContext::SRPTimerExpiredCallback(chip::System::Layer * systemLayer, void * callbackContext) diff --git a/src/platform/Darwin/DnssdImpl.h b/src/platform/Darwin/DnssdImpl.h index d4cd05fecfe20b..9d10b4b3a13444 100644 --- a/src/platform/Darwin/DnssdImpl.h +++ b/src/platform/Darwin/DnssdImpl.h @@ -233,6 +233,7 @@ struct InterfaceInfo std::vector addresses; std::string fullyQualifiedDomainName; bool isDNSLookUpRequested = false; + bool HasAddresses() const { return addresses.size() != 0; }; }; struct InterfaceKey @@ -247,6 +248,11 @@ struct InterfaceKey (this->isSRPResult < other.isSRPResult)); } + inline bool operator==(const InterfaceKey & other) const + { + return this->interfaceId == other.interfaceId && this->hostname == other.hostname && this->isSRPResult == other.isSRPResult; + } + uint32_t interfaceId; std::string hostname; bool isSRPResult = false; @@ -310,16 +316,6 @@ struct ResolveContext : public GenericContext * */ void CancelSRPTimerIfRunning(); - -private: - /** - * Try reporting the results we got on the provided interface index. - * Returns true if information was reported, false if not (e.g. if there - * were no IP addresses, etc). - */ - bool TryReportingResultsForInterfaceIndex(uint32_t interfaceIndex, const std::string & hostname, bool isSRPResult); - - bool TryReportingResultsForInterfaceIndex(uint32_t interfaceIndex); }; } // namespace Dnssd diff --git a/src/platform/ESP32/OTAImageProcessorImpl.cpp b/src/platform/ESP32/OTAImageProcessorImpl.cpp index a35ca9a274ca67..ab27b9c50df0cb 100644 --- a/src/platform/ESP32/OTAImageProcessorImpl.cpp +++ b/src/platform/ESP32/OTAImageProcessorImpl.cpp @@ -297,6 +297,7 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) if (imageProcessor->mOTAUpdatePartition == NULL) { ChipLogError(SoftwareUpdate, "OTA partition not found"); + imageProcessor->mDownloader->OnPreparedForDownload(CHIP_ERROR_INTERNAL); return; } #ifdef CONFIG_ENABLE_DELTA_OTA diff --git a/src/platform/ESP32/nimble/BLEManagerImpl.cpp b/src/platform/ESP32/nimble/BLEManagerImpl.cpp index db3ade84d0234b..ff48f5d9d6aa78 100644 --- a/src/platform/ESP32/nimble/BLEManagerImpl.cpp +++ b/src/platform/ESP32/nimble/BLEManagerImpl.cpp @@ -1563,7 +1563,7 @@ void BLEManagerImpl::HandleC3CharRead(struct ble_gatt_char_context * param) additionalDataFields); SuccessOrExit(err); - os_mbuf_append(param->ctxt->om, bufferHandle->Start(), bufferHandle->DataLength()); + os_mbuf_append(param->ctxt->om, bufferHandle->Start(), static_cast(bufferHandle->DataLength())); exit: if (err != CHIP_NO_ERROR) diff --git a/src/platform/Linux/PlatformManagerImpl.cpp b/src/platform/Linux/PlatformManagerImpl.cpp index 68f3d58c1ac87b..dba3cb447d30d8 100644 --- a/src/platform/Linux/PlatformManagerImpl.cpp +++ b/src/platform/Linux/PlatformManagerImpl.cpp @@ -281,14 +281,14 @@ void PlatformManagerImpl::_Shutdown() } #if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP -CHIP_ERROR PlatformManagerImpl::_GLibMatterContextInvokeSync(CHIP_ERROR (*func)(void *), void * userData) +void PlatformManagerImpl::_GLibMatterContextInvokeSync(LambdaBridge && bridge) { // Because of TSAN false positives, we need to use a mutex to synchronize access to all members of // the GLibMatterContextInvokeData object (including constructor and destructor). This is a temporary // workaround until TSAN-enabled GLib will be used in our CI. std::unique_lock lock(mGLibMainLoopCallbackIndirectionMutex); - GLibMatterContextInvokeData invokeData{ func, userData }; + GLibMatterContextInvokeData invokeData{ std::move(bridge) }; lock.unlock(); @@ -300,15 +300,11 @@ CHIP_ERROR PlatformManagerImpl::_GLibMatterContextInvokeSync(CHIP_ERROR (*func)( // XXX: Temporary workaround for TSAN false positives. std::unique_lock lock_(PlatformMgrImpl().mGLibMainLoopCallbackIndirectionMutex); - auto mFunc = data->mFunc; - auto mUserData = data->mFuncUserData; - lock_.unlock(); - auto result = mFunc(mUserData); + data->bridge(); lock_.lock(); - data->mDone = true; - data->mFuncResult = result; + data->mDone = true; data->mDoneCond.notify_one(); return G_SOURCE_REMOVE; @@ -316,10 +312,7 @@ CHIP_ERROR PlatformManagerImpl::_GLibMatterContextInvokeSync(CHIP_ERROR (*func)( &invokeData, nullptr); lock.lock(); - invokeData.mDoneCond.wait(lock, [&invokeData]() { return invokeData.mDone; }); - - return invokeData.mFuncResult; } #endif // CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP diff --git a/src/platform/Linux/PlatformManagerImpl.h b/src/platform/Linux/PlatformManagerImpl.h index 5669ce5dd28d62..d50687bf43420c 100644 --- a/src/platform/Linux/PlatformManagerImpl.h +++ b/src/platform/Linux/PlatformManagerImpl.h @@ -23,6 +23,7 @@ #pragma once +#include "lib/core/CHIPError.h" #include #include @@ -69,7 +70,21 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener template CHIP_ERROR GLibMatterContextInvokeSync(CHIP_ERROR (*func)(T *), T * userData) { - return _GLibMatterContextInvokeSync((CHIP_ERROR(*)(void *)) func, (void *) userData); + struct + { + CHIP_ERROR returnValue = CHIP_NO_ERROR; + CHIP_ERROR (*functionToCall)(T *); + T * userData; + } context; + + context.functionToCall = func; + context.userData = userData; + + LambdaBridge bridge; + bridge.Initialize([&context]() { context.returnValue = context.functionToCall(context.userData); }); + + _GLibMatterContextInvokeSync(std::move(bridge)); + return context.returnValue; } unsigned int GLibMatterContextAttachSource(GSource * source) @@ -102,9 +117,7 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener struct GLibMatterContextInvokeData { - CHIP_ERROR (*mFunc)(void *); - void * mFuncUserData; - CHIP_ERROR mFuncResult; + LambdaBridge bridge; // Sync primitives to wait for the function to be executed std::condition_variable mDoneCond; bool mDone = false; @@ -113,10 +126,13 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener /** * @brief Invoke a function on the Matter GLib context. * - * @note This function does not provide type safety for the user data. Please, - * use the GLibMatterContextInvokeSync() template function instead. + * @param[in] bridge a LambdaBridge object that holds the lambda to be invoked within the GLib context. + * + * @note This function moves the LambdaBridge into the GLib context for invocation. + * The LambdaBridge is created and initialised in GLibMatterContextInvokeSync(). + * use the GLibMatterContextInvokeSync() template function instead of this one. */ - CHIP_ERROR _GLibMatterContextInvokeSync(CHIP_ERROR (*func)(void *), void * userData); + void _GLibMatterContextInvokeSync(LambdaBridge && bridge); // XXX: Mutex for guarding access to glib main event loop callback indirection // synchronization primitives. This is a workaround to suppress TSAN warnings. diff --git a/src/platform/NuttX/PlatformManagerImpl.cpp b/src/platform/NuttX/PlatformManagerImpl.cpp index d590f58c343232..a44f0846e6522f 100644 --- a/src/platform/NuttX/PlatformManagerImpl.cpp +++ b/src/platform/NuttX/PlatformManagerImpl.cpp @@ -281,14 +281,14 @@ void PlatformManagerImpl::_Shutdown() } #if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP -CHIP_ERROR PlatformManagerImpl::_GLibMatterContextInvokeSync(CHIP_ERROR (*func)(void *), void * userData) +void PlatformManagerImpl::_GLibMatterContextInvokeSync(LambdaBridge && bridge) { // Because of TSAN false positives, we need to use a mutex to synchronize access to all members of // the GLibMatterContextInvokeData object (including constructor and destructor). This is a temporary // workaround until TSAN-enabled GLib will be used in our CI. std::unique_lock lock(mGLibMainLoopCallbackIndirectionMutex); - GLibMatterContextInvokeData invokeData{ func, userData }; + GLibMatterContextInvokeData invokeData{ std::move(bridge) }; lock.unlock(); @@ -300,15 +300,11 @@ CHIP_ERROR PlatformManagerImpl::_GLibMatterContextInvokeSync(CHIP_ERROR (*func)( // XXX: Temporary workaround for TSAN false positives. std::unique_lock lock_(PlatformMgrImpl().mGLibMainLoopCallbackIndirectionMutex); - auto mFunc = data->mFunc; - auto mUserData = data->mFuncUserData; - lock_.unlock(); - auto result = mFunc(mUserData); + data->bridge(); lock_.lock(); - data->mDone = true; - data->mFuncResult = result; + data->mDone = true; data->mDoneCond.notify_one(); return G_SOURCE_REMOVE; @@ -318,8 +314,6 @@ CHIP_ERROR PlatformManagerImpl::_GLibMatterContextInvokeSync(CHIP_ERROR (*func)( lock.lock(); invokeData.mDoneCond.wait(lock, [&invokeData]() { return invokeData.mDone; }); - - return invokeData.mFuncResult; } #endif // CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP diff --git a/src/platform/NuttX/PlatformManagerImpl.h b/src/platform/NuttX/PlatformManagerImpl.h index 5669ce5dd28d62..f911ccb3c73a21 100644 --- a/src/platform/NuttX/PlatformManagerImpl.h +++ b/src/platform/NuttX/PlatformManagerImpl.h @@ -69,7 +69,21 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener template CHIP_ERROR GLibMatterContextInvokeSync(CHIP_ERROR (*func)(T *), T * userData) { - return _GLibMatterContextInvokeSync((CHIP_ERROR(*)(void *)) func, (void *) userData); + struct + { + CHIP_ERROR returnValue = CHIP_NO_ERROR; + CHIP_ERROR (*functionToCall)(T *); + T * userData; + } context; + + context.functionToCall = func; + context.userData = userData; + + LambdaBridge bridge; + bridge.Initialize([&context]() { context.returnValue = context.functionToCall(context.userData); }); + + _GLibMatterContextInvokeSync(std::move(bridge)); + return context.returnValue; } unsigned int GLibMatterContextAttachSource(GSource * source) @@ -102,9 +116,7 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener struct GLibMatterContextInvokeData { - CHIP_ERROR (*mFunc)(void *); - void * mFuncUserData; - CHIP_ERROR mFuncResult; + LambdaBridge bridge; // Sync primitives to wait for the function to be executed std::condition_variable mDoneCond; bool mDone = false; @@ -113,10 +125,13 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener /** * @brief Invoke a function on the Matter GLib context. * - * @note This function does not provide type safety for the user data. Please, - * use the GLibMatterContextInvokeSync() template function instead. + * @param[in] bridge a LambdaBridge object that holds the lambda to be invoked within the GLib context. + * + * @note This function moves the LambdaBridge into the GLib context for invocation. + * The LambdaBridge is created and initialised in GLibMatterContextInvokeSync(). + * use the GLibMatterContextInvokeSync() template function instead of this one. */ - CHIP_ERROR _GLibMatterContextInvokeSync(CHIP_ERROR (*func)(void *), void * userData); + void _GLibMatterContextInvokeSync(LambdaBridge && bridge); // XXX: Mutex for guarding access to glib main event loop callback indirection // synchronization primitives. This is a workaround to suppress TSAN warnings. diff --git a/src/platform/Tizen/PlatformManagerImpl.cpp b/src/platform/Tizen/PlatformManagerImpl.cpp index 58e1e014f41e28..91cb91be0a6a32 100644 --- a/src/platform/Tizen/PlatformManagerImpl.cpp +++ b/src/platform/Tizen/PlatformManagerImpl.cpp @@ -56,9 +56,7 @@ namespace { struct GLibMatterContextInvokeData { - CHIP_ERROR (*mFunc)(void *); - void * mFuncUserData; - CHIP_ERROR mFuncResult; + LambdaBridge bridge; // Sync primitives to wait for the function to be executed std::mutex mDoneMutex; std::condition_variable mDoneCond; @@ -144,18 +142,17 @@ void PlatformManagerImpl::_Shutdown() mGLibMainLoop = nullptr; } -CHIP_ERROR PlatformManagerImpl::_GLibMatterContextInvokeSync(CHIP_ERROR (*func)(void *), void * userData) +void PlatformManagerImpl::_GLibMatterContextInvokeSync(LambdaBridge && bridge) { - GLibMatterContextInvokeData invokeData{ func, userData }; + GLibMatterContextInvokeData invokeData{ std::move(bridge) }; g_main_context_invoke_full( g_main_loop_get_context(mGLibMainLoop), G_PRIORITY_HIGH_IDLE, [](void * userData_) { auto * data = reinterpret_cast(userData_); VerifyOrExit(g_main_context_get_thread_default() != nullptr, - ChipLogError(DeviceLayer, "GLib thread default main context is not set"); - data->mFuncResult = CHIP_ERROR_INCORRECT_STATE); - data->mFuncResult = data->mFunc(data->mFuncUserData); + ChipLogError(DeviceLayer, "GLib thread default main context is not set")); + data->bridge(); exit: data->mDoneMutex.lock(); data->mDone = true; @@ -167,8 +164,6 @@ CHIP_ERROR PlatformManagerImpl::_GLibMatterContextInvokeSync(CHIP_ERROR (*func)( std::unique_lock lock(invokeData.mDoneMutex); invokeData.mDoneCond.wait(lock, [&invokeData]() { return invokeData.mDone; }); - - return invokeData.mFuncResult; } } // namespace DeviceLayer diff --git a/src/platform/Tizen/PlatformManagerImpl.h b/src/platform/Tizen/PlatformManagerImpl.h index 8a3d0e450d9742..ebb61aa2b5d084 100644 --- a/src/platform/Tizen/PlatformManagerImpl.h +++ b/src/platform/Tizen/PlatformManagerImpl.h @@ -64,7 +64,21 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener template CHIP_ERROR GLibMatterContextInvokeSync(CHIP_ERROR (*func)(T *), T * userData) { - return _GLibMatterContextInvokeSync((CHIP_ERROR(*)(void *)) func, (void *) userData); + struct + { + CHIP_ERROR returnValue = CHIP_NO_ERROR; + CHIP_ERROR (*functionToCall)(T *); + T * userData; + } context; + + context.functionToCall = func; + context.userData = userData; + + LambdaBridge bridge; + bridge.Initialize([&context]() { context.returnValue = context.functionToCall(context.userData); }); + + _GLibMatterContextInvokeSync(std::move(bridge)); + return context.returnValue; } System::Clock::Timestamp GetStartTime() { return mStartTime; } @@ -87,10 +101,13 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener /** * @brief Invoke a function on the Matter GLib context. * - * @note This function does not provide type safety for the user data. Please, - * use the GLibMatterContextInvokeSync() template function instead. + * @param[in] bridge a LambdaBridge object that holds the lambda to be invoked within the GLib context. + * + * @note This function moves the LambdaBridge into the GLib context for invocation. + * The LambdaBridge is created and initialised in GLibMatterContextInvokeSync(). + * use the GLibMatterContextInvokeSync() template function instead of this one. */ - CHIP_ERROR _GLibMatterContextInvokeSync(CHIP_ERROR (*func)(void *), void * userData); + void _GLibMatterContextInvokeSync(LambdaBridge && bridge); GMainLoop * mGLibMainLoop; GThread * mGLibMainLoopThread; diff --git a/src/platform/Tizen/SystemInfo.cpp b/src/platform/Tizen/SystemInfo.cpp index e9ac7d7b1b1675..dd4f9f83ec8d0a 100644 --- a/src/platform/Tizen/SystemInfo.cpp +++ b/src/platform/Tizen/SystemInfo.cpp @@ -26,8 +26,6 @@ #include "ErrorUtils.h" -using namespace std; - namespace chip { namespace DeviceLayer { namespace Internal { diff --git a/src/platform/nxp/zephyr/nxp-zephyr-mbedtls-config.h b/src/platform/nxp/zephyr/nxp-zephyr-mbedtls-config.h index f5f44390cd5410..81f1bb77e63d9d 100644 --- a/src/platform/nxp/zephyr/nxp-zephyr-mbedtls-config.h +++ b/src/platform/nxp/zephyr/nxp-zephyr-mbedtls-config.h @@ -18,6 +18,7 @@ #if CONFIG_CHIP_CRYPTO_PSA #define MBEDTLS_PSA_CRYPTO_DRIVERS +#define MBEDTLS_PSA_KEY_SLOT_COUNT 64 #endif /* CONFIG_CHIP_CRYPTO_PSA */ #if CONFIG_MCUX_ELS_PKC diff --git a/src/platform/stm32/CHIPMem-Platform.cpp b/src/platform/stm32/CHIPMem-Platform.cpp index b9bf90f429f444..cbf52cfde94a84 100644 --- a/src/platform/stm32/CHIPMem-Platform.cpp +++ b/src/platform/stm32/CHIPMem-Platform.cpp @@ -67,8 +67,6 @@ extern "C" void memMonitoringTrackFree(void * ptr, size_t size); #define USE_FREERTOS -using namespace std; - // Define the new operator for C++ to use the freeRTOS memory management // functions. // diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index 96cd7e17eef449..e0a0fa744e4cc3 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -872,7 +872,12 @@ CHIP_ERROR CASESession::SendSigma1() mState = State::kSentSigma1; } - ChipLogProgress(SecureChannel, "Sent Sigma1 msg to " ChipLogFormatScopedNodeId, ChipLogValueScopedNodeId(GetPeer())); +#if CHIP_PROGRESS_LOGGING + const auto localMRPConfig = mLocalMRPConfig.Value(); +#endif // CHIP_PROGRESS_LOGGING + ChipLogProgress(SecureChannel, "Sent Sigma1 msg to " ChipLogFormatScopedNodeId " [II:%" PRIu32 "ms AI:%" PRIu32 "ms AT:%ums]", + ChipLogValueScopedNodeId(GetPeer()), localMRPConfig.mIdleRetransTimeout.count(), + localMRPConfig.mActiveRetransTimeout.count(), localMRPConfig.mActiveThresholdTime.count()); mDelegate->OnSessionEstablishmentStarted(); diff --git a/src/protocols/secure_channel/PASESession.cpp b/src/protocols/secure_channel/PASESession.cpp index 1702a159bb111c..6178348ad5d5d5 100644 --- a/src/protocols/secure_channel/PASESession.cpp +++ b/src/protocols/secure_channel/PASESession.cpp @@ -314,7 +314,12 @@ CHIP_ERROR PASESession::SendPBKDFParamRequest() mNextExpectedMsg.SetValue(MsgType::PBKDFParamResponse); - ChipLogDetail(SecureChannel, "Sent PBKDF param request"); +#if CHIP_PROGRESS_LOGGING + const auto localMRPConfig = mLocalMRPConfig.Value(); +#endif // CHIP_PROGRESS_LOGGING + ChipLogProgress(SecureChannel, "Sent PBKDF param request [II:%" PRIu32 "ms AI:%" PRIu32 "ms AT:%ums)", + localMRPConfig.mIdleRetransTimeout.count(), localMRPConfig.mActiveRetransTimeout.count(), + localMRPConfig.mActiveThresholdTime.count()); return CHIP_NO_ERROR; } diff --git a/src/python_testing/TC_ACE_1_2.py b/src/python_testing/TC_ACE_1_2.py index 9bd26523f3cbba..7d227f5a5c0e72 100644 --- a/src/python_testing/TC_ACE_1_2.py +++ b/src/python_testing/TC_ACE_1_2.py @@ -19,12 +19,19 @@ # for details about the block below. # # === BEGIN CI TEST ARGUMENTS === -# test-runner-runs: run1 -# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} -# test-runner-run/run1/factoryreset: True -# test-runner-run/run1/quiet: True -# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json -# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# factoryreset: true +# quiet: true +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # === END CI TEST ARGUMENTS === import logging diff --git a/src/python_testing/TC_ACE_1_3.py b/src/python_testing/TC_ACE_1_3.py index 3c64171571eb95..29aabf3462083b 100644 --- a/src/python_testing/TC_ACE_1_3.py +++ b/src/python_testing/TC_ACE_1_3.py @@ -19,12 +19,19 @@ # for details about the block below. # # === BEGIN CI TEST ARGUMENTS === -# test-runner-runs: run1 -# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} -# test-runner-run/run1/factoryreset: True -# test-runner-run/run1/quiet: True -# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json -# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# factoryreset: true +# quiet: true +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # === END CI TEST ARGUMENTS === import logging diff --git a/src/python_testing/TC_ACE_1_4.py b/src/python_testing/TC_ACE_1_4.py index f6f04e3508860b..9344b0bd3e9876 100644 --- a/src/python_testing/TC_ACE_1_4.py +++ b/src/python_testing/TC_ACE_1_4.py @@ -19,12 +19,21 @@ # for details about the block below. # # === BEGIN CI TEST ARGUMENTS === -# test-runner-runs: run1 -# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} -# test-runner-run/run1/factoryreset: True -# test-runner-run/run1/quiet: True -# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json -# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --int-arg PIXIT.ACE.APPENDPOINT:1 PIXIT.ACE.APPDEVTYPEID:0x0100 --string-arg PIXIT.ACE.APPCLUSTER:OnOff PIXIT.ACE.APPATTRIBUTE:OnOff --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# factoryreset: true +# quiet: true +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --int-arg PIXIT.ACE.APPENDPOINT:1 PIXIT.ACE.APPDEVTYPEID:0x0100 +# --string-arg PIXIT.ACE.APPCLUSTER:OnOff PIXIT.ACE.APPATTRIBUTE:OnOff +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # === END CI TEST ARGUMENTS === import sys diff --git a/src/python_testing/TC_ACE_1_5.py b/src/python_testing/TC_ACE_1_5.py index 00bd343d461cb3..cda418737af048 100644 --- a/src/python_testing/TC_ACE_1_5.py +++ b/src/python_testing/TC_ACE_1_5.py @@ -19,12 +19,20 @@ # for details about the block below. # # === BEGIN CI TEST ARGUMENTS === -# test-runner-runs: run1 -# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} -# test-runner-run/run1/factoryreset: True -# test-runner-run/run1/quiet: True -# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json -# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS src/app/tests/suites/certification/ci-pics-values --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# factoryreset: true +# quiet: true +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # === END CI TEST ARGUMENTS === import logging diff --git a/src/python_testing/TC_ACL_2_11.py b/src/python_testing/TC_ACL_2_11.py index f5ebed221b272b..88ef1d26cee1d1 100644 --- a/src/python_testing/TC_ACL_2_11.py +++ b/src/python_testing/TC_ACL_2_11.py @@ -19,12 +19,23 @@ # for details about the block below. # # === BEGIN CI TEST ARGUMENTS === -# test-runner-runs: run1 -# test-runner-run/run1/app: ${NETWORK_MANAGEMENT_APP} -# test-runner-run/run1/factoryreset: True -# test-runner-run/run1/quiet: True -# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --commissioning-arl-entries "[{\"endpoint\": 1,\"cluster\": 1105,\"restrictions\": [{\"type\": 0,\"id\": 0}]}]" --arl-entries "[{\"endpoint\": 1,\"cluster\": 1105,\"restrictions\": [{\"type\": 0,\"id\": 0}]}]" -# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# test-runner-runs: +# run1: +# app: ${NETWORK_MANAGEMENT_APP} +# factoryreset: true +# quiet: true +# app-args: > +# --discriminator 1234 --KVS kvs1 +# --trace-to json:${TRACE_APP}.json +# --commissioning-arl-entries "[{\"endpoint\": 1,\"cluster\": 1105,\"restrictions\": [{\"type\": 0,\"id\": 0}]}]" +# --arl-entries "[{\"endpoint\": 1,\"cluster\": 1105,\"restrictions\": [{\"type\": 0,\"id\": 0}]}]" +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # === END CI TEST ARGUMENTS === import logging diff --git a/src/python_testing/TC_ACL_2_2.py b/src/python_testing/TC_ACL_2_2.py index a1e755b7397f88..b0880b096bdb5a 100644 --- a/src/python_testing/TC_ACL_2_2.py +++ b/src/python_testing/TC_ACL_2_2.py @@ -16,12 +16,19 @@ # # === BEGIN CI TEST ARGUMENTS === -# test-runner-runs: run1 -# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} -# test-runner-run/run1/factoryreset: True -# test-runner-run/run1/quiet: True -# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json -# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# factoryreset: true +# quiet: true +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # === END CI TEST ARGUMENTS === import chip.clusters as Clusters diff --git a/src/python_testing/TC_AccessChecker.py b/src/python_testing/TC_AccessChecker.py index 36c643407937e2..a2429ee3540147 100644 --- a/src/python_testing/TC_AccessChecker.py +++ b/src/python_testing/TC_AccessChecker.py @@ -2,12 +2,19 @@ # for details about the block below. # # === BEGIN CI TEST ARGUMENTS === -# test-runner-runs: run1 -# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} -# test-runner-run/run1/factoryreset: True -# test-runner-run/run1/quiet: True -# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json -# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# factoryreset: true +# quiet: true +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # === END CI TEST ARGUMENTS === import logging diff --git a/src/python_testing/TC_DRLK_2_5.py b/src/python_testing/TC_DRLK_2_5.py new file mode 100644 index 00000000000000..a43067b05bf4af --- /dev/null +++ b/src/python_testing/TC_DRLK_2_5.py @@ -0,0 +1,392 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${CHIP_LOCK_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS src/app/tests/suites/certification/ci-pics-values --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# === END CI TEST ARGUMENTS === + +import logging + +import chip.clusters as Clusters +from chip.interaction_model import InteractionModelError, Status +from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main, type_matches +from mobly import asserts + +logger = logging.getLogger(__name__) + +drlkcluster = Clusters.DoorLock + + +class TC_DRLK_2_5(MatterBaseTest): + + def steps_TC_DRLK_2_5(self) -> list[TestStep]: + steps = [ + + + TestStep("1", "TH reads NumberOfWeekDaySchedulesSupportedPerUser attribute.", + "Verify that TH is able to read the attribute successfully."), + TestStep("2a", "TH sends SetUser Command to DUT.", "Verify that the DUT sends SUCCESS response."), + TestStep("2b", "TH sends SetWeekDaySchedule Command to DUT.", "Verify that the DUT sends SUCCESS response."), + TestStep("2c", "TH sends SetWeekDaySchedule to DUT with different DaysMaskMap.", + "Verify that the DUT sends SUCCESS response."), + TestStep("3", "TH sends GetWeekDaySchedule Command to DUT.", + "Verify that the DUT sends GetWeekDayScheduleResponse command with expected values."), + TestStep("4", "TH sends SetWeekDaySchedule Command to DUT.", + "Verify that the DUT responds with INVALID_COMMAND."), + TestStep("5", "TH sends SetWeekDaySchedule Command to DUT.", + "Verify that the DUT responds with INVALID_COMMAND."), + TestStep("6", "TH sends SetWeekDaySchedule Command to DUT.", + "Verify that the DUT responds with INVALID_COMMAND."), + TestStep("7", "TH sends SetWeekDaySchedule Command to DUT.", + "Verify that the DUT responds with INVALID_COMMAND."), + TestStep("8", "TH sends GetWeekDaySchedule Command to DUT.", + "Verify that the DUT responds with with INVALID_COMMAND."), + TestStep("9", "TH sends GetWeekDaySchedule Command to DUT.", + "Verify that the DUT responds with GetWeekDayScheduleResponse command with Status NOT_FOUND."), + TestStep("10a", "TH sends ClearWeekDaySchedule Command to DUT.", "Verify that the DUT sends SUCCESS response."), + TestStep("10b", "TH sends ClearWeekDaySchedule Command to DUT.", "Verify that the DUT sends INVALID_COMMAND response."), + TestStep("10c", "TH sends ClearWeekDaySchedule Command to DUT.", "Verify that the DUT sends INVALID_COMMAND response."), + TestStep("11", "TH sends GetWeekDaySchedule Command to DUT.", "Verify that the DUT sends NOT_FOUND response."), + TestStep("12", "TH sends ClearUser Command to DUT.", "Verify that the DUT sends SUCCESS response."), + ] + + return steps + + async def read_attributes_from_dut(self, endpoint, cluster, attribute, expected_status: Status = Status.Success): + try: + attribute_value = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, + attribute=attribute) + asserts.assert_equal(expected_status, Status.Success) + return attribute_value + except Exception as e: + logging.error(e) + logging.info("Error reading attributes,%s" % (attribute)) + + def pics_TC_DRLK_2_5(self) -> list[str]: + return ["DRLK.S", "DRLK.S.F04"] + + async def clear_user_cmd(self, user_index, expected_status: Status = Status.Success): + try: + await self.send_single_cmd(cmd=Clusters.DoorLock.Commands.ClearUser(userIndex=user_index), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + asserts.assert_equal(expected_status, Status.Success) + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, f"Unexpected error returned: {e}") + + async def clear_week_day_schedule_cmd(self, week_day_index, user_index, expected_status): + try: + await self.send_single_cmd(cmd=Clusters.DoorLock.Commands.ClearWeekDaySchedule(weekDayIndex=week_day_index, userIndex=user_index), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, f"Unexpected error returned: {e}") + + async def get_weekday_schedule_cmd(self, week_day_index, user_index, days_Mask, start_Hour, start_Minute, end_Hour, end_Minute, expected_status): + + try: + + response = await self.send_single_cmd(cmd=Clusters.DoorLock.Commands.GetWeekDaySchedule( + weekDayIndex=week_day_index, userIndex=user_index), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + asserts.assert_true(type_matches(response, Clusters.DoorLock.Commands.GetWeekDayScheduleResponse), + "Unexpected return type for GetWeekDayScheduleResponse") + + if (expected_status == Status.Success): + + asserts.assert_true(response.weekDayIndex == week_day_index, + "Error when executing GetWeekDayScheduleResponse command, weekDayIndex={}".format( + str(response.weekDayIndex))) + asserts.assert_true(response.userIndex == user_index, + "Error when executing GetWeekDayScheduleResponse command, userIndex={}".format( + str(response.userIndex))) + + asserts.assert_true(response.daysMask == days_Mask, + "Error when executing GetWeekDayScheduleResponse command, days_Mask={}".format( + str(response.daysMask))) + asserts.assert_true(response.startHour == start_Hour, + "Error when executing GetWeekDayScheduleResponse command, startHour={}".format( + str(response.startHour))) + asserts.assert_true(response.startMinute == start_Minute, + "Error when executing GetWeekDayScheduleResponse command, startMinute={}".format( + str(response.startMinute))) + asserts.assert_true(response.endHour == end_Hour, + "Error when executing GetWeekDayScheduleResponse command, endHour={}".format( + str(response.endHour))) + asserts.assert_true(response.endMinute == end_Minute, + "Error when executing GetWeekDayScheduleResponse command, endMinute={}".format( + str(response.endMinute))) + + return response + except InteractionModelError as e: + logging.error(e) + asserts.assert_equal(e.status, expected_status, f"Unexpected error returned: {e}") + + async def set_week_days_schedule_cmd(self, week_day_index, user_index, day_mask_map_index, start_Hour, start_Minute, end_Hour, end_Minute, expected_status): + try: + + await self.send_single_cmd(cmd=Clusters.DoorLock.Commands.SetWeekDaySchedule( + weekDayIndex=week_day_index, + userIndex=user_index, + daysMask=day_mask_map_index, + startHour=start_Hour, + startMinute=start_Minute, + endHour=end_Hour, + endMinute=end_Minute), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + except InteractionModelError as e: + logging.error(e) + asserts.assert_equal(e.status, expected_status, f"Unexpected error returned: {e}") + + async def clear_credentials_cmd(self, credential, step=None, expected_status: Status = Status.Success): + try: + + await self.send_single_cmd(cmd=Clusters.DoorLock.Commands.ClearCredential(credential=credential), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + except InteractionModelError as e: + logging.exception(e) + asserts.assert_equal(e.status, expected_status, f"Unexpected error returned: {e}") + + @async_test_body + async def test_TC_DRLK_2_5(self): + + self.common_cluster_endpoint = 0 + self.app_cluster_endpoint = 1 + user_name = "xxx" + user_index = 1 + user_unique_id = 6452 + week_day_index = 1 + day_mask_map_index = 1 + start_Hour = 15 + start_Minute = 45 + end_Hour = 16 + end_Minute = 55 + + self.step("1") + if self.pics_guard(self.check_pics("DRLK.S.F04") and self.check_pics("DRLK.S.A0014")): + number_week_day_schedules_supported_per_user = await self.read_attributes_from_dut(endpoint=self.app_cluster_endpoint, + cluster=drlkcluster, + attribute=Clusters.DoorLock.Attributes.NumberOfWeekDaySchedulesSupportedPerUser) + logging.info("NumberOfWeekDaySchedulesSupportedPerUser %s" % (number_week_day_schedules_supported_per_user)) + asserts.assert_in(number_week_day_schedules_supported_per_user, range( + 0, 255), "NumberOfWeekDaySchedulesSupportedPerUser value is out of range") + self.step("2a") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C1a.Rsp")): + try: + await self.send_single_cmd(cmd=drlkcluster.Commands.SetUser( + operationType=Clusters.DoorLock.Enums.DataOperationTypeEnum.kAdd, + userIndex=user_index, + userName=user_name, + userUniqueID=user_unique_id, + userStatus=Clusters.DoorLock.Enums.UserStatusEnum.kOccupiedEnabled, + userType=Clusters.DoorLock.Enums.UserTypeEnum.kUnrestrictedUser, + credentialRule=Clusters.DoorLock.Enums.CredentialRuleEnum.kSingle), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + except InteractionModelError as e: + logging.exception(e) + + self.step("2b") + if self.pics_guard(self.check_pics("DRLK.S.F04") and self.check_pics("DRLK.S.C0b.Rsp")): + try: + await self.set_week_days_schedule_cmd( + week_day_index, + user_index, + day_mask_map_index, + start_Hour, + start_Minute, + end_Hour, + end_Minute, + Status.Success) + + except InteractionModelError as e: + logging.exception(e) + self.step("2c") + if self.pics_guard(self.check_pics("DRLK.S.F04") and self.check_pics("DRLK.S.C0b.Rsp")): + try: + days_masks_map = [2, 4, 8, 16, 32, 64, 24, 42, 51, 107, 123, 127] + for day_mask_map_index in days_masks_map: + await self.set_week_days_schedule_cmd( + week_day_index, + user_index, + day_mask_map_index, + start_Hour, + start_Minute, + end_Hour, + end_Minute, + Status.Success) + except InteractionModelError as e: + logging.exception(e) + + self.step("3") + if self.pics_guard(self.check_pics("DRLK.S.F04") and self.check_pics("DRLK.S.C0c.Rsp") and self.check_pics("DRLK.S.C0c.Tx")): + day_mask_map_index = 127 + await self.get_weekday_schedule_cmd( + week_day_index, + user_index, + day_mask_map_index, + start_Hour, + start_Minute, + end_Hour, + end_Minute, + Status.Success) + self.step("4") + if self.pics_guard(self.check_pics("DRLK.S.F04") and self.check_pics("DRLK.S.C0b.Rsp")): + week_day_index = 0 + day_mask_map_index = 2 + await self.set_week_days_schedule_cmd( + week_day_index, + user_index, + day_mask_map_index, + start_Hour, + start_Minute, + end_Hour, + end_Minute, + Status.InvalidCommand) + self.step("5") + if self.pics_guard(self.check_pics("DRLK.S.F04") and self.check_pics("DRLK.S.C0b.Rsp")): + week_day_index = 1 # Valid value + day_mask_map_index = 0 # invalid value + await self.set_week_days_schedule_cmd( + week_day_index, + user_index, + day_mask_map_index, + start_Hour, + start_Minute, + end_Hour, + end_Minute, + Status.InvalidCommand) + self.step("6") + if self.pics_guard(self.check_pics("DRLK.S.F04") and self.check_pics("DRLK.S.C0b.Rsp")): + week_day_index = 1 # valid value + day_mask_map_index = 128 # invalid value + await self.set_week_days_schedule_cmd( + week_day_index, + user_index, + day_mask_map_index, + start_Hour, + start_Minute, + end_Hour, + end_Minute, + Status.InvalidCommand) + + self.step("7") + if self.pics_guard(self.check_pics("DRLK.S.F04") and self.check_pics("DRLK.S.C0b.Rsp")): + week_day_index = 1 # valid value + day_mask_map_index = 1 # valid value + start_Hour = 18 # inavlid value > end hour + await self.set_week_days_schedule_cmd( + week_day_index, + user_index, + day_mask_map_index, + start_Hour, + start_Minute, + end_Hour, + end_Minute, + Status.InvalidCommand) + + self.step("8") + if self.pics_guard(self.check_pics("DRLK.S.F04") and self.check_pics("DRLK.S.C0c.Rsp") and self.check_pics("DRLK.S.C0c.Tx")): + week_day_index = 0 + user_index = 1 + await self.get_weekday_schedule_cmd( + week_day_index, + user_index, + day_mask_map_index, + start_Hour, + start_Minute, + end_Hour, + end_Minute, + Status.InvalidCommand) + self.step("9") + if self.pics_guard(self.check_pics("DRLK.S.F04") and self.check_pics("DRLK.S.C0c.Rsp") and self.check_pics("DRLK.S.C0c.Tx")): + week_day_index = 1 + user_index = 2 # invalid value as it does not exist + await self.get_weekday_schedule_cmd( + week_day_index, + user_index, + day_mask_map_index, + start_Hour, + start_Minute, + end_Hour, + end_Minute, + Status.NotFound) + self.step("10a") + if self.pics_guard(self.check_pics("DRLK.S.F04") and self.check_pics("DRLK.S.C0d.Rsp")): + week_day_index = 1 + user_index = 1 + await self.clear_week_day_schedule_cmd(week_day_index, + user_index, + Status.Success) + + self.step("10b") + if self.pics_guard(self.check_pics("DRLK.S.F04") and self.check_pics("DRLK.S.C0d.Rsp")): + week_day_index = 0 + user_index = 1 + try: + await self.send_single_cmd(cmd=Clusters.DoorLock.Commands.ClearWeekDaySchedule(week_day_index, user_index), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + asserts.fail("Unexpected success in sending ClearWeekDaySchedule Command with invalid week_day_index") + + except InteractionModelError as e: + asserts.assert_equal(e.status, Status.InvalidCommand, + "Unexpected error sending ClearWeekDaySchedule Command with invalid week_day_index") + self.step("10c") + if self.pics_guard(self.check_pics("DRLK.S.F04") and self.check_pics("DRLK.S.C0d.Rsp")): + week_day_index = 1 + user_index = 0 + + try: + await self.send_single_cmd(cmd=Clusters.DoorLock.Commands.ClearWeekDaySchedule(week_day_index, user_index), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + asserts.fail("Unexpected success in sending ClearWeekDaySchedule Command with invalid week_day_index") + + except InteractionModelError as e: + asserts.assert_equal(e.status, Status.InvalidCommand, + "Unexpected error sending ClearWeekDaySchedule Command with invalid week_day_index") + + self.step("11") + if self.pics_guard(self.check_pics("DRLK.S.F04") and self.check_pics("DRLK.S.C0c.Rsp") and self.check_pics("DRLK.S.C0c.Tx")): + user_index = 1 # invalid value as it is cleared + await self.get_weekday_schedule_cmd( + week_day_index, + user_index, + day_mask_map_index, + start_Hour, + start_Minute, + end_Hour, + end_Minute, + Status.NotFound) + self.step("12") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C1d.Rsp")): + await self.clear_user_cmd(user_index) + + +if __name__ == '__main__': + default_matter_test_main() diff --git a/src/python_testing/TC_DRLK_2_9.py b/src/python_testing/TC_DRLK_2_9.py new file mode 100644 index 00000000000000..954ca7dd7b2f3d --- /dev/null +++ b/src/python_testing/TC_DRLK_2_9.py @@ -0,0 +1,799 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${CHIP_LOCK_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS src/app/tests/suites/certification/ci-pics-values --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# === END CI TEST ARGUMENTS === + +import logging +import random +import string + +import chip.clusters as Clusters +from chip.clusters.Types import NullValue +from chip.interaction_model import InteractionModelError, Status +from drlk_2_x_common import DRLK_COMMON +from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main, type_matches +from mobly import asserts + +logger = logging.getLogger(__name__) + +drlkcluster = Clusters.DoorLock + + +class TC_DRLK_2_9(MatterBaseTest, DRLK_COMMON): + + def steps_TC_DRLK_2_9(self) -> list[TestStep]: + steps = [ + + TestStep("1", "TH reads NumberOfTotalUsersSupported attribute.", + "Verify that TH is able to read the attribute successfully."), + TestStep("2a", "TH sends SetUser Command to DUT.", "Verify that the DUT sends SUCCESS response"), + TestStep("2b", "TH reads MinPINCodeLength attribute .", + "Verify that TH is able to read the attribute successfully and value is within range."), + TestStep("2c", "TH reads MaxPINCodeLength attribute.", + "Verify that TH is able to read the attribute successfully and value is within range."), + TestStep("2d", "TH reads MinRFIDCodeLength attribute.", + "Verify that TH is able to read the attribute successfully."), + TestStep("2e", "TH reads MaxRFIDCodeLength attribute.", + "Verify that TH is able to read the attribute successfully and value is within range."), + TestStep("2f", "TH sends SetCredential Command to DUT.", + "Verify that the DUT responds with SetCredentialResponse command with Status SUCCESS."), + TestStep("3", "TH sends GetCredentialStatus Command .", + "Verify that the DUT responds with GetCredentialStatusResponse Command ."), + TestStep("4", "TH sends SetCredential Command to DUT.", + "Verify that the DUT responds with SetCredentialResponse command with Status INVALID_COMMAND."), + TestStep("5", "TH sends SetCredential Command to DUT.", + "Verify that the DUT responds with SetCredentialResponse command with Status DUPLICATE."), + TestStep("6a", "TH sends SetCredential Command to DUT.", + "Verify that the DUT responds with SetCredentialResponse command with Status DUPLICATE or OCCUPIED."), + TestStep("6b", "TH sends SetCredential Command to DUT.", + "Verify that the DUT responds with SetCredentialResponse command with Status DUPLICATE or OCCUPIED."), + TestStep("7", "TH sends SetCredential Command to DUT.", + "Verify that the DUT responds with SetCredentialResponse command with Status INVALID_COMMAND."), + TestStep("8", "TH sends ClearCredential Command to DUT.", + "Verify that the DUT sends SUCCESS response."), + TestStep("9a", "TH sends GetCredentialStatus command to DUT ", + "Verify that the DUT responds with GetCredentialStatusResponse Command."), + TestStep("9b", "TH sends ClearUser Command to DUT.", + "Verify that the DUT sends SUCCESS response"), + TestStep("10", "TH sends SetUser Command to DUT.", + "Verify that the DUT sends SUCCESS response."), + TestStep("11", "TH sends SetCredential Command to DUT.", + "Verify that the DUT responds with SetCredentialResponse command with Status SUCCESS."), + TestStep("12a", "TH sends ClearCredential Command to DUT.", + " Verify that the DUT sends SUCCESS response."), + TestStep("13", " TH sends GetCredentialStatus Command.", + "Verify that the DUT responds with GetCredentialStatusResponse Command with credentialExists=FALSE."), + TestStep("14a", "TH sends ClearCredential Command to DUT", + "if {PICS_SF_ALIRO} verify that the DUT sends a SUCCESS response else DUT sends an INVALID_COMMAND response."), + TestStep("14b", "TH sends ClearCredential Command to DUT with Invalid Credential Type.", + "Verify that the DUT sends an INVALID_COMMAND."), + TestStep("14c", "TH sends ClearUser Command to DUT to clear all the users.", + "Verify that the DUT sends SUCCESS response."), + TestStep("14d", "TH reads NumberOfPINUsersSupported attribute.", + "Verify that TH is able to read the attribute successfully and value is within range."), + TestStep("15a", "TH reads NumberOfCredentialsSupportedPerUser attribute from DUT.", + "Verify that TH is able to read the attribute successfully and value is within range."), + TestStep("15b", "TH sends SetUser Command to DUT.", + "Verify that the DUT sends SUCCESS response."), + TestStep("15c", "TH sends SetCredential Command to DUT.", + "Verify that the DUT sends SetCredentialResponse command with Status SUCCESS."), + TestStep("15d", " TH sends SetCredential Command with CredentialIndex as 'max-num-credential-user'.", + "Verify that the DUT sends SetCredentialResponse command with Status RESOURCE_EXHAUSTION."), + TestStep("15e", "TH sends ClearCredential Command to DUT to clear all the credentials of PIN type.", + "Verify that the DUT sends SUCCESS response."), + TestStep("15f", "TH sends ClearUser Command to DUT with UserIndex as 0xFFFE to clear all the users.", + "Verify that the DUT sends SUCCESS response."), + TestStep("16", " TH sends SetUser Command to DUT.", + "Verify that the DUT sends SUCCESS response"), + TestStep("17", "TH sends SetCredential Command to DUT with CredentialType.RFID.", + "Verify that the DUT sends SetCredentialResponse command with Status SUCCESS."), + TestStep("18", "TH sends SetCredential Command to DUT with CredentialType.PIN.", + "Verify that the DUT sends SetCredentialResponse command with Status SUCCESS."), + TestStep("19", "TH sends GetUser Command to DUT.", + "Verify that the DUT responds with GetUserResponse Command."), + TestStep("20", "TH sends SetCredential Command to DUT to modify the CredentialData.", + "Verify that the DUT sends SetCredentialResponse command with Status SUCCESS."), + TestStep("21", "TH sends GetUser Command to DUT.", + "Verify that the DUT responds with GetUserResponse Command."), + TestStep("22", "TH sends ClearCredential Command to DUT to clear all the credentials.", + "Verify that the DUT sends SUCCESS response."), + TestStep("23", "TH sends ClearUser Command to DUT to clear all the users.", + "Verify that the DUT sends SUCCESS response."), + TestStep("24", "TH sends SetUser Command to DUT.", + "Verify that the DUT sends SUCCESS response."), + TestStep("25", "TH sends ClearAliroReaderConfig Command to DUT.", + "Verify that the DUT sends SUCCESS response."), + TestStep("26", ",TH sends SetAliroReaderConfig Command to DUT without GroupResolvingKey.", + "Verify that DUT sends success response."), + TestStep("27", ",TH sends SetAliroReaderConfig Command to DUT with GroupResolvingKey.", + "Verify that DUT sends success response."), + TestStep("28", "TH sends SetCredential Command CredentialType as AliroEvictableEndpointKey.", + "Verify that the DUT responds with SetCredentialResponse commad with status success "), + TestStep("29", "TH sends SetCredential Command to DUT with CredentialType.PIN.", + "Verify that the DUT sends SetCredentialResponse command with Status SUCCESS."), + TestStep("30", "TH sends GetUser Command to DUT.", + "Verify that the DUT sends SUCCESS response."), + TestStep("31", "TH sends SetCredential Command to modify PIN CredentialType", + "Verify that the DUT responds with SetCredentialResponse command with status success "), + TestStep("32", "TH sends GetUser Command to DUT.", + "Verify that the DUT sends SUCCESS response."), + TestStep("33", "TH sends SetCredential Command to modify AliroEvictableEndpointKey CredentialType", + "Verify that the DUT responds with SetCredentialResponse command with status success "), + TestStep("34", "TH sends GetUser Command to DUT.", + "Verify that the DUT sends SUCCESS response."), + TestStep("35", "TH sends ClearUser Command to DUT.", + "Verify that the DUT sends SUCCESS response."), + TestStep("36", "TH sends ClearCredential Command to DUT to clear all the credentials.", + "Verify that the DUT sends SUCCESS response."), + TestStep("37", "TH sends ClearAliroReaderConfig Command to DUT.", + "Verify that the DUT sends SUCCESS response."), ] + + return steps + + async def read_attributes_from_dut(self, endpoint, cluster, attribute, expected_status: Status = Status.Success): + try: + attribute_value = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, + attribute=attribute) + asserts.assert_equal(expected_status, Status.Success) + return attribute_value + except Exception as e: + logging.error(e) + asserts.assert_equal(expected_status, Status.Success, + f"Error reading attributes, response={attribute_value}") + + def pics_TC_DRLK_2_9(self) -> list[str]: + return ["DRLK.S"] + + async def generate_max_pincode_len(self, maxPincodeLength): + return ''.join(random.choices(string.digits, k=maxPincodeLength)) + + async def generate_code(self): + if (self.maxpincodelength is not None): + validpincodestr = await self.generate_max_pincode_len(self.maxpincodelength) + self.pin_code = bytes(validpincodestr, 'ascii') + validpincodestr = await self.generate_max_pincode_len(self.maxpincodelength) + self.pin_code1 = bytes(validpincodestr, 'ascii') + validpincodestr = await self.generate_max_pincode_len(self.maxpincodelength) + self.pin_code2 = bytes(validpincodestr, 'ascii') + inavlidpincodestr = await self.generate_max_pincode_len(self.maxpincodelength+1) + self.inavlid_pincode = bytes(inavlidpincodestr, 'ascii') + if (self.maxrfidcodelength is not None): + validpincodestr = await self.generate_max_pincode_len(self.maxrfidcodelength) + self.rfid_tag = bytes(validpincodestr, 'ascii') + + async def send_clear_user_cmd(self, user_index, expected_status: Status = Status.Success): + try: + await self.send_single_cmd(cmd=Clusters.DoorLock.Commands.ClearUser(userIndex=user_index), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + asserts.assert_equal(expected_status, Status.Success) + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, f"Unexpected error returned: {e}") + + async def get_user(self, userindex, username, useruniqueid, credentiallist, expected_status: Status = Status.Success): + try: + response = await self.send_single_cmd(cmd=Clusters.DoorLock.Commands.GetUser(userIndex=userindex), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + + asserts.assert_true(type_matches(response, Clusters.DoorLock.Commands.GetUserResponse), + "Unexpected return type for GetUserResponse") + asserts.assert_true(response.userIndex == userindex, + "Error when executing GetUserResponse command, userIndex={}".format( + str(response.userIndex))) + asserts.assert_true(response.userName == username, + "Error when executing GetUserResponse command, userName={}".format( + str(response.userName))) + asserts.assert_true(response.userUniqueID == useruniqueid, + "Error when executing GetUserResponse command, userUniqueID={}".format( + str(response.userUniqueID))) + logging.info("Credentials value is GetUserResponse Command %s" % (str(response.credentials))) + + asserts.assert_equal(len(credentiallist), len(response.credentials), "Error mismatch in expected credential from GetUserResponse command = {}".format( + str(credentiallist))) + # traverse through input credentials and match each value with the resonse credential + for input_credential_index in range(len(credentiallist)): + match_found = False + for response_credential_index in range(len(response.credentials)): + if (response.credentials[response_credential_index] == credentiallist[input_credential_index]): + match_found = True + break + asserts.assert_equal(match_found, True, "Error mismatch in expected credential from GetUserResponse command = {}".format( + str(credentiallist))) + + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, f"Unexpected error returned: {e}") + + async def get_credentials_status(self, credentialIndex: int, credentialType: drlkcluster.Enums.CredentialTypeEnum, credential_exists, next_credential_index): + + try: + credentials_struct = drlkcluster.Structs.CredentialStruct(credentialIndex=credentialIndex, + credentialType=credentialType) + response = await self.send_single_cmd(endpoint=self.app_cluster_endpoint, timedRequestTimeoutMs=1000, + cmd=drlkcluster.Commands.GetCredentialStatus( + credential=credentials_struct)) + asserts.assert_true(type_matches(response, Clusters.DoorLock.Commands.GetCredentialStatusResponse), + "Unexpected return type for GetCredentialStatus") + asserts.assert_true(response.credentialExists == credential_exists, + "Error when executing GetCredentialStatus command, credentialExists={}".format( + str(response.credentialExists))) + if (not credential_exists): + asserts.assert_true(response.userIndex == NullValue, + "Error when executing GetCredentialStatus command, userIndex={}".format( + str(response.userIndex))) + asserts.assert_true(response.nextCredentialIndex == next_credential_index, + "Error when executing GetCredentialStatus command, nextCredentialIndex={}".format( + str(response.nextCredentialIndex))) + return response + except InteractionModelError as e: + logging.error(e) + asserts.assert_equal(e.status, Status.Success, f"Unexpected error returned: {e}") + + async def set_credential_cmd(self, credential_enum: drlkcluster.Enums.CredentialTypeEnum, statuscode, credentialIndex, + operationType, userIndex, credentialData, userStatus, userType): + custom_status_code = 149 + + credentials = drlkcluster.Structs.CredentialStruct( + credentialType=credential_enum, + credentialIndex=credentialIndex) + try: + + logging.info("Credential Data is %s" % (credentialData)) + response = await self.send_single_cmd(cmd=drlkcluster.Commands.SetCredential( + operationType=operationType, + credential=credentials, + credentialData=credentialData, + userStatus=userStatus, + userType=userType, + userIndex=userIndex), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + asserts.assert_true(type_matches(response, drlkcluster.Commands.SetCredentialResponse), + "Unexpected return type for SetCredential") + asserts.assert_equal(response.userIndex, NullValue) + if (statuscode != custom_status_code): + asserts.assert_true(response.status == statuscode, + "Error sending SetCredential command, status={}".format(str(response.status))) + else: + asserts.assert_true(response.status == 2 or response.status == 3, + "Error sending SetCredential command, status={}".format(str(response.status))) + return response.nextCredentialIndex + except InteractionModelError as e: + logging.exception(e) + asserts.assert_equal(e.status, statuscode, f"Unexpected error returned: {e}") + return -1 + + async def clear_credentials_cmd(self, credential, expected_status: Status = Status.Success): + try: + + await self.send_single_cmd(cmd=Clusters.DoorLock.Commands.ClearCredential(credential=credential), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + except InteractionModelError as e: + logging.exception(e) + asserts.assert_equal(e.status, expected_status, f"Unexpected error returned: {e}") + + async def send_clear_aliro_reader_config_cmd(self, expected_status: Status = Status.Success): + try: + await self.send_single_cmd(cmd=Clusters.DoorLock.Commands.ClearAliroReaderConfig(), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + asserts.assert_equal(expected_status, Status.Success) + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, f"Unexpected error returned: {e}") + + async def send_set_aliro_reader_config_cmd(self, use_group_resolving_key: bool, + expected_status: Status = Status.Success): + try: + + signingKey = bytes.fromhex("89d085fc302ca53e279bfcdecdf3c4adb2f5d9bc9ea6c49e9566d144367df3ff") + verificationKey = bytes.fromhex( + "047a4c992d753924cdf3779a3c84fec2debaa6f0b3084450878acc7ddcce7856ae57b1ebbe2561015103dd7474c2a183675378ec55f1e465ac3436bf3dd5ca54d4") + groupIdentifier = bytes.fromhex("89d085fc302ca53e279bfcdecdf3c4ad") + groupResolvingKey = bytes.fromhex("89d0859bfcdecdf3c4adfc302ca53e27") + + # Checks Pics condition + if use_group_resolving_key is False: + pics_check = self.pics_guard(self.check_pics("DRLK.S.F0d") and not self.check_pics("DRLK.S.F0e") and + self.check_pics("DRLK.S.C28.Rsp")) + else: + pics_check = self.pics_guard(self.check_pics("DRLK.S.F0e") and self.check_pics("DRLK.S.C28.Rsp")) + + if not use_group_resolving_key and pics_check: + await self.send_single_cmd(cmd=Clusters.DoorLock.Commands.SetAliroReaderConfig( + signingKey=signingKey, + verificationKey=verificationKey, + groupIdentifier=groupIdentifier), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + asserts.assert_equal(expected_status, Status.Success) + elif use_group_resolving_key and pics_check: + await self.send_single_cmd(cmd=Clusters.DoorLock.Commands.SetAliroReaderConfig( + signingKey=signingKey, + verificationKey=verificationKey, + groupIdentifier=groupIdentifier, + groupResolvingKey=groupResolvingKey), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + asserts.assert_equal(expected_status, Status.Success) + except InteractionModelError as e: + logging.exception(f"Got exception when performing SetAliroReaderConfig {e}") + asserts.assert_equal(e.status, expected_status, f"Unexpected error returned: {e}") + + @async_test_body + async def test_TC_DRLK_2_9(self): + + self.Attrib = 0 + numberofcredentialsupportedperuser = None + self.app_cluster_endpoint = 1 + invalid_credential_type = 9 + user_unique_id = 6459 + user_name = "xxx" + credentialIndex_1 = 1 + credentialIndex_2 = 2 + credentialIndex_3 = 3 + userIndex_1 = 1 + userIndex_2 = 2 + invalid_user_status = 5 + invalid_user_type = 10 + + self.pin_code = b"" + self.pin_code1 = b"" + self.pin_code2 = b"" + self.inavlid_pincode = b"" + self.rfid_tag = b"" + + self.minpincodelength = None + self.maxpincodelength = None + self.maxrfidcodelength = None + self.minrfidcodelength = None + + self.endpoint = self.user_params.get("endpoint", 1) + print("endpoint", self.endpoint) + + # Aliro Keys for setting Aliro configuration and credential + + aliroevictableendpointkey1 = bytes.fromhex( + "047a4c772d753924cdf3779a3c84fec2debaa6f0b3084450878acc7ddcce7856ae57b1ebbe2561015103dd7474c2a183675378ec55f1e465ac3436bf3dd5ca54d4") + + aliroevictableendpointkey2 = bytes.fromhex( + "047a4c662d753924cdf3779a3c84fec2debaa6f0b3084450878acc7ddcce7856ae57b1ebbe2561015103dd7474c2a183675378ec55f1e465ac3436bf3dd5ca54d4") + + self.step("1") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.A0011")): + self.numberoftotaluserssupported = await self.read_attributes_from_dut(endpoint=self.app_cluster_endpoint, + cluster=drlkcluster, + attribute=Clusters.DoorLock.Attributes.NumberOfTotalUsersSupported) + asserts.assert_in(self.numberoftotaluserssupported, range( + 0, 65534), "NumberOfTotalUsersSupported value is out of range") + self.step("2a") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C1a.Rsp")): + try: + await self.send_single_cmd(cmd=drlkcluster.Commands.SetUser( + operationType=Clusters.DoorLock.Enums.DataOperationTypeEnum.kAdd, + userIndex=userIndex_1, + userName=user_name, + userUniqueID=user_unique_id, + userStatus=Clusters.DoorLock.Enums.UserStatusEnum.kOccupiedEnabled, + userType=Clusters.DoorLock.Enums.UserTypeEnum.kUnrestrictedUser, + credentialRule=Clusters.DoorLock.Enums.CredentialRuleEnum.kSingle), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + except InteractionModelError as e: + logging.exception(e) + + self.step("2b") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.F00")): + self.minpincodelength = await self.read_attributes_from_dut(endpoint=self.app_cluster_endpoint, + cluster=drlkcluster, + attribute=Clusters.DoorLock.Attributes.MinPINCodeLength) + asserts.assert_in(self.minpincodelength, range( + 0, 255), "MinPINCodeLength value is out of range") + self.step("2c") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.F00")): + self.maxpincodelength = await self.read_attributes_from_dut(endpoint=self.app_cluster_endpoint, + cluster=drlkcluster, + attribute=Clusters.DoorLock.Attributes.MaxPINCodeLength) + asserts.assert_in(self.maxpincodelength, range( + 0, 255), "MaxPINCodeLength value is out of range") + self.step("2d") + if self.pics_guard(self.check_pics("DRLK.S.F01")): + self.minrfidcodelength = await self.read_attributes_from_dut(endpoint=self.app_cluster_endpoint, + cluster=drlkcluster, + attribute=Clusters.DoorLock.Attributes.MinRFIDCodeLength) + asserts.assert_in(self.minrfidcodelength, range( + 0, 255), "MinRFIDCodeLength value is out of range") + self.step("2e") + if self.pics_guard(self.check_pics("DRLK.S.F01")): + self.maxrfidcodelength = await self.read_attributes_from_dut(endpoint=self.app_cluster_endpoint, + cluster=drlkcluster, + attribute=Clusters.DoorLock.Attributes.MaxRFIDCodeLength) + asserts.assert_in(self.maxrfidcodelength, range( + 0, 255), "MaxRFIDCodeLength value is out of range") + self.step("2f") + await self.generate_code() + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F08") + and self.check_pics("DRLK.S.C22.Rsp") and self.check_pics("DRLK.S.C23.Tx")): + + await self.set_credential_cmd(credentialData=self.pin_code, + operationType=drlkcluster.Enums.DataOperationTypeEnum.kAdd, + credential_enum=drlkcluster.Enums.CredentialTypeEnum.kPin, + credentialIndex=credentialIndex_1, userIndex=userIndex_1, userStatus=NullValue, userType=NullValue, statuscode=Status.Success) + self.step("3") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F08") + and self.check_pics("DRLK.S.C24.Rsp") and self.check_pics("DRLK.S.C25.Tx")): + await self.get_credentials_status(credentialIndex=credentialIndex_1, + credentialType=drlkcluster.Enums.CredentialTypeEnum.kPin, credential_exists=True, next_credential_index=NullValue) + self.step("4") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F08") + and self.check_pics("DRLK.S.C22.Rsp") and self.check_pics("DRLK.S.C23.Tx")): + + await self.set_credential_cmd(credentialData=self.inavlid_pincode, + operationType=drlkcluster.Enums.DataOperationTypeEnum.kAdd, + credential_enum=drlkcluster.Enums.CredentialTypeEnum.kPin, + credentialIndex=credentialIndex_2, userIndex=NullValue, userStatus=invalid_user_status, userType=invalid_user_type, statuscode=Status.InvalidCommand) + self.step("5") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F08") + and self.check_pics("DRLK.S.C22.Rsp") and self.check_pics("DRLK.S.C23.Tx")): + await self.set_credential_cmd(credentialData=self.pin_code, + operationType=drlkcluster.Enums.DataOperationTypeEnum.kAdd, + credential_enum=drlkcluster.Enums.CredentialTypeEnum.kPin, + credentialIndex=credentialIndex_2, userIndex=NullValue, userStatus=NullValue, userType=NullValue, statuscode=2) + + self.step("6a") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F08") + and self.check_pics("DRLK.S.C22.Rsp") and self.check_pics("DRLK.S.C23.Tx")): + await self.set_credential_cmd(credentialData=self.pin_code, + operationType=drlkcluster.Enums.DataOperationTypeEnum.kAdd, + credential_enum=drlkcluster.Enums.CredentialTypeEnum.kPin, + credentialIndex=credentialIndex_1, userIndex=NullValue, userStatus=NullValue, userType=NullValue, statuscode=149) + self.step("6b") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F08") + and self.check_pics("DRLK.S.C22.Rsp") and self.check_pics("DRLK.S.C23.Tx")): + await self.set_credential_cmd(credentialData=self.pin_code1, + operationType=drlkcluster.Enums.DataOperationTypeEnum.kAdd, + credential_enum=drlkcluster.Enums.CredentialTypeEnum.kPin, + credentialIndex=credentialIndex_1, userIndex=NullValue, userStatus=NullValue, userType=NullValue, statuscode=149) + self.step("7") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F08") + and self.check_pics("DRLK.S.C22.Rsp") and self.check_pics("DRLK.S.C23.Tx")): + await self.set_credential_cmd(credentialData=self.pin_code2, + operationType=drlkcluster.Enums.DataOperationTypeEnum.kModify, + credential_enum=drlkcluster.Enums.CredentialTypeEnum.kPin, + credentialIndex=credentialIndex_3, userIndex=userIndex_1, userStatus=NullValue, userType=NullValue, statuscode=Status.InvalidCommand) + self.step("8") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C26.Rsp")): + credentials = drlkcluster.Structs.CredentialStruct(credentialIndex=1, + credentialType=drlkcluster.Enums.CredentialTypeEnum.kPin) + await self.clear_credentials_cmd(credential=credentials) + + self.step("9a") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C24.Rsp")): + await self.get_credentials_status(credentialIndex=credentialIndex_1, + credentialType=drlkcluster.Enums.CredentialTypeEnum.kPin, credential_exists=False, next_credential_index=NullValue) + self.step("9b") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C1d.Rsp")): + await self.send_clear_user_cmd(user_index=1) + + self.step("10") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C1a.Rsp")): + try: + await self.send_single_cmd(cmd=drlkcluster.Commands.SetUser( + operationType=Clusters.DoorLock.Enums.DataOperationTypeEnum.kAdd, + userIndex=userIndex_2, + userName=user_name, + userUniqueID=user_unique_id, + userStatus=Clusters.DoorLock.Enums.UserStatusEnum.kOccupiedEnabled, + userType=Clusters.DoorLock.Enums.UserTypeEnum.kUnrestrictedUser, + credentialRule=Clusters.DoorLock.Enums.CredentialRuleEnum.kSingle), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + except InteractionModelError as e: + logging.exception(e) + + self.step("11") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F08") + and self.check_pics("DRLK.S.C22.Rsp") and self.check_pics("DRLK.S.C23.Tx")): + await self.set_credential_cmd(credentialData=self.pin_code, + operationType=drlkcluster.Enums.DataOperationTypeEnum.kAdd, + credential_enum=drlkcluster.Enums.CredentialTypeEnum.kPin, + credentialIndex=credentialIndex_1, userIndex=userIndex_2, userStatus=NullValue, userType=NullValue, statuscode=Status.Success) + self.step("12a") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C26.Rsp")): + credentials = drlkcluster.Structs.CredentialStruct(credentialIndex=0xFFFE, + credentialType=drlkcluster.Enums.CredentialTypeEnum.kPin) + await self.clear_credentials_cmd(credential=credentials) + + self.step("13") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C24.Rsp") and self.check_pics("DRLK.S.C25.Tx")): + await self.get_credentials_status(credentialIndex=credentialIndex_1, + credentialType=drlkcluster.Enums.CredentialTypeEnum.kPin, credential_exists=False, next_credential_index=NullValue) + self.step("14a") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C26.Rsp")): + feature_map = await self.read_attributes_from_dut(endpoint=self.app_cluster_endpoint, + cluster=drlkcluster, + attribute=Clusters.DoorLock.Attributes.FeatureMap) + aliro_enabled = feature_map & Clusters.DoorLock.Bitmaps.Feature.kAliroProvisioning + credentials = drlkcluster.Structs.CredentialStruct(credentialIndex=credentialIndex_1, + credentialType=drlkcluster.Enums.CredentialTypeEnum.kAliroNonEvictableEndpointKey) + if (aliro_enabled): + + await self.clear_credentials_cmd(credential=credentials) + else: + try: + await self.send_single_cmd(cmd=Clusters.DoorLock.Commands.ClearCredential(credential=credentials), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + asserts.fail("Unexpected success in sending ClearCredential Command with invalid CredentialTpe") + + except InteractionModelError as e: + asserts.assert_equal(e.status, Status.InvalidCommand, + "Unexpected error sending ClearCredential Command with invalid CredentialTpe") + + self.step("14b") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C26.Rsp")): + credentials = drlkcluster.Structs.CredentialStruct(credentialIndex=credentialIndex_1, + credentialType=invalid_credential_type) + try: + await self.send_single_cmd(cmd=Clusters.DoorLock.Commands.ClearCredential(credential=credentials), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + asserts.fail("Unexpected success in sending ClearCredential Command with invalid CredentialTpe") + except InteractionModelError as e: + asserts.assert_equal(e.status, Status.InvalidCommand, + "Unexpected error sending ClearCredential Command with invalid CredentialTpe") + + self.step("14c") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C1d.Rsp")): + await self.send_clear_user_cmd(user_index=int(0xFFFE)) + + self.step("14d") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.A0012")): + num_pin_users_supported = await self.read_attributes_from_dut(endpoint=self.app_cluster_endpoint, + cluster=drlkcluster, + attribute=Clusters.DoorLock.Attributes.NumberOfPINUsersSupported) + asserts.assert_in(num_pin_users_supported, range( + 0, 65534), "NumberOfPINUsersSupported value is out of range") + self.step("15a") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.A001c")): + + numberofcredentialsupportedperuser = await self.read_attributes_from_dut(endpoint=self.app_cluster_endpoint, + cluster=drlkcluster, + attribute=Clusters.DoorLock.Attributes.NumberOfCredentialsSupportedPerUser) + asserts.assert_in(numberofcredentialsupportedperuser, range( + 0, 255), "NumberOfCredentialsSupportedPerUser value is out of range") + self.step("15b") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C1a.Rsp")): + try: + await self.send_single_cmd(cmd=drlkcluster.Commands.SetUser( + operationType=Clusters.DoorLock.Enums.DataOperationTypeEnum.kAdd, + userIndex=userIndex_1, + userName=user_name, + userUniqueID=user_unique_id, + userStatus=Clusters.DoorLock.Enums.UserStatusEnum.kOccupiedEnabled, + userType=Clusters.DoorLock.Enums.UserTypeEnum.kUnrestrictedUser, + credentialRule=Clusters.DoorLock.Enums.CredentialRuleEnum.kSingle), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + except InteractionModelError as e: + logging.exception(e) + + self.step("15c") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F08") + and self.check_pics("DRLK.S.C22.Rsp") and self.check_pics("DRLK.S.C23.Tx")): + if (numberofcredentialsupportedperuser < num_pin_users_supported): + logging.info("setting 'start_credential_index' to value 1 ") + start_credential_index = 1 + nextCredentialIndex = 1 + while 1: + uniquePincodeString = await self.generate_max_pincode_len(self.maxpincodelength) + uniquePincode = bytes(uniquePincodeString, 'ascii') + logging.info("Credential Data value is %s" % (uniquePincode)) + if start_credential_index <= (numberofcredentialsupportedperuser): + nextCredentialIndex = await self.set_credential_cmd(credentialData=uniquePincode, + operationType=drlkcluster.Enums.DataOperationTypeEnum.kAdd, + credential_enum=drlkcluster.Enums.CredentialTypeEnum.kPin, + + credentialIndex=start_credential_index, userIndex=userIndex_1, userStatus=NullValue, userType=NullValue, statuscode=Status.Success) + logging.info(f"The updated value of nextCredentialIndex is {nextCredentialIndex}") + start_credential_index += 1 + asserts.assert_true(nextCredentialIndex == start_credential_index, + "Error mismatch in expected nextCredentialIndex={}".format(str(nextCredentialIndex))) + logging.info(f"The updated value of start_credential_index is {start_credential_index}") + else: + break + self.step("15d") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F08") + and self.check_pics("DRLK.S.C22.Rsp") and self.check_pics("DRLK.S.C23.Tx")): + if (numberofcredentialsupportedperuser < num_pin_users_supported): + await self.set_credential_cmd(credentialData=self.pin_code, + operationType=drlkcluster.Enums.DataOperationTypeEnum.kAdd, + credential_enum=drlkcluster.Enums.CredentialTypeEnum.kPin, + credentialIndex=start_credential_index, userIndex=userIndex_1, userStatus=NullValue, userType=NullValue, statuscode=Status.ResourceExhausted) + self.step("15e") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C26.Rsp")): + credentials = drlkcluster.Structs.CredentialStruct(credentialIndex=0xFFFE, + credentialType=drlkcluster.Enums.CredentialTypeEnum.kPin) + await self.clear_credentials_cmd(credential=credentials) + self.step("15f") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C1d.Rsp")): + await self.send_clear_user_cmd(user_index=int(0xFFFE)) + + self.step("16") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C1a.Rsp")): + try: + await self.send_single_cmd(cmd=drlkcluster.Commands.SetUser( + operationType=Clusters.DoorLock.Enums.DataOperationTypeEnum.kAdd, + userIndex=userIndex_1, + userName=user_name, + userUniqueID=user_unique_id, + userStatus=Clusters.DoorLock.Enums.UserStatusEnum.kOccupiedEnabled, + userType=Clusters.DoorLock.Enums.UserTypeEnum.kUnrestrictedUser, + credentialRule=Clusters.DoorLock.Enums.CredentialRuleEnum.kSingle), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + except InteractionModelError as e: + logging.exception(e) + + self.step("17") + if self.pics_guard(self.check_pics("DRLK.S.F01") and self.check_pics("DRLK.S.C22.Rsp") + and self.check_pics("DRLK.S.C23.Tx")): + await self.set_credential_cmd(credentialData=self.rfid_tag, + operationType=drlkcluster.Enums.DataOperationTypeEnum.kAdd, + credential_enum=drlkcluster.Enums.CredentialTypeEnum.kRfid, + credentialIndex=credentialIndex_1, userIndex=userIndex_1, userStatus=NullValue, userType=NullValue, statuscode=Status.Success) + self.step("18") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.C22.Rsp") and self.check_pics("DRLK.S.C23.Tx")): + await self.set_credential_cmd(credentialData=self.pin_code, + operationType=drlkcluster.Enums.DataOperationTypeEnum.kAdd, + credential_enum=drlkcluster.Enums.CredentialTypeEnum.kPin, + credentialIndex=credentialIndex_1, userIndex=userIndex_1, userStatus=NullValue, userType=NullValue, statuscode=Status.Success) + + self.step("19") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F01") and self.check_pics("DRLK.S.C1b.Rsp")): + + credentiallist: list[drlkcluster.Structs.CredentialStruct] + credentiallist = [drlkcluster.Structs.CredentialStruct(credentialIndex=credentialIndex_1, + credentialType=drlkcluster.Enums.CredentialTypeEnum.kRfid), + drlkcluster.Structs.CredentialStruct(credentialIndex=credentialIndex_1, + credentialType=drlkcluster.Enums.CredentialTypeEnum.kPin)] + await self.get_user(userIndex_1, user_name, user_unique_id, credentiallist, Status.Success) + + self.step("20") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.C22.Rsp") and self.check_pics("DRLK.S.C23.Tx")): + await self.set_credential_cmd(credentialData=self.pin_code1, + operationType=drlkcluster.Enums.DataOperationTypeEnum.kModify, + credential_enum=drlkcluster.Enums.CredentialTypeEnum.kPin, + credentialIndex=credentialIndex_1, userIndex=userIndex_1, userStatus=NullValue, userType=NullValue, statuscode=Status.Success) + + self.step("21") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F01") and self.check_pics("DRLK.S.C1b.Rsp")): + await self.get_user(userIndex_1, user_name, user_unique_id, credentiallist, Status.Success) + + self.step("22") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C26.Rsp")): + await self.clear_credentials_cmd(credential=NullValue) + + self.step("23") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C1d.Rsp")): + await self.send_clear_user_cmd(userIndex_1) + + self.step("24") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C1a.Rsp")): + try: + await self.send_single_cmd(cmd=drlkcluster.Commands.SetUser( + operationType=Clusters.DoorLock.Enums.DataOperationTypeEnum.kAdd, + userIndex=userIndex_1, + userName=user_name, + userUniqueID=user_unique_id, + userStatus=Clusters.DoorLock.Enums.UserStatusEnum.kOccupiedEnabled, + userType=Clusters.DoorLock.Enums.UserTypeEnum.kUnrestrictedUser, + credentialRule=Clusters.DoorLock.Enums.CredentialRuleEnum.kSingle), + endpoint=self.app_cluster_endpoint, + timedRequestTimeoutMs=1000) + except InteractionModelError as e: + logging.exception(e) + + self.step("25") + if self.check_pics("DRLK.S.C29.Rsp"): + await self.send_clear_aliro_reader_config_cmd() + + self.step("26") + await self.send_set_aliro_reader_config_cmd(use_group_resolving_key=False, expected_status=Status.Success) + self.step("27") + await self.send_set_aliro_reader_config_cmd(use_group_resolving_key=True, expected_status=Status.Success) + + self.step("28") + if self.pics_guard(self.check_pics("DRLK.S.F0d") + and self.check_pics("DRLK.S.C22.Rsp") and self.check_pics("DRLK.S.C23.Tx")): + await self.set_credential_cmd(credentialData=aliroevictableendpointkey1, + operationType=drlkcluster.Enums.DataOperationTypeEnum.kAdd, + credential_enum=drlkcluster.Enums.CredentialTypeEnum.kAliroEvictableEndpointKey, + credentialIndex=credentialIndex_1, userIndex=userIndex_1, userStatus=NullValue, userType=NullValue, statuscode=Status.Success) + + self.step("29") + if self.pics_guard(self.check_pics("DRLK.S.F00") + and self.check_pics("DRLK.S.C22.Rsp") and self.check_pics("DRLK.S.C23.Tx")): + await self.set_credential_cmd(credentialData=self.pin_code, + operationType=drlkcluster.Enums.DataOperationTypeEnum.kAdd, + credential_enum=drlkcluster.Enums.CredentialTypeEnum.kPin, + credentialIndex=credentialIndex_1, userIndex=userIndex_1, userStatus=NullValue, userType=NullValue, statuscode=Status.Success) + self.step("30") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F0d") and self.check_pics("DRLK.S.C1b.Rsp")): + + credentiallist: list[drlkcluster.Structs.CredentialStruct] + credentiallist = [drlkcluster.Structs.CredentialStruct(credentialIndex=credentialIndex_1, + credentialType=drlkcluster.Enums.CredentialTypeEnum.kAliroEvictableEndpointKey), + drlkcluster.Structs.CredentialStruct(credentialIndex=credentialIndex_1, + credentialType=drlkcluster.Enums.CredentialTypeEnum.kPin)] + await self.get_user(userIndex_1, user_name, user_unique_id, credentiallist, Status.Success) + self.step("31") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.C22.Rsp") and self.check_pics("DRLK.S.C23.Tx")): + await self.set_credential_cmd(credentialData=self.pin_code2, + operationType=drlkcluster.Enums.DataOperationTypeEnum.kModify, + credential_enum=drlkcluster.Enums.CredentialTypeEnum.kPin, + credentialIndex=credentialIndex_1, userIndex=userIndex_1, userStatus=NullValue, userType=NullValue, statuscode=Status.Success) + + self.step("32") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F0d") and self.check_pics("DRLK.S.C1b.Rsp")): + + credentiallist: list[drlkcluster.Structs.CredentialStruct] + credentiallist = [drlkcluster.Structs.CredentialStruct(credentialIndex=credentialIndex_1, + credentialType=drlkcluster.Enums.CredentialTypeEnum.kAliroEvictableEndpointKey), + drlkcluster.Structs.CredentialStruct(credentialIndex=credentialIndex_1, + credentialType=drlkcluster.Enums.CredentialTypeEnum.kPin)] + await self.get_user(userIndex_1, user_name, user_unique_id, credentiallist, Status.Success) + self.step("33") + if self.pics_guard(self.check_pics("DRLK.S.F0d") and self.check_pics("DRLK.S.C22.Rsp") and self.check_pics("DRLK.S.C23.Tx")): + await self.set_credential_cmd(credentialData=aliroevictableendpointkey2, + operationType=drlkcluster.Enums.DataOperationTypeEnum.kModify, + credential_enum=drlkcluster.Enums.CredentialTypeEnum.kAliroEvictableEndpointKey, + credentialIndex=credentialIndex_1, userIndex=userIndex_1, userStatus=NullValue, userType=NullValue, statuscode=Status.Success) + self.step("34") + if self.pics_guard(self.check_pics("DRLK.S.F00") and self.check_pics("DRLK.S.F0d") and self.check_pics("DRLK.S.C1b.Rsp")): + + credentiallist: list[drlkcluster.Structs.CredentialStruct] + credentiallist = [drlkcluster.Structs.CredentialStruct(credentialIndex=credentialIndex_1, + credentialType=drlkcluster.Enums.CredentialTypeEnum.kAliroEvictableEndpointKey), + drlkcluster.Structs.CredentialStruct(credentialIndex=credentialIndex_1, + credentialType=drlkcluster.Enums.CredentialTypeEnum.kPin)] + await self.get_user(userIndex_1, user_name, user_unique_id, credentiallist, Status.Success) + + self.step("35") + if self.pics_guard(self.check_pics("DRLK.S.F08") and self.check_pics("DRLK.S.C1d.Rsp")): + await self.send_clear_user_cmd(userIndex_1) + + self.step("36") + if self.pics_guard(self.check_pics("DRLK.S.C26.Rsp")): + await self.clear_credentials_cmd(credential=NullValue) + + self.step("37") + if self.pics_guard(self.check_pics("DRLK.S.C29.Rsp")): + await self.send_clear_aliro_reader_config_cmd() + + +if __name__ == '__main__': + default_matter_test_main() diff --git a/src/python_testing/TC_SWTCH.py b/src/python_testing/TC_SWTCH.py index 3d369be456962d..4609043a3ef477 100644 --- a/src/python_testing/TC_SWTCH.py +++ b/src/python_testing/TC_SWTCH.py @@ -892,6 +892,7 @@ def test_multi_press_sequence(starting_step: str, count: int, short_long: bool = self.step("7a") if not has_msl_feature: self.skip_all_remaining_steps("7b") + return # subscription is already established self.step("7b") diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/metadata.py b/src/python_testing/matter_testing_infrastructure/chip/testing/metadata.py index aa829c40d855c7..803160e5c736e5 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/metadata.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/metadata.py @@ -12,17 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +import logging import re -import sys from dataclasses import dataclass +from io import StringIO from typing import Any, Dict, List import yaml -def bool_from_str(value: str) -> bool: +# TODO #35787: Remove support for non-YAML format +def cast_to_bool(value: Any) -> bool: """Convert True/true/False/false strings to bool.""" - return value.strip().lower() == "true" + if isinstance(value, str): + return value.strip().lower() == "true" + return bool(value) @dataclass @@ -67,16 +71,22 @@ def copy_from_dict(self, attr_dict: Dict[str, Any]) -> None: self.py_script_path = attr_dict["py_script_path"] if "factoryreset" in attr_dict: - self.factoryreset = bool_from_str(attr_dict["factoryreset"]) + self.factoryreset = cast_to_bool(attr_dict["factoryreset"]) if "factoryreset_app_only" in attr_dict: - self.factoryreset_app_only = bool_from_str(attr_dict["factoryreset_app_only"]) + self.factoryreset_app_only = cast_to_bool(attr_dict["factoryreset_app_only"]) if "script_gdb" in attr_dict: - self.script_gdb = bool_from_str(attr_dict["script_gdb"]) + self.script_gdb = cast_to_bool(attr_dict["script_gdb"]) if "quiet" in attr_dict: - self.quiet = bool_from_str(attr_dict["quiet"]) + self.quiet = cast_to_bool(attr_dict["quiet"]) + + +class NamedStringIO(StringIO): + def __init__(self, content, name): + super().__init__(content) + self.name = name def extract_runs_arg_lines(py_script_path: str) -> Dict[str, Dict[str, str]]: @@ -91,23 +101,34 @@ def extract_runs_arg_lines(py_script_path: str) -> Dict[str, Dict[str, str]]: runs_arg_lines: Dict[str, Dict[str, str]] = {} + ci_args_section_lines = [] with open(py_script_path, 'r', encoding='utf8') as py_script: for line_idx, line in enumerate(py_script.readlines()): line = line.strip() line_num = line_idx + 1 + # Append empty line to the line capture, so during YAML parsing + # line numbers will match the original file. + ci_args_section_lines.append("") + # Detect the single CI args section, to skip the lines otherwise. if not done_ci_args_section and line.startswith("# === BEGIN CI TEST ARGUMENTS ==="): found_ci_args_section = True + continue elif found_ci_args_section and line.startswith("# === END CI TEST ARGUMENTS ==="): done_ci_args_section = True found_ci_args_section = False + continue + + if found_ci_args_section: + # Update the last line in the line capture. + ci_args_section_lines[-1] = " " + line.lstrip("#") runs_match = runs_def_ptrn.match(line) args_match = arg_def_ptrn.match(line) if not found_ci_args_section and (runs_match or args_match): - print(f"WARNING: {py_script_path}:{line_num}: Found CI args outside of CI TEST ARGUMENTS block!", file=sys.stderr) + logging.warning(f"{py_script_path}:{line_num}: Found CI args outside of CI TEST ARGUMENTS block") continue if runs_match: @@ -119,6 +140,17 @@ def extract_runs_arg_lines(py_script_path: str) -> Dict[str, Dict[str, str]]: elif args_match: runs_arg_lines[args_match.group("run_id")][args_match.group("arg_name")] = args_match.group("arg_val") + if not runs_arg_lines: + try: + runs = yaml.safe_load(NamedStringIO("\n".join(ci_args_section_lines), py_script_path)) + for run, args in runs.get("test-runner-runs", {}).items(): + runs_arg_lines[run] = {} + runs_arg_lines[run]['run'] = run + runs_arg_lines[run]['py_script_path'] = py_script_path + runs_arg_lines[run].update(args) + except yaml.YAMLError as e: + logging.error(f"Failed to parse CI arguments YAML: {e}") + return runs_arg_lines @@ -155,10 +187,12 @@ def __resolve_env_vals__(self, metadata_dict: Dict[str, str]) -> None: the value for that argument defined in the test script. """ for arg, arg_val in metadata_dict.items(): + if not isinstance(arg_val, str): + continue # We do not expect to recurse (like ${FOO_${BAR}}) so just expand once for name, value in self.env.items(): arg_val = arg_val.replace(f'${{{name}}}', value) - metadata_dict[arg] = arg_val + metadata_dict[arg] = arg_val.strip() def parse_script(self, py_script_path: str) -> List[Metadata]: """ diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/test_metadata.py b/src/python_testing/matter_testing_infrastructure/chip/testing/test_metadata.py index 863add965c315e..ce41969fe0af1f 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/test_metadata.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/test_metadata.py @@ -34,6 +34,21 @@ class TestMetadataReader(unittest.TestCase): # test-runner-run/run1/quiet: False ''' + test_file_content_yaml = ''' + # === BEGIN CI TEST ARGUMENTS === + # test-runner-runs: + # run1: + # app: ${ALL_CLUSTERS_APP} + # app-args: --discriminator 1234 --trace-to json:${TRACE_APP}.json + # script-args: > + # --commissioning-method on-network + # --trace-to json:${TRACE_TEST_JSON}.json + # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + # factoryreset: true + # quiet: true + # === END CI TEST ARGUMENTS === + ''' + env_file_content = ''' ALL_CLUSTERS_APP: out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app CHIP_LOCK_APP: out/linux-x64-lock-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-lock-app @@ -61,15 +76,21 @@ def generate_temp_file(self, directory: str, file_content: str) -> str: def test_run_arg_generation(self): with tempfile.TemporaryDirectory() as temp_dir: - temp_file = self.generate_temp_file(temp_dir, self.test_file_content) + test_file = self.generate_temp_file(temp_dir, self.test_file_content) env_file = self.generate_temp_file(temp_dir, self.env_file_content) reader = MetadataReader(env_file) - self.maxDiff = None + self.expected_metadata.py_script_path = test_file + self.assertEqual(self.expected_metadata, reader.parse_script(test_file)[0]) - self.expected_metadata.py_script_path = temp_file - actual = reader.parse_script(temp_file)[0] - self.assertEqual(self.expected_metadata, actual) + def test_run_arg_generation_yaml(self): + with tempfile.TemporaryDirectory() as temp_dir: + test_file = self.generate_temp_file(temp_dir, self.test_file_content_yaml) + env_file = self.generate_temp_file(temp_dir, self.env_file_content) + + reader = MetadataReader(env_file) + self.expected_metadata.py_script_path = test_file + self.assertEqual(self.expected_metadata, reader.parse_script(test_file)[0]) if __name__ == "__main__": diff --git a/src/setup_payload/tests/TestQRCode.cpp b/src/setup_payload/tests/TestQRCode.cpp index e5d68227c2956e..ce5048489113e6 100644 --- a/src/setup_payload/tests/TestQRCode.cpp +++ b/src/setup_payload/tests/TestQRCode.cpp @@ -32,7 +32,6 @@ #include using namespace chip; -using namespace std; namespace { @@ -121,7 +120,7 @@ TEST(TestQRCode, TestPayloadByteArrayRep) { SetupPayload payload = GetDefaultPayload(); - string expected = " 0000 000000000000000100000000000 000010000000 00000001 00 0000000000000001 0000000000001100 000"; + std::string expected = " 0000 000000000000000100000000000 000010000000 00000001 00 0000000000000001 0000000000001100 000"; EXPECT_TRUE(CompareBinary(payload, expected)); } @@ -130,7 +129,7 @@ TEST(TestQRCode, TestPayloadBase38Rep) SetupPayload payload = GetDefaultPayload(); QRCodeSetupPayloadGenerator generator(payload); - string result; + std::string result; CHIP_ERROR err = generator.payloadBase38Representation(result); bool didSucceed = err == CHIP_NO_ERROR; EXPECT_EQ(didSucceed, true); @@ -241,10 +240,10 @@ TEST(TestQRCode, TestBase38) base38Encode(ByteSpan((uint8_t *) "Hello World!", sizeof("Hello World!") - 1), encodedSpan); EXPECT_STREQ(encodedBuf, "KKHF3W2S013OPM3EJX11"); - vector decoded = vector(); + std::vector decoded = std::vector(); EXPECT_EQ(base38Decode("KKHF3W2S013OPM3EJX11", decoded), CHIP_NO_ERROR); - string hello_world; + std::string hello_world; for (uint8_t b : decoded) { hello_world += static_cast(b); @@ -347,8 +346,8 @@ TEST(TestQRCode, TestSetupPayloadVerify) TEST(TestQRCode, TestInvalidQRCodePayload_WrongCharacterSet) { - string invalidString = kDefaultPayloadQRCode; - invalidString.back() = ' '; // space is not contained in the base38 alphabet + std::string invalidString = kDefaultPayloadQRCode; + invalidString.back() = ' '; // space is not contained in the base38 alphabet QRCodeSetupPayloadParser parser = QRCodeSetupPayloadParser(invalidString); SetupPayload payload; @@ -360,7 +359,7 @@ TEST(TestQRCode, TestInvalidQRCodePayload_WrongCharacterSet) TEST(TestQRCode, TestInvalidQRCodePayload_WrongLength) { - string invalidString = kDefaultPayloadQRCode; + std::string invalidString = kDefaultPayloadQRCode; invalidString.pop_back(); QRCodeSetupPayloadParser parser = QRCodeSetupPayloadParser(invalidString); @@ -395,7 +394,7 @@ TEST(TestQRCode, TestQRCodeToPayloadGeneration) SetupPayload payload = GetDefaultPayload(); QRCodeSetupPayloadGenerator generator(payload); - string base38Rep; + std::string base38Rep; CHIP_ERROR err = generator.payloadBase38Representation(base38Rep); bool didSucceed = err == CHIP_NO_ERROR; EXPECT_EQ(didSucceed, true); @@ -422,7 +421,7 @@ TEST(TestQRCode, TestGenerateWithShortDiscriminatorInvalid) EXPECT_FALSE(payload.isValidQRCodePayload()); // QRCodeSetupPayloadGenerator should therefore return an error - string base38Rep; + std::string base38Rep; QRCodeSetupPayloadGenerator generator(payload); EXPECT_EQ(generator.payloadBase38Representation(base38Rep), CHIP_ERROR_INVALID_ARGUMENT); @@ -441,7 +440,7 @@ TEST(TestQRCode, TestGenerateWithoutRendezvousInformation) EXPECT_FALSE(payload.isValidQRCodePayload()); // QRCodeSetupPayloadGenerator should therefore return an error - string base38Rep; + std::string base38Rep; QRCodeSetupPayloadGenerator generator(payload); EXPECT_EQ(generator.payloadBase38Representation(base38Rep), CHIP_ERROR_INVALID_ARGUMENT); @@ -452,23 +451,23 @@ TEST(TestQRCode, TestGenerateWithoutRendezvousInformation) TEST(TestQRCode, TestExtractPayload) { - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("MT:ABC")), string("ABC")); - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("MT:")), string("")); - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("H:")), string("")); - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("ASMT:")), string("")); - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("Z%MT:ABC%")), string("ABC")); - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("Z%MT:ABC")), string("ABC")); - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("%Z%MT:ABC")), string("ABC")); - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("%Z%MT:ABC%")), string("ABC")); - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("%Z%MT:ABC%DDD")), string("ABC")); - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("MT:ABC%DDD")), string("ABC")); - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("MT:ABC%")), string("ABC")); - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("%MT:")), string("")); - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("%MT:%")), string("")); - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("A%")), string("")); - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("MT:%")), string("")); - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("%MT:ABC")), string("ABC")); - EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(string("ABC")), string("")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("MT:ABC")), std::string("ABC")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("MT:")), std::string("")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("H:")), std::string("")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("ASMT:")), std::string("")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("Z%MT:ABC%")), std::string("ABC")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("Z%MT:ABC")), std::string("ABC")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("%Z%MT:ABC")), std::string("ABC")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("%Z%MT:ABC%")), std::string("ABC")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("%Z%MT:ABC%DDD")), std::string("ABC")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("MT:ABC%DDD")), std::string("ABC")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("MT:ABC%")), std::string("ABC")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("%MT:")), std::string("")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("%MT:%")), std::string("")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("A%")), std::string("")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("MT:%")), std::string("")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("%MT:ABC")), std::string("ABC")); + EXPECT_EQ(QRCodeSetupPayloadParser::ExtractPayload(std::string("ABC")), std::string("")); } } // namespace diff --git a/src/setup_payload/tests/TestQRCodeTLV.cpp b/src/setup_payload/tests/TestQRCodeTLV.cpp index 7ea2b974070275..3cada5cb505264 100644 --- a/src/setup_payload/tests/TestQRCodeTLV.cpp +++ b/src/setup_payload/tests/TestQRCodeTLV.cpp @@ -24,7 +24,6 @@ #include using namespace chip; -using namespace std; namespace { @@ -38,7 +37,7 @@ class TestQRCodeTLV : public ::testing::Test TEST_F(TestQRCodeTLV, TestOptionalDataAddRemove) { SetupPayload payload = GetDefaultPayload(); - vector optionalData; + std::vector optionalData; CHIP_ERROR err; optionalData = payload.getAllOptionalVendorData(); @@ -86,11 +85,11 @@ TEST_F(TestQRCodeTLV, TestSimpleWrite) SetupPayload inPayload = GetDefaultPayload(); QRCodeSetupPayloadGenerator generator(inPayload); - string result; + std::string result; CHIP_ERROR err = generator.payloadBase38Representation(result); EXPECT_EQ(err, CHIP_NO_ERROR); - string result2; + std::string result2; err = generator.payloadBase38RepresentationWithAutoTLVBuffer(result2); EXPECT_EQ(err, CHIP_NO_ERROR); @@ -103,7 +102,7 @@ TEST_F(TestQRCodeTLV, TestSimpleRead) SetupPayload outPayload; QRCodeSetupPayloadGenerator generator(inPayload); - string result; + std::string result; CHIP_ERROR err = generator.payloadBase38Representation(result); EXPECT_EQ(err, CHIP_NO_ERROR); @@ -139,7 +138,7 @@ TEST_F(TestQRCodeTLV, TestSerialNumberAddRemove) { SetupPayload inPayload = GetDefaultPayload(); - string sn; + std::string sn; EXPECT_EQ(inPayload.getSerialNumber(sn), CHIP_ERROR_KEY_NOT_FOUND); EXPECT_EQ(inPayload.removeSerialNumber(), CHIP_ERROR_KEY_NOT_FOUND); @@ -149,7 +148,7 @@ TEST_F(TestQRCodeTLV, TestSerialNumberAddRemove) EXPECT_EQ(inPayload.addSerialNumber(kSerialNumberDefaultUInt32Value), CHIP_NO_ERROR); EXPECT_EQ(inPayload.getSerialNumber(sn), CHIP_NO_ERROR); - EXPECT_EQ(sn, to_string(kSerialNumberDefaultUInt32Value)); + EXPECT_EQ(sn, std::to_string(kSerialNumberDefaultUInt32Value)); EXPECT_EQ(inPayload.removeSerialNumber(), CHIP_NO_ERROR); EXPECT_EQ(inPayload.getSerialNumber(sn), CHIP_ERROR_KEY_NOT_FOUND); @@ -164,7 +163,7 @@ TEST_F(TestQRCodeTLV, TestOptionalDataWriteSerial) EXPECT_EQ(err, CHIP_NO_ERROR); QRCodeSetupPayloadGenerator generator(inPayload); - string result; + std::string result; err = generator.payloadBase38Representation(result); EXPECT_NE(err, CHIP_NO_ERROR); @@ -172,7 +171,7 @@ TEST_F(TestQRCodeTLV, TestOptionalDataWriteSerial) err = generator.payloadBase38Representation(result, optionalInfo, sizeof(optionalInfo)); EXPECT_EQ(err, CHIP_NO_ERROR); - string result2; + std::string result2; err = generator.payloadBase38RepresentationWithAutoTLVBuffer(result2); EXPECT_EQ(err, CHIP_NO_ERROR); @@ -184,12 +183,12 @@ TEST_F(TestQRCodeTLV, TestOptionalDataWrite) SetupPayload inPayload = GetDefaultPayloadWithOptionalDefaults(); QRCodeSetupPayloadGenerator generator(inPayload); - string result; + std::string result; uint8_t optionalInfo[kDefaultBufferSizeInBytes]; CHIP_ERROR err = generator.payloadBase38Representation(result, optionalInfo, sizeof(optionalInfo)); EXPECT_EQ(err, CHIP_NO_ERROR); - string result2; + std::string result2; err = generator.payloadBase38RepresentationWithAutoTLVBuffer(result2); EXPECT_EQ(err, CHIP_NO_ERROR); @@ -235,7 +234,7 @@ TEST_F(TestQRCodeTLV, TestOptionalDataWriteNoBuffer) SetupPayload inPayload = GetDefaultPayloadWithOptionalDefaults(); QRCodeSetupPayloadGenerator generator(inPayload); - string result; + std::string result; CHIP_ERROR err = generator.payloadBase38Representation(result); EXPECT_NE(err, CHIP_NO_ERROR); } @@ -245,7 +244,7 @@ TEST_F(TestQRCodeTLV, TestOptionalDataWriteSmallBuffer) SetupPayload inPayload = GetDefaultPayloadWithOptionalDefaults(); QRCodeSetupPayloadGenerator generator(inPayload); - string result; + std::string result; uint8_t optionalInfo[kSmallBufferSizeInBytes]; CHIP_ERROR err = generator.payloadBase38Representation(result, optionalInfo, sizeof(optionalInfo)); EXPECT_NE(err, CHIP_NO_ERROR); diff --git a/third_party/abseil-cpp/src b/third_party/abseil-cpp/src index 3ab97e7212bff9..e9ca8d1ca225ef 160000 --- a/third_party/abseil-cpp/src +++ b/third_party/abseil-cpp/src @@ -1 +1 @@ -Subproject commit 3ab97e7212bff931a201c794fa1331960158bbfa +Subproject commit e9ca8d1ca225ef94fd20890b5440b22f490a410a diff --git a/third_party/fuzztest b/third_party/fuzztest index 6eb010c7223a6a..b7257a64c701fc 160000 --- a/third_party/fuzztest +++ b/third_party/fuzztest @@ -1 +1 @@ -Subproject commit 6eb010c7223a6aa609b94d49bfc06ac88f922961 +Subproject commit b7257a64c701fc30265eb91179bf9310549bf440 diff --git a/third_party/googletest b/third_party/googletest index 1d17ea141d2c11..6dae7eb4a5c3a1 160000 --- a/third_party/googletest +++ b/third_party/googletest @@ -1 +1 @@ -Subproject commit 1d17ea141d2c11b8917d2c7d029f1c4e2b9769b2 +Subproject commit 6dae7eb4a5c3a169f3e298392bff4680224aa94a diff --git a/third_party/nxp/nxp_matter_support b/third_party/nxp/nxp_matter_support index b2855d3e28556d..e46fdce014aef0 160000 --- a/third_party/nxp/nxp_matter_support +++ b/third_party/nxp/nxp_matter_support @@ -1 +1 @@ -Subproject commit b2855d3e28556d145889fdba889fba286c60a93f +Subproject commit e46fdce014aef075c68a62cbd87e4a6791edd392