/*
 *    Copyright (c) 2022 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 aborting existing exchanges (except
 *      one) for a fabric.
 */

#include <gtest/gtest.h>

#include "messaging/ExchangeDelegate.h"
#include "system/SystemClock.h"
#include <messaging/ExchangeContext.h>
#include <messaging/ExchangeHolder.h>
#include <messaging/ExchangeMgr.h>
#include <messaging/tests/MessagingContext.h>
#include <protocols/Protocols.h>
#include <system/SystemPacketBuffer.h>
#include <transport/SessionManager.h>

namespace chip {
namespace Protocols {

//
// Let's create a mock protocol that encapsulates a 3 message exchange to test out the ExchangeHolder
// and the various states the underlying exchange might be set to, altering the clean-up behavior
// the holder will execute depending on those states.
//
namespace MockProtocol {
static constexpr Id Id(VendorId::TestVendor1, 1);

enum class MessageType : uint8_t
{
    kMsg1 = 0x01,
    kMsg2 = 0x02,
    kMsg3 = 0x03
};
} // namespace MockProtocol

template <>
struct MessageTypeTraits<MockProtocol::MessageType>
{
    static constexpr const Protocols::Id & ProtocolId() { return MockProtocol::Id; }
};

} // namespace Protocols
} // namespace chip

namespace {

using namespace chip;
using namespace chip::Messaging;
using namespace chip::System;
using namespace chip::Protocols;

struct TestExchangeHolder : public chip::Test::LoopbackMessagingContext, public ::testing::Test
{
    static void SetUpTestSuite() { chip::Test::LoopbackMessagingContext::SetUpTestSuite(); }

    static void TearDownTestSuite() { chip::Test::LoopbackMessagingContext::TearDownTestSuite(); }

    void SetUp() override { chip::Test::LoopbackMessagingContext::SetUp(); }

    void TearDown() override { chip::Test::LoopbackMessagingContext::TearDown(); }
};

class MockProtocolResponder : public ExchangeDelegate, public Messaging::UnsolicitedMessageHandler
{
public:
    enum class BehaviorModifier : uint8_t
    {
        kNone                          = 0x00,
        kHoldMsg2                      = 0x01,
        kErrMsg2                       = 0x02,
        kExpireSessionBeforeMsg2Send   = 0x04,
        kExpireSessionAfterMsg2Send    = 0x08,
        kExpireSessionAfterMsg3Receive = 0x10,
    };

    template <typename... Args>
    MockProtocolResponder(TestExchangeHolder & ctx, BehaviorModifier modifier1, Args &&... args) :
        mExchangeCtx(*this), mBehaviorModifier(modifier1, std::forward<Args>(args)...), testExchangeHolder(ctx)
    {
        testExchangeHolder.GetExchangeManager().RegisterUnsolicitedMessageHandlerForProtocol(chip::Protocols::MockProtocol::Id,
                                                                                             this);
        ChipLogDetail(ExchangeManager, "[%p] MockProtocolResponder: %p", this, &mExchangeCtx);
    }

    MockProtocolResponder(TestExchangeHolder & ctx, BehaviorModifier modifier = BehaviorModifier::kNone) :
        mExchangeCtx(*this), testExchangeHolder(ctx)
    {
        mBehaviorModifier.Set(modifier);
        testExchangeHolder.GetExchangeManager().RegisterUnsolicitedMessageHandlerForProtocol(chip::Protocols::MockProtocol::Id,
                                                                                             this);
        ChipLogDetail(ExchangeManager, "[%p] MockProtocolResponder: %p", this, &mExchangeCtx);
    }

    ~MockProtocolResponder()
    {
        ChipLogDetail(ExchangeManager, "[%p] ~MockProtocolResponder", this);
        testExchangeHolder.GetExchangeManager().UnregisterUnsolicitedMessageHandlerForProtocol(chip::Protocols::MockProtocol::Id);
    }

    bool DidInteractionSucceed() { return mInteractionSucceeded; }

private:
    CHIP_ERROR OnMessageReceived(ExchangeContext * ec, const PayloadHeader & payloadHeader,
                                 System::PacketBufferHandle && buffer) override;

    CHIP_ERROR OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, ExchangeDelegate *& newDelegate) override
    {
        newDelegate = this;
        return CHIP_NO_ERROR;
    }

    void OnResponseTimeout(ExchangeContext * ec) override {}

    ExchangeHolder mExchangeCtx;
    BitFlags<BehaviorModifier> mBehaviorModifier = BehaviorModifier::kNone;
    bool mInteractionSucceeded                   = false;
    TestExchangeHolder & testExchangeHolder;
};

class MockProtocolInitiator : public ExchangeDelegate
{
public:
    enum class BehaviorModifier : uint8_t
    {
        kNone                        = 0x00,
        kHoldMsg3                    = 0x01,
        kErrMsg1                     = 0x02,
        kErrMsg3                     = 0x04,
        kDontSendMsg1                = 0x08,
        kExpireSessionBeforeMsg1Send = 0x10,
        kExpireSessionAfterMsg1Send  = 0x12,
        kExpireSessionBeforeMsg3Send = 0x14,
        kExpireSessionAfterMsg3Send  = 0x18,
    };

    MockProtocolInitiator(TestExchangeHolder & ctx, BehaviorModifier modifier = BehaviorModifier::kNone) :
        mExchangeCtx(*this), testExchangeHolder(ctx)
    {
        mBehaviorModifier.Set(modifier);
        ChipLogDetail(ExchangeManager, "[%p] MockProtocolInitiator: %p", this, &mExchangeCtx);
    }

    template <typename... Args>
    MockProtocolInitiator(TestExchangeHolder & ctx, BehaviorModifier modifier1, Args &&... args) :
        mExchangeCtx(*this), mBehaviorModifier(modifier1, std::forward<Args>(args)...), testExchangeHolder(ctx)
    {
        ChipLogDetail(ExchangeManager, "[%p] MockProtocolInitiator: %p", this, &mExchangeCtx);
    }

    ~MockProtocolInitiator() { ChipLogDetail(ExchangeManager, "[%p] ~MockProtocolInitiator", this); }

    CHIP_ERROR StartInteraction(SessionHandle & sessionHandle);

    bool DidInteractionSucceed() { return mInteractionSucceeded; }

private:
    CHIP_ERROR OnMessageReceived(ExchangeContext * ec, const PayloadHeader & payloadHeader,
                                 System::PacketBufferHandle && buffer) override;

    void OnResponseTimeout(ExchangeContext * ec) override {}

    ExchangeHolder mExchangeCtx;
    BitFlags<BehaviorModifier> mBehaviorModifier = BehaviorModifier::kNone;
    bool mInteractionSucceeded                   = false;
    TestExchangeHolder & testExchangeHolder;
};

CHIP_ERROR MockProtocolResponder::OnMessageReceived(ExchangeContext * ec, const PayloadHeader & payloadHeader,
                                                    System::PacketBufferHandle && buffer)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    if (payloadHeader.HasMessageType(chip::Protocols::MockProtocol::MessageType::kMsg1))
    {
        //
        // This is the first message in the exchange - let's have our holder start managing the exchange by grabbing it.
        //
        mExchangeCtx.Grab(ec);

        if (!mBehaviorModifier.Has(BehaviorModifier::kHoldMsg2))
        {
            PacketBufferHandle respBuffer = MessagePacketBuffer::New(0);
            VerifyOrReturnError(!buffer.IsNull(), CHIP_ERROR_NO_MEMORY);

            if (mBehaviorModifier.Has(BehaviorModifier::kErrMsg2))
            {
                mExchangeCtx->InjectFailure(ExchangeContext::InjectedFailureType::kFailOnSend);
            }

            if (mBehaviorModifier.Has(BehaviorModifier::kExpireSessionBeforeMsg2Send))
            {
                mExchangeCtx->GetSessionHolder().Release();
                mExchangeCtx->OnSessionReleased();
            }

            if (mExchangeCtx)
            {
                err = mExchangeCtx->SendMessage(chip::Protocols::MockProtocol::MessageType::kMsg2, std::move(respBuffer),
                                                SendMessageFlags::kExpectResponse);
                if (mExchangeCtx)
                {
                    mExchangeCtx->ClearInjectedFailures();
                }

                ReturnErrorOnFailure(err);
            }

            if (mBehaviorModifier.Has(BehaviorModifier::kExpireSessionAfterMsg2Send))
            {
                mExchangeCtx->GetSessionHolder().Release();
                mExchangeCtx->OnSessionReleased();
            }
        }
        else
        {
            mExchangeCtx->WillSendMessage();
        }
    }
    else if (payloadHeader.HasMessageType(chip::Protocols::MockProtocol::MessageType::kMsg3))
    {
        if (mBehaviorModifier.Has(BehaviorModifier::kExpireSessionAfterMsg3Receive))
        {
            mExchangeCtx->GetSessionHolder().Release();
            mExchangeCtx->OnSessionReleased();
        }

        mInteractionSucceeded = true;
    }
    else
    {
        err = CHIP_ERROR_INVALID_MESSAGE_TYPE;
    }

    return err;
}

CHIP_ERROR MockProtocolInitiator::StartInteraction(SessionHandle & sessionHandle)
{
    PacketBufferHandle buffer = MessagePacketBuffer::New(0);
    VerifyOrReturnError(!buffer.IsNull(), CHIP_ERROR_NO_MEMORY);

    auto exchange = testExchangeHolder.GetExchangeManager().NewContext(sessionHandle, this);
    VerifyOrReturnError(exchange != nullptr, CHIP_ERROR_NO_MEMORY);

    //
    // This is the first exchange in this interaction - let's have our holder start managing the exchange by grabbing it.
    //
    mExchangeCtx.Grab(exchange);

    if (mBehaviorModifier.Has(BehaviorModifier::kErrMsg1))
    {
        mExchangeCtx->InjectFailure(ExchangeContext::InjectedFailureType::kFailOnSend);
    }

    if (mBehaviorModifier.Has(BehaviorModifier::kExpireSessionBeforeMsg1Send))
    {
        mExchangeCtx->GetSessionHolder().Release();
        mExchangeCtx->OnSessionReleased();
    }

    if (!mBehaviorModifier.Has(BehaviorModifier::kDontSendMsg1))
    {
        auto err = mExchangeCtx->SendMessage(chip::Protocols::MockProtocol::MessageType::kMsg1, std::move(buffer),
                                             SendMessageFlags::kExpectResponse);
        if (mExchangeCtx)
        {
            mExchangeCtx->ClearInjectedFailures();
        }

        ReturnErrorOnFailure(err);
    }

    if (mBehaviorModifier.Has(BehaviorModifier::kExpireSessionAfterMsg1Send))
    {
        mExchangeCtx->GetSessionHolder().Release();
        mExchangeCtx->OnSessionReleased();
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR MockProtocolInitiator::OnMessageReceived(ExchangeContext * ec, const PayloadHeader & payloadHeader,
                                                    System::PacketBufferHandle && buffer)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    if (payloadHeader.HasMessageType(chip::Protocols::MockProtocol::MessageType::kMsg2))
    {
        if (!mBehaviorModifier.Has(BehaviorModifier::kHoldMsg3))
        {
            if (mBehaviorModifier.Has(BehaviorModifier::kExpireSessionBeforeMsg3Send))
            {
                mExchangeCtx->GetSessionHolder().Release();
                mExchangeCtx->OnSessionReleased();
            }

            PacketBufferHandle respBuffer = MessagePacketBuffer::New(0);
            VerifyOrReturnError(!buffer.IsNull(), CHIP_ERROR_NO_MEMORY);

            if (mBehaviorModifier.Has(BehaviorModifier::kErrMsg3))
            {
                mExchangeCtx->InjectFailure(ExchangeContext::InjectedFailureType::kFailOnSend);
            }

            if (mExchangeCtx)
            {
                err = mExchangeCtx->SendMessage(chip::Protocols::MockProtocol::MessageType::kMsg3, std::move(respBuffer),
                                                SendMessageFlags::kNone);
                if (mExchangeCtx)
                {
                    mExchangeCtx->ClearInjectedFailures();
                }

                ReturnErrorOnFailure(err);
            }

            if (mBehaviorModifier.Has(BehaviorModifier::kExpireSessionAfterMsg3Send))
            {
                mExchangeCtx->GetSessionHolder().Release();
                mExchangeCtx->OnSessionReleased();
            }

            mInteractionSucceeded = true;
        }
        else
        {
            mExchangeCtx->WillSendMessage();
        }
    }
    else
    {
        err = CHIP_ERROR_INVALID_MESSAGE_TYPE;
    }

    return err;
}

TEST_F(TestExchangeHolder, TestExchangeHolder)
{
    auto sessionHandle = GetSessionAliceToBob();

    SetMRPMode(chip::Test::MessagingContext::MRPMode::kResponsive);

    //
    // #1: Initiator (AllocExchange)
    //
    // The initiator just allocated the exchange, but doesn't send a message on it.
    //
    // Then, destroy both objects. Initiator's holder should correctly abort the exchange since it still owns
    // it.
    //
    {
        ChipLogProgress(ExchangeManager, "-------- #1: Initiator (AllocExchange) ----------");

        {
            MockProtocolInitiator initiator(*this, MockProtocolInitiator::BehaviorModifier::kDontSendMsg1);
            MockProtocolResponder responder(*this);

            auto err = initiator.StartInteraction(sessionHandle);
            EXPECT_EQ(err, CHIP_NO_ERROR);
        }

        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    //
    // #2: Initiator --X Msg1
    //
    // Inject a failure to transmit Msg1. This should retain the WillSendMessage flag on the initiator's exchange.
    //
    // Then, destroy both objects. Initiator's holder should correctly abort the exchange since it's still has the
    // WillSendMessage flag on it.
    //
    //
    {
        ChipLogProgress(ExchangeManager, "-------- #2: Initiator --X (SendErr) Msg1 --------- ");

        {
            MockProtocolInitiator initiator(*this, MockProtocolInitiator::BehaviorModifier::kErrMsg1);
            MockProtocolResponder responder(*this);

            auto err = initiator.StartInteraction(sessionHandle);
            EXPECT_NE(err, CHIP_NO_ERROR);
        }

        //
        // Service IO AFTER the objects above cease to exist to prevent Msg1 from getting to Responder. This also
        // flush any pending messages in the queue.
        //
        DrainAndServiceIO();
        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    //
    // #3: Initiator --X (Session Released Before) -- Msg1
    //
    // Inject a release of the session associated with the exchange on the initiator before sending Msg1. This
    // should just close out the exchange without releasing the ref.
    //
    // Then, destroy both objects. The initiator's holder should correctly abort the exchange since WillSendMessage
    // should still be present on the EC.
    //
    {
        ChipLogProgress(ExchangeManager, "-------- #3: Initiator --X (SessionReleased before) Msg1 --------- ");

        {
            MockProtocolInitiator initiator(*this, MockProtocolInitiator::BehaviorModifier::kExpireSessionBeforeMsg1Send);
            MockProtocolResponder responder(*this);

            auto err = initiator.StartInteraction(sessionHandle);
            EXPECT_NE(err, CHIP_NO_ERROR);
        }

        //
        // Service IO AFTER the objects above cease to exist to prevent Msg1 from getting to Responder. This also
        // flush any pending messages in the queue.
        //
        DrainAndServiceIO();
        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    //
    // #4: Initiator --X (SendErr + Session Released After) -- Msg1
    //
    // Inject an error at Msg1 transmission followed by the release of a session (scenario in #21544). This should
    // just close out the exchange without releasing the ref since the WillSendMessage flag should still be set.
    //
    // Then, destroy both objects. The initiator's holder should correctly abort the exchange since WillSendMessage
    // should still be present on the EC.
    //
    {
        ChipLogProgress(ExchangeManager, "-------- #4: Initiator --X (SendErr + SessionReleased after) Msg1 --------- ");

        {
            MockProtocolInitiator initiator(*this, MockProtocolInitiator::BehaviorModifier::kExpireSessionAfterMsg1Send,
                                            MockProtocolInitiator::BehaviorModifier::kErrMsg1);
            MockProtocolResponder responder(*this);

            auto err = initiator.StartInteraction(sessionHandle);
            EXPECT_NE(err, CHIP_NO_ERROR);
        }

        //
        // Service IO AFTER the objects above cease to exist to prevent Msg1 from getting to Responder. This also
        // flush any pending messages in the queue.
        //
        DrainAndServiceIO();
        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    //
    // #5: Initiator >--- Msg1 --X  Responder.
    //
    // Initiator sends Msg1 to Responder, but we set it up such that Responder doesn't actually
    // receive the message.
    //
    // Then, destroy both objects. Initiator's holder should correctly abort the exchange since it's waiting for
    // a response.
    //
    {
        ChipLogProgress(ExchangeManager, "-------- #5: Initiator >-- Msg1 --X Responder ---------");

        {
            MockProtocolInitiator initiator(*this);
            MockProtocolResponder responder(*this);

            auto err = initiator.StartInteraction(sessionHandle);
            EXPECT_EQ(err, CHIP_NO_ERROR);
        }

        //
        // Service IO AFTER the objects above cease to exist to prevent Msg1 from getting to Responder. This also
        // flush any pending messages in the queue.
        //
        DrainAndServiceIO();
        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    //
    // #6: Initiator --- Msg1 -->  Responder (WillSend)
    //
    // Initiator sends Msg1 to Responder, which is received successfully. However, Responder
    // doesn't send a response right away (calls WillSendMessage() on the EC).
    //
    // Then, destroy both objects. Initiator's holder should correctly abort the exchange since it's waiting for
    // a response, and so should the Responder's holder since it has yet to send a message.
    //
    {
        {
            ChipLogProgress(ExchangeManager, "-------- #6: Initiator >-- Msg1 --> Responder (WillSend) ---------");

            MockProtocolInitiator initiator(*this);
            MockProtocolResponder responder(*this, MockProtocolResponder::BehaviorModifier::kHoldMsg2);

            auto err = initiator.StartInteraction(sessionHandle);
            EXPECT_EQ(err, CHIP_NO_ERROR);

            DrainAndServiceIO();
        }

        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    //
    // #7:            Initiator --- Msg1           -->  Responder
    //                              Msg2 (SendErr) X--  Responder
    //
    //  Inject an error in the responder when attempting to send Msg2.
    //
    //  Then, destroy both objects. The holder on the responder should abort the exchange since
    //  the transmission failed, and the ref is still with the holder. The holder on the initiator
    //  should abort the exchange since it is waiting for a response.
    //
    //
    {
        {
            ChipLogProgress(ExchangeManager, "-------- #7: Msg2 (SendFailure) X-- Responder ---------");

            MockProtocolInitiator initiator(*this);
            MockProtocolResponder responder(*this, MockProtocolResponder::BehaviorModifier::kErrMsg2);

            auto err = initiator.StartInteraction(sessionHandle);
            EXPECT_EQ(err, CHIP_NO_ERROR);

            DrainAndServiceIO();
        }

        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    //
    // #8:            Initiator --- Msg1                          -->  Responder
    //                              Msg2 (SessionReleased before) X--  Responder
    //
    // Release the session right before sending Msg2 on the responder. This should abort the underlying exchange
    // immediately since neither WillSendMessage or ResponseExpected flags are set.
    //
    // Then, destroy both objects. The holders on both should just null out their internal reference to the EC.
    //
    {
        {
            ChipLogProgress(ExchangeManager, "-------- #8: Msg2 (SessionReleased Before) X-- Responder ---------");

            MockProtocolInitiator initiator(*this);
            MockProtocolResponder responder(*this, MockProtocolResponder::BehaviorModifier::kExpireSessionBeforeMsg2Send);

            auto err = initiator.StartInteraction(sessionHandle);
            EXPECT_EQ(err, CHIP_NO_ERROR);

            DrainAndServiceIO();
        }

        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    //
    // #9:            Initiator --- Msg1                                    -->  Responder
    //                              Msg2 (SendErr + SessionReleased after)  X--  Responder
    //
    // Trigger a send error when sending Msg2 from the responder, and release the session immediately after. This should still
    // preserve the WillSendMessage flags on the exchange and just close out the EC without releasing the ref.
    //
    // Then, destroy both objects. The holders on both should abort their respective ECs.
    //
    {
        {
            ChipLogProgress(ExchangeManager, "-------- #9: Msg2 (SendErr + SessionReleased after) X-- Responder ---------");

            MockProtocolInitiator initiator(*this);
            MockProtocolResponder responder(*this, MockProtocolResponder::BehaviorModifier::kErrMsg2,
                                            MockProtocolResponder::BehaviorModifier::kExpireSessionAfterMsg2Send);

            auto err = initiator.StartInteraction(sessionHandle);
            EXPECT_EQ(err, CHIP_NO_ERROR);

            DrainAndServiceIO();
        }

        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    //
    // #10:            Initiator --- Msg1 -->  Responder
    //      (WillSend) Initiator <-- Msg2 <--  Responder
    //
    // Initiator receives Msg2 back from Responder, but calls WillSend on that EC.
    //
    // Then, destroy both objects. Initiator's holder should correctly abort the exchange since it's waiting
    // to send a response, and Responder's holder should abort as well since it's waiting for a response.
    //
    {
        {
            ChipLogProgress(ExchangeManager, "-------- #10: (WillSend) Initiator <-- Msg2 <-- Responder ---------");

            MockProtocolInitiator initiator(*this, MockProtocolInitiator::BehaviorModifier::kHoldMsg3);
            MockProtocolResponder responder(*this);

            auto err = initiator.StartInteraction(sessionHandle);
            EXPECT_EQ(err, CHIP_NO_ERROR);

            DrainAndServiceIO();
        }

        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    //
    // #11:           Initiator                          --- Msg1 -->  Responder
    //                Initiator                          <-- Msg2 <--  Responder
    //                Initiator (SessionReleased before) X-- Msg3
    //
    // Release the session right before the initiator sends Msg3. This should abort the underlying EC immediately on the initiator.
    //
    // Then destroy both objects. Both holders on the initiator and responder should be pointing to null.
    //
    {
        {
            ChipLogProgress(ExchangeManager, "-------- #11: Initiator --X (SessionReleased before) Msg3 ------------");

            MockProtocolInitiator initiator(*this, MockProtocolInitiator::BehaviorModifier::kExpireSessionBeforeMsg3Send);
            MockProtocolResponder responder(*this);

            auto err = initiator.StartInteraction(sessionHandle);
            EXPECT_NE(err, CHIP_NO_ERROR);

            DrainAndServiceIO();
        }

        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    //
    // #12:            Initiator                                     --- Msg1 -->  Responder
    //                 Initiator                                     <-- Msg2 <--  Responder
    //                 Initiator X (SendErr + SessionReleased after) -- Msg3
    //
    // Trigger a send error on the initiator when sending Msg3, followed by a session release. Since a send was initiated, the ref
    // is with the initiator's holder and the EC will just close itself out without removing the ref.
    //
    // Then, destroy both objects. The responder's holder will have a null ref but the initiator's holder will have a non-null ref,
    // and should abort it.
    //
    {
        {
            ChipLogProgress(ExchangeManager, "-------- #12: Initiator --X (SendErr + SessionReleased after) Msg3 ------------");

            MockProtocolInitiator initiator(*this, MockProtocolInitiator::BehaviorModifier::kErrMsg3,
                                            MockProtocolInitiator::BehaviorModifier::kExpireSessionAfterMsg3Send);
            MockProtocolResponder responder(*this);

            auto err = initiator.StartInteraction(sessionHandle);
            EXPECT_EQ(err, CHIP_NO_ERROR);

            DrainAndServiceIO();
        }

        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    //
    // #13:            Initiator --- Msg1 -->  Responder
    //                 Initiator <-- Msg2 <--  Responder
    //                 Initiator >-- Msg3 -->  Responder
    //
    // Initiator sends final message in exchange to Responder, which is received successfully.
    //
    // Then, destroy both objects. Initiator's holder should NOT abort the underlying exchange since
    // it has sent the final message in the exchange, while responder's holder should NOT abor the underlying
    // exchange either since it is not going to send any further messages on the exchange.
    //
    {
        {
            ChipLogProgress(ExchangeManager, "-------- #13: Initiator >-- Msg3 -->  Responder ---------");

            MockProtocolInitiator initiator(*this);
            MockProtocolResponder responder(*this);

            auto err = initiator.StartInteraction(sessionHandle);
            EXPECT_EQ(err, CHIP_NO_ERROR);

            DrainAndServiceIO();
        }

        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    //
    // #14:           Initiator --- Msg1 -->  Responder
    //                Initiator <-- Msg2 <--  Responder
    //                Initiator >-- Msg3 -->  Responder (SessionReleased)
    //
    // Released the session right on reception of Msg3 on the responder. Since there no responses expected or send expected,
    // the EC aborts immediately.
    //
    // Then, destroy both objects. Both holders should be point to null and should do nothing.
    //
    {
        {
            ChipLogProgress(ExchangeManager, "-------- #14: Initiator >-- Msg3 -->  Responder (SessionReleased) ---------");

            MockProtocolInitiator initiator(*this);
            MockProtocolResponder responder(*this, MockProtocolResponder::BehaviorModifier::kExpireSessionAfterMsg3Receive);

            auto err = initiator.StartInteraction(sessionHandle);
            EXPECT_EQ(err, CHIP_NO_ERROR);

            DrainAndServiceIO();

            //
            // Because of the session expiration right after Msg3 is received, it causes an abort of the underlying EC
            // on the reponder side. This means that Msg3 won't be ACK'ed. Msg3 on the initiator side remains un-acked. Since
            // the exchange was just closed and not aborted on the initiator side, it is still sitting in the retransmission table
            // and consequently, the exchange still has a ref-count of 1. If we were to just check the number of active
            // exchanges, it would still show 1 active exchange.
            //
            // This will only be released once the re-transmission table
            // entry has been removed. To make this happen, drive the IO forward enough that a single re-transmission happens. This
            // will result in a duplicate message ACK being delivered by the responder, causing the EC to finally get released.
            //
            GetIOContext().DriveIOUntil(System::Clock::Seconds16(5),
                                        [&]() { return GetExchangeManager().GetNumActiveExchanges() == 0; });
        }

        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    //
    // #15:           Initiator --- Msg1 -->  Responder (WillSend)
    //                Initiator --- Msg1 -->  Responder (WillSend)
    //
    // Similar to #6, except we have Initiator start the interaction again. This validates
    // ExchangeHolder::Grab in correctly aborting a previous exchange and acquiring a new one.
    //
    // Then, destroy both objects. Both holders should abort the exchange (see #6).
    //
    {
        {
            ChipLogProgress(ExchangeManager, "-------- #15: Initiator >-- Msg1 -->  Responder (WillSend) X2 ---------");

            MockProtocolInitiator initiator(*this);
            MockProtocolResponder responder(*this, MockProtocolResponder::BehaviorModifier::kHoldMsg2);

            auto err = initiator.StartInteraction(sessionHandle);
            EXPECT_EQ(err, CHIP_NO_ERROR);

            DrainAndServiceIO();

            err = initiator.StartInteraction(sessionHandle);
            EXPECT_EQ(err, CHIP_NO_ERROR);

            DrainAndServiceIO();
        }

        DrainAndServiceIO();
        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    //
    // #16:           Initiator --- Msg1 -->  Responder
    //                Initiator <-- Msg2 <--  Responder
    //                Initiator >-- Msg3 -->  Responder
    //
    //                X2
    //
    // We do the entire interaction twice. This validates ExchangeHolder::Grab in correctly releasing a reference
    // to a previous exchange (but not aborting it) and acquiring a new one.
    //
    // Then, destroy both objects. Both holders should release their reference without aborting.
    //
    {
        {
            ChipLogProgress(ExchangeManager, "-------- #16: Initiator >-- Msg3 -->  Responder X2 ---------");

            MockProtocolInitiator initiator(*this);
            MockProtocolResponder responder(*this);

            auto err = initiator.StartInteraction(sessionHandle);
            EXPECT_EQ(err, CHIP_NO_ERROR);

            DrainAndServiceIO();

            err = initiator.StartInteraction(sessionHandle);
            EXPECT_EQ(err, CHIP_NO_ERROR);

            DrainAndServiceIO();
        }

        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }
}
} // anonymous namespace
