From 1436544b779a2e875cd6f2376594231cbadcbdbc Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Mon, 7 Feb 2022 15:11:10 -0500 Subject: [PATCH] Add correct checking for whether a command is supported. (#14806) This also fixes the status reporting for unsupported endpoints and clusters. And fixes some tests to use the right endpoint, now that we are checking that sort of thing. Fixes https://github.com/project-chip/connectedhomeip/issues/7612 Fixes https://github.com/project-chip/connectedhomeip/issues/13920 Fixes https://github.com/project-chip/connectedhomeip/issues/14022 Fixes https://github.com/project-chip/connectedhomeip/issues/11578 Fixes https://github.com/project-chip/connectedhomeip/issues/11185 --- .github/.wordlist.txt | 4 + examples/bridge-app/esp32/README.md | 6 +- examples/bridge-app/esp32/main/main.cpp | 19 +- examples/bridge-app/linux/README.md | 6 +- examples/bridge-app/linux/main.cpp | 27 +- examples/tv-app/linux/AppImpl.cpp | 95 ++++++- src/app/CommandHandler.cpp | 36 +-- src/app/CommandHandler.h | 9 +- src/app/InteractionModelEngine.cpp | 2 +- src/app/InteractionModelEngine.h | 16 +- src/app/tests/TestCommandInteraction.cpp | 30 +- .../tests/integration/chip_im_initiator.cpp | 6 +- .../tests/integration/chip_im_responder.cpp | 24 +- src/app/tests/suites/TestCluster.yaml | 14 +- .../certification/Test_TC_SWDIAG_1_1.yaml | 5 +- .../certification/Test_TC_SWDIAG_2_1.yaml | 2 +- .../certification/Test_TC_SWDIAG_3_1.yaml | 8 +- .../certification/Test_TC_WIFIDIAG_1_1.yaml | 11 +- .../certification/Test_TC_WIFIDIAG_3_1.yaml | 4 +- src/app/util/af.h | 6 +- src/app/util/attribute-storage.cpp | 10 + src/app/util/attribute-storage.h | 9 +- .../util/ember-compatibility-functions.cpp | 56 +++- src/controller/tests/TestReadChunking.cpp | 4 +- .../tests/TestServerCommandDispatch.cpp | 12 +- .../tests/data_model/TestCommands.cpp | 20 +- src/controller/tests/data_model/TestRead.cpp | 20 +- src/controller/tests/data_model/TestWrite.cpp | 20 +- .../Framework/CHIPTests/CHIPClustersTests.m | 111 ++++---- .../linux-cirque/MobileDeviceTest.py | 2 +- .../chip-tool/zap-generated/test/Commands.h | 263 +++++++++++------- 31 files changed, 580 insertions(+), 277 deletions(-) diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index bfad18cce35fa0..707a0fd79c1252 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -504,6 +504,7 @@ ImplClass implementers imx imxlinux +incomingCommands indexhtml Inet InetLayer @@ -550,6 +551,7 @@ jupyterlab KA Kconfig KeypadInput +kInvalidCommandId KitProg kNodeIdNotSpecified knownissues @@ -716,6 +718,7 @@ nrfdks nrfutil nrfxlib NTAG +nullptr NUM nwk NXP @@ -763,6 +766,7 @@ otasoftwareupdaterequestor otaURL OTBR otcli +outgoingCommands PAA PacketBuffer PAI diff --git a/examples/bridge-app/esp32/README.md b/examples/bridge-app/esp32/README.md index 963ae595bece86..df50e4becfce52 100644 --- a/examples/bridge-app/esp32/README.md +++ b/examples/bridge-app/esp32/README.md @@ -58,7 +58,7 @@ defined: application's `main.cpp` for an example of this implementation. `DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(clusterListName)` -`DECLARE_DYNAMIC_CLUSTER(clusterId, clusterAttrs)` +`DECLARE_DYNAMIC_CLUSTER(clusterId, clusterAttrs, incomingCommands, outgoingCommands)` `DECLARE_DYNAMIC_CLUSTER_LIST_END` - These three macros are used to declare a list of clusters for use within a @@ -66,7 +66,9 @@ defined: `DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN` macro which will define the name of the allocated cluster structure. Each cluster is then added by the `DECLARE_DYNAMIC_CLUSTER` macro referencing attribute list previously - defined by the `DECLARE_DYNAMIC_ATTRIBUTE...` macros. Finally, + defined by the `DECLARE_DYNAMIC_ATTRIBUTE...` macros and the lists of + incoming/outgoing commands terminated by kInvalidCommandId (or nullptr if + there aren't any commands in the list). Finally, `DECLARE_DYNAMIC_CLUSTER_LIST_END` macro should be used to close the definition. diff --git a/examples/bridge-app/esp32/main/main.cpp b/examples/bridge-app/esp32/main/main.cpp index be17e3fa11466a..d12a81b2c10ed8 100644 --- a/examples/bridge-app/esp32/main/main.cpp +++ b/examples/bridge-app/esp32/main/main.cpp @@ -97,10 +97,23 @@ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_LABEL_LIST_ATTRIBUTE_ID, ARRAY, kFixedLabelAttribu DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); // Declare Cluster List for Bridged Light endpoint +// TODO: It's not clear whether it would be better to get the command lists from +// the ZAP config on our last fixed endpoint instead. +constexpr CommandId onOffIncomingCommands[] = { + app::Clusters::OnOff::Commands::Off::Id, + app::Clusters::OnOff::Commands::On::Id, + app::Clusters::OnOff::Commands::Toggle::Id, + app::Clusters::OnOff::Commands::OffWithEffect::Id, + app::Clusters::OnOff::Commands::OnWithRecallGlobalScene::Id, + app::Clusters::OnOff::Commands::OnWithTimedOff::Id, + kInvalidCommandId, +}; + DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedLightClusters) -DECLARE_DYNAMIC_CLUSTER(ZCL_ON_OFF_CLUSTER_ID, onOffAttrs), DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, descriptorAttrs), - DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, bridgedDeviceBasicAttrs), - DECLARE_DYNAMIC_CLUSTER(ZCL_FIXED_LABEL_CLUSTER_ID, fixedLabelAttrs) DECLARE_DYNAMIC_CLUSTER_LIST_END; +DECLARE_DYNAMIC_CLUSTER(ZCL_ON_OFF_CLUSTER_ID, onOffAttrs, onOffIncomingCommands, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, descriptorAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, bridgedDeviceBasicAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_FIXED_LABEL_CLUSTER_ID, fixedLabelAttrs, nullptr, nullptr), DECLARE_DYNAMIC_CLUSTER_LIST_END; // Declare Bridged Light endpoint DECLARE_DYNAMIC_ENDPOINT(bridgedLightEndpoint, bridgedLightClusters); diff --git a/examples/bridge-app/linux/README.md b/examples/bridge-app/linux/README.md index 9cdd2a30f8080c..5ff4087b7d89c0 100644 --- a/examples/bridge-app/linux/README.md +++ b/examples/bridge-app/linux/README.md @@ -55,7 +55,7 @@ defined: application's `main.cpp` for an example of this implementation. `DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(clusterListName)` -`DECLARE_DYNAMIC_CLUSTER(clusterId, clusterAttrs)` +`DECLARE_DYNAMIC_CLUSTER(clusterId, clusterAttrs, incomingCommands, outgoingCommands)` `DECLARE_DYNAMIC_CLUSTER_LIST_END` - These three macros are used to declare a list of clusters for use within a @@ -63,7 +63,9 @@ defined: `DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN` macro which will define the name of the allocated cluster structure. Each cluster is then added by the `DECLARE_DYNAMIC_CLUSTER` macro referencing attribute list previously - defined by the `DECLARE_DYNAMIC_ATTRIBUTE...` macros. Finally, + defined by the `DECLARE_DYNAMIC_ATTRIBUTE...` macros and the lists of + incoming/outgoing commands terminated by kInvalidCommandId (or nullptr if + there aren't any commands in the list). Finally, `DECLARE_DYNAMIC_CLUSTER_LIST_END` macro should be used to close the definition. diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp index bf4627f8109d5a..9c98f4f7822c4a 100644 --- a/examples/bridge-app/linux/main.cpp +++ b/examples/bridge-app/linux/main.cpp @@ -117,10 +117,23 @@ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_LABEL_LIST_ATTRIBUTE_ID, ARRAY, kFixedLabelAttribu DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); // Declare Cluster List for Bridged Light endpoint +// TODO: It's not clear whether it would be better to get the command lists from +// the ZAP config on our last fixed endpoint instead. +constexpr CommandId onOffIncomingCommands[] = { + app::Clusters::OnOff::Commands::Off::Id, + app::Clusters::OnOff::Commands::On::Id, + app::Clusters::OnOff::Commands::Toggle::Id, + app::Clusters::OnOff::Commands::OffWithEffect::Id, + app::Clusters::OnOff::Commands::OnWithRecallGlobalScene::Id, + app::Clusters::OnOff::Commands::OnWithTimedOff::Id, + kInvalidCommandId, +}; + DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedLightClusters) -DECLARE_DYNAMIC_CLUSTER(ZCL_ON_OFF_CLUSTER_ID, onOffAttrs), DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, descriptorAttrs), - DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, bridgedDeviceBasicAttrs), - DECLARE_DYNAMIC_CLUSTER(ZCL_FIXED_LABEL_CLUSTER_ID, fixedLabelAttrs) DECLARE_DYNAMIC_CLUSTER_LIST_END; +DECLARE_DYNAMIC_CLUSTER(ZCL_ON_OFF_CLUSTER_ID, onOffAttrs, onOffIncomingCommands, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, descriptorAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, bridgedDeviceBasicAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_FIXED_LABEL_CLUSTER_ID, fixedLabelAttrs, nullptr, nullptr), DECLARE_DYNAMIC_CLUSTER_LIST_END; // Declare Bridged Light endpoint DECLARE_DYNAMIC_ENDPOINT(bridgedLightEndpoint, bridgedLightClusters); @@ -166,10 +179,10 @@ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_LABEL_LIST_ATTRIBUTE_ID, ARRAY, kFixedLabelAttribu // Declare Cluster List for Bridged Switch endpoint DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedSwitchClusters) -DECLARE_DYNAMIC_CLUSTER(ZCL_SWITCH_CLUSTER_ID, switchAttrs), - DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, switchDescriptorAttrs), - DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, switchBridgedDeviceBasicAttrs), - DECLARE_DYNAMIC_CLUSTER(ZCL_FIXED_LABEL_CLUSTER_ID, switchFixedLabelAttrs) DECLARE_DYNAMIC_CLUSTER_LIST_END; +DECLARE_DYNAMIC_CLUSTER(ZCL_SWITCH_CLUSTER_ID, switchAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, switchDescriptorAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, switchBridgedDeviceBasicAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_FIXED_LABEL_CLUSTER_ID, switchFixedLabelAttrs, nullptr, nullptr) DECLARE_DYNAMIC_CLUSTER_LIST_END; // Declare Bridged Switch endpoint DECLARE_DYNAMIC_ENDPOINT(bridgedSwitchEndpoint, bridgedSwitchClusters); diff --git a/examples/tv-app/linux/AppImpl.cpp b/examples/tv-app/linux/AppImpl.cpp index a1af141d7ec959..9870636db1f33c 100644 --- a/examples/tv-app/linux/AppImpl.cpp +++ b/examples/tv-app/linux/AppImpl.cpp @@ -132,17 +132,94 @@ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CHANNEL_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttri DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CHANNEL_CURRENT_CHANNEL_ATTRIBUTE_ID, STRUCT, 1, 0), /* current channel */ DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); +constexpr CommandId keypadInputIncomingCommands[] = { + app::Clusters::KeypadInput::Commands::SendKeyRequest::Id, + kInvalidCommandId, +}; +constexpr CommandId keypadInputOutgoingCommands[] = { + app::Clusters::KeypadInput::Commands::SendKeyResponse::Id, + kInvalidCommandId, +}; +constexpr CommandId applicationLauncherIncomingCommands[] = { + app::Clusters::ApplicationLauncher::Commands::LaunchAppRequest::Id, + app::Clusters::ApplicationLauncher::Commands::StopAppRequest::Id, + app::Clusters::ApplicationLauncher::Commands::HideAppRequest::Id, + kInvalidCommandId, +}; +constexpr CommandId applicationLauncherOutgoingCommands[] = { + app::Clusters::ApplicationLauncher::Commands::LauncherResponse::Id, + kInvalidCommandId, +}; +constexpr CommandId accountLoginIncomingCommands[] = { + app::Clusters::AccountLogin::Commands::GetSetupPINRequest::Id, + app::Clusters::AccountLogin::Commands::LoginRequest::Id, + app::Clusters::AccountLogin::Commands::LogoutRequest::Id, + kInvalidCommandId, +}; +constexpr CommandId accountLoginOutgoingCommands[] = { + app::Clusters::AccountLogin::Commands::GetSetupPINResponse::Id, + kInvalidCommandId, +}; +// TODO: Sort out when the optional commands here should be listed. +constexpr CommandId contentLauncherIncomingCommands[] = { + app::Clusters::ContentLauncher::Commands::LaunchContentRequest::Id, + app::Clusters::ContentLauncher::Commands::LaunchURLRequest::Id, + kInvalidCommandId, +}; +constexpr CommandId contentLauncherOutgoingCommands[] = { + app::Clusters::ContentLauncher::Commands::LaunchResponse::Id, + kInvalidCommandId, +}; +// TODO: Sort out when the optional commands here should be listed. +constexpr CommandId mediaPlaybackIncomingCommands[] = { + app::Clusters::MediaPlayback::Commands::PlayRequest::Id, app::Clusters::MediaPlayback::Commands::PauseRequest::Id, + app::Clusters::MediaPlayback::Commands::StopRequest::Id, app::Clusters::MediaPlayback::Commands::StartOverRequest::Id, + app::Clusters::MediaPlayback::Commands::PreviousRequest::Id, app::Clusters::MediaPlayback::Commands::NextRequest::Id, + app::Clusters::MediaPlayback::Commands::RewindRequest::Id, app::Clusters::MediaPlayback::Commands::FastForwardRequest::Id, + app::Clusters::MediaPlayback::Commands::SkipForwardRequest::Id, app::Clusters::MediaPlayback::Commands::SkipBackwardRequest::Id, + app::Clusters::MediaPlayback::Commands::SeekRequest::Id, kInvalidCommandId, +}; +constexpr CommandId mediaPlaybackOutgoingCommands[] = { + app::Clusters::MediaPlayback::Commands::PlaybackResponse::Id, + kInvalidCommandId, +}; +constexpr CommandId targetNavigatorIncomingCommands[] = { + app::Clusters::TargetNavigator::Commands::NavigateTargetRequest::Id, + kInvalidCommandId, +}; +constexpr CommandId targetNavigatorOutgoingCommands[] = { + app::Clusters::TargetNavigator::Commands::NavigateTargetResponse::Id, + kInvalidCommandId, +}; +// TODO: Sort out when the optional commands here should be listed. +constexpr CommandId channelIncomingCommands[] = { + app::Clusters::Channel::Commands::ChangeChannelRequest::Id, + app::Clusters::Channel::Commands::ChangeChannelByNumberRequest::Id, + app::Clusters::Channel::Commands::SkipChannelRequest::Id, + kInvalidCommandId, +}; +constexpr CommandId channelOutgoingCommands[] = { + app::Clusters::Channel::Commands::ChangeChannelResponse::Id, + kInvalidCommandId, +}; // Declare Cluster List for Content App endpoint DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(contentAppClusters) -DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, descriptorAttrs), - DECLARE_DYNAMIC_CLUSTER(ZCL_APPLICATION_BASIC_CLUSTER_ID, applicationBasicAttrs), - DECLARE_DYNAMIC_CLUSTER(ZCL_KEYPAD_INPUT_CLUSTER_ID, keypadInputAttrs), - DECLARE_DYNAMIC_CLUSTER(ZCL_APPLICATION_LAUNCHER_CLUSTER_ID, applicationLauncherAttrs), - DECLARE_DYNAMIC_CLUSTER(ZCL_ACCOUNT_LOGIN_CLUSTER_ID, accountLoginAttrs), - DECLARE_DYNAMIC_CLUSTER(ZCL_CONTENT_LAUNCH_CLUSTER_ID, contentLauncherAttrs), - DECLARE_DYNAMIC_CLUSTER(ZCL_MEDIA_PLAYBACK_CLUSTER_ID, mediaPlaybackAttrs), - DECLARE_DYNAMIC_CLUSTER(ZCL_TARGET_NAVIGATOR_CLUSTER_ID, targetNavigatorAttrs), - DECLARE_DYNAMIC_CLUSTER(ZCL_CHANNEL_CLUSTER_ID, channelAttrs) DECLARE_DYNAMIC_CLUSTER_LIST_END; +DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, descriptorAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_APPLICATION_BASIC_CLUSTER_ID, applicationBasicAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_KEYPAD_INPUT_CLUSTER_ID, keypadInputAttrs, keypadInputIncomingCommands, + keypadInputOutgoingCommands), + DECLARE_DYNAMIC_CLUSTER(ZCL_APPLICATION_LAUNCHER_CLUSTER_ID, applicationLauncherAttrs, applicationLauncherIncomingCommands, + applicationLauncherOutgoingCommands), + DECLARE_DYNAMIC_CLUSTER(ZCL_ACCOUNT_LOGIN_CLUSTER_ID, accountLoginAttrs, accountLoginIncomingCommands, + accountLoginOutgoingCommands), + DECLARE_DYNAMIC_CLUSTER(ZCL_CONTENT_LAUNCH_CLUSTER_ID, contentLauncherAttrs, contentLauncherIncomingCommands, + contentLauncherOutgoingCommands), + DECLARE_DYNAMIC_CLUSTER(ZCL_MEDIA_PLAYBACK_CLUSTER_ID, mediaPlaybackAttrs, mediaPlaybackIncomingCommands, + mediaPlaybackOutgoingCommands), + DECLARE_DYNAMIC_CLUSTER(ZCL_TARGET_NAVIGATOR_CLUSTER_ID, targetNavigatorAttrs, targetNavigatorIncomingCommands, + targetNavigatorOutgoingCommands), + DECLARE_DYNAMIC_CLUSTER(ZCL_CHANNEL_CLUSTER_ID, channelAttrs, channelIncomingCommands, channelOutgoingCommands), + DECLARE_DYNAMIC_CLUSTER_LIST_END; // Declare Content App endpoint DECLARE_DYNAMIC_ENDPOINT(contentAppEndpoint, contentAppClusters); diff --git a/src/app/CommandHandler.cpp b/src/app/CommandHandler.cpp index 476a080c1c801e..e83b45a09dda1c 100644 --- a/src/app/CommandHandler.cpp +++ b/src/app/CommandHandler.cpp @@ -254,7 +254,18 @@ CHIP_ERROR CommandHandler::ProcessCommandDataIB(CommandDataIB::Parser & aCommand err = commandPath.GetEndpointId(&concretePath.mEndpointId); SuccessOrExit(err); - VerifyOrExit(mpCallback->CommandExists(concretePath), err = CHIP_ERROR_INVALID_PROFILE_ID); + using Protocols::InteractionModel::Status; + { + Status commandExists = mpCallback->CommandExists(concretePath); + if (commandExists != Status::Success) + { + ChipLogDetail(DataManagement, "No command " ChipLogFormatMEI " in Cluster " ChipLogFormatMEI " on Endpoint 0x%" PRIx16, + ChipLogValueMEI(concretePath.mCommandId), ChipLogValueMEI(concretePath.mClusterId), + concretePath.mEndpointId); + return AddStatus(concretePath, commandExists); + } + } + VerifyOrExit(mpExchangeCtx != nullptr && mpExchangeCtx->HasSessionHandle(), err = CHIP_ERROR_INCORRECT_STATE); { @@ -272,10 +283,10 @@ CHIP_ERROR CommandHandler::ProcessCommandDataIB(CommandDataIB::Parser & aCommand { if (err != CHIP_ERROR_ACCESS_DENIED) { - return AddStatus(concretePath, Protocols::InteractionModel::Status::Failure); + return AddStatus(concretePath, Status::Failure); } // TODO: when wildcard invokes are supported, handle them to discard rather than fail with status - return AddStatus(concretePath, Protocols::InteractionModel::Status::UnsupportedAccess); + return AddStatus(concretePath, Status::UnsupportedAccess); } } @@ -308,18 +319,7 @@ CHIP_ERROR CommandHandler::ProcessCommandDataIB(CommandDataIB::Parser & aCommand exit: if (err != CHIP_NO_ERROR) { - // The Path is the path in the request if there are any error occurred before we dispatch the command to clusters. - // Currently, it could be failed to decode Path or failed to find cluster / command on desired endpoint. - // TODO: The behavior when receiving a malformed message is not clear in the Spec. (Spec#3259) - // TODO: The error code should be updated after #7072 added error codes required by IM. - if (err == CHIP_ERROR_INVALID_PROFILE_ID) - { - ChipLogDetail(DataManagement, "No Cluster " ChipLogFormatMEI " on Endpoint 0x%" PRIx16, - ChipLogValueMEI(concretePath.mClusterId), concretePath.mEndpointId); - } - - // TODO:in particular different reasons for ServerClusterCommandExists to test false should result in different errors here - AddStatus(concretePath, Protocols::InteractionModel::Status::InvalidCommand); + return AddStatus(concretePath, Status::InvalidCommand); } // We have handled the error status above and put the error status in response, now return success status so we can process @@ -394,10 +394,10 @@ CHIP_ERROR CommandHandler::ProcessGroupCommandDataIB(CommandDataIB::Parser & aCo const ConcreteCommandPath concretePath(mapping.endpoint_id, clusterId, commandId); - if (!mpCallback->CommandExists(concretePath)) + if (mpCallback->CommandExists(concretePath) != Protocols::InteractionModel::Status::Success) { - ChipLogError(DataManagement, "No Cluster " ChipLogFormatMEI " on Endpoint 0x%" PRIx16, ChipLogValueMEI(clusterId), - mapping.endpoint_id); + ChipLogDetail(DataManagement, "No command " ChipLogFormatMEI " in Cluster " ChipLogFormatMEI " on Endpoint 0x%" PRIx16, + ChipLogValueMEI(mapping.endpoint_id), ChipLogValueMEI(clusterId), mapping.endpoint_id); continue; } diff --git a/src/app/CommandHandler.h b/src/app/CommandHandler.h index 690bc6e104f74d..bf4e3d52b51780 100644 --- a/src/app/CommandHandler.h +++ b/src/app/CommandHandler.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -74,9 +75,13 @@ class CommandHandler TLV::TLVReader & apPayload) = 0; /* - * Check to see if a command implementation exists for a specific concrete command path. + * Check to see if a command implementation exists for a specific + * concrete command path. If it does, Success will be returned. If + * not, one of UnsupportedEndpoint, UnsupportedCluster, or + * UnsupportedCommand will be returned, depending on how the command + * fails to exist. */ - virtual bool CommandExists(const ConcreteCommandPath & aCommandPath) = 0; + virtual Protocols::InteractionModel::Status CommandExists(const ConcreteCommandPath & aCommandPath) = 0; }; class Handle diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp index c283a5177cffab..b08db60763aa2f 100644 --- a/src/app/InteractionModelEngine.cpp +++ b/src/app/InteractionModelEngine.cpp @@ -596,7 +596,7 @@ void InteractionModelEngine::DispatchCommand(CommandHandler & apCommandObj, cons DispatchSingleClusterCommand(aCommandPath, apPayload, &apCommandObj); } -bool InteractionModelEngine::CommandExists(const ConcreteCommandPath & aCommandPath) +Protocols::InteractionModel::Status InteractionModelEngine::CommandExists(const ConcreteCommandPath & aCommandPath) { return ServerClusterCommandExists(aCommandPath); } diff --git a/src/app/InteractionModelEngine.h b/src/app/InteractionModelEngine.h index 41aa33db976a6b..c6b916fd8ba07b 100644 --- a/src/app/InteractionModelEngine.h +++ b/src/app/InteractionModelEngine.h @@ -272,7 +272,7 @@ class InteractionModelEngine : public Messaging::ExchangeDelegate, public Comman void DispatchCommand(CommandHandler & apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & apPayload) override; - bool CommandExists(const ConcreteCommandPath & aCommandPath) override; + Protocols::InteractionModel::Status CommandExists(const ConcreteCommandPath & aCommandPath) override; bool HasActiveRead(); @@ -305,16 +305,12 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, chip CommandHandler * apCommandObj); /** - * Check whether the given cluster exists on the given endpoint and supports the given command. - * TODO: The implementation lives in ember-compatibility-functions.cpp, this should be replaced by IM command catalog look up - * function after we have a cluster catalog in interaction model engine. - * TODO: The endpoint id on response command (client side command) is unclear, so we don't have a ClientClusterCommandExists - * function. (Spec#3258) - * - * @retval True if the endpoint contains the server side of the given cluster and that cluster implements the given command, false - * otherwise. + * Check whether the given cluster exists on the given endpoint and supports + * the given command. If it does, Success will be returned. If it does not, + * one of UnsupportedEndpoint, UnsupportedCluster, or UnsupportedCommand + * will be returned, depending on how the command fails to exist. */ -bool ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath); +Protocols::InteractionModel::Status ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath); /** * Fetch attribute value and version info and write to the AttributeReport provided. diff --git a/src/app/tests/TestCommandInteraction.cpp b/src/app/tests/TestCommandInteraction.cpp index c0a040d3968a27..cf8a78bf196919 100644 --- a/src/app/tests/TestCommandInteraction.cpp +++ b/src/app/tests/TestCommandInteraction.cpp @@ -45,6 +45,7 @@ #include using TestContext = chip::Test::AppContext; +using namespace chip::Protocols; namespace chip { @@ -65,11 +66,27 @@ namespace app { CommandHandler::Handle asyncCommandHandle; -bool ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath) +InteractionModel::Status ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath) { - // Mock cluster catalog, only support one command on one cluster on one endpoint. - return (aCommandPath.mEndpointId == kTestEndpointId && aCommandPath.mClusterId == kTestClusterId && - aCommandPath.mCommandId != kTestNonExistCommandId); + // Mock cluster catalog, only support commands on one cluster on one endpoint. + using InteractionModel::Status; + + if (aCommandPath.mEndpointId != kTestEndpointId) + { + return Status::UnsupportedEndpoint; + } + + if (aCommandPath.mClusterId != kTestClusterId) + { + return Status::UnsupportedCluster; + } + + if (aCommandPath.mCommandId == kTestNonExistCommandId) + { + return Status::UnsupportedCommand; + } + + return Status::Success; } void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, chip::TLV::TLVReader & aReader, @@ -142,7 +159,10 @@ class MockCommandHandlerCallback : public CommandHandler::Callback { DispatchSingleClusterCommand(aCommandPath, apPayload, &apCommandObj); } - bool CommandExists(const ConcreteCommandPath & aCommandPath) { return ServerClusterCommandExists(aCommandPath); } + InteractionModel::Status CommandExists(const ConcreteCommandPath & aCommandPath) + { + return ServerClusterCommandExists(aCommandPath); + } int onFinalCalledTimes = 0; } mockCommandHandlerDelegate; diff --git a/src/app/tests/integration/chip_im_initiator.cpp b/src/app/tests/integration/chip_im_initiator.cpp index 472948c1c3fb3f..7f700638a37e99 100644 --- a/src/app/tests/integration/chip_im_initiator.cpp +++ b/src/app/tests/integration/chip_im_initiator.cpp @@ -632,10 +632,10 @@ void SubscribeRequestTimerHandler(chip::System::Layer * systemLayer, void * appS namespace chip { namespace app { -bool ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath) +Protocols::InteractionModel::Status ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath) { - // Always return true in test. - return true; + // Always return success in test. + return Protocols::InteractionModel::Status::Success; } void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, chip::TLV::TLVReader & aReader, diff --git a/src/app/tests/integration/chip_im_responder.cpp b/src/app/tests/integration/chip_im_responder.cpp index a3d399e98ba8cc..c9d5e86c7b6eec 100644 --- a/src/app/tests/integration/chip_im_responder.cpp +++ b/src/app/tests/integration/chip_im_responder.cpp @@ -45,11 +45,27 @@ namespace chip { namespace app { -bool ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath) +Protocols::InteractionModel::Status ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath) { // The Mock cluster catalog -- only have one command on one cluster on one endpoint. - return (aCommandPath.mEndpointId == kTestEndpointId && aCommandPath.mClusterId == kTestClusterId && - aCommandPath.mCommandId == kTestCommandId); + using Protocols::InteractionModel::Status; + + if (aCommandPath.mEndpointId != kTestEndpointId) + { + return Status::UnsupportedEndpoint; + } + + if (aCommandPath.mClusterId != kTestClusterId) + { + return Status::UnsupportedCluster; + } + + if (aCommandPath.mCommandId != kTestCommandId) + { + return Status::UnsupportedCommand; + } + + return Status::Success; } void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, chip::TLV::TLVReader & aReader, @@ -57,7 +73,7 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, chip { static bool statusCodeFlipper = false; - if (!ServerClusterCommandExists(aCommandPath)) + if (ServerClusterCommandExists(aCommandPath) != Protocols::InteractionModel::Status::Success) { return; } diff --git a/src/app/tests/suites/TestCluster.yaml b/src/app/tests/suites/TestCluster.yaml index 285e56fbaccdb8..545305a6afb74b 100644 --- a/src/app/tests/suites/TestCluster.yaml +++ b/src/app/tests/suites/TestCluster.yaml @@ -954,17 +954,13 @@ tests: command: "test" endpoint: 200 response: - # No such endpoint, so expect an error. - # SDK returning wrong error code here so far. - errorWrongValue: UNSUPPORTED_ENDPOINT + error: UNSUPPORTED_ENDPOINT - label: "Send Test Command to unsupported cluster" command: "test" endpoint: 0 response: - # No TestCluster on that, so expect an error. - # SDK returning wrong error code here so far. - errorWrongValue: UNSUPPORTED_CLUSTER + error: UNSUPPORTED_CLUSTER # Tests for vendor id @@ -2838,16 +2834,14 @@ tests: command: "readAttribute" attribute: "list_int8u" response: - # SDK returning wrong error code here so far. - errorWrongValue: UNSUPPORTED_ENDPOINT + error: UNSUPPORTED_ENDPOINT - label: "Read attribute from nonexistent cluster." endpoint: 0 command: "readAttribute" attribute: "list_int8u" response: - # SDK returning wrong error code here so far. - errorWrongValue: UNSUPPORTED_CLUSTER + error: UNSUPPORTED_CLUSTER # Tests for command with optional arguments - label: diff --git a/src/app/tests/suites/certification/Test_TC_SWDIAG_1_1.yaml b/src/app/tests/suites/certification/Test_TC_SWDIAG_1_1.yaml index dcbccd4cdf2ca2..ae45e8cea85052 100644 --- a/src/app/tests/suites/certification/Test_TC_SWDIAG_1_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_SWDIAG_1_1.yaml @@ -16,18 +16,15 @@ name: 45.1.1. [TC-SWDIAG-1.1] Attributes with server as DUT config: cluster: "Software Diagnostics" - endpoint: 1 + endpoint: 0 tests: - label: "Wait for the commissioned device to be retrieved" cluster: "DelayCommands" command: "WaitForCommissionee" - #Issue #11185 Disabled as ThreadMetrics attribute missing - #disabled due to issue #13441 - label: "Reads a list of ThreadMetrics struct non-global attribute from DUT." - disabled: true command: "readAttribute" attribute: "ThreadMetrics" PICS: A_THREADMETRICS diff --git a/src/app/tests/suites/certification/Test_TC_SWDIAG_2_1.yaml b/src/app/tests/suites/certification/Test_TC_SWDIAG_2_1.yaml index 159935ef59a7ef..70c0fa0ba2ce9a 100644 --- a/src/app/tests/suites/certification/Test_TC_SWDIAG_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_SWDIAG_2_1.yaml @@ -16,7 +16,7 @@ name: 45.1.3. [TC-SWDIAG-2.1] Event functionality with server as DUT config: cluster: "Software Diagnostics" - endpoint: 1 + endpoint: 0 tests: #issue #11725 Reading the List is not implemented in YAML framework diff --git a/src/app/tests/suites/certification/Test_TC_SWDIAG_3_1.yaml b/src/app/tests/suites/certification/Test_TC_SWDIAG_3_1.yaml index 5444450d919801..a7149d134902a7 100644 --- a/src/app/tests/suites/certification/Test_TC_SWDIAG_3_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_SWDIAG_3_1.yaml @@ -16,27 +16,25 @@ name: 45.1.4. [TC-SWDIAG-3.1] Command received functionality with server as DUT config: cluster: "Software Diagnostics" - endpoint: 1 + endpoint: 0 tests: - label: "Wait for the commissioned device to be retrieved" cluster: "DelayCommands" command: "WaitForCommissionee" - #issue #11578 ResetWatermarks command is Failing - label: "Sends ResetWatermarks to DUT" - disabled: true command: "ResetWatermarks" PICS: CR_RESETWATERMARKS - #Disabled due to issue #13441 - label: "Reads a list of ThreadMetrics struct attribute from DUT." disabled: true command: "readAttribute" attribute: "ThreadMetrics" PICS: A_THREADMETRICS response: - value: 0 + # TODO: Say something about the values? + value: {} - label: "Reads CurrentHeapUsed attribute value from DUT" optional: true diff --git a/src/app/tests/suites/certification/Test_TC_WIFIDIAG_1_1.yaml b/src/app/tests/suites/certification/Test_TC_WIFIDIAG_1_1.yaml index 6258d1750d4ac3..e2c0f53419a22b 100644 --- a/src/app/tests/suites/certification/Test_TC_WIFIDIAG_1_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_WIFIDIAG_1_1.yaml @@ -16,16 +16,14 @@ name: 54.1.1. [TC-WIFIDIAG-1.1] Attributes with server as DUT config: cluster: "WiFi Network Diagnostics" - endpoint: 1 + endpoint: 0 tests: - label: "Wait for the commissioned device to be retrieved" cluster: "DelayCommands" command: "WaitForCommissionee" - #Below steps disabled due to issue #13645 and 11670 - label: "Reads NetworkInterface structure attribute from DUT" - disabled: true cluster: "General Diagnostics" command: "readAttribute" attribute: "NetworkInterfaces" @@ -33,6 +31,9 @@ tests: constraints: type: list + # Various tests disabled for now until + # https://github.com/project-chip/connectedhomeip/pull/14755 is + # fixed and the SDK has the right types. - label: "Reads SecurityType attribute from DUT" disabled: true command: "readAttribute" @@ -185,14 +186,18 @@ tests: constraints: type: uint32 + # Disabled because this fails on Linux because we have no Wi-Fi interface. - label: "Reads CurrentMaxRate attribute from DUT" + disabled: true optional: true command: "readAttribute" attribute: "CurrentMaxRate" response: value: 0 + # Disabled because this fails on Linux because we have no Wi-Fi interface. - label: "Reads CurrentMaxRate attribute constraints" + disabled: true optional: true command: "readAttribute" attribute: "CurrentMaxRate" diff --git a/src/app/tests/suites/certification/Test_TC_WIFIDIAG_3_1.yaml b/src/app/tests/suites/certification/Test_TC_WIFIDIAG_3_1.yaml index ba69ea1d0917c7..337c939846ecf5 100644 --- a/src/app/tests/suites/certification/Test_TC_WIFIDIAG_3_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_WIFIDIAG_3_1.yaml @@ -17,7 +17,7 @@ name: config: cluster: "WiFi Network Diagnostics" - endpoint: 1 + endpoint: 0 tests: - label: "Wait for the commissioned device to be retrieved" @@ -25,6 +25,8 @@ tests: command: "WaitForCommissionee" #Below steps disabled due to issue #13645 + # Also, ResetCounts may not work on some platforms yet? + # And on Linux since we don't have actual Wi-Fi these error out. - label: "TH sends ResetCounts command to DUT" disabled: true command: "ResetCounts" diff --git a/src/app/util/af.h b/src/app/util/af.h index 60bd133994eec1..84e76f7147e713 100644 --- a/src/app/util/af.h +++ b/src/app/util/af.h @@ -286,12 +286,14 @@ extern EmberAfDefinedEndpoint emAfEndpoints[]; chip::EndpointId emberAfEndpointFromIndex(uint16_t index); /** - * Returns the index of a given endpoint + * Returns the index of a given endpoint. Will return 0xFFFF if this is not a + * valid endpoint id or if the endpoint is disabled. */ uint16_t emberAfIndexFromEndpoint(chip::EndpointId endpoint); /** - * Returns the index of a given endpoint; Does not ignore disabled endpoints + * Returns the index of a given endpoint; Does not ignore disabled endpoints. + * Will return 0xFFFF if this is not a valid endpoint id. */ uint16_t emberAfIndexFromEndpointIncludingDisabledEndpoints(chip::EndpointId endpoint); diff --git a/src/app/util/attribute-storage.cpp b/src/app/util/attribute-storage.cpp index 1b8180dc9f64c5..61fdb72285c2f3 100644 --- a/src/app/util/attribute-storage.cpp +++ b/src/app/util/attribute-storage.cpp @@ -662,6 +662,16 @@ EmberAfStatus emAfReadOrWriteAttribute(EmberAfAttributeSearchRecord * attRecord, return EMBER_ZCL_STATUS_UNSUPPORTED_ATTRIBUTE; // Sorry, attribute was not found. } +const EmberAfEndpointType * emberAfFindEndpointType(chip::EndpointId endpointId) +{ + uint16_t ep = emberAfIndexFromEndpoint(endpointId); + if (ep == 0xFFFF) + { + return nullptr; + } + return emAfEndpoints[ep].endpointType; +} + const EmberAfCluster * emberAfFindClusterInType(const EmberAfEndpointType * endpointType, ClusterId clusterId, EmberAfClusterMask mask, uint8_t * index) { diff --git a/src/app/util/attribute-storage.h b/src/app/util/attribute-storage.h index 1ae15547871cb1..6a4e4d079a4ab1 100644 --- a/src/app/util/attribute-storage.h +++ b/src/app/util/attribute-storage.h @@ -78,9 +78,10 @@ #define DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(clusterListName) EmberAfCluster clusterListName[] = { -#define DECLARE_DYNAMIC_CLUSTER(clusterId, clusterAttrs) \ +#define DECLARE_DYNAMIC_CLUSTER(clusterId, clusterAttrs, incomingCommands, outgoingCommands) \ { \ - clusterId, clusterAttrs, sizeof(clusterAttrs) / sizeof(EmberAfAttributeMetadata), 0, ZAP_CLUSTER_MASK(SERVER), NULL \ + clusterId, clusterAttrs, sizeof(clusterAttrs) / sizeof(EmberAfAttributeMetadata), 0, ZAP_CLUSTER_MASK(SERVER), NULL, \ + incomingCommands, outgoingCommands \ } #define DECLARE_DYNAMIC_CLUSTER_LIST_END } @@ -128,6 +129,10 @@ bool emAfMatchCluster(const EmberAfCluster * cluster, EmberAfAttributeSearchReco bool emAfMatchAttribute(const EmberAfCluster * cluster, const EmberAfAttributeMetadata * am, EmberAfAttributeSearchRecord * attRecord); +// Returns endpoint type for the given endpoint id if there is an enabled +// endpoint with that endpoint id. Otherwise returns null. +const EmberAfEndpointType * emberAfFindEndpointType(chip::EndpointId endpointId); + // Check if a cluster is implemented or not. If yes, the cluster is returned. // // mask = 0 -> find either client or server diff --git a/src/app/util/ember-compatibility-functions.cpp b/src/app/util/ember-compatibility-functions.cpp index d8ece370e6e47b..f2b39780d5e003 100644 --- a/src/app/util/ember-compatibility-functions.cpp +++ b/src/app/util/ember-compatibility-functions.cpp @@ -247,11 +247,31 @@ CHIP_ERROR attributeBufferToNumericTlvData(TLV::TLVWriter & writer, bool isNulla } // anonymous namespace -bool ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath) +Protocols::InteractionModel::Status ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath) { - // TODO: Currently, we are using cluster catalog from the ember library, this should be modified or replaced after several - // updates to Commands. - return emberAfContainsServer(aCommandPath.mEndpointId, aCommandPath.mClusterId); + using Protocols::InteractionModel::Status; + + const EmberAfEndpointType * type = emberAfFindEndpointType(aCommandPath.mEndpointId); + if (type == nullptr) + { + return Status::UnsupportedEndpoint; + } + + const EmberAfCluster * cluster = emberAfFindClusterInType(type, aCommandPath.mClusterId, CLUSTER_MASK_SERVER); + if (cluster == nullptr) + { + return Status::UnsupportedCluster; + } + + for (const CommandId * cmd = cluster->clientGeneratedCommandList; cmd != nullptr; cmd++) + { + if (*cmd == aCommandPath.mCommandId) + { + return Status::Success; + } + } + + return Status::UnsupportedCommand; } namespace { @@ -403,6 +423,30 @@ CHIP_ERROR ReadViaAccessInterface(FabricIndex aAccessingFabricIndex, bool aIsFab return CHIP_NO_ERROR; } +// Determine the appropriate status response for an unsupported attribute for +// the given path. Must be called when the attribute is known to be unsupported +// (i.e. we found no attribute metadata for it). +Protocols::InteractionModel::Status UnsupportedAttributeStatus(const ConcreteAttributePath & aPath) +{ + using Protocols::InteractionModel::Status; + + const EmberAfEndpointType * type = emberAfFindEndpointType(aPath.mEndpointId); + if (type == nullptr) + { + return Status::UnsupportedEndpoint; + } + + const EmberAfCluster * cluster = emberAfFindClusterInType(type, aPath.mClusterId, CLUSTER_MASK_SERVER); + if (cluster == nullptr) + { + return Status::UnsupportedCluster; + } + + // Since we know the attribute is unsupported and the endpoint/cluster are + // OK, this is the only option left. + return Status::UnsupportedAttribute; +} + } // anonymous namespace CHIP_ERROR ReadSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, bool aIsFabricFiltered, @@ -436,7 +480,7 @@ CHIP_ERROR ReadSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, b if (attributeCluster == nullptr && attributeMetadata == nullptr) { - return SendFailureStatus(aPath, aAttributeReports, Protocols::InteractionModel::Status::UnsupportedAttribute, nullptr); + return SendFailureStatus(aPath, aAttributeReports, UnsupportedAttributeStatus(aPath), nullptr); } // Check access control. A failed check will disallow the operation, and may or may not generate an attribute report @@ -873,7 +917,7 @@ CHIP_ERROR WriteSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, if (attributeMetadata == nullptr) { - return apWriteHandler->AddStatus(aPath, Protocols::InteractionModel::Status::UnsupportedAttribute); + return apWriteHandler->AddStatus(aPath, UnsupportedAttributeStatus(aPath)); } if (attributeMetadata->IsReadOnly()) diff --git a/src/controller/tests/TestReadChunking.cpp b/src/controller/tests/TestReadChunking.cpp index 9304e24c8039c8..d704e16fb94f5e 100644 --- a/src/controller/tests/TestReadChunking.cpp +++ b/src/controller/tests/TestReadChunking.cpp @@ -75,7 +75,7 @@ DECLARE_DYNAMIC_ATTRIBUTE(0x00000001, INT8U, 1, 0), DECLARE_DYNAMIC_ATTRIBUTE(0x DECLARE_DYNAMIC_ATTRIBUTE(0x00000005, INT8U, 1, 0), DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(testEndpointClusters) -DECLARE_DYNAMIC_CLUSTER(TestCluster::Id, testClusterAttrs), DECLARE_DYNAMIC_CLUSTER_LIST_END; +DECLARE_DYNAMIC_CLUSTER(TestCluster::Id, testClusterAttrs, nullptr, nullptr), DECLARE_DYNAMIC_CLUSTER_LIST_END; DECLARE_DYNAMIC_ENDPOINT(testEndpoint, testEndpointClusters); @@ -84,7 +84,7 @@ DECLARE_DYNAMIC_ATTRIBUTE(kTestListAttribute, ARRAY, 1, 0), DECLARE_DYNAMIC_ATTR DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(testEndpoint3Clusters) -DECLARE_DYNAMIC_CLUSTER(TestCluster::Id, testClusterAttrsOnEndpoint3), DECLARE_DYNAMIC_CLUSTER_LIST_END; +DECLARE_DYNAMIC_CLUSTER(TestCluster::Id, testClusterAttrsOnEndpoint3, nullptr, nullptr), DECLARE_DYNAMIC_CLUSTER_LIST_END; DECLARE_DYNAMIC_ENDPOINT(testEndpoint3, testEndpoint3Clusters); diff --git a/src/controller/tests/TestServerCommandDispatch.cpp b/src/controller/tests/TestServerCommandDispatch.cpp index f094f717b65ac7..a6515ddd7f6551 100644 --- a/src/controller/tests/TestServerCommandDispatch.cpp +++ b/src/controller/tests/TestServerCommandDispatch.cpp @@ -144,7 +144,8 @@ void TestCommandInteraction::TestNoHandler(nlTestSuite * apSuite, void * apConte // not safe to do so. auto onFailureCb = [apSuite](CHIP_ERROR aError) { NL_TEST_ASSERT(apSuite, - aError.IsIMStatus() && app::StatusIB(aError).mStatus == Protocols::InteractionModel::Status::InvalidCommand); + aError.IsIMStatus() && + app::StatusIB(aError).mStatus == Protocols::InteractionModel::Status::UnsupportedEndpoint); }; responseDirective = kSendDataResponse; @@ -176,9 +177,14 @@ DECLARE_DYNAMIC_ATTRIBUTE(chip::app::Clusters::Descriptor::Attributes::DeviceLis DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(testClusterAttrs) DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); +constexpr CommandId testClusterCommands[] = { + TestCluster::Commands::TestSimpleArgumentRequest::Id, + kInvalidCommandId, +}; DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(testEndpointClusters) -DECLARE_DYNAMIC_CLUSTER(chip::app::Clusters::TestCluster::Id, testClusterAttrs), - DECLARE_DYNAMIC_CLUSTER(chip::app::Clusters::Descriptor::Id, descriptorAttrs), DECLARE_DYNAMIC_CLUSTER_LIST_END; +DECLARE_DYNAMIC_CLUSTER(chip::app::Clusters::TestCluster::Id, testClusterAttrs, testClusterCommands, nullptr), + DECLARE_DYNAMIC_CLUSTER(chip::app::Clusters::Descriptor::Id, descriptorAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER_LIST_END; DECLARE_DYNAMIC_ENDPOINT(testEndpoint, testEndpointClusters); diff --git a/src/controller/tests/data_model/TestCommands.cpp b/src/controller/tests/data_model/TestCommands.cpp index c4bc3ba4881c87..d13f08f83faabd 100644 --- a/src/controller/tests/data_model/TestCommands.cpp +++ b/src/controller/tests/data_model/TestCommands.cpp @@ -36,12 +36,14 @@ #include #include #include +#include using TestContext = chip::Test::AppContext; using namespace chip; using namespace chip::app; using namespace chip::app::Clusters; +using namespace chip::Protocols; namespace { chip::ClusterStatus kTestSuccessClusterStatus = 1; @@ -129,10 +131,22 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, chip } } -bool ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath) +InteractionModel::Status ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath) { - // Mock cluster catalog, only support one command on one cluster on one endpoint. - return (aCommandPath.mEndpointId == kTestEndpointId && aCommandPath.mClusterId == TestCluster::Id); + // Mock cluster catalog, only support commands on one cluster on one endpoint. + using InteractionModel::Status; + + if (aCommandPath.mEndpointId != kTestEndpointId) + { + return Status::UnsupportedEndpoint; + } + + if (aCommandPath.mClusterId != TestCluster::Id) + { + return Status::UnsupportedCluster; + } + + return Status::Success; } CHIP_ERROR ReadSingleClusterData(const Access::SubjectDescriptor & aSubjectDescriptor, bool aIsFabricFiltered, diff --git a/src/controller/tests/data_model/TestRead.cpp b/src/controller/tests/data_model/TestRead.cpp index 6082280c2f0106..cbf8e5ddd550ec 100644 --- a/src/controller/tests/data_model/TestRead.cpp +++ b/src/controller/tests/data_model/TestRead.cpp @@ -25,11 +25,13 @@ #include #include #include +#include using TestContext = chip::Test::AppContext; using namespace chip; using namespace chip::app::Clusters; +using namespace chip::Protocols; namespace { @@ -52,10 +54,22 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, chip CommandHandler * apCommandObj) {} -bool ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath) +InteractionModel::Status ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath) { - // Mock cluster catalog, only support one command on one cluster on one endpoint. - return (aCommandPath.mEndpointId == kTestEndpointId && aCommandPath.mClusterId == TestCluster::Id); + // Mock cluster catalog, only support commands on one cluster on one endpoint. + using InteractionModel::Status; + + if (aCommandPath.mEndpointId != kTestEndpointId) + { + return Status::UnsupportedEndpoint; + } + + if (aCommandPath.mClusterId != TestCluster::Id) + { + return Status::UnsupportedCluster; + } + + return Status::Success; } CHIP_ERROR ReadSingleClusterData(const Access::SubjectDescriptor & aSubjectDescriptor, bool aIsFabricFiltered, diff --git a/src/controller/tests/data_model/TestWrite.cpp b/src/controller/tests/data_model/TestWrite.cpp index 274948956792f7..be60e8317add34 100644 --- a/src/controller/tests/data_model/TestWrite.cpp +++ b/src/controller/tests/data_model/TestWrite.cpp @@ -26,11 +26,13 @@ #include #include #include +#include using TestContext = chip::Test::AppContext; using namespace chip; using namespace chip::app::Clusters; +using namespace chip::Protocols; namespace { @@ -53,10 +55,22 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, chip CommandHandler * apCommandObj) {} -bool ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath) +InteractionModel::Status ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath) { - // Mock cluster catalog, only support one command on one cluster on one endpoint. - return (aCommandPath.mEndpointId == kTestEndpointId && aCommandPath.mClusterId == TestCluster::Id); + // Mock cluster catalog, only support commands on one cluster on one endpoint. + using InteractionModel::Status; + + if (aCommandPath.mEndpointId != kTestEndpointId) + { + return Status::UnsupportedEndpoint; + } + + if (aCommandPath.mClusterId != TestCluster::Id) + { + return Status::UnsupportedCluster; + } + + return Status::Success; } CHIP_ERROR ReadSingleClusterData(const Access::SubjectDescriptor & aSubjectDescriptor, bool aIsFabricFiltered, diff --git a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m index bb4439fdd94179..015bab228debb2 100644 --- a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m +++ b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m @@ -23207,53 +23207,15 @@ - (void)testSendClusterTest_TC_WIFIDIAG_1_1_000000_WaitForCommissionee } - (void)testSendClusterTest_TC_WIFIDIAG_1_1_000001_ReadAttribute { - XCTestExpectation * expectation = [self expectationWithDescription:@"Reads CurrentMaxRate attribute from DUT"]; + XCTestExpectation * expectation = [self expectationWithDescription:@"Reads NetworkInterface structure attribute from DUT"]; CHIPDevice * device = GetConnectedDevice(); dispatch_queue_t queue = dispatch_get_main_queue(); - CHIPTestWiFiNetworkDiagnostics * cluster = [[CHIPTestWiFiNetworkDiagnostics alloc] initWithDevice:device - endpoint:1 - queue:queue]; - XCTAssertNotNil(cluster); - - [cluster readAttributeCurrentMaxRateWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { - NSLog(@"Reads CurrentMaxRate attribute from DUT Error: %@", err); - - if (err.code == CHIPErrorCodeUnsupportedAttribute) { - [expectation fulfill]; - return; - } - - XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], 0); - - { - id actualValue = value; - XCTAssertEqual([actualValue unsignedLongLongValue], 0ULL); - } - - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; -} -- (void)testSendClusterTest_TC_WIFIDIAG_1_1_000002_ReadAttribute -{ - XCTestExpectation * expectation = [self expectationWithDescription:@"Reads CurrentMaxRate attribute constraints"]; - - CHIPDevice * device = GetConnectedDevice(); - dispatch_queue_t queue = dispatch_get_main_queue(); - CHIPTestWiFiNetworkDiagnostics * cluster = [[CHIPTestWiFiNetworkDiagnostics alloc] initWithDevice:device - endpoint:1 - queue:queue]; + CHIPTestGeneralDiagnostics * cluster = [[CHIPTestGeneralDiagnostics alloc] initWithDevice:device endpoint:0 queue:queue]; XCTAssertNotNil(cluster); - [cluster readAttributeCurrentMaxRateWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { - NSLog(@"Reads CurrentMaxRate attribute constraints Error: %@", err); - - if (err.code == CHIPErrorCodeUnsupportedAttribute) { - [expectation fulfill]; - return; - } + [cluster readAttributeNetworkInterfacesWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable err) { + NSLog(@"Reads NetworkInterface structure attribute from DUT Error: %@", err); XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], 0); @@ -28764,7 +28726,7 @@ - (void)testSendClusterTestCluster_000144_Test [cluster testWithCompletionHandler:^(NSError * _Nullable err) { NSLog(@"Send Test Command to unsupported endpoint Error: %@", err); - XCTAssertNotEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], 0); + XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], EMBER_ZCL_STATUS_UNSUPPORTED_ENDPOINT); [expectation fulfill]; }]; @@ -28782,7 +28744,7 @@ - (void)testSendClusterTestCluster_000145_Test [cluster testWithCompletionHandler:^(NSError * _Nullable err) { NSLog(@"Send Test Command to unsupported cluster Error: %@", err); - XCTAssertNotEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], 0); + XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], EMBER_ZCL_STATUS_UNSUPPORTED_CLUSTER); [expectation fulfill]; }]; @@ -34622,7 +34584,7 @@ - (void)testSendClusterTestCluster_000360_ReadAttribute [cluster readAttributeListInt8uWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable err) { NSLog(@"Read attribute from nonexistent endpoint. Error: %@", err); - XCTAssertNotEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], 0); + XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], EMBER_ZCL_STATUS_UNSUPPORTED_ENDPOINT); [expectation fulfill]; }]; @@ -34640,7 +34602,7 @@ - (void)testSendClusterTestCluster_000361_ReadAttribute [cluster readAttributeListInt8uWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable err) { NSLog(@"Read attribute from nonexistent cluster. Error: %@", err); - XCTAssertNotEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], 0); + XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], EMBER_ZCL_STATUS_UNSUPPORTED_CLUSTER); [expectation fulfill]; }]; @@ -42566,13 +42528,33 @@ - (void)testSendClusterTest_TC_SWDIAG_1_1_000000_WaitForCommissionee [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; } - (void)testSendClusterTest_TC_SWDIAG_1_1_000001_ReadAttribute +{ + XCTestExpectation * expectation = + [self expectationWithDescription:@"Reads a list of ThreadMetrics struct non-global attribute from DUT."]; + + CHIPDevice * device = GetConnectedDevice(); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPTestSoftwareDiagnostics * cluster = [[CHIPTestSoftwareDiagnostics alloc] initWithDevice:device endpoint:0 queue:queue]; + XCTAssertNotNil(cluster); + + [cluster readAttributeThreadMetricsWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable err) { + NSLog(@"Reads a list of ThreadMetrics struct non-global attribute from DUT. Error: %@", err); + + XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], 0); + + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} +- (void)testSendClusterTest_TC_SWDIAG_1_1_000002_ReadAttribute { XCTestExpectation * expectation = [self expectationWithDescription:@"Reads CurrentHeapFree non-global attribute value from DUT"]; CHIPDevice * device = GetConnectedDevice(); dispatch_queue_t queue = dispatch_get_main_queue(); - CHIPTestSoftwareDiagnostics * cluster = [[CHIPTestSoftwareDiagnostics alloc] initWithDevice:device endpoint:1 queue:queue]; + CHIPTestSoftwareDiagnostics * cluster = [[CHIPTestSoftwareDiagnostics alloc] initWithDevice:device endpoint:0 queue:queue]; XCTAssertNotNil(cluster); [cluster readAttributeCurrentHeapFreeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { @@ -42590,14 +42572,14 @@ - (void)testSendClusterTest_TC_SWDIAG_1_1_000001_ReadAttribute [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; } -- (void)testSendClusterTest_TC_SWDIAG_1_1_000002_ReadAttribute +- (void)testSendClusterTest_TC_SWDIAG_1_1_000003_ReadAttribute { XCTestExpectation * expectation = [self expectationWithDescription:@"Reads CurrentHeapUsed non-global attribute value from DUT"]; CHIPDevice * device = GetConnectedDevice(); dispatch_queue_t queue = dispatch_get_main_queue(); - CHIPTestSoftwareDiagnostics * cluster = [[CHIPTestSoftwareDiagnostics alloc] initWithDevice:device endpoint:1 queue:queue]; + CHIPTestSoftwareDiagnostics * cluster = [[CHIPTestSoftwareDiagnostics alloc] initWithDevice:device endpoint:0 queue:queue]; XCTAssertNotNil(cluster); [cluster readAttributeCurrentHeapUsedWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { @@ -42615,14 +42597,14 @@ - (void)testSendClusterTest_TC_SWDIAG_1_1_000002_ReadAttribute [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; } -- (void)testSendClusterTest_TC_SWDIAG_1_1_000003_ReadAttribute +- (void)testSendClusterTest_TC_SWDIAG_1_1_000004_ReadAttribute { XCTestExpectation * expectation = [self expectationWithDescription:@"Reads CurrentHeapHighWaterMark non-global attribute value from DUT"]; CHIPDevice * device = GetConnectedDevice(); dispatch_queue_t queue = dispatch_get_main_queue(); - CHIPTestSoftwareDiagnostics * cluster = [[CHIPTestSoftwareDiagnostics alloc] initWithDevice:device endpoint:1 queue:queue]; + CHIPTestSoftwareDiagnostics * cluster = [[CHIPTestSoftwareDiagnostics alloc] initWithDevice:device endpoint:0 queue:queue]; XCTAssertNotNil(cluster); [cluster readAttributeCurrentHeapHighWatermarkWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { @@ -42649,13 +42631,32 @@ - (void)testSendClusterTest_TC_SWDIAG_3_1_000000_WaitForCommissionee WaitForCommissionee(expectation, queue); [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; } -- (void)testSendClusterTest_TC_SWDIAG_3_1_000001_ReadAttribute +- (void)testSendClusterTest_TC_SWDIAG_3_1_000001_ResetWatermarks +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Sends ResetWatermarks to DUT"]; + + CHIPDevice * device = GetConnectedDevice(); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPTestSoftwareDiagnostics * cluster = [[CHIPTestSoftwareDiagnostics alloc] initWithDevice:device endpoint:0 queue:queue]; + XCTAssertNotNil(cluster); + + [cluster resetWatermarksWithCompletionHandler:^(NSError * _Nullable err) { + NSLog(@"Sends ResetWatermarks to DUT Error: %@", err); + + XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], 0); + + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} +- (void)testSendClusterTest_TC_SWDIAG_3_1_000002_ReadAttribute { XCTestExpectation * expectation = [self expectationWithDescription:@"Reads CurrentHeapUsed attribute value from DUT"]; CHIPDevice * device = GetConnectedDevice(); dispatch_queue_t queue = dispatch_get_main_queue(); - CHIPTestSoftwareDiagnostics * cluster = [[CHIPTestSoftwareDiagnostics alloc] initWithDevice:device endpoint:1 queue:queue]; + CHIPTestSoftwareDiagnostics * cluster = [[CHIPTestSoftwareDiagnostics alloc] initWithDevice:device endpoint:0 queue:queue]; XCTAssertNotNil(cluster); [cluster readAttributeCurrentHeapUsedWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { @@ -42678,13 +42679,13 @@ - (void)testSendClusterTest_TC_SWDIAG_3_1_000001_ReadAttribute [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; } -- (void)testSendClusterTest_TC_SWDIAG_3_1_000002_ReadAttribute +- (void)testSendClusterTest_TC_SWDIAG_3_1_000003_ReadAttribute { XCTestExpectation * expectation = [self expectationWithDescription:@"Reads CurrentHeapHighWaterMark attribute value from DUT"]; CHIPDevice * device = GetConnectedDevice(); dispatch_queue_t queue = dispatch_get_main_queue(); - CHIPTestSoftwareDiagnostics * cluster = [[CHIPTestSoftwareDiagnostics alloc] initWithDevice:device endpoint:1 queue:queue]; + CHIPTestSoftwareDiagnostics * cluster = [[CHIPTestSoftwareDiagnostics alloc] initWithDevice:device endpoint:0 queue:queue]; XCTAssertNotNil(cluster); [cluster readAttributeCurrentHeapHighWatermarkWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { diff --git a/src/test_driver/linux-cirque/MobileDeviceTest.py b/src/test_driver/linux-cirque/MobileDeviceTest.py index ac95881b8e41cd..20fb5022a9cb98 100755 --- a/src/test_driver/linux-cirque/MobileDeviceTest.py +++ b/src/test_driver/linux-cirque/MobileDeviceTest.py @@ -118,7 +118,7 @@ def run_controller_test(self): "Toggle on/off from 0 to 1", "Received command for Endpoint=1 Cluster=0x0000_0006 Command=0x0000_0000", "Toggle on/off from 1 to 0", - "No Cluster 0x0000_0006 on Endpoint 0xe9"]), + "No command 0x0000_0001 in Cluster 0x0000_0006 on Endpoint 0xe9"]), "Datamodel test failed: cannot find matching string from device {}".format(device_id)) diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h index 3dce5ddec4cd69..69344067e3912f 100644 --- a/zzz_generated/chip-tool/zap-generated/test/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h @@ -40758,12 +40758,8 @@ class Test_TC_WIFIDIAG_1_1 : public TestCommand err = TestWaitForTheCommissionedDeviceToBeRetrieved_0(); break; case 1: - ChipLogProgress(chipTool, " ***** Test Step 1 : Reads CurrentMaxRate attribute from DUT\n"); - err = TestReadsCurrentMaxRateAttributeFromDut_1(); - break; - case 2: - ChipLogProgress(chipTool, " ***** Test Step 2 : Reads CurrentMaxRate attribute constraints\n"); - err = TestReadsCurrentMaxRateAttributeConstraints_2(); + ChipLogProgress(chipTool, " ***** Test Step 1 : Reads NetworkInterface structure attribute from DUT\n"); + err = TestReadsNetworkInterfaceStructureAttributeFromDut_1(); break; } @@ -40776,7 +40772,7 @@ class Test_TC_WIFIDIAG_1_1 : public TestCommand private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 3; + const uint16_t mTestCount = 2; chip::Optional mCluster; chip::Optional mEndpoint; @@ -40786,19 +40782,12 @@ class Test_TC_WIFIDIAG_1_1 : public TestCommand (static_cast(context))->OnFailureResponse_1(error); } - static void OnSuccessCallback_1(void * context, uint64_t currentMaxRate) - { - (static_cast(context))->OnSuccessResponse_1(currentMaxRate); - } - - static void OnFailureCallback_2(void * context, CHIP_ERROR error) - { - (static_cast(context))->OnFailureResponse_2(error); - } - - static void OnSuccessCallback_2(void * context, uint64_t currentMaxRate) + static void OnSuccessCallback_1( + void * context, + const chip::app::DataModel::DecodableList< + chip::app::Clusters::GeneralDiagnostics::Structs::NetworkInterfaceType::DecodableType> & networkInterfaces) { - (static_cast(context))->OnSuccessResponse_2(currentMaxRate); + (static_cast(context))->OnSuccessResponse_1(networkInterfaces); } // @@ -40811,14 +40800,14 @@ class Test_TC_WIFIDIAG_1_1 : public TestCommand return WaitForCommissionee(); } - CHIP_ERROR TestReadsCurrentMaxRateAttributeFromDut_1() + CHIP_ERROR TestReadsNetworkInterfaceStructureAttributeFromDut_1() { - const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; - chip::Controller::WiFiNetworkDiagnosticsClusterTest cluster; + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 0; + chip::Controller::GeneralDiagnosticsClusterTest cluster; cluster.Associate(mDevices[kIdentityAlpha], endpoint); ReturnErrorOnFailure( - cluster.ReadAttribute( + cluster.ReadAttribute( this, OnSuccessCallback_1, OnFailureCallback_1)); return CHIP_NO_ERROR; } @@ -40826,37 +40815,14 @@ class Test_TC_WIFIDIAG_1_1 : public TestCommand void OnFailureResponse_1(CHIP_ERROR error) { chip::app::StatusIB status(error); - (status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute) ? NextTest() : ThrowFailureResponse(); - } - - void OnSuccessResponse_1(uint64_t currentMaxRate) - { - VerifyOrReturn(CheckValue("currentMaxRate", currentMaxRate, 0ULL)); - - NextTest(); - } - - CHIP_ERROR TestReadsCurrentMaxRateAttributeConstraints_2() - { - const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; - chip::Controller::WiFiNetworkDiagnosticsClusterTest cluster; - cluster.Associate(mDevices[kIdentityAlpha], endpoint); - - ReturnErrorOnFailure( - cluster.ReadAttribute( - this, OnSuccessCallback_2, OnFailureCallback_2)); - return CHIP_NO_ERROR; - } - - void OnFailureResponse_2(CHIP_ERROR error) - { - chip::app::StatusIB status(error); - (status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute) ? NextTest() : ThrowFailureResponse(); + ThrowFailureResponse(); } - void OnSuccessResponse_2(uint64_t currentMaxRate) + void + OnSuccessResponse_1(const chip::app::DataModel::DecodableList< + chip::app::Clusters::GeneralDiagnostics::Structs::NetworkInterfaceType::DecodableType> & networkInterfaces) { - VerifyOrReturn(CheckConstraintType("currentMaxRate", "", "uint64")); + VerifyOrReturn(CheckConstraintType("networkInterfaces", "", "list")); NextTest(); } }; @@ -56705,7 +56671,7 @@ class TestCluster : public TestCommand void OnFailureResponse_144(CHIP_ERROR error) { chip::app::StatusIB status(error); - VerifyOrReturn(CheckConstraintNotValue("status", chip::to_underlying(status.mStatus), 0)); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_ENDPOINT)); NextTest(); } @@ -56733,7 +56699,7 @@ class TestCluster : public TestCommand void OnFailureResponse_145(CHIP_ERROR error) { chip::app::StatusIB status(error); - VerifyOrReturn(CheckConstraintNotValue("status", chip::to_underlying(status.mStatus), 0)); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_CLUSTER)); NextTest(); } @@ -62527,7 +62493,7 @@ class TestCluster : public TestCommand void OnFailureResponse_360(CHIP_ERROR error) { chip::app::StatusIB status(error); - VerifyOrReturn(CheckConstraintNotValue("status", chip::to_underlying(status.mStatus), 0)); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_ENDPOINT)); NextTest(); } @@ -62547,7 +62513,7 @@ class TestCluster : public TestCommand void OnFailureResponse_361(CHIP_ERROR error) { chip::app::StatusIB status(error); - VerifyOrReturn(CheckConstraintNotValue("status", chip::to_underlying(status.mStatus), 0)); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_CLUSTER)); NextTest(); } @@ -73040,26 +73006,35 @@ class Test_TC_SWDIAG_1_1 : public TestCommand err = TestWaitForTheCommissionedDeviceToBeRetrieved_0(); break; case 1: - ChipLogProgress(chipTool, " ***** Test Step 1 : Reads CurrentHeapFree non-global attribute value from DUT\n"); - err = TestReadsCurrentHeapFreeNonGlobalAttributeValueFromDut_1(); + ChipLogProgress(chipTool, " ***** Test Step 1 : Reads a list of ThreadMetrics struct non-global attribute from DUT.\n"); + if (ShouldSkip("A_THREADMETRICS")) + { + NextTest(); + return; + } + err = TestReadsAListOfThreadMetricsStructNonGlobalAttributeFromDut_1(); break; case 2: - ChipLogProgress(chipTool, " ***** Test Step 2 : Reads CurrentHeapUsed non-global attribute value from DUT\n"); + ChipLogProgress(chipTool, " ***** Test Step 2 : Reads CurrentHeapFree non-global attribute value from DUT\n"); + err = TestReadsCurrentHeapFreeNonGlobalAttributeValueFromDut_2(); + break; + case 3: + ChipLogProgress(chipTool, " ***** Test Step 3 : Reads CurrentHeapUsed non-global attribute value from DUT\n"); if (ShouldSkip("A_CURRENTHEAPUSED")) { NextTest(); return; } - err = TestReadsCurrentHeapUsedNonGlobalAttributeValueFromDut_2(); + err = TestReadsCurrentHeapUsedNonGlobalAttributeValueFromDut_3(); break; - case 3: - ChipLogProgress(chipTool, " ***** Test Step 3 : Reads CurrentHeapHighWaterMark non-global attribute value from DUT\n"); + case 4: + ChipLogProgress(chipTool, " ***** Test Step 4 : Reads CurrentHeapHighWaterMark non-global attribute value from DUT\n"); if (ShouldSkip("A_CURRENTHEAPHIGHWATERMARK")) { NextTest(); return; } - err = TestReadsCurrentHeapHighWaterMarkNonGlobalAttributeValueFromDut_3(); + err = TestReadsCurrentHeapHighWaterMarkNonGlobalAttributeValueFromDut_4(); break; } @@ -73072,7 +73047,7 @@ class Test_TC_SWDIAG_1_1 : public TestCommand private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 4; + const uint16_t mTestCount = 5; chip::Optional mCluster; chip::Optional mEndpoint; @@ -73082,9 +73057,12 @@ class Test_TC_SWDIAG_1_1 : public TestCommand (static_cast(context))->OnFailureResponse_1(error); } - static void OnSuccessCallback_1(void * context, uint64_t currentHeapFree) + static void OnSuccessCallback_1( + void * context, + const chip::app::DataModel::DecodableList & + threadMetrics) { - (static_cast(context))->OnSuccessResponse_1(currentHeapFree); + (static_cast(context))->OnSuccessResponse_1(threadMetrics); } static void OnFailureCallback_2(void * context, CHIP_ERROR error) @@ -73092,9 +73070,9 @@ class Test_TC_SWDIAG_1_1 : public TestCommand (static_cast(context))->OnFailureResponse_2(error); } - static void OnSuccessCallback_2(void * context, uint64_t currentHeapUsed) + static void OnSuccessCallback_2(void * context, uint64_t currentHeapFree) { - (static_cast(context))->OnSuccessResponse_2(currentHeapUsed); + (static_cast(context))->OnSuccessResponse_2(currentHeapFree); } static void OnFailureCallback_3(void * context, CHIP_ERROR error) @@ -73102,9 +73080,19 @@ class Test_TC_SWDIAG_1_1 : public TestCommand (static_cast(context))->OnFailureResponse_3(error); } - static void OnSuccessCallback_3(void * context, uint64_t currentHeapHighWatermark) + static void OnSuccessCallback_3(void * context, uint64_t currentHeapUsed) + { + (static_cast(context))->OnSuccessResponse_3(currentHeapUsed); + } + + static void OnFailureCallback_4(void * context, CHIP_ERROR error) + { + (static_cast(context))->OnFailureResponse_4(error); + } + + static void OnSuccessCallback_4(void * context, uint64_t currentHeapHighWatermark) { - (static_cast(context))->OnSuccessResponse_3(currentHeapHighWatermark); + (static_cast(context))->OnSuccessResponse_4(currentHeapHighWatermark); } // @@ -73117,71 +73105,96 @@ class Test_TC_SWDIAG_1_1 : public TestCommand return WaitForCommissionee(); } - CHIP_ERROR TestReadsCurrentHeapFreeNonGlobalAttributeValueFromDut_1() + CHIP_ERROR TestReadsAListOfThreadMetricsStructNonGlobalAttributeFromDut_1() { - const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 0; chip::Controller::SoftwareDiagnosticsClusterTest cluster; cluster.Associate(mDevices[kIdentityAlpha], endpoint); - ReturnErrorOnFailure(cluster.ReadAttribute( + ReturnErrorOnFailure(cluster.ReadAttribute( this, OnSuccessCallback_1, OnFailureCallback_1)); return CHIP_NO_ERROR; } void OnFailureResponse_1(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_1( + const chip::app::DataModel::DecodableList & + threadMetrics) + { + + NextTest(); + } + + CHIP_ERROR TestReadsCurrentHeapFreeNonGlobalAttributeValueFromDut_2() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 0; + chip::Controller::SoftwareDiagnosticsClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + ReturnErrorOnFailure(cluster.ReadAttribute( + this, OnSuccessCallback_2, OnFailureCallback_2)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_2(CHIP_ERROR error) { chip::app::StatusIB status(error); (status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute) ? NextTest() : ThrowFailureResponse(); } - void OnSuccessResponse_1(uint64_t currentHeapFree) + void OnSuccessResponse_2(uint64_t currentHeapFree) { VerifyOrReturn(CheckConstraintType("currentHeapFree", "", "uint64")); NextTest(); } - CHIP_ERROR TestReadsCurrentHeapUsedNonGlobalAttributeValueFromDut_2() + CHIP_ERROR TestReadsCurrentHeapUsedNonGlobalAttributeValueFromDut_3() { - const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 0; chip::Controller::SoftwareDiagnosticsClusterTest cluster; cluster.Associate(mDevices[kIdentityAlpha], endpoint); ReturnErrorOnFailure(cluster.ReadAttribute( - this, OnSuccessCallback_2, OnFailureCallback_2)); + this, OnSuccessCallback_3, OnFailureCallback_3)); return CHIP_NO_ERROR; } - void OnFailureResponse_2(CHIP_ERROR error) + void OnFailureResponse_3(CHIP_ERROR error) { chip::app::StatusIB status(error); (status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute) ? NextTest() : ThrowFailureResponse(); } - void OnSuccessResponse_2(uint64_t currentHeapUsed) + void OnSuccessResponse_3(uint64_t currentHeapUsed) { VerifyOrReturn(CheckConstraintType("currentHeapUsed", "", "uint64")); NextTest(); } - CHIP_ERROR TestReadsCurrentHeapHighWaterMarkNonGlobalAttributeValueFromDut_3() + CHIP_ERROR TestReadsCurrentHeapHighWaterMarkNonGlobalAttributeValueFromDut_4() { - const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 0; chip::Controller::SoftwareDiagnosticsClusterTest cluster; cluster.Associate(mDevices[kIdentityAlpha], endpoint); ReturnErrorOnFailure( cluster.ReadAttribute( - this, OnSuccessCallback_3, OnFailureCallback_3)); + this, OnSuccessCallback_4, OnFailureCallback_4)); return CHIP_NO_ERROR; } - void OnFailureResponse_3(CHIP_ERROR error) + void OnFailureResponse_4(CHIP_ERROR error) { chip::app::StatusIB status(error); (status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute) ? NextTest() : ThrowFailureResponse(); } - void OnSuccessResponse_3(uint64_t currentHeapHighWatermark) + void OnSuccessResponse_4(uint64_t currentHeapHighWatermark) { VerifyOrReturn(CheckConstraintType("currentHeapHighWatermark", "", "uint64")); NextTest(); @@ -73288,22 +73301,31 @@ class Test_TC_SWDIAG_3_1 : public TestCommand err = TestWaitForTheCommissionedDeviceToBeRetrieved_0(); break; case 1: - ChipLogProgress(chipTool, " ***** Test Step 1 : Reads CurrentHeapUsed attribute value from DUT\n"); - if (ShouldSkip("A_CURRENTHEAPUSED")) + ChipLogProgress(chipTool, " ***** Test Step 1 : Sends ResetWatermarks to DUT\n"); + if (ShouldSkip("CR_RESETWATERMARKS")) { NextTest(); return; } - err = TestReadsCurrentHeapUsedAttributeValueFromDut_1(); + err = TestSendsResetWatermarksToDut_1(); break; case 2: - ChipLogProgress(chipTool, " ***** Test Step 2 : Reads CurrentHeapHighWaterMark attribute value from DUT\n"); + ChipLogProgress(chipTool, " ***** Test Step 2 : Reads CurrentHeapUsed attribute value from DUT\n"); + if (ShouldSkip("A_CURRENTHEAPUSED")) + { + NextTest(); + return; + } + err = TestReadsCurrentHeapUsedAttributeValueFromDut_2(); + break; + case 3: + ChipLogProgress(chipTool, " ***** Test Step 3 : Reads CurrentHeapHighWaterMark attribute value from DUT\n"); if (ShouldSkip("A_CURRENTHEAPHIGHWATERMARK")) { NextTest(); return; } - err = TestReadsCurrentHeapHighWaterMarkAttributeValueFromDut_2(); + err = TestReadsCurrentHeapHighWaterMarkAttributeValueFromDut_3(); break; } @@ -73316,29 +73338,29 @@ class Test_TC_SWDIAG_3_1 : public TestCommand private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 3; + const uint16_t mTestCount = 4; chip::Optional mCluster; chip::Optional mEndpoint; - static void OnFailureCallback_1(void * context, CHIP_ERROR error) + static void OnFailureCallback_2(void * context, CHIP_ERROR error) { - (static_cast(context))->OnFailureResponse_1(error); + (static_cast(context))->OnFailureResponse_2(error); } - static void OnSuccessCallback_1(void * context, uint64_t currentHeapUsed) + static void OnSuccessCallback_2(void * context, uint64_t currentHeapUsed) { - (static_cast(context))->OnSuccessResponse_1(currentHeapUsed); + (static_cast(context))->OnSuccessResponse_2(currentHeapUsed); } - static void OnFailureCallback_2(void * context, CHIP_ERROR error) + static void OnFailureCallback_3(void * context, CHIP_ERROR error) { - (static_cast(context))->OnFailureResponse_2(error); + (static_cast(context))->OnFailureResponse_3(error); } - static void OnSuccessCallback_2(void * context, uint64_t currentHeapHighWatermark) + static void OnSuccessCallback_3(void * context, uint64_t currentHeapHighWatermark) { - (static_cast(context))->OnSuccessResponse_2(currentHeapHighWatermark); + (static_cast(context))->OnSuccessResponse_3(currentHeapHighWatermark); } // @@ -73351,49 +73373,76 @@ class Test_TC_SWDIAG_3_1 : public TestCommand return WaitForCommissionee(); } - CHIP_ERROR TestReadsCurrentHeapUsedAttributeValueFromDut_1() + CHIP_ERROR TestSendsResetWatermarksToDut_1() { - const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 0; + using RequestType = chip::app::Clusters::SoftwareDiagnostics::Commands::ResetWatermarks::Type; + + RequestType request; + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_1(); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_1(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_1(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_1() { NextTest(); } + + CHIP_ERROR TestReadsCurrentHeapUsedAttributeValueFromDut_2() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 0; chip::Controller::SoftwareDiagnosticsClusterTest cluster; cluster.Associate(mDevices[kIdentityAlpha], endpoint); ReturnErrorOnFailure(cluster.ReadAttribute( - this, OnSuccessCallback_1, OnFailureCallback_1)); + this, OnSuccessCallback_2, OnFailureCallback_2)); return CHIP_NO_ERROR; } - void OnFailureResponse_1(CHIP_ERROR error) + void OnFailureResponse_2(CHIP_ERROR error) { chip::app::StatusIB status(error); (status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute) ? NextTest() : ThrowFailureResponse(); } - void OnSuccessResponse_1(uint64_t currentHeapUsed) + void OnSuccessResponse_2(uint64_t currentHeapUsed) { VerifyOrReturn(CheckValue("currentHeapUsed", currentHeapUsed, 0ULL)); NextTest(); } - CHIP_ERROR TestReadsCurrentHeapHighWaterMarkAttributeValueFromDut_2() + CHIP_ERROR TestReadsCurrentHeapHighWaterMarkAttributeValueFromDut_3() { - const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 0; chip::Controller::SoftwareDiagnosticsClusterTest cluster; cluster.Associate(mDevices[kIdentityAlpha], endpoint); ReturnErrorOnFailure( cluster.ReadAttribute( - this, OnSuccessCallback_2, OnFailureCallback_2)); + this, OnSuccessCallback_3, OnFailureCallback_3)); return CHIP_NO_ERROR; } - void OnFailureResponse_2(CHIP_ERROR error) + void OnFailureResponse_3(CHIP_ERROR error) { chip::app::StatusIB status(error); (status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute) ? NextTest() : ThrowFailureResponse(); } - void OnSuccessResponse_2(uint64_t currentHeapHighWatermark) + void OnSuccessResponse_3(uint64_t currentHeapHighWatermark) { VerifyOrReturn(CheckValue("currentHeapHighWatermark", currentHeapHighWatermark, 0ULL));