Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IM] Use DataModel::Encode in EncodeScalarAttributeWritePayload for complex types #10386

Merged
merged 4 commits into from
Oct 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/app/WriteClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <app/MessageDef/AttributeDataList.h>
#include <app/MessageDef/AttributeStatusIB.h>
#include <app/MessageDef/WriteRequest.h>
#include <app/data-model/Encode.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/CHIPTLVDebug.hpp>
#include <lib/support/CodeUtils.h>
Expand Down Expand Up @@ -183,14 +184,15 @@ class WriteClientHandle
* Encode an attribute value that can be directly encoded using TLVWriter::Put
*/
template <class T>
CHIP_ERROR EncodeScalarAttributeWritePayload(const chip::app::AttributePathParams & attributePath, T value)
CHIP_ERROR EncodeAttributeWritePayload(const chip::app::AttributePathParams & attributePath, const T & value)
{
chip::TLV::TLVWriter * writer = nullptr;

VerifyOrReturnError(mpWriteClient != nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorOnFailure(mpWriteClient->PrepareAttribute(attributePath));
VerifyOrReturnError((writer = mpWriteClient->GetAttributeDataElementTLVWriter()) != nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorOnFailure(writer->Put(chip::TLV::ContextTag(chip::app::AttributeDataElement::kCsTag_Data), value));
ReturnErrorOnFailure(
DataModel::Encode(*writer, chip::TLV::ContextTag(chip::app::AttributeDataElement::kCsTag_Data), value));
ReturnErrorOnFailure(mpWriteClient->FinishAttribute());

return CHIP_NO_ERROR;
Expand Down
80 changes: 80 additions & 0 deletions src/app/tests/TestWriteInteraction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* limitations under the License.
*/

#include <app-common/zap-generated/cluster-objects.h>
#include <app/InteractionModelEngine.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/CHIPTLV.h>
Expand Down Expand Up @@ -43,6 +44,9 @@ chip::TransportMgrBase gTransportManager;
chip::Test::LoopbackTransport gLoopback;
chip::Test::IOContext gIOContext;

uint8_t attributeDataTLV[CHIP_CONFIG_DEFAULT_UDP_MTU_SIZE];
size_t attributeDataTLVLen = 0;

using TestContext = chip::Test::MessagingContext;
TestContext sContext;

Expand All @@ -55,6 +59,7 @@ class TestWriteInteraction
static void TestWriteClient(nlTestSuite * apSuite, void * apContext);
static void TestWriteHandler(nlTestSuite * apSuite, void * apContext);
static void TestWriteRoundtrip(nlTestSuite * apSuite, void * apContext);
static void TestWriteRoundtripWithClusterObjects(nlTestSuite * apSuite, void * apContext);

private:
static void AddAttributeDataElement(nlTestSuite * apSuite, void * apContext, WriteClientHandle & aWriteClient);
Expand Down Expand Up @@ -257,6 +262,10 @@ void TestWriteInteraction::TestWriteHandler(nlTestSuite * apSuite, void * apCont

CHIP_ERROR WriteSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVReader & aReader, WriteHandler * aWriteHandler)
{
TLV::TLVWriter writer;
writer.Init(attributeDataTLV);
writer.CopyElement(TLV::AnonymousTag, aReader);
attributeDataTLVLen = writer.GetLengthWritten();
return aWriteHandler->AddAttributeStatusCode(
AttributePathParams(aClusterInfo.mNodeId, aClusterInfo.mEndpointId, aClusterInfo.mClusterId, aClusterInfo.mFieldId,
aClusterInfo.mListIndex, AttributePathParams::Flags::kFieldIdValid),
Expand All @@ -279,6 +288,76 @@ class RoundtripDelegate : public chip::app::InteractionModelDelegate
bool mGotResponse = false;
};

void TestWriteInteraction::TestWriteRoundtripWithClusterObjects(nlTestSuite * apSuite, void * apContext)
{
TestContext & ctx = *static_cast<TestContext *>(apContext);

CHIP_ERROR err = CHIP_NO_ERROR;

Messaging::ReliableMessageMgr * rm = ctx.GetExchangeManager().GetReliableMessageMgr();
// Shouldn't have anything in the retransmit table when starting the test.
NL_TEST_ASSERT(apSuite, rm->TestGetCountRetransTable() == 0);

RoundtripDelegate delegate;
auto * engine = chip::app::InteractionModelEngine::GetInstance();
err = engine->Init(&ctx.GetExchangeManager(), &delegate);
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);

app::WriteClientHandle writeClient;
err = engine->NewWriteClient(writeClient);
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);

System::PacketBufferHandle buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize);

AttributePathParams attributePathParams;
attributePathParams.mNodeId = 1;
attributePathParams.mEndpointId = 2;
attributePathParams.mClusterId = 3;
attributePathParams.mFieldId = 4;
attributePathParams.mFlags.Set(AttributePathParams::Flags::kFieldIdValid);

const uint8_t byteSpanData[] = { 0xde, 0xad, 0xbe, 0xef };
const char charSpanData[] = "a simple test string";

app::Clusters::TestCluster::Structs::SimpleStruct::Type dataTx;
dataTx.a = 12;
dataTx.b = true;
dataTx.d = chip::ByteSpan(byteSpanData);
// Spec A.11.2 strings SHALL NOT include a terminating null character to mark the end of a string.
dataTx.e = chip::Span<const char>(charSpanData, strlen(charSpanData));

writeClient.EncodeAttributeWritePayload(attributePathParams, dataTx);
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);

NL_TEST_ASSERT(apSuite, !delegate.mGotResponse);

SessionHandle session = ctx.GetSessionBobToAlice();

err = writeClient.SendWriteRequest(ctx.GetAliceNodeId(), ctx.GetFabricIndex(), Optional<SessionHandle>::Value(session));
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);

NL_TEST_ASSERT(apSuite, delegate.mGotResponse);

{
app::Clusters::TestCluster::Structs::SimpleStruct::Type dataRx;
TLV::TLVReader reader;
reader.Init(attributeDataTLV, attributeDataTLVLen);
reader.Next();
NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == DataModel::Decode(reader, dataRx));
NL_TEST_ASSERT(apSuite, dataRx.a == dataTx.a);
NL_TEST_ASSERT(apSuite, dataRx.b == dataTx.b);
NL_TEST_ASSERT(apSuite, dataRx.d.data_equal(dataTx.d));
// Equals to dataRx.e.size() == dataTx.e.size() && memncmp(dataRx.e.data(), dataTx.e.data(), dataTx.e.size()) == 0
NL_TEST_ASSERT(apSuite, dataRx.e.data_equal(dataTx.e));
erjiaqing marked this conversation as resolved.
Show resolved Hide resolved
}

// By now we should have closed all exchanges and sent all pending acks, so
// there should be no queued-up things in the retransmit table.
NL_TEST_ASSERT(apSuite, rm->TestGetCountRetransTable() == 0);

engine->Shutdown();
}

void TestWriteInteraction::TestWriteRoundtrip(nlTestSuite * apSuite, void * apContext)
{
TestContext & ctx = *static_cast<TestContext *>(apContext);
Expand Down Expand Up @@ -332,6 +411,7 @@ const nlTest sTests[] =
NL_TEST_DEF("CheckWriteClient", chip::app::TestWriteInteraction::TestWriteClient),
NL_TEST_DEF("CheckWriteHandler", chip::app::TestWriteInteraction::TestWriteHandler),
NL_TEST_DEF("CheckWriteRoundtrip", chip::app::TestWriteInteraction::TestWriteRoundtrip),
NL_TEST_DEF("TestWriteRoundtripWithClusterObjects", chip::app::TestWriteInteraction::TestWriteRoundtripWithClusterObjects),
NL_TEST_SENTINEL()
};
// clang-format on
Expand Down
2 changes: 1 addition & 1 deletion src/app/zap-templates/templates/app/CHIPClusters-src.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ CHIP_ERROR {{asUpperCamelCase parent.name}}Cluster::WriteAttribute{{asUpperCamel
attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid);

ReturnErrorOnFailure(app::InteractionModelEngine::GetInstance()->NewWriteClient(handle));
ReturnErrorOnFailure(handle.EncodeScalarAttributeWritePayload(attributePath, value));
ReturnErrorOnFailure(handle.EncodeAttributeWritePayload(attributePath, value));

return mDevice->SendWriteAttributeRequest(std::move(handle), onSuccessCallback, onFailureCallback);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ CHIP_ERROR {{asUpperCamelCase parent.name}}ClusterTest::WriteAttribute{{asUpperC
attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid);

ReturnErrorOnFailure(app::InteractionModelEngine::GetInstance()->NewWriteClient(handle));
ReturnErrorOnFailure(handle.EncodeScalarAttributeWritePayload(attributePath, {{asLowerCamelCase name}}));
ReturnErrorOnFailure(handle.EncodeAttributeWritePayload(attributePath, {{asLowerCamelCase name}}));

return mDevice->SendWriteAttributeRequest(std::move(handle), onSuccessCallback, onFailureCallback);
}
Expand Down
Loading