From 0480d46c9f38ddebe386267ce34b1d0223c10989 Mon Sep 17 00:00:00 2001 From: yunhanw-google Date: Mon, 7 Jun 2021 09:48:39 -0700 Subject: [PATCH] FieldId and Listindex should not be exclusive (#7295) Problems: We would only support toplevel attributes and list items inside toplevel attribute Summary of Changes: --Support two situation in attribute path, one is FieldId only, another is FieldId + ListIndex. --- src/app/AttributePathParams.h | 46 ++-- src/app/ClusterInfo.h | 9 +- src/app/InteractionModelEngine.cpp | 2 +- src/app/MessageDef/AttributePath.cpp | 10 +- src/app/ReadClient.cpp | 76 ++++--- src/app/ReadClient.h | 2 + src/app/ReadHandler.cpp | 30 ++- src/app/tests/BUILD.gn | 1 - src/app/tests/TestAttributePathParams.cpp | 104 --------- src/app/tests/TestReadInteraction.cpp | 200 +++++++++++++++++- .../tests/integration/chip_im_initiator.cpp | 2 +- 11 files changed, 288 insertions(+), 194 deletions(-) delete mode 100644 src/app/tests/TestAttributePathParams.cpp diff --git a/src/app/AttributePathParams.h b/src/app/AttributePathParams.h index 367610abc1456a..9350dd329c1b99 100644 --- a/src/app/AttributePathParams.h +++ b/src/app/AttributePathParams.h @@ -23,46 +23,26 @@ namespace chip { namespace app { -enum class AttributePathFlags : uint8_t -{ - kFieldIdValid = 0x01, - kListIndexValid = 0x02, -}; - struct AttributePathParams { + enum class Flags : uint8_t + { + kFieldIdValid = 0x01, + kListIndexValid = 0x02, + }; + AttributePathParams(NodeId aNodeId, EndpointId aEndpointId, ClusterId aClusterId, FieldId aFieldId, ListIndex aListIndex, - const BitFlags aFlags) : + const BitFlags aFlags) : mNodeId(aNodeId), mEndpointId(aEndpointId), mClusterId(aClusterId), mFieldId(aFieldId), mListIndex(aListIndex), mFlags(aFlags) {} AttributePathParams() {} - bool IsSamePath(const AttributePathParams & other) const - { - if (other.mNodeId != mNodeId || other.mEndpointId != mEndpointId || other.mClusterId != mClusterId) - { - return false; - } - if (mFlags != other.mFlags) - { - return false; - } - if (mFlags == AttributePathFlags::kFieldIdValid && other.mFieldId != mFieldId) - { - return false; - } - if (mFlags == AttributePathFlags::kListIndexValid && other.mListIndex != mListIndex) - { - return false; - } - return true; - } - chip::NodeId mNodeId = 0; - chip::EndpointId mEndpointId = 0; - chip::ClusterId mClusterId = 0; - chip::FieldId mFieldId = 0; - chip::ListIndex mListIndex = 0; - BitFlags mFlags; + NodeId mNodeId = 0; + EndpointId mEndpointId = 0; + ClusterId mClusterId = 0; + FieldId mFieldId = 0; + ListIndex mListIndex = 0; + BitFlags mFlags; }; } // namespace app } // namespace chip diff --git a/src/app/ClusterInfo.h b/src/app/ClusterInfo.h index ef68b036961740..77284f3750d2ca 100644 --- a/src/app/ClusterInfo.h +++ b/src/app/ClusterInfo.h @@ -25,9 +25,8 @@ namespace chip { namespace app { struct ClusterInfo { - enum class Type : uint8_t + enum class Flags : uint8_t { - kInvalid = 0, kFieldIdValid = 0x01, kListIndexValid = 0x02, kEventIdValid = 0x03, @@ -43,9 +42,9 @@ struct ClusterInfo FieldId mFieldId = 0; EndpointId mEndpointId = 0; bool mDirty = false; - Type mType = Type::kInvalid; - ClusterInfo * mpNext = nullptr; - EventId mEventId = 0; + BitFlags mFlags; + ClusterInfo * mpNext = nullptr; + EventId mEventId = 0; /* For better structure alignment * Above ordering is by bit-size to ensure least amount of memory alignment padding. * Changing order to something more natural (e.g. clusterid before nodeid) will result diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp index 3b8515a858e92b..254f12ff399982 100644 --- a/src/app/InteractionModelEngine.cpp +++ b/src/app/InteractionModelEngine.cpp @@ -286,7 +286,7 @@ void InteractionModelEngine::ReleaseClusterInfoList(ClusterInfo *& aClusterInfo) lastClusterInfo = lastClusterInfo->mpNext; } lastClusterInfo->ClearDirty(); - lastClusterInfo->mType = ClusterInfo::Type::kInvalid; + lastClusterInfo->mFlags.ClearAll(); lastClusterInfo->mpNext = mpNextAvailableClusterInfo; mpNextAvailableClusterInfo = aClusterInfo; aClusterInfo = nullptr; diff --git a/src/app/MessageDef/AttributePath.cpp b/src/app/MessageDef/AttributePath.cpp index 699e021cb658eb..0ea08418e81a5a 100644 --- a/src/app/MessageDef/AttributePath.cpp +++ b/src/app/MessageDef/AttributePath.cpp @@ -151,16 +151,14 @@ CHIP_ERROR AttributePath::Parser::CheckSchemaValidity() const // if we have exhausted this container if (CHIP_END_OF_TLV == err) { - // check for required fields: - const uint16_t RequiredFields = (1 << kCsTag_EndpointId) | (1 << kCsTag_ClusterId); - - if ((TagPresenceMask & RequiredFields) == RequiredFields) + // Not allow for situation where ListIndex exists, but FieldId not exists + if ((TagPresenceMask & (1 << kCsTag_FieldId)) == 0 && (TagPresenceMask & (1 << kCsTag_ListIndex)) != 0) { - err = CHIP_NO_ERROR; + err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH; } else { - err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH; + err = CHIP_NO_ERROR; } } SuccessOrExit(err); diff --git a/src/app/ReadClient.cpp b/src/app/ReadClient.cpp index e857eb5ea37396..d1c139ad0e7529 100644 --- a/src/app/ReadClient.cpp +++ b/src/app/ReadClient.cpp @@ -132,32 +132,8 @@ CHIP_ERROR ReadClient::SendReadRequest(NodeId aNodeId, Transport::AdminId aAdmin if (aAttributePathParamsListSize != 0 && apAttributePathParamsList != nullptr) { - AttributePathList::Builder attributePathListBuilder = request.CreateAttributePathListBuilder(); - SuccessOrExit(err = attributePathListBuilder.GetError()); - for (size_t index = 0; index < aAttributePathParamsListSize; index++) - { - AttributePath::Builder attributePathBuilder = attributePathListBuilder.CreateAttributePathBuilder(); - attributePathBuilder.NodeId(apAttributePathParamsList[index].mNodeId) - .EndpointId(apAttributePathParamsList[index].mEndpointId) - .ClusterId(apAttributePathParamsList[index].mClusterId); - if (apAttributePathParamsList[index].mFlags == AttributePathFlags::kFieldIdValid) - { - attributePathBuilder.FieldId(apAttributePathParamsList[index].mFieldId); - } - else if (apAttributePathParamsList[index].mFlags == AttributePathFlags::kListIndexValid) - { - attributePathBuilder.ListIndex(apAttributePathParamsList[index].mListIndex); - } - else - { - err = CHIP_ERROR_INVALID_ARGUMENT; - ExitNow(); - } - attributePathBuilder.EndOfAttributePath(); - SuccessOrExit(err = attributePathBuilder.GetError()); - } - attributePathListBuilder.EndOfAttributePathList(); - SuccessOrExit(err = attributePathListBuilder.GetError()); + err = GenerateAttributePathList(request, apAttributePathParamsList, aAttributePathParamsListSize); + SuccessOrExit(err); } request.EndOfReadRequest(); @@ -187,6 +163,36 @@ CHIP_ERROR ReadClient::SendReadRequest(NodeId aNodeId, Transport::AdminId aAdmin return err; } +CHIP_ERROR ReadClient::GenerateAttributePathList(ReadRequest::Builder & aRequest, AttributePathParams * apAttributePathParamsList, + size_t aAttributePathParamsListSize) +{ + AttributePathList::Builder attributePathListBuilder = aRequest.CreateAttributePathListBuilder(); + ReturnErrorOnFailure(attributePathListBuilder.GetError()); + for (size_t index = 0; index < aAttributePathParamsListSize; index++) + { + AttributePath::Builder attributePathBuilder = attributePathListBuilder.CreateAttributePathBuilder(); + attributePathBuilder.NodeId(apAttributePathParamsList[index].mNodeId) + .EndpointId(apAttributePathParamsList[index].mEndpointId) + .ClusterId(apAttributePathParamsList[index].mClusterId); + if (apAttributePathParamsList[index].mFlags.Has(AttributePathParams::Flags::kFieldIdValid)) + { + attributePathBuilder.FieldId(apAttributePathParamsList[index].mFieldId); + } + + if (apAttributePathParamsList[index].mFlags.Has(AttributePathParams::Flags::kListIndexValid)) + { + VerifyOrReturnError(apAttributePathParamsList[index].mFlags.Has(AttributePathParams::Flags::kFieldIdValid), + CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); + attributePathBuilder.ListIndex(apAttributePathParamsList[index].mListIndex); + } + + attributePathBuilder.EndOfAttributePath(); + ReturnErrorOnFailure(attributePathBuilder.GetError()); + } + attributePathListBuilder.EndOfAttributePathList(); + return attributePathListBuilder.GetError(); +} + void ReadClient::OnMessageReceived(Messaging::ExchangeContext * apExchangeContext, const PacketHeader & aPacketHeader, const PayloadHeader & aPayloadHeader, System::PacketBufferHandle && aPayload) { @@ -351,13 +357,23 @@ CHIP_ERROR ReadClient::ProcessAttributeDataList(TLV::TLVReader & aAttributeDataL err = attributePathParser.GetFieldId(&(clusterInfo.mFieldId)); if (CHIP_NO_ERROR == err) { - clusterInfo.mType = ClusterInfo::Type::kFieldIdValid; + clusterInfo.mFlags.Set(ClusterInfo::Flags::kFieldIdValid); } else if (CHIP_END_OF_TLV == err) { - err = attributePathParser.GetListIndex(&(clusterInfo.mListIndex)); - SuccessOrExit(err); - clusterInfo.mType = ClusterInfo::Type::kListIndexValid; + err = CHIP_NO_ERROR; + } + SuccessOrExit(err); + + err = attributePathParser.GetListIndex(&(clusterInfo.mListIndex)); + if (CHIP_NO_ERROR == err) + { + VerifyOrExit(clusterInfo.mFlags.Has(ClusterInfo::Flags::kFieldIdValid), err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); + clusterInfo.mFlags.Set(ClusterInfo::Flags::kListIndexValid); + } + else if (CHIP_END_OF_TLV == err) + { + err = CHIP_NO_ERROR; } SuccessOrExit(err); diff --git a/src/app/ReadClient.h b/src/app/ReadClient.h index dae8a6878101f0..e26263525da5af 100644 --- a/src/app/ReadClient.h +++ b/src/app/ReadClient.h @@ -111,6 +111,8 @@ class ReadClient : public Messaging::ExchangeDelegate */ bool IsFree() const { return mState == ClientState::Uninitialized; }; + CHIP_ERROR GenerateAttributePathList(ReadRequest::Builder & aRequest, AttributePathParams * apAttributePathParamsList, + size_t aAttributePathParamsListSize); CHIP_ERROR ProcessAttributeDataList(TLV::TLVReader & aAttributeDataListReader); void MoveToState(const ClientState aTargetState); diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp index cef5e6a3d8977e..d7615483346455 100644 --- a/src/app/ReadHandler.cpp +++ b/src/app/ReadHandler.cpp @@ -184,15 +184,26 @@ CHIP_ERROR ReadHandler::ProcessAttributePathList(AttributePathList::Parser & aAt err = path.GetFieldId(&(clusterInfo.mFieldId)); if (CHIP_NO_ERROR == err) { - clusterInfo.mType = ClusterInfo::Type::kFieldIdValid; + clusterInfo.mFlags.Set(ClusterInfo::Flags::kFieldIdValid); } else if (CHIP_END_OF_TLV == err) { - err = path.GetListIndex(&(clusterInfo.mListIndex)); - SuccessOrExit(err); - clusterInfo.mType = ClusterInfo::Type::kListIndexValid; + err = CHIP_NO_ERROR; } SuccessOrExit(err); + + err = path.GetListIndex(&(clusterInfo.mListIndex)); + if (CHIP_NO_ERROR == err) + { + VerifyOrExit(clusterInfo.mFlags.Has(ClusterInfo::Flags::kFieldIdValid), err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); + clusterInfo.mFlags.Set(ClusterInfo::Flags::kListIndexValid); + } + else if (CHIP_END_OF_TLV == err) + { + err = CHIP_NO_ERROR; + } + SuccessOrExit(err); + err = InteractionModelEngine::GetInstance()->PushFront(mpAttributeClusterInfoList, clusterInfo); SuccessOrExit(err); mpAttributeClusterInfoList->SetDirty(); @@ -229,9 +240,16 @@ CHIP_ERROR ReadHandler::ProcessEventPathList(EventPathList::Parser & aEventPathL err = path.GetClusterId(&(clusterInfo.mClusterId)); SuccessOrExit(err); err = path.GetEventId(&(clusterInfo.mEventId)); + if (CHIP_NO_ERROR == err) + { + clusterInfo.mFlags.Set(ClusterInfo::Flags::kEventIdValid); + } + else if (CHIP_END_OF_TLV == err) + { + err = CHIP_NO_ERROR; + } SuccessOrExit(err); - clusterInfo.mType = ClusterInfo::Type::kEventIdValid; - err = InteractionModelEngine::GetInstance()->PushFront(mpEventClusterInfoList, clusterInfo); + err = InteractionModelEngine::GetInstance()->PushFront(mpEventClusterInfoList, clusterInfo); SuccessOrExit(err); } diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index d3310dad97ee38..72fe10d4fcaca0 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -22,7 +22,6 @@ chip_test_suite("tests") { output_name = "libAppTests" test_sources = [ - "TestAttributePathParams.cpp", "TestClusterInfo.cpp", "TestCommandInteraction.cpp", "TestCommandPathParams.cpp", diff --git a/src/app/tests/TestAttributePathParams.cpp b/src/app/tests/TestAttributePathParams.cpp deleted file mode 100644 index 5c41aa0e62202e..00000000000000 --- a/src/app/tests/TestAttributePathParams.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * - * Copyright (c) 2021 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * This file implements unit tests for CommandPathParams - * - */ - -#include -#include -#include - -namespace chip { -namespace app { -namespace TestAttributePathParams { -void TestSamePath(nlTestSuite * apSuite, void * apContext) -{ - AttributePathParams attributePathParams1(1, 2, 3, 4, 5, AttributePathFlags::kFieldIdValid); - AttributePathParams attributePathParams2(1, 2, 3, 4, 5, AttributePathFlags::kFieldIdValid); - NL_TEST_ASSERT(apSuite, attributePathParams1.IsSamePath(attributePathParams2)); -} - -void TestDifferentNodeId(nlTestSuite * apSuite, void * apContext) -{ - AttributePathParams attributePathParams1(1, 2, 3, 4, 5, AttributePathFlags::kFieldIdValid); - AttributePathParams attributePathParams2(6, 2, 3, 4, 5, AttributePathFlags::kFieldIdValid); - NL_TEST_ASSERT(apSuite, !attributePathParams1.IsSamePath(attributePathParams2)); -} - -void TestDifferentEndpointId(nlTestSuite * apSuite, void * apContext) -{ - AttributePathParams attributePathParams1(1, 2, 3, 4, 5, AttributePathFlags::kFieldIdValid); - AttributePathParams attributePathParams2(1, 6, 3, 4, 5, AttributePathFlags::kFieldIdValid); - NL_TEST_ASSERT(apSuite, !attributePathParams1.IsSamePath(attributePathParams2)); -} - -void TestDifferentClusterId(nlTestSuite * apSuite, void * apContext) -{ - AttributePathParams attributePathParams1(1, 2, 3, 4, 5, AttributePathFlags::kFieldIdValid); - AttributePathParams attributePathParams2(1, 2, 6, 4, 5, AttributePathFlags::kFieldIdValid); - NL_TEST_ASSERT(apSuite, !attributePathParams1.IsSamePath(attributePathParams2)); -} - -void TestDifferentFieldId(nlTestSuite * apSuite, void * apContext) -{ - AttributePathParams attributePathParams1(1, 2, 3, 4, 5, AttributePathFlags::kFieldIdValid); - AttributePathParams attributePathParams2(1, 2, 3, 6, 5, AttributePathFlags::kFieldIdValid); - NL_TEST_ASSERT(apSuite, !attributePathParams1.IsSamePath(attributePathParams2)); -} - -void TestDifferentListIndex(nlTestSuite * apSuite, void * apContext) -{ - AttributePathParams attributePathParams1(1, 2, 3, 4, 5, AttributePathFlags::kListIndexValid); - AttributePathParams attributePathParams2(1, 2, 3, 4, 6, AttributePathFlags::kListIndexValid); - NL_TEST_ASSERT(apSuite, !attributePathParams1.IsSamePath(attributePathParams2)); -} - -void TestDifferentPathFlag(nlTestSuite * apSuite, void * apContext) -{ - AttributePathParams attributePathParams1(1, 2, 3, 4, 5, AttributePathFlags::kFieldIdValid); - AttributePathParams attributePathParams2(1, 2, 3, 4, 5, AttributePathFlags::kListIndexValid); - NL_TEST_ASSERT(apSuite, !attributePathParams1.IsSamePath(attributePathParams2)); -} -} // namespace TestAttributePathParams -} // namespace app -} // namespace chip - -namespace { -const nlTest sTests[] = { NL_TEST_DEF("TestSamePath", chip::app::TestAttributePathParams::TestSamePath), - NL_TEST_DEF("TestDifferentNodeId", chip::app::TestAttributePathParams::TestDifferentNodeId), - NL_TEST_DEF("TestDifferentEndpointId", chip::app::TestAttributePathParams::TestDifferentEndpointId), - NL_TEST_DEF("TestDifferentClusterId", chip::app::TestAttributePathParams::TestDifferentClusterId), - NL_TEST_DEF("TestDifferentFieldId", chip::app::TestAttributePathParams::TestDifferentFieldId), - NL_TEST_DEF("TestDifferentListIndex", chip::app::TestAttributePathParams::TestDifferentListIndex), - NL_TEST_DEF("TestDifferentPathFlag", chip::app::TestAttributePathParams::TestDifferentPathFlag), - NL_TEST_SENTINEL() }; -} - -int TestAttributePathParams() -{ - nlTestSuite theSuite = { "AttributePathParams", &sTests[0], nullptr, nullptr }; - - nlTestRunner(&theSuite, nullptr); - - return (nlTestRunnerStats(&theSuite)); -} - -CHIP_REGISTER_TEST_SUITE(TestAttributePathParams) diff --git a/src/app/tests/TestReadInteraction.cpp b/src/app/tests/TestReadInteraction.cpp index 5831a2ffc68a55..35f642c40f577a 100644 --- a/src/app/tests/TestReadInteraction.cpp +++ b/src/app/tests/TestReadInteraction.cpp @@ -56,12 +56,18 @@ class TestReadInteraction public: static void TestReadClient(nlTestSuite * apSuite, void * apContext); static void TestReadHandler(nlTestSuite * apSuite, void * apContext); + static void TestReadClientGenerateAttributePathList(nlTestSuite * apSuite, void * apContext); + static void TestReadClientGenerateInvalidAttributePathList(nlTestSuite * apSuite, void * apContext); + static void TestReadClientInvalidReport(nlTestSuite * apSuite, void * apContext); + static void TestReadHandlerInvalidAttributePath(nlTestSuite * apSuite, void * apContext); private: - static void GenerateReportData(nlTestSuite * apSuite, void * apContext, System::PacketBufferHandle & aPayload); + static void GenerateReportData(nlTestSuite * apSuite, void * apContext, System::PacketBufferHandle & aPayload, + bool aNeedInvalidReport = false); }; -void TestReadInteraction::GenerateReportData(nlTestSuite * apSuite, void * apContext, System::PacketBufferHandle & aPayload) +void TestReadInteraction::GenerateReportData(nlTestSuite * apSuite, void * apContext, System::PacketBufferHandle & aPayload, + bool aNeedInvalidReport) { CHIP_ERROR err = CHIP_NO_ERROR; System::PacketBufferTLVWriter writer; @@ -72,6 +78,56 @@ void TestReadInteraction::GenerateReportData(nlTestSuite * apSuite, void * apCon err = reportDataBuilder.Init(&writer); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + AttributeDataList::Builder attributeDataListBuilder = reportDataBuilder.CreateAttributeDataListBuilder(); + NL_TEST_ASSERT(apSuite, reportDataBuilder.GetError() == CHIP_NO_ERROR); + + AttributeDataElement::Builder attributeDataElementBuilder = attributeDataListBuilder.CreateAttributeDataElementBuilder(); + NL_TEST_ASSERT(apSuite, attributeDataListBuilder.GetError() == CHIP_NO_ERROR); + + AttributePath::Builder attributePathBuilder = attributeDataElementBuilder.CreateAttributePathBuilder(); + NL_TEST_ASSERT(apSuite, attributeDataElementBuilder.GetError() == CHIP_NO_ERROR); + + if (aNeedInvalidReport) + { + attributePathBuilder.NodeId(1).EndpointId(2).ClusterId(3).ListIndex(5).EndOfAttributePath(); + } + else + { + attributePathBuilder.NodeId(1).EndpointId(2).ClusterId(3).FieldId(4).ListIndex(5).EndOfAttributePath(); + } + + err = attributePathBuilder.GetError(); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + attributeDataElementBuilder.DataVersion(2); + err = attributeDataElementBuilder.GetError(); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + // Construct attribute data + { + chip::TLV::TLVWriter * pWriter = attributeDataElementBuilder.GetWriter(); + chip::TLV::TLVType dummyType = chip::TLV::kTLVType_NotSpecified; + err = pWriter->StartContainer(chip::TLV::ContextTag(AttributeDataElement::kCsTag_Data), chip::TLV::kTLVType_Structure, + dummyType); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + err = pWriter->PutBoolean(chip::TLV::ContextTag(1), true); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + err = pWriter->EndContainer(dummyType); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + } + + attributeDataElementBuilder.MoreClusterData(false); + err = attributeDataElementBuilder.GetError(); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + attributeDataElementBuilder.EndOfAttributeDataElement(); + NL_TEST_ASSERT(apSuite, attributeDataElementBuilder.GetError() == CHIP_NO_ERROR); + + attributeDataListBuilder.EndOfAttributeDataList(); + NL_TEST_ASSERT(apSuite, attributeDataListBuilder.GetError() == CHIP_NO_ERROR); + reportDataBuilder.SuppressResponse(true); NL_TEST_ASSERT(apSuite, reportDataBuilder.GetError() == CHIP_NO_ERROR); @@ -92,14 +148,15 @@ void TestReadInteraction::TestReadClient(nlTestSuite * apSuite, void * apContext app::ReadClient readClient; EventNumber eventNumber = 0; + chip::app::InteractionModelDelegate delegate; System::PacketBufferHandle buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); - err = readClient.Init(&gExchangeManager, nullptr); + err = readClient.Init(&gExchangeManager, &delegate); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); err = readClient.SendReadRequest(kTestDeviceNodeId, gAdminId, nullptr /*apEventPathParamsList*/, 0 /*aEventPathParamsListSize*/, nullptr /*apAttributePathParamsList*/, 0 /*aAttributePathParamsListSize*/, eventNumber /*aEventNumber*/); - NL_TEST_ASSERT(apSuite, err == CHIP_ERROR_INCORRECT_STATE); + NL_TEST_ASSERT(apSuite, err == CHIP_ERROR_NOT_CONNECTED); GenerateReportData(apSuite, apContext, buf); @@ -117,8 +174,8 @@ void TestReadInteraction::TestReadHandler(nlTestSuite * apSuite, void * apContex System::PacketBufferHandle reportDatabuf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); System::PacketBufferHandle readRequestbuf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); ReadRequest::Builder readRequestBuilder; - - err = InteractionModelEngine::GetInstance()->Init(&gExchangeManager, nullptr); + chip::app::InteractionModelDelegate delegate; + err = InteractionModelEngine::GetInstance()->Init(&gExchangeManager, &delegate); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); readHandler.Init(nullptr); @@ -129,7 +186,17 @@ void TestReadInteraction::TestReadHandler(nlTestSuite * apSuite, void * apContex writer.Init(std::move(readRequestbuf)); err = readRequestBuilder.Init(&writer); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); - readRequestBuilder.EventNumber(1); + + AttributePathList::Builder attributePathListBuilder = readRequestBuilder.CreateAttributePathListBuilder(); + NL_TEST_ASSERT(apSuite, attributePathListBuilder.GetError() == CHIP_NO_ERROR); + + AttributePath::Builder attributePathBuilder = attributePathListBuilder.CreateAttributePathBuilder(); + NL_TEST_ASSERT(apSuite, attributePathListBuilder.GetError() == CHIP_NO_ERROR); + + attributePathBuilder.NodeId(1).EndpointId(2).ClusterId(3).FieldId(4).ListIndex(5).EndOfAttributePath(); + err = attributePathBuilder.GetError(); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(apSuite, readRequestBuilder.GetError() == CHIP_NO_ERROR); readRequestBuilder.EndOfReadRequest(); NL_TEST_ASSERT(apSuite, readRequestBuilder.GetError() == CHIP_NO_ERROR); @@ -140,6 +207,121 @@ void TestReadInteraction::TestReadHandler(nlTestSuite * apSuite, void * apContex NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); } +void TestReadInteraction::TestReadClientGenerateAttributePathList(nlTestSuite * apSuite, void * apContext) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + app::ReadClient readClient; + chip::app::InteractionModelDelegate delegate; + System::PacketBufferHandle msgBuf; + System::PacketBufferTLVWriter writer; + ReadRequest::Builder request; + msgBuf = System::PacketBufferHandle::New(kMaxSecureSduLengthBytes); + NL_TEST_ASSERT(apSuite, !msgBuf.IsNull()); + writer.Init(std::move(msgBuf)); + err = request.Init(&writer); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + err = readClient.Init(&gExchangeManager, &delegate); + + AttributePathParams attributePathParams[2]; + attributePathParams[0].mFlags.Set(AttributePathParams::Flags::kFieldIdValid); + attributePathParams[1].mFlags.Set(AttributePathParams::Flags::kFieldIdValid); + attributePathParams[1].mFlags.Set(AttributePathParams::Flags::kListIndexValid); + err = readClient.GenerateAttributePathList(request, attributePathParams, 2 /*aAttributePathParamsListSize*/); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); +} + +void TestReadInteraction::TestReadClientGenerateInvalidAttributePathList(nlTestSuite * apSuite, void * apContext) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + app::ReadClient readClient; + chip::app::InteractionModelDelegate delegate; + System::PacketBufferHandle msgBuf; + System::PacketBufferTLVWriter writer; + ReadRequest::Builder request; + msgBuf = System::PacketBufferHandle::New(kMaxSecureSduLengthBytes); + NL_TEST_ASSERT(apSuite, !msgBuf.IsNull()); + writer.Init(std::move(msgBuf)); + err = readClient.Init(&gExchangeManager, &delegate); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + err = request.Init(&writer); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + AttributePathParams attributePathParams[2]; + attributePathParams[0].mFlags.Set(AttributePathParams::Flags::kFieldIdValid); + attributePathParams[1].mFlags.Set(AttributePathParams::Flags::kListIndexValid); + err = readClient.GenerateAttributePathList(request, attributePathParams, 2 /*aAttributePathParamsListSize*/); + NL_TEST_ASSERT(apSuite, err == CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); +} + +void TestReadInteraction::TestReadClientInvalidReport(nlTestSuite * apSuite, void * apContext) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + app::ReadClient readClient; + chip::app::InteractionModelDelegate delegate; + EventNumber eventNumber = 0; + + System::PacketBufferHandle buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); + err = readClient.Init(&gExchangeManager, &delegate); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + err = readClient.SendReadRequest(kTestDeviceNodeId, gAdminId, nullptr /*apEventPathParamsList*/, 0 /*aEventPathParamsListSize*/, + nullptr /*apAttributePathParamsList*/, 0 /*aAttributePathParamsListSize*/, + eventNumber /*aEventNumber*/); + NL_TEST_ASSERT(apSuite, err == CHIP_ERROR_NOT_CONNECTED); + + GenerateReportData(apSuite, apContext, buf, true /*aNeedInvalidReport*/); + + err = readClient.ProcessReportData(std::move(buf)); + NL_TEST_ASSERT(apSuite, err == CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); + + readClient.Shutdown(); +} + +void TestReadInteraction::TestReadHandlerInvalidAttributePath(nlTestSuite * apSuite, void * apContext) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + app::ReadHandler readHandler; + System::PacketBufferTLVWriter writer; + System::PacketBufferHandle reportDatabuf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); + System::PacketBufferHandle readRequestbuf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); + ReadRequest::Builder readRequestBuilder; + chip::app::InteractionModelDelegate delegate; + + err = InteractionModelEngine::GetInstance()->Init(&gExchangeManager, &delegate); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + readHandler.Init(nullptr); + + GenerateReportData(apSuite, apContext, reportDatabuf); + err = readHandler.SendReportData(std::move(reportDatabuf)); + NL_TEST_ASSERT(apSuite, err == CHIP_ERROR_INCORRECT_STATE); + + writer.Init(std::move(readRequestbuf)); + err = readRequestBuilder.Init(&writer); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + AttributePathList::Builder attributePathListBuilder = readRequestBuilder.CreateAttributePathListBuilder(); + NL_TEST_ASSERT(apSuite, attributePathListBuilder.GetError() == CHIP_NO_ERROR); + + AttributePath::Builder attributePathBuilder = attributePathListBuilder.CreateAttributePathBuilder(); + NL_TEST_ASSERT(apSuite, attributePathListBuilder.GetError() == CHIP_NO_ERROR); + + attributePathBuilder.NodeId(1).EndpointId(2).ClusterId(3).ListIndex(5).EndOfAttributePath(); + err = attributePathBuilder.GetError(); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + NL_TEST_ASSERT(apSuite, readRequestBuilder.GetError() == CHIP_NO_ERROR); + readRequestBuilder.EndOfReadRequest(); + NL_TEST_ASSERT(apSuite, readRequestBuilder.GetError() == CHIP_NO_ERROR); + err = writer.Finalize(&readRequestbuf); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + err = readHandler.OnReadRequest(nullptr, std::move(readRequestbuf)); + NL_TEST_ASSERT(apSuite, err == CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); +} + } // namespace app } // namespace chip @@ -179,6 +361,10 @@ const nlTest sTests[] = { NL_TEST_DEF("CheckReadClient", chip::app::TestReadInteraction::TestReadClient), NL_TEST_DEF("CheckReadHandler", chip::app::TestReadInteraction::TestReadHandler), + NL_TEST_DEF("TestReadClientGenerateAttributePathList", chip::app::TestReadInteraction::TestReadClientGenerateAttributePathList), + NL_TEST_DEF("TestReadClientGenerateInvalidAttributePathList", chip::app::TestReadInteraction::TestReadClientGenerateInvalidAttributePathList), + NL_TEST_DEF("TestReadClientInvalidReport", chip::app::TestReadInteraction::TestReadClientInvalidReport), + NL_TEST_DEF("TestReadHandlerInvalidAttributePath", chip::app::TestReadInteraction::TestReadHandlerInvalidAttributePath), NL_TEST_SENTINEL() }; // clang-format on diff --git a/src/app/tests/integration/chip_im_initiator.cpp b/src/app/tests/integration/chip_im_initiator.cpp index 24598dece3e019..732100e1692a21 100644 --- a/src/app/tests/integration/chip_im_initiator.cpp +++ b/src/app/tests/integration/chip_im_initiator.cpp @@ -182,7 +182,7 @@ CHIP_ERROR SendReadRequest(void) false /*not urgent*/); chip::app::AttributePathParams attributePathParams(chip::kTestDeviceNodeId, kTestEndpointId, kTestClusterId, 1, 0, - chip::app::AttributePathFlags::kFieldIdValid); + chip::app::AttributePathParams::Flags::kFieldIdValid); printf("\nSend read request message to Node: %" PRIu64 "\n", chip::kTestDeviceNodeId);