add mNumReportsInFlight check test when failing to send report (#24106)

diff --git a/src/app/tests/TestReadInteraction.cpp b/src/app/tests/TestReadInteraction.cpp
index d9e42b9..af2e7a1 100644
--- a/src/app/tests/TestReadInteraction.cpp
+++ b/src/app/tests/TestReadInteraction.cpp
@@ -319,6 +319,7 @@
     static void TestSubscribeRoundtripStatusReportTimeout(nlTestSuite * apSuite, void * apContext);
     static void TestPostSubscribeRoundtripStatusReportTimeout(nlTestSuite * apSuite, void * apContext);
     static void TestReadChunkingStatusReportTimeout(nlTestSuite * apSuite, void * apContext);
+    static void TestReadReportFailure(nlTestSuite * apSuite, void * apContext);
     static void TestSubscribeRoundtripChunkStatusReportTimeout(nlTestSuite * apSuite, void * apContext);
     static void TestPostSubscribeRoundtripChunkStatusReportTimeout(nlTestSuite * apSuite, void * apContext);
     static void TestPostSubscribeRoundtripChunkReportTimeout(nlTestSuite * apSuite, void * apContext);
@@ -2531,6 +2532,57 @@
     ctx.CreateSessionBobToAlice();
 }
 
+// ReadClient sends the read request, but handler fails to send the one report (SendMessage returns an error).
+// Since this is an un-chunked read, we are not in the AwaitingReportResponse state, so the "reports in flight"
+// counter should not increase.
+void TestReadInteraction::TestReadReportFailure(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);
+
+    MockInteractionModelApp delegate;
+    auto * engine = chip::app::InteractionModelEngine::GetInstance();
+    err           = engine->Init(&ctx.GetExchangeManager(), &ctx.GetFabricTable());
+    NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+    NL_TEST_ASSERT(apSuite, !delegate.mGotEventResponse);
+
+    chip::app::AttributePathParams attributePathParams[1];
+    attributePathParams[0].mEndpointId  = Test::kMockEndpoint2;
+    attributePathParams[0].mClusterId   = Test::MockClusterId(3);
+    attributePathParams[0].mAttributeId = Test::MockAttributeId(1);
+
+    ReadPrepareParams readPrepareParams(ctx.GetSessionBobToAlice());
+    readPrepareParams.mpEventPathParamsList        = nullptr;
+    readPrepareParams.mEventPathParamsListSize     = 0;
+    readPrepareParams.mpAttributePathParamsList    = attributePathParams;
+    readPrepareParams.mAttributePathParamsListSize = 1;
+
+    {
+        app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(), delegate,
+                                   chip::app::ReadClient::InteractionType::Read);
+
+        ctx.GetLoopback().mNumMessagesToAllowBeforeError = 1;
+        ctx.GetLoopback().mMessageSendError              = CHIP_ERROR_INCORRECT_STATE;
+        err                                              = readClient.SendRequest(readPrepareParams);
+        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+
+        ctx.DrainAndServiceIO();
+        NL_TEST_ASSERT(apSuite, engine->GetReportingEngine().GetNumReportsInFlight() == 0);
+        NL_TEST_ASSERT(apSuite, engine->GetNumActiveReadHandlers() == 0);
+
+        ctx.GetLoopback().mNumMessagesToAllowBeforeError = 0;
+        ctx.GetLoopback().mMessageSendError              = CHIP_NO_ERROR;
+    }
+
+    NL_TEST_ASSERT(apSuite, engine->GetNumActiveReadClients() == 0);
+    engine->Shutdown();
+    NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
+}
+
 void TestReadInteraction::TestSubscribeRoundtripChunkStatusReportTimeout(nlTestSuite * apSuite, void * apContext)
 {
     TestContext & ctx = *static_cast<TestContext *>(apContext);
@@ -4155,6 +4207,7 @@
     NL_TEST_DEF("TestSubscribeRoundtripStatusReportTimeout", chip::app::TestReadInteraction::TestSubscribeRoundtripStatusReportTimeout),
     NL_TEST_DEF("TestPostSubscribeRoundtripStatusReportTimeout", chip::app::TestReadInteraction::TestPostSubscribeRoundtripStatusReportTimeout),
     NL_TEST_DEF("TestReadChunkingStatusReportTimeout", chip::app::TestReadInteraction::TestReadChunkingStatusReportTimeout),
+    NL_TEST_DEF("TestReadReportFailure", chip::app::TestReadInteraction::TestReadReportFailure),
     NL_TEST_DEF("TestSubscribeRoundtripChunkStatusReportTimeout", chip::app::TestReadInteraction::TestSubscribeRoundtripChunkStatusReportTimeout),
     NL_TEST_DEF("TestPostSubscribeRoundtripChunkStatusReportTimeout", chip::app::TestReadInteraction::TestPostSubscribeRoundtripChunkStatusReportTimeout),
     NL_TEST_DEF("TestPostSubscribeRoundtripChunkReportTimeout", chip::app::TestReadInteraction::TestPostSubscribeRoundtripChunkReportTimeout),
diff --git a/src/transport/raw/tests/NetworkTestHelpers.h b/src/transport/raw/tests/NetworkTestHelpers.h
index 6de687e..2ee7b9f 100644
--- a/src/transport/raw/tests/NetworkTestHelpers.h
+++ b/src/transport/raw/tests/NetworkTestHelpers.h
@@ -103,9 +103,16 @@
 
     CHIP_ERROR SendMessage(const Transport::PeerAddress & address, System::PacketBufferHandle && msgBuf) override
     {
-        ReturnErrorOnFailure(mMessageSendError);
+        if (mNumMessagesToAllowBeforeError == 0)
+        {
+            ReturnErrorOnFailure(mMessageSendError);
+        }
         mSentMessageCount++;
         bool dropMessage = false;
+        if (mNumMessagesToAllowBeforeError > 0)
+        {
+            --mNumMessagesToAllowBeforeError;
+        }
         if (mNumMessagesToAllowBeforeDropping > 0)
         {
             --mNumMessagesToAllowBeforeDropping;
@@ -141,6 +148,7 @@
         mDroppedMessageCount              = 0;
         mSentMessageCount                 = 0;
         mNumMessagesToAllowBeforeDropping = 0;
+        mNumMessagesToAllowBeforeError    = 0;
         mMessageSendError                 = CHIP_NO_ERROR;
     }
 
@@ -160,6 +168,7 @@
     uint32_t mDroppedMessageCount              = 0;
     uint32_t mSentMessageCount                 = 0;
     uint32_t mNumMessagesToAllowBeforeDropping = 0;
+    uint32_t mNumMessagesToAllowBeforeError    = 0;
     CHIP_ERROR mMessageSendError               = CHIP_NO_ERROR;
     LoopbackTransportDelegate * mDelegate      = nullptr;
 };