Skip to content

Commit

Permalink
Add test for ReadClient data version truncation
Browse files Browse the repository at this point in the history
  • Loading branch information
ksperling-apple authored and woody-apple committed Jul 1, 2024
1 parent 4f5923f commit 005d220
Showing 1 changed file with 77 additions and 0 deletions.
77 changes: 77 additions & 0 deletions src/controller/tests/data_model/TestRead.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <app/ConcreteAttributePath.h>
#include <app/ConcreteEventPath.h>
#include <app/InteractionModelEngine.h>
#include <app/ReadClient.h>
#include <app/tests/AppTestContext.h>
#include <app/util/mock/Constants.h>
#include <app/util/mock/Functions.h>
Expand Down Expand Up @@ -3094,6 +3095,82 @@ TEST_F(TestRead, TestReadHandler_MultipleSubscriptionsWithDataVersionFilter)
EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
}

TEST_F(TestRead, TestReadHandler_DataVersionFiltersTruncated)
{
struct : public chip::Test::LoopbackTransportDelegate
{
size_t requestSize;
void WillSendMessage(const Transport::PeerAddress & peer, const System::PacketBufferHandle & message) override
{
// We only care about the messages we (Alice) send to Bob, not the responses.
// Assume the first message we see in an iteration is the request.
if (peer == mpContext->GetBobAddress() && requestSize == 0)
{
requestSize = message->TotalLength();
}
}
} loopbackDelegate;
mpContext->GetLoopback().SetLoopbackTransportDelegate(&loopbackDelegate);

// Note that on the server side, wildcard expansion does not actually work for kTestEndpointId due
// to lack of meta-data, but we don't care about the reports we get back in this test.
AttributePathParams wildcardPath(kTestEndpointId, kInvalidClusterId, kInvalidAttributeId);
constexpr size_t maxDataVersionFilterCount = 100;
DataVersionFilter dataVersionFilters[maxDataVersionFilterCount];
ClusterId nextClusterId = 0;
for (auto & dv : dataVersionFilters)
{
dv.mEndpointId = wildcardPath.mEndpointId;
dv.mClusterId = nextClusterId++;
dv.mDataVersion = MakeOptional(0x01000000u);
}

// Keep increasing the number of data version filters until we see truncation kick in.
size_t lastRequestSize;
for (size_t count = 1; count <= maxDataVersionFilterCount; count++)
{
lastRequestSize = loopbackDelegate.requestSize;
loopbackDelegate.requestSize = 0; // reset

ReadPrepareParams read(mpContext->GetSessionAliceToBob());
read.mpAttributePathParamsList = &wildcardPath;
read.mAttributePathParamsListSize = 1;
read.mpDataVersionFilterList = dataVersionFilters;
read.mDataVersionFilterListSize = count;

struct : public ReadClient::Callback
{
CHIP_ERROR error = CHIP_NO_ERROR;
bool done = false;
void OnError(CHIP_ERROR aError) override { error = aError; }
void OnDone(ReadClient * apReadClient) override { done = true; };

} readCallback;

ReadClient readClient(app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(), readCallback,
ReadClient::InteractionType::Read);

EXPECT_EQ(readClient.SendRequest(read), CHIP_NO_ERROR);

mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.done; });
EXPECT_EQ(readCallback.error, CHIP_NO_ERROR);
EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);

EXPECT_NE(loopbackDelegate.requestSize, 0u);
EXPECT_GE(loopbackDelegate.requestSize, lastRequestSize);
if (loopbackDelegate.requestSize == lastRequestSize)
{
ChipLogProgress(DataManagement, "Data Version truncation detected after %zu elements", count - 1);
// With the parameters used in this test and current encoding rules we can fit 68 data versions
// into a packet. If we're seeing substantially less then something is likely gone wrong.
EXPECT_GE(count, 60u);
break;
}
}

mpContext->GetLoopback().SetLoopbackTransportDelegate(nullptr);
}

TEST_F(TestRead, TestReadHandlerResourceExhaustion_MultipleReads)
{
auto sessionHandle = mpContext->GetSessionBobToAlice();
Expand Down

0 comments on commit 005d220

Please sign in to comment.