diff --git a/docs/cluster_and_device_type_dev/img/cluster_commands.png b/docs/cluster_and_device_type_dev/img/cluster_commands.png index 959774e071b717..c04dbe7279b28b 100644 Binary files a/docs/cluster_and_device_type_dev/img/cluster_commands.png and b/docs/cluster_and_device_type_dev/img/cluster_commands.png differ diff --git a/src/app/tests/TestCommandInteraction.cpp b/src/app/tests/TestCommandInteraction.cpp index 6aab66ec8549c3..d917315f2a43ec 100644 --- a/src/app/tests/TestCommandInteraction.cpp +++ b/src/app/tests/TestCommandInteraction.cpp @@ -119,6 +119,12 @@ struct ForcedSizeBuffer } }; +enum class ForcedSizeBufferLengthHint +{ + kSizeBetween0and255, + kSizeGreaterThan255, +}; + InteractionModel::Status ServerClusterCommandExists(const ConcreteCommandPath & aRequestCommandPath) { // Mock cluster catalog, only support commands on one cluster on one endpoint. @@ -379,6 +385,8 @@ class TestCommandInteraction static void AddInvokeResponseData(nlTestSuite * apSuite, void * apContext, CommandHandler * apCommandHandler, bool aNeedStatusCode, CommandId aResponseCommandId = kTestCommandIdWithData, CommandId aRequestCommandId = kTestCommandIdWithData); + static uint32_t GetAddResponseDataOverheadSizeForPath(nlTestSuite * apSuite, const ConcreteCommandPath & aRequestCommandPath, + ForcedSizeBufferLengthHint aBufferSizeHint); static void FillCurrentInvokeResponseBuffer(nlTestSuite * apSuite, CommandHandler * apCommandHandler, const ConcreteCommandPath & aRequestCommandPath, uint32_t aSizeToLeaveInBuffer); static void ValidateCommandHandlerEncodeInvokeResponseMessage(nlTestSuite * apSuite, void * apContext, bool aNeedStatusCode); @@ -577,6 +585,36 @@ void TestCommandInteraction::AddInvokeResponseData(nlTestSuite * apSuite, void * } } +uint32_t TestCommandInteraction::GetAddResponseDataOverheadSizeForPath(nlTestSuite * apSuite, + const ConcreteCommandPath & aRequestCommandPath, + ForcedSizeBufferLengthHint aBufferSizeHint) +{ + BasicCommandPathRegistry<4> mBasicCommandPathRegistry; + CommandHandler commandHandler(kCommandHandlerTestOnlyMarker, &mockCommandHandlerDelegate, &mBasicCommandPathRegistry); + commandHandler.mReserveSpaceForMoreChunkMessages = true; + ConcreteCommandPath requestCommandPath1 = { kTestEndpointId, kTestClusterId, kTestCommandIdFillResponseMessage }; + ConcreteCommandPath requestCommandPath2 = { kTestEndpointId, kTestClusterId, kTestCommandIdCommandSpecificResponse }; + + CHIP_ERROR err = mBasicCommandPathRegistry.Add(requestCommandPath1, MakeOptional(static_cast(1))); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + err = mBasicCommandPathRegistry.Add(requestCommandPath2, MakeOptional(static_cast(2))); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + err = commandHandler.AllocateBuffer(); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + uint32_t remainingSizeBefore = commandHandler.mInvokeResponseBuilder.GetWriter()->GetRemainingFreeLength(); + + // When ForcedSizeBuffer exceeds 255, an extra byte is needed for length, affecting the overhead size required by + // AddResponseData. In order to have this accounted for in overhead calculation we set the length to be 256. + uint32_t sizeOfForcedSizeBuffer = aBufferSizeHint == ForcedSizeBufferLengthHint::kSizeGreaterThan255 ? 256 : 0; + err = commandHandler.AddResponseData(aRequestCommandPath, ForcedSizeBuffer(sizeOfForcedSizeBuffer)); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + uint32_t remainingSizeAfter = commandHandler.mInvokeResponseBuilder.GetWriter()->GetRemainingFreeLength(); + uint32_t delta = remainingSizeBefore - remainingSizeAfter - sizeOfForcedSizeBuffer; + + return delta; +} + void TestCommandInteraction::FillCurrentInvokeResponseBuffer(nlTestSuite * apSuite, CommandHandler * apCommandHandler, const ConcreteCommandPath & aRequestCommandPath, uint32_t aSizeToLeaveInBuffer) @@ -587,13 +625,17 @@ void TestCommandInteraction::FillCurrentInvokeResponseBuffer(nlTestSuite * apSui NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); uint32_t remainingSize = apCommandHandler->mInvokeResponseBuilder.GetWriter()->GetRemainingFreeLength(); - // TODO(#30453): Have this value derived from IM layer similar to GetSizeToEndInvokeResponseMessage() - // This number was derived by executing this method with aSizeToLeaveInBuffer = 100 and - // subsequently analyzing the remaining size to determine the overhead associated with calling - // AddResponseData with `ForcedSizeBuffer`. - uint32_t sizeNeededForAddingResponse = 27; - NL_TEST_ASSERT(apSuite, remainingSize > (aSizeToLeaveInBuffer + sizeNeededForAddingResponse)); - uint32_t sizeToFill = remainingSize - aSizeToLeaveInBuffer - sizeNeededForAddingResponse; + // AddResponseData's overhead calculation depends on the size of ForcedSizeBuffer. If the buffer exceeds 255 bytes, an extra + // length byte is required. Since tests using FillCurrentInvokeResponseBuffer currently end up with sizeToFill > 255, we + // inform the calculation of this expectation. Nonetheless, we also validate this assumption for correctness. + ForcedSizeBufferLengthHint bufferSizeHint = ForcedSizeBufferLengthHint::kSizeGreaterThan255; + uint32_t overheadSizeNeededForAddingResponse = + GetAddResponseDataOverheadSizeForPath(apSuite, aRequestCommandPath, bufferSizeHint); + NL_TEST_ASSERT(apSuite, remainingSize > (aSizeToLeaveInBuffer + overheadSizeNeededForAddingResponse)); + uint32_t sizeToFill = remainingSize - aSizeToLeaveInBuffer - overheadSizeNeededForAddingResponse; + + // Validating assumption. If this fails, it means overheadSizeNeededForAddingResponse is likely too large. + NL_TEST_ASSERT(apSuite, sizeToFill >= 256); err = apCommandHandler->AddResponseData(aRequestCommandPath, ForcedSizeBuffer(sizeToFill)); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); @@ -1534,36 +1576,31 @@ void TestCommandInteraction::TestCommandHandlerRejectMultipleIdenticalCommands(n CHIP_ERROR err = CHIP_NO_ERROR; isCommandDispatched = false; - mockCommandSenderDelegate.ResetCounter(); - app::CommandSender commandSender(&mockCommandSenderDelegate, &ctx.GetExchangeManager()); + mockCommandSenderExtendedDelegate.ResetCounter(); + PendingResponseTrackerImpl pendingResponseTracker; + app::CommandSender commandSender(kCommandSenderTestOnlyMarker, &mockCommandSenderExtendedDelegate, &ctx.GetExchangeManager(), + &pendingResponseTracker); - { - // Command ID is not important here, since the command handler should reject the commands without handling it. - auto commandPathParams = MakeTestCommandPath(kTestCommandIdCommandSpecificResponse); + app::CommandSender::ConfigParameters configParameters; + configParameters.SetRemoteMaxPathsPerInvoke(2); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == commandSender.SetCommandSenderConfig(configParameters)); - commandSender.AllocateBuffer(); + // Command ID is not important here, since the command handler should reject the commands without handling it. + auto commandPathParams = MakeTestCommandPath(kTestCommandIdCommandSpecificResponse); - // TODO(#30453): CommandSender does support sending multiple commands, update this test to use that. - for (int i = 0; i < 2; i++) - { - InvokeRequests::Builder & invokeRequests = commandSender.mInvokeRequestBuilder.GetInvokeRequests(); - CommandDataIB::Builder & invokeRequest = invokeRequests.CreateCommandData(); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequests.GetError()); - CommandPathIB::Builder & path = invokeRequest.CreatePath(); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequest.GetError()); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == path.Encode(commandPathParams)); - NL_TEST_ASSERT(apSuite, - CHIP_NO_ERROR == - invokeRequest.GetWriter()->StartContainer(TLV::ContextTag(CommandDataIB::Tag::kFields), - TLV::kTLVType_Structure, - commandSender.mDataElementContainerType)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequest.GetWriter()->PutBoolean(chip::TLV::ContextTag(1), true)); - NL_TEST_ASSERT(apSuite, - CHIP_NO_ERROR == invokeRequest.GetWriter()->EndContainer(commandSender.mDataElementContainerType)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequest.EndOfCommandDataIB()); - } + for (uint16_t i = 0; i < 2; i++) + { + app::CommandSender::PrepareCommandParameters prepareCommandParams; + prepareCommandParams.SetStartDataStruct(true); + prepareCommandParams.SetCommandRef(i); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == commandSender.PrepareCommand(commandPathParams, prepareCommandParams)); + NL_TEST_ASSERT(apSuite, + CHIP_NO_ERROR == commandSender.GetCommandDataIBTLVWriter()->PutBoolean(chip::TLV::ContextTag(1), true)); - commandSender.MoveToState(app::CommandSender::State::AddedCommand); + app::CommandSender::FinishCommandParameters finishCommandParams; + finishCommandParams.SetEndDataStruct(true); + finishCommandParams.SetCommandRef(i); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == commandSender.FinishCommand(finishCommandParams)); } err = commandSender.SendCommandRequest(ctx.GetSessionBobToAlice()); @@ -1573,14 +1610,17 @@ void TestCommandInteraction::TestCommandHandlerRejectMultipleIdenticalCommands(n ctx.DrainAndServiceIO(); NL_TEST_ASSERT(apSuite, - mockCommandSenderDelegate.onResponseCalledTimes == 0 && mockCommandSenderDelegate.onFinalCalledTimes == 1 && - mockCommandSenderDelegate.onErrorCalledTimes == 1); + mockCommandSenderExtendedDelegate.onResponseCalledTimes == 0 && + mockCommandSenderExtendedDelegate.onFinalCalledTimes == 1 && + mockCommandSenderExtendedDelegate.onErrorCalledTimes == 1); NL_TEST_ASSERT(apSuite, !chip::isCommandDispatched); NL_TEST_ASSERT(apSuite, GetNumActiveHandlerObjects() == 0); NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0); } +#if CONFIG_BUILD_FOR_HOST_UNIT_TEST + void TestCommandInteraction::TestCommandHandlerRejectsMultipleCommandsWithIdenticalCommandRef(nlTestSuite * apSuite, void * apContext) { @@ -1588,45 +1628,44 @@ void TestCommandInteraction::TestCommandHandlerRejectsMultipleCommandsWithIdenti CHIP_ERROR err = CHIP_NO_ERROR; isCommandDispatched = false; - mockCommandSenderDelegate.ResetCounter(); + mockCommandSenderExtendedDelegate.ResetCounter(); + PendingResponseTrackerImpl pendingResponseTracker; + app::CommandSender commandSender(kCommandSenderTestOnlyMarker, &mockCommandSenderExtendedDelegate, &ctx.GetExchangeManager(), + &pendingResponseTracker); - // Using commandSender to help build afterward we take the buffer to feed into standalone CommandHandler - app::CommandSender commandSender(&mockCommandSenderDelegate, &ctx.GetExchangeManager()); + app::CommandSender::ConfigParameters configParameters; + configParameters.SetRemoteMaxPathsPerInvoke(2); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == commandSender.SetCommandSenderConfig(configParameters)); - size_t numberOfCommandsToSend = 2; + uint16_t numberOfCommandsToSend = 2; { CommandPathParams requestCommandPaths[] = { MakeTestCommandPath(kTestCommandIdWithData), MakeTestCommandPath(kTestCommandIdCommandSpecificResponse), }; - commandSender.AllocateBuffer(); + uint16_t hardcodedCommandRef = 0; - // TODO(#30453): CommandSender does support sending multiple commands, update this test to use that. - for (size_t i = 0; i < numberOfCommandsToSend; i++) + for (uint16_t i = 0; i < numberOfCommandsToSend; i++) { - InvokeRequests::Builder & invokeRequests = commandSender.mInvokeRequestBuilder.GetInvokeRequests(); - CommandDataIB::Builder & invokeRequest = invokeRequests.CreateCommandData(); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequests.GetError()); - CommandPathIB::Builder & path = invokeRequest.CreatePath(); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequest.GetError()); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == path.Encode(requestCommandPaths[i])); + app::CommandSender::PrepareCommandParameters prepareCommandParams; + prepareCommandParams.SetStartDataStruct(true); + prepareCommandParams.SetCommandRef(i); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == commandSender.PrepareCommand(requestCommandPaths[i], prepareCommandParams)); NL_TEST_ASSERT(apSuite, - CHIP_NO_ERROR == - invokeRequest.GetWriter()->StartContainer(TLV::ContextTag(CommandDataIB::Tag::kFields), - TLV::kTLVType_Structure, - commandSender.mDataElementContainerType)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequest.GetWriter()->PutBoolean(chip::TLV::ContextTag(1), true)); - NL_TEST_ASSERT(apSuite, - CHIP_NO_ERROR == invokeRequest.GetWriter()->EndContainer(commandSender.mDataElementContainerType)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequest.Ref(1)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequest.EndOfCommandDataIB()); + CHIP_NO_ERROR == commandSender.GetCommandDataIBTLVWriter()->PutBoolean(chip::TLV::ContextTag(1), true)); + // TODO fix this comment + // We are taking advantage of the fact that the commandRef was set into finishCommandParams during PrepareCommand + // But setting it to a different value here, we are overriding what it was supposed to be. + app::CommandSender::FinishCommandParameters finishCommandParams; + finishCommandParams.SetEndDataStruct(true); + finishCommandParams.SetCommandRef(hardcodedCommandRef); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == commandSender.TestOnlyFinishCommand(finishCommandParams)); } - - commandSender.MoveToState(app::CommandSender::State::AddedCommand); } - CommandHandler commandHandler(&mockCommandHandlerDelegate); + BasicCommandPathRegistry<4> mBasicCommandPathRegistry; + CommandHandler commandHandler(kCommandHandlerTestOnlyMarker, &mockCommandHandlerDelegate, &mBasicCommandPathRegistry); TestExchangeDelegate delegate; auto exchange = ctx.NewExchangeToAlice(&delegate, false); commandHandler.mResponseSender.SetExchangeContext(exchange); @@ -1654,6 +1693,8 @@ void TestCommandInteraction::TestCommandHandlerRejectsMultipleCommandsWithIdenti exchange->Close(); } +#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST + void TestCommandInteraction::TestCommandHandlerRejectMultipleCommandsWhenHandlerOnlySupportsOne(nlTestSuite * apSuite, void * apContext) { @@ -1661,46 +1702,39 @@ void TestCommandInteraction::TestCommandHandlerRejectMultipleCommandsWhenHandler CHIP_ERROR err = CHIP_NO_ERROR; isCommandDispatched = false; - mockCommandSenderDelegate.ResetCounter(); - // Using commandSender to help build afterward we take the buffer to feed into standalone CommandHandler - app::CommandSender commandSender(&mockCommandSenderDelegate, &ctx.GetExchangeManager()); + mockCommandSenderExtendedDelegate.ResetCounter(); + PendingResponseTrackerImpl pendingResponseTracker; + app::CommandSender commandSender(kCommandSenderTestOnlyMarker, &mockCommandSenderExtendedDelegate, &ctx.GetExchangeManager(), + &pendingResponseTracker); + + app::CommandSender::ConfigParameters configParameters; + configParameters.SetRemoteMaxPathsPerInvoke(2); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == commandSender.SetCommandSenderConfig(configParameters)); - size_t numberOfCommandsToSend = 2; + uint16_t numberOfCommandsToSend = 2; { CommandPathParams requestCommandPaths[] = { MakeTestCommandPath(kTestCommandIdWithData), MakeTestCommandPath(kTestCommandIdCommandSpecificResponse), }; - commandSender.AllocateBuffer(); - - // TODO(#30453): CommandSender does support sending multiple commands, update this test to use that. - for (size_t i = 0; i < numberOfCommandsToSend; i++) + for (uint16_t i = 0; i < numberOfCommandsToSend; i++) { - InvokeRequests::Builder & invokeRequests = commandSender.mInvokeRequestBuilder.GetInvokeRequests(); - CommandDataIB::Builder & invokeRequest = invokeRequests.CreateCommandData(); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequests.GetError()); - CommandPathIB::Builder & path = invokeRequest.CreatePath(); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequest.GetError()); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == path.Encode(requestCommandPaths[i])); - NL_TEST_ASSERT(apSuite, - CHIP_NO_ERROR == - invokeRequest.GetWriter()->StartContainer(TLV::ContextTag(CommandDataIB::Tag::kFields), - TLV::kTLVType_Structure, - commandSender.mDataElementContainerType)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequest.GetWriter()->PutBoolean(chip::TLV::ContextTag(1), true)); + app::CommandSender::PrepareCommandParameters prepareCommandParams; + prepareCommandParams.SetStartDataStruct(true); + prepareCommandParams.SetCommandRef(i); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == commandSender.PrepareCommand(requestCommandPaths[i], prepareCommandParams)); NL_TEST_ASSERT(apSuite, - CHIP_NO_ERROR == invokeRequest.GetWriter()->EndContainer(commandSender.mDataElementContainerType)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequest.Ref(static_cast(i))); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequest.EndOfCommandDataIB()); + CHIP_NO_ERROR == commandSender.GetCommandDataIBTLVWriter()->PutBoolean(chip::TLV::ContextTag(1), true)); + app::CommandSender::FinishCommandParameters finishCommandParams; + finishCommandParams.SetEndDataStruct(true); + finishCommandParams.SetCommandRef(i); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == commandSender.FinishCommand(finishCommandParams)); } - - commandSender.MoveToState(app::CommandSender::State::AddedCommand); } - BasicCommandPathRegistry<4> mBasicCommandPathRegistry; - CommandHandler commandHandler(kCommandHandlerTestOnlyMarker, &mockCommandHandlerDelegate, &mBasicCommandPathRegistry); + CommandHandler commandHandler(&mockCommandHandlerDelegate); TestExchangeDelegate delegate; auto exchange = ctx.NewExchangeToAlice(&delegate, false); commandHandler.mResponseSender.SetExchangeContext(exchange); @@ -1715,9 +1749,9 @@ void TestCommandInteraction::TestCommandHandlerRejectMultipleCommandsWhenHandler commandDispatchedCount = 0; InteractionModel::Status status = commandHandler.ProcessInvokeRequest(std::move(commandDatabuf), false); - NL_TEST_ASSERT(apSuite, status == InteractionModel::Status::Success); + NL_TEST_ASSERT(apSuite, status == InteractionModel::Status::InvalidAction); - NL_TEST_ASSERT(apSuite, commandDispatchedCount == 2); + NL_TEST_ASSERT(apSuite, commandDispatchedCount == 0); // // Ordinarily, the ExchangeContext will close itself on a responder exchange when unwinding back from an @@ -1735,39 +1769,35 @@ void TestCommandInteraction::TestCommandHandlerAcceptMultipleCommands(nlTestSuit CHIP_ERROR err = CHIP_NO_ERROR; isCommandDispatched = false; - mockCommandSenderDelegate.ResetCounter(); - // Using commandSender to help build afterward we take the buffer to feed into standalone CommandHandler - app::CommandSender commandSender(&mockCommandSenderDelegate, &ctx.GetExchangeManager()); + mockCommandSenderExtendedDelegate.ResetCounter(); + PendingResponseTrackerImpl pendingResponseTracker; + app::CommandSender commandSender(kCommandSenderTestOnlyMarker, &mockCommandSenderExtendedDelegate, &ctx.GetExchangeManager(), + &pendingResponseTracker); - size_t numberOfCommandsToSend = 2; + app::CommandSender::ConfigParameters configParameters; + configParameters.SetRemoteMaxPathsPerInvoke(2); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == commandSender.SetCommandSenderConfig(configParameters)); + + uint16_t numberOfCommandsToSend = 2; { CommandPathParams requestCommandPaths[] = { MakeTestCommandPath(kTestCommandIdWithData), MakeTestCommandPath(kTestCommandIdCommandSpecificResponse), }; - commandSender.AllocateBuffer(); - - // TODO(#30453): CommandSender does support sending multiple commands, update this test to use that. - for (size_t i = 0; i < numberOfCommandsToSend; i++) + for (uint16_t i = 0; i < numberOfCommandsToSend; i++) { - InvokeRequests::Builder & invokeRequests = commandSender.mInvokeRequestBuilder.GetInvokeRequests(); - CommandDataIB::Builder & invokeRequest = invokeRequests.CreateCommandData(); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequests.GetError()); - CommandPathIB::Builder & path = invokeRequest.CreatePath(); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequest.GetError()); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == path.Encode(requestCommandPaths[i])); + app::CommandSender::PrepareCommandParameters prepareCommandParams; + prepareCommandParams.SetStartDataStruct(true); + prepareCommandParams.SetCommandRef(i); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == commandSender.PrepareCommand(requestCommandPaths[i], prepareCommandParams)); NL_TEST_ASSERT(apSuite, - CHIP_NO_ERROR == - invokeRequest.GetWriter()->StartContainer(TLV::ContextTag(CommandDataIB::Tag::kFields), - TLV::kTLVType_Structure, - commandSender.mDataElementContainerType)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequest.GetWriter()->PutBoolean(chip::TLV::ContextTag(1), true)); - NL_TEST_ASSERT(apSuite, - CHIP_NO_ERROR == invokeRequest.GetWriter()->EndContainer(commandSender.mDataElementContainerType)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequest.Ref(static_cast(i))); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == invokeRequest.EndOfCommandDataIB()); + CHIP_NO_ERROR == commandSender.GetCommandDataIBTLVWriter()->PutBoolean(chip::TLV::ContextTag(1), true)); + app::CommandSender::FinishCommandParameters finishCommandParams; + finishCommandParams.SetEndDataStruct(true); + finishCommandParams.SetCommandRef(i); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == commandSender.FinishCommand(finishCommandParams)); } commandSender.MoveToState(app::CommandSender::State::AddedCommand); @@ -1784,6 +1814,7 @@ void TestCommandInteraction::TestCommandHandlerAcceptMultipleCommands(nlTestSuit err = commandSender.Finalize(commandDatabuf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + sendResponse = true; mockCommandHandlerDelegate.ResetCounter(); commandDispatchedCount = 0; @@ -1810,11 +1841,11 @@ void TestCommandInteraction::TestCommandHandler_FillUpInvokeResponseMessageWhere commandHandler.mReserveSpaceForMoreChunkMessages = true; ConcreteCommandPath requestCommandPath1 = { kTestEndpointId, kTestClusterId, kTestCommandIdFillResponseMessage }; ConcreteCommandPath requestCommandPath2 = { kTestEndpointId, kTestClusterId, kTestCommandIdCommandSpecificResponse }; - Optional commandRef; - commandRef.SetValue(1); - mBasicCommandPathRegistry.Add(requestCommandPath1, commandRef); - commandRef.SetValue(2); - mBasicCommandPathRegistry.Add(requestCommandPath2, commandRef); + + CHIP_ERROR err = mBasicCommandPathRegistry.Add(requestCommandPath1, MakeOptional(static_cast(1))); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + err = mBasicCommandPathRegistry.Add(requestCommandPath2, MakeOptional(static_cast(2))); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); uint32_t sizeToLeave = 0; FillCurrentInvokeResponseBuffer(apSuite, &commandHandler, requestCommandPath1, sizeToLeave); @@ -1836,11 +1867,11 @@ void TestCommandInteraction::TestCommandHandler_FillUpInvokeResponseMessageWhere commandHandler.mReserveSpaceForMoreChunkMessages = true; ConcreteCommandPath requestCommandPath1 = { kTestEndpointId, kTestClusterId, kTestCommandIdFillResponseMessage }; ConcreteCommandPath requestCommandPath2 = { kTestEndpointId, kTestClusterId, kTestCommandIdCommandSpecificResponse }; - Optional commandRef; - commandRef.SetValue(1); - mBasicCommandPathRegistry.Add(requestCommandPath1, commandRef); - commandRef.SetValue(2); - mBasicCommandPathRegistry.Add(requestCommandPath2, commandRef); + + CHIP_ERROR err = mBasicCommandPathRegistry.Add(requestCommandPath1, MakeOptional(static_cast(1))); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + err = mBasicCommandPathRegistry.Add(requestCommandPath2, MakeOptional(static_cast(2))); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); uint32_t sizeToLeave = 0; FillCurrentInvokeResponseBuffer(apSuite, &commandHandler, requestCommandPath1, sizeToLeave); @@ -1862,11 +1893,11 @@ void TestCommandInteraction::TestCommandHandler_FillUpInvokeResponseMessageWhere commandHandler.mReserveSpaceForMoreChunkMessages = true; ConcreteCommandPath requestCommandPath1 = { kTestEndpointId, kTestClusterId, kTestCommandIdFillResponseMessage }; ConcreteCommandPath requestCommandPath2 = { kTestEndpointId, kTestClusterId, kTestCommandIdCommandSpecificResponse }; - Optional commandRef; - commandRef.SetValue(1); - mBasicCommandPathRegistry.Add(requestCommandPath1, commandRef); - commandRef.SetValue(2); - mBasicCommandPathRegistry.Add(requestCommandPath2, commandRef); + + CHIP_ERROR err = mBasicCommandPathRegistry.Add(requestCommandPath1, MakeOptional(static_cast(1))); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + err = mBasicCommandPathRegistry.Add(requestCommandPath2, MakeOptional(static_cast(2))); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); uint32_t sizeToLeave = 0; FillCurrentInvokeResponseBuffer(apSuite, &commandHandler, requestCommandPath1, sizeToLeave); @@ -1874,7 +1905,7 @@ void TestCommandInteraction::TestCommandHandler_FillUpInvokeResponseMessageWhere NL_TEST_ASSERT(apSuite, remainingSize == sizeToLeave); uint32_t sizeToFill = 50; - CHIP_ERROR err = commandHandler.AddResponseData(requestCommandPath2, ForcedSizeBuffer(sizeToFill)); + err = commandHandler.AddResponseData(requestCommandPath2, ForcedSizeBuffer(sizeToFill)); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); remainingSize = commandHandler.mInvokeResponseBuilder.GetWriter()->GetRemainingFreeLength(); @@ -1938,7 +1969,9 @@ const nlTest sTests[] = NL_TEST_DEF("TestCommandHandlerWithProcessReceivedNotExistCommand", chip::app::TestCommandInteraction::TestCommandHandlerWithProcessReceivedNotExistCommand), NL_TEST_DEF("TestCommandHandlerWithProcessReceivedEmptyDataMsg", chip::app::TestCommandInteraction::TestCommandHandlerWithProcessReceivedEmptyDataMsg), NL_TEST_DEF("TestCommandHandlerRejectMultipleIdenticalCommands", chip::app::TestCommandInteraction::TestCommandHandlerRejectMultipleIdenticalCommands), +#if CONFIG_BUILD_FOR_HOST_UNIT_TEST NL_TEST_DEF("TestCommandHandlerRejectsMultipleCommandsWithIdenticalCommandRef", chip::app::TestCommandInteraction::TestCommandHandlerRejectsMultipleCommandsWithIdenticalCommandRef), +#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST NL_TEST_DEF("TestCommandHandlerRejectMultipleCommandsWhenHandlerOnlySupportsOne", chip::app::TestCommandInteraction::TestCommandHandlerRejectMultipleCommandsWhenHandlerOnlySupportsOne), NL_TEST_DEF("TestCommandHandlerAcceptMultipleCommands", chip::app::TestCommandInteraction::TestCommandHandlerAcceptMultipleCommands), NL_TEST_DEF("TestCommandHandler_FillUpInvokeResponseMessageWhereSecondResponseIsStatusResponse", chip::app::TestCommandInteraction::TestCommandHandler_FillUpInvokeResponseMessageWhereSecondResponseIsStatusResponse),