blob: 4e52cb96972ea688908c147cc6891a7fba457edf [file] [log] [blame]
/*
*
* 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 the ExchangeManager implementation.
*/
#include <errno.h>
#include <utility>
#include <gtest/gtest.h>
#include <lib/core/CHIPCore.h>
#include <lib/support/CHIPFaultInjection.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <messaging/ExchangeContext.h>
#include <messaging/ExchangeMgr.h>
#include <messaging/Flags.h>
#include <messaging/tests/MessagingContext.h>
#include <protocols/Protocols.h>
#include <protocols/echo/Echo.h>
#include <transport/SessionManager.h>
#include <transport/TransportMgr.h>
namespace {
using namespace chip;
using namespace chip::Inet;
using namespace chip::Transport;
using namespace chip::Messaging;
using namespace chip::Protocols;
using namespace chip::System::Clock::Literals;
using TestContext = Test::UDPMessagingContext;
struct TestMessagingLayer : public chip::Test::UDPMessagingContext, public ::testing::Test
{
static void SetUpTestSuite() { chip::Test::UDPMessagingContext::SetUpTestSuite(); }
static void TearDownTestSuite() { chip::Test::UDPMessagingContext::TearDownTestSuite(); }
// Performs setup for each individual test in the test suite
void SetUp() override { chip::Test::UDPMessagingContext::SetUp(); }
void TearDown() override { chip::Test::UDPMessagingContext::TearDown(); }
};
// The message timeout value in milliseconds.
constexpr System::Clock::Timeout kMessageTimeout = System::Clock::Milliseconds32(100);
class MockAppDelegate : public UnsolicitedMessageHandler, public ExchangeDelegate
{
public:
CHIP_ERROR OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, ExchangeDelegate *& newDelegate) override
{
newDelegate = this;
return CHIP_NO_ERROR;
}
CHIP_ERROR OnMessageReceived(ExchangeContext * ec, const PayloadHeader & payloadHeader,
System::PacketBufferHandle && buffer) override
{
IsOnMessageReceivedCalled = true;
return CHIP_NO_ERROR;
}
void OnResponseTimeout(ExchangeContext * ec) override { IsOnResponseTimeoutCalled = true; }
bool IsOnMessageReceivedCalled = false;
bool IsOnResponseTimeoutCalled = false;
};
/**
* Tests sending exchange message with Success:
*
* DUT = sender, PEER = remote device
*
* 1) DUT sends message w/o MRP to PEER
* - Confirm the message is sent successfully
* - Observe DUT response timeout with no response
*/
TEST_F(TestMessagingLayer, CheckExchangeOutgoingMessagesSuccess)
{
// create solicited exchange
MockAppDelegate mockSolicitedAppDelegate;
ExchangeContext * ec = NewExchangeToAlice(&mockSolicitedAppDelegate);
ASSERT_NE(ec, nullptr);
ec->SetResponseTimeout(kMessageTimeout);
CHIP_ERROR err = ec->SendMessage(Echo::MsgType::EchoRequest, System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize),
SendFlags(SendMessageFlags::kExpectResponse).Set(SendMessageFlags::kNoAutoRequestAck));
// Wait for the initial message to fail (should take 330-413ms)
GetIOContext().DriveIOUntil(500_ms32, [&] { return mockSolicitedAppDelegate.IsOnMessageReceivedCalled; });
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_TRUE(mockSolicitedAppDelegate.IsOnResponseTimeoutCalled);
}
/**
* Tests sending exchange message with Failure:
*
* DUT = sender, PEER = remote device
*
* 1) DUT configured to drop the outgoing UDP packet
* 2) DUT sends message w/o MRP to PEER
* - Confirm the message is sent with failure
* - Confirm the DUT response timeout timer is cancelled
*/
TEST_F(TestMessagingLayer, CheckExchangeOutgoingMessagesFail)
{
// create solicited exchange
MockAppDelegate mockSolicitedAppDelegate;
ExchangeContext * ec = NewExchangeToAlice(&mockSolicitedAppDelegate);
ASSERT_NE(ec, nullptr);
ec->SetResponseTimeout(kMessageTimeout);
chip::FaultInjection::GetManager().FailAtFault(chip::FaultInjection::kFault_DropOutgoingUDPMsg, 0, 1);
CHIP_ERROR err = ec->SendMessage(Echo::MsgType::EchoRequest, System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize),
SendFlags(SendMessageFlags::kExpectResponse).Set(SendMessageFlags::kNoAutoRequestAck));
// Wait for the initial message to fail (should take 330-413ms)
GetIOContext().DriveIOUntil(500_ms32, [&] { return mockSolicitedAppDelegate.IsOnMessageReceivedCalled; });
EXPECT_NE(err, CHIP_NO_ERROR);
EXPECT_FALSE(mockSolicitedAppDelegate.IsOnResponseTimeoutCalled);
ec->Close();
}
} // namespace