blob: 9db2f6feca40dd12cd4ba636944e4d83e9bc572a [file] [log] [blame]
/*
*
* Copyright (c) 2020 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 ReliableMessageProtocol
* implementation.
*/
#include "TestMessagingLayer.h"
#include <core/CHIPCore.h>
#include <messaging/ReliableMessageContext.h>
#include <messaging/ReliableMessageManager.h>
#include <protocols/Protocols.h>
#include <support/CodeUtils.h>
#include <transport/raw/tests/NetworkTestHelpers.h>
#include <nlbyteorder.h>
#include <nlunit-test.h>
#include <errno.h>
namespace {
using namespace chip;
using namespace chip::Inet;
using namespace chip::messaging;
using TestContext = chip::Test::IOContext;
TestContext sContext;
ReliableMessageManager manager;
void test_os_sleep_ms(uint64_t millisecs)
{
struct timespec sleep_time;
uint64_t s = millisecs / 1000;
millisecs -= s * 1000;
sleep_time.tv_sec = static_cast<time_t>(s);
sleep_time.tv_nsec = static_cast<long>(millisecs * 1000000);
nanosleep(&sleep_time, nullptr);
}
class ReliableMessageDelegateObject : public ReliableMessageDelegate
{
public:
~ReliableMessageDelegateObject() override {}
/* Application callbacks */
void OnThrottleRcvd(uint32_t pauseTime) override {}
void OnDelayedDeliveryRcvd(uint32_t pauseTime) override {}
void OnSendError(CHIP_ERROR err) override { SendErrorCalled = true; }
void OnAckRcvd() override {}
bool SendErrorCalled = false;
};
void CheckAddClearRetrans(nlTestSuite * inSuite, void * inContext)
{
TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
auto & m = manager;
m.Init(ctx.GetSystemLayer());
ReliableMessageContext rc;
rc.Init(&m);
ReliableMessageManager::RetransTableEntry * entry;
m.AddToRetransTable(&rc, nullptr, 1, 0, &entry);
NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 1);
m.ClearRetransmitTable(*entry);
NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 0);
m.Shutdown();
}
void CheckFailRetrans(nlTestSuite * inSuite, void * inContext)
{
TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
auto & m = manager;
m.Init(ctx.GetSystemLayer());
ReliableMessageContext rc;
rc.Init(&m);
ReliableMessageDelegateObject delegate;
rc.SetDelegate(&delegate);
ReliableMessageManager::RetransTableEntry * entry;
auto buf = System::PacketBuffer::New();
m.AddToRetransTable(&rc, buf.Release_ForNow(), 1, 0, &entry);
NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 1);
NL_TEST_ASSERT(inSuite, !delegate.SendErrorCalled);
m.FailRetransmitTableEntries(&rc, CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 0);
NL_TEST_ASSERT(inSuite, delegate.SendErrorCalled);
m.Shutdown();
}
void CheckRetransExpire(nlTestSuite * inSuite, void * inContext)
{
TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
auto & m = manager;
m.TestSetIntervalShift(4); // 16ms per tick
m.Init(ctx.GetSystemLayer());
ReliableMessageContext rc;
rc.Init(&m);
ReliableMessageDelegateObject delegate;
rc.SetDelegate(&delegate);
rc.SetConfig({
1, // CHIP_CONFIG_RMP_DEFAULT_INITIAL_RETRANS_TIMEOUT_TICK
1, // CHIP_CONFIG_RMP_DEFAULT_ACTIVE_RETRANS_TIMEOUT_TICK
1, // CHIP_CONFIG_RMP_DEFAULT_ACK_TIMEOUT_TICK
2, // CHIP_CONFIG_RMP_DEFAULT_MAX_RETRANS
});
ReliableMessageManager::RetransTableEntry * entry;
auto buf = System::PacketBuffer::New();
m.AddToRetransTable(&rc, buf.Release_ForNow(), 1, 0, &entry);
NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 1);
test_os_sleep_ms(20);
ReliableMessageManager::Timeout(&ctx.GetSystemLayer(), &m, CHIP_SYSTEM_NO_ERROR);
NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 1);
// 1st retrans
test_os_sleep_ms(20);
ReliableMessageManager::Timeout(&ctx.GetSystemLayer(), &m, CHIP_SYSTEM_NO_ERROR);
NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 1);
NL_TEST_ASSERT(inSuite, !delegate.SendErrorCalled);
// 2nd retrans
test_os_sleep_ms(20);
ReliableMessageManager::Timeout(&ctx.GetSystemLayer(), &m, CHIP_SYSTEM_NO_ERROR);
NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 0);
NL_TEST_ASSERT(inSuite, delegate.SendErrorCalled);
// send error
m.Shutdown();
}
void CheckDelayDelivery(nlTestSuite * inSuite, void * inContext)
{
TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
auto & m = manager;
m.TestSetIntervalShift(4); // 16ms per tick
m.Init(ctx.GetSystemLayer());
ReliableMessageContext rc;
rc.Init(&m);
ReliableMessageDelegateObject delegate;
rc.SetDelegate(&delegate);
rc.SetConfig({
1, // CHIP_CONFIG_RMP_DEFAULT_INITIAL_RETRANS_TIMEOUT_TICK
1, // CHIP_CONFIG_RMP_DEFAULT_ACTIVE_RETRANS_TIMEOUT_TICK
1, // CHIP_CONFIG_RMP_DEFAULT_ACK_TIMEOUT_TICK
1, // CHIP_CONFIG_RMP_DEFAULT_MAX_RETRANS
});
ReliableMessageManager::RetransTableEntry * entry;
auto buf = System::PacketBuffer::New();
m.AddToRetransTable(&rc, buf.Release_ForNow(), 1, 0, &entry);
m.ProcessDelayedDeliveryMessage(&rc, 64);
NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 1);
test_os_sleep_ms(50);
ReliableMessageManager::Timeout(&ctx.GetSystemLayer(), &m, CHIP_SYSTEM_NO_ERROR);
NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 1);
// not send, delayed
test_os_sleep_ms(50);
ReliableMessageManager::Timeout(&ctx.GetSystemLayer(), &m, CHIP_SYSTEM_NO_ERROR);
NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 1);
NL_TEST_ASSERT(inSuite, !delegate.SendErrorCalled);
// 1st retrans
test_os_sleep_ms(20);
ReliableMessageManager::Timeout(&ctx.GetSystemLayer(), &m, CHIP_SYSTEM_NO_ERROR);
NL_TEST_ASSERT(inSuite, m.TestGetCountRetransTable() == 0);
NL_TEST_ASSERT(inSuite, delegate.SendErrorCalled);
// send error
m.Shutdown();
}
// Test Suite
/**
* Test Suite that lists all the test functions.
*/
// clang-format off
const nlTest sTests[] =
{
NL_TEST_DEF("Test ReliableMessageManager::CheckAddClearRetrans", CheckAddClearRetrans),
NL_TEST_DEF("Test ReliableMessageManager::CheckFailRetrans", CheckFailRetrans),
NL_TEST_DEF("Test ReliableMessageManager::CheckRetransExpire", CheckRetransExpire),
NL_TEST_DEF("Test ReliableMessageManager::CheckDelayDelivery", CheckDelayDelivery),
NL_TEST_SENTINEL()
};
// clang-format on
int Initialize(void * aContext);
int Finalize(void * aContext);
// clang-format off
nlTestSuite sSuite =
{
"Test-CHIP-ReliableMessageProtocol",
&sTests[0],
Initialize,
Finalize
};
// clang-format on
/**
* Initialize the test suite.
*/
int Initialize(void * aContext)
{
CHIP_ERROR err = reinterpret_cast<TestContext *>(aContext)->Init(&sSuite);
return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE;
}
/**
* Finalize the test suite.
*/
int Finalize(void * aContext)
{
CHIP_ERROR err = reinterpret_cast<TestContext *>(aContext)->Shutdown();
return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE;
}
} // namespace
namespace chip {
namespace messaging {
// Stub implementation
CHIP_ERROR ReliableMessageManager::SendMessage(ReliableMessageContext * context, System::PacketBuffer * msgBuf, uint16_t sendFlags)
{
return CHIP_NO_ERROR;
}
CHIP_ERROR ReliableMessageManager::SendMessage(ReliableMessageContext * context, uint32_t profileId, uint8_t msgType,
System::PacketBuffer * msgBuf, BitFlags<uint16_t, SendMessageFlags> sendFlags)
{
return CHIP_NO_ERROR;
}
void ReliableMessageManager::FreeContext(ReliableMessageContext *) {}
} // namespace messaging
} // namespace chip
/**
* Main
*/
int TestReliableMessageProtocol()
{
// Run test suit against one context
nlTestRunner(&sSuite, &sContext);
return (nlTestRunnerStats(&sSuite));
}