|
16 | 16 | * limitations under the License.
|
17 | 17 | */
|
18 | 18 |
|
19 |
| -#include <gtest/gtest.h> |
| 19 | +#include <lib/core/StringBuilderAdapters.h> |
| 20 | +#include <pw_unit_test/framework.h> |
20 | 21 |
|
21 | 22 | #include "system/SystemClock.h"
|
22 | 23 | #include "transport/SecureSession.h"
|
|
25 | 26 | #include <app/ConcreteAttributePath.h>
|
26 | 27 | #include <app/ConcreteEventPath.h>
|
27 | 28 | #include <app/InteractionModelEngine.h>
|
| 29 | +#include <app/ReadClient.h> |
28 | 30 | #include <app/tests/AppTestContext.h>
|
29 | 31 | #include <app/util/mock/Constants.h>
|
30 | 32 | #include <app/util/mock/Functions.h>
|
@@ -3093,6 +3095,86 @@ TEST_F(TestRead, TestReadHandler_MultipleSubscriptionsWithDataVersionFilter)
|
3093 | 3095 | EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u);
|
3094 | 3096 | }
|
3095 | 3097 |
|
| 3098 | +TEST_F(TestRead, TestReadHandler_DataVersionFiltersTruncated) |
| 3099 | +{ |
| 3100 | + struct : public chip::Test::LoopbackTransportDelegate |
| 3101 | + { |
| 3102 | + size_t requestSize = 0; |
| 3103 | + void WillSendMessage(const Transport::PeerAddress & peer, const System::PacketBufferHandle & message) override |
| 3104 | + { |
| 3105 | + // We only care about the messages we (Alice) send to Bob, not the responses. |
| 3106 | + // Assume the first message we see in an iteration is the request. |
| 3107 | + if (peer == mpContext->GetBobAddress() && requestSize == 0) |
| 3108 | + { |
| 3109 | + requestSize = message->TotalLength(); |
| 3110 | + } |
| 3111 | + } |
| 3112 | + } loopbackDelegate; |
| 3113 | + mpContext->GetLoopback().SetLoopbackTransportDelegate(&loopbackDelegate); |
| 3114 | + |
| 3115 | + // Note that on the server side, wildcard expansion does not actually work for kTestEndpointId due |
| 3116 | + // to lack of meta-data, but we don't care about the reports we get back in this test. |
| 3117 | + AttributePathParams wildcardPath(kTestEndpointId, kInvalidClusterId, kInvalidAttributeId); |
| 3118 | + constexpr size_t maxDataVersionFilterCount = 100; |
| 3119 | + DataVersionFilter dataVersionFilters[maxDataVersionFilterCount]; |
| 3120 | + ClusterId nextClusterId = 0; |
| 3121 | + for (auto & dv : dataVersionFilters) |
| 3122 | + { |
| 3123 | + dv.mEndpointId = wildcardPath.mEndpointId; |
| 3124 | + dv.mClusterId = nextClusterId++; |
| 3125 | + dv.mDataVersion = MakeOptional(0x01000000u); |
| 3126 | + } |
| 3127 | + |
| 3128 | + // Keep increasing the number of data version filters until we see truncation kick in. |
| 3129 | + size_t lastRequestSize; |
| 3130 | + for (size_t count = 1; count <= maxDataVersionFilterCount; count++) |
| 3131 | + { |
| 3132 | + lastRequestSize = loopbackDelegate.requestSize; |
| 3133 | + loopbackDelegate.requestSize = 0; // reset |
| 3134 | + |
| 3135 | + ReadPrepareParams read(mpContext->GetSessionAliceToBob()); |
| 3136 | + read.mpAttributePathParamsList = &wildcardPath; |
| 3137 | + read.mAttributePathParamsListSize = 1; |
| 3138 | + read.mpDataVersionFilterList = dataVersionFilters; |
| 3139 | + read.mDataVersionFilterListSize = count; |
| 3140 | + |
| 3141 | + struct : public ReadClient::Callback |
| 3142 | + { |
| 3143 | + CHIP_ERROR error = CHIP_NO_ERROR; |
| 3144 | + bool done = false; |
| 3145 | + void OnError(CHIP_ERROR aError) override { error = aError; } |
| 3146 | + void OnDone(ReadClient * apReadClient) override { done = true; }; |
| 3147 | + |
| 3148 | + } readCallback; |
| 3149 | + |
| 3150 | + ReadClient readClient(app::InteractionModelEngine::GetInstance(), &mpContext->GetExchangeManager(), readCallback, |
| 3151 | + ReadClient::InteractionType::Read); |
| 3152 | + |
| 3153 | + EXPECT_EQ(readClient.SendRequest(read), CHIP_NO_ERROR); |
| 3154 | + |
| 3155 | + mpContext->GetIOContext().DriveIOUntil(System::Clock::Seconds16(5), [&]() { return readCallback.done; }); |
| 3156 | + EXPECT_EQ(readCallback.error, CHIP_NO_ERROR); |
| 3157 | + EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u); |
| 3158 | + |
| 3159 | + EXPECT_NE(loopbackDelegate.requestSize, 0u); |
| 3160 | + EXPECT_GE(loopbackDelegate.requestSize, lastRequestSize); |
| 3161 | + if (loopbackDelegate.requestSize == lastRequestSize) |
| 3162 | + { |
| 3163 | + ChipLogProgress(DataManagement, "Data Version truncation detected after %llu elements", |
| 3164 | + static_cast<unsigned long long>(count - 1)); |
| 3165 | + // With the parameters used in this test and current encoding rules we can fit 68 data versions |
| 3166 | + // into a packet. If we're seeing substantially less then something is likely gone wrong. |
| 3167 | + EXPECT_GE(count, 60u); |
| 3168 | + ExitNow(); |
| 3169 | + } |
| 3170 | + } |
| 3171 | + ChipLogProgress(DataManagement, "Unable to detect Data Version truncation, maxDataVersionFilterCount too small?"); |
| 3172 | + ADD_FAILURE(); |
| 3173 | + |
| 3174 | +exit: |
| 3175 | + mpContext->GetLoopback().SetLoopbackTransportDelegate(nullptr); |
| 3176 | +} |
| 3177 | + |
3096 | 3178 | TEST_F(TestRead, TestReadHandlerResourceExhaustion_MultipleReads)
|
3097 | 3179 | {
|
3098 | 3180 | auto sessionHandle = mpContext->GetSessionBobToAlice();
|
|
0 commit comments