3 * Copyright (c) 2020-2021 Project CHIP Authors
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 * This file implements unit tests for the ReliableMessageProtocol
25 #include "TestMessagingLayer.h"
27 #include <core/CHIPCore.h>
28 #include <messaging/ReliableMessageContext.h>
29 #include <messaging/ReliableMessageMgr.h>
30 #include <protocols/Protocols.h>
31 #include <protocols/echo/Echo.h>
32 #include <support/CodeUtils.h>
33 #include <transport/SecureSessionMgr.h>
34 #include <transport/TransportMgr.h>
36 #include <nlbyteorder.h>
37 #include <nlunit-test.h>
41 #include <messaging/ExchangeContext.h>
42 #include <messaging/ExchangeMgr.h>
43 #include <messaging/Flags.h>
44 #include <messaging/tests/MessagingContext.h>
49 using namespace chip::Inet;
50 using namespace chip::Transport;
51 using namespace chip::Messaging;
52 using namespace chip::Protocols;
54 using TestContext = chip::Test::MessagingContext;
58 const char PAYLOAD[] = "Hello!";
60 int gSendMessageCount = 0;
62 class OutgoingTransport : public Transport::Base
65 /// Transports are required to have a constructor that takes exactly one argument
66 CHIP_ERROR Init(const char * unused) { return CHIP_NO_ERROR; }
68 CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBufferHandle msgBuf) override
70 ReturnErrorOnFailure(header.EncodeBeforeData(msgBuf));
77 bool CanSendToPeer(const PeerAddress & address) override { return true; }
80 TransportMgr<OutgoingTransport> gTransportMgr;
82 class MockAppDelegate : public ExchangeDelegate
85 void OnMessageReceived(ExchangeContext * ec, const PacketHeader & packetHeader, const PayloadHeader & payloadHeader,
86 System::PacketBufferHandle buffer) override
88 IsOnMessageReceivedCalled = true;
91 void OnResponseTimeout(ExchangeContext * ec) override {}
93 bool IsOnMessageReceivedCalled = false;
96 void test_os_sleep_ms(uint64_t millisecs)
98 struct timespec sleep_time;
99 uint64_t s = millisecs / 1000;
101 millisecs -= s * 1000;
102 sleep_time.tv_sec = static_cast<time_t>(s);
103 sleep_time.tv_nsec = static_cast<long>(millisecs * 1000000);
105 nanosleep(&sleep_time, nullptr);
108 class ReliableMessageDelegateObject : public ReliableMessageDelegate
111 ~ReliableMessageDelegateObject() override {}
113 /* Application callbacks */
114 void OnSendError(CHIP_ERROR err) override { SendErrorCalled = true; }
115 void OnAckRcvd() override {}
117 bool SendErrorCalled = false;
120 void CheckAddClearRetrans(nlTestSuite * inSuite, void * inContext)
122 TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
124 MockAppDelegate mockAppDelegate;
125 ExchangeContext * exchange = ctx.NewExchangeToPeer(&mockAppDelegate);
126 NL_TEST_ASSERT(inSuite, exchange != nullptr);
128 ReliableMessageMgr * rm = ctx.GetExchangeManager().GetReliableMessageMgr();
129 ReliableMessageContext * rc = exchange->GetReliableMessageContext();
130 NL_TEST_ASSERT(inSuite, rm != nullptr);
131 NL_TEST_ASSERT(inSuite, rc != nullptr);
133 ReliableMessageMgr::RetransTableEntry * entry;
135 rm->AddToRetransTable(rc, &entry);
136 NL_TEST_ASSERT(inSuite, rm->TestGetCountRetransTable() == 1);
137 rm->ClearRetransTable(*entry);
138 NL_TEST_ASSERT(inSuite, rm->TestGetCountRetransTable() == 0);
141 void CheckFailRetrans(nlTestSuite * inSuite, void * inContext)
143 TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
145 ctx.GetInetLayer().SystemLayer()->Init(nullptr);
147 MockAppDelegate mockAppDelegate;
148 ExchangeContext * exchange = ctx.NewExchangeToPeer(&mockAppDelegate);
149 NL_TEST_ASSERT(inSuite, exchange != nullptr);
151 ReliableMessageMgr * rm = ctx.GetExchangeManager().GetReliableMessageMgr();
152 ReliableMessageContext * rc = exchange->GetReliableMessageContext();
153 NL_TEST_ASSERT(inSuite, rm != nullptr);
154 NL_TEST_ASSERT(inSuite, rc != nullptr);
156 ReliableMessageMgr::RetransTableEntry * entry;
157 ReliableMessageDelegateObject delegate;
158 rc->SetDelegate(&delegate);
159 rm->AddToRetransTable(rc, &entry);
160 NL_TEST_ASSERT(inSuite, rm->TestGetCountRetransTable() == 1);
161 NL_TEST_ASSERT(inSuite, !delegate.SendErrorCalled);
162 rm->FailRetransTableEntries(rc, CHIP_NO_ERROR);
163 NL_TEST_ASSERT(inSuite, rm->TestGetCountRetransTable() == 0);
164 NL_TEST_ASSERT(inSuite, delegate.SendErrorCalled);
167 void CheckResendMessage(nlTestSuite * inSuite, void * inContext)
169 TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
171 ctx.GetInetLayer().SystemLayer()->Init(nullptr);
173 chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, sizeof(PAYLOAD));
174 NL_TEST_ASSERT(inSuite, !buffer.IsNull());
177 IPAddress::FromString("127.0.0.1", addr);
179 CHIP_ERROR err = CHIP_NO_ERROR;
181 MockAppDelegate mockSender;
182 // TODO: temprary create a SecureSessionHandle from node id, will be fix in PR 3602
183 ExchangeContext * exchange = ctx.NewExchangeToPeer(&mockSender);
184 NL_TEST_ASSERT(inSuite, exchange != nullptr);
186 ReliableMessageMgr * rm = ctx.GetExchangeManager().GetReliableMessageMgr();
187 ReliableMessageContext * rc = exchange->GetReliableMessageContext();
188 NL_TEST_ASSERT(inSuite, rm != nullptr);
189 NL_TEST_ASSERT(inSuite, rc != nullptr);
192 1, // CHIP_CONFIG_RMP_DEFAULT_INITIAL_RETRANS_TIMEOUT_TICK
193 1, // CHIP_CONFIG_RMP_DEFAULT_ACTIVE_RETRANS_TIMEOUT_TICK
194 1, // CHIP_CONFIG_RMP_DEFAULT_ACK_TIMEOUT_TICK
195 3, // CHIP_CONFIG_RMP_DEFAULT_MAX_RETRANS
198 gSendMessageCount = 0;
200 err = exchange->SendMessage(Echo::MsgType::EchoRequest, std::move(buffer),
201 Messaging::SendFlags(Messaging::SendMessageFlags::kNone));
202 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
204 // 1 tick is 64 ms, sleep 65 ms to trigger first re-transmit
205 test_os_sleep_ms(65);
206 ReliableMessageMgr::Timeout(&ctx.GetSystemLayer(), rm, CHIP_SYSTEM_NO_ERROR);
207 NL_TEST_ASSERT(inSuite, gSendMessageCount == 2);
209 // sleep another 65 ms to trigger second re-transmit
210 test_os_sleep_ms(65);
211 ReliableMessageMgr::Timeout(&ctx.GetSystemLayer(), rm, CHIP_SYSTEM_NO_ERROR);
212 NL_TEST_ASSERT(inSuite, gSendMessageCount == 3);
215 void CheckSendStandaloneAckMessage(nlTestSuite * inSuite, void * inContext)
217 TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
219 ctx.GetInetLayer().SystemLayer()->Init(nullptr);
221 MockAppDelegate mockAppDelegate;
222 ExchangeContext * exchange = ctx.NewExchangeToPeer(&mockAppDelegate);
223 NL_TEST_ASSERT(inSuite, exchange != nullptr);
225 ReliableMessageMgr * rm = ctx.GetExchangeManager().GetReliableMessageMgr();
226 ReliableMessageContext * rc = exchange->GetReliableMessageContext();
227 NL_TEST_ASSERT(inSuite, rm != nullptr);
228 NL_TEST_ASSERT(inSuite, rc != nullptr);
230 ReliableMessageDelegateObject delegate;
231 rc->SetDelegate(&delegate);
233 NL_TEST_ASSERT(inSuite, rc->SendStandaloneAckMessage() == CHIP_NO_ERROR);
239 * Test Suite that lists all the test functions.
242 const nlTest sTests[] =
244 NL_TEST_DEF("Test ReliableMessageMgr::CheckAddClearRetrans", CheckAddClearRetrans),
245 NL_TEST_DEF("Test ReliableMessageMgr::CheckFailRetrans", CheckFailRetrans),
246 NL_TEST_DEF("Test ReliableMessageMgr::CheckResendMessage", CheckResendMessage),
247 NL_TEST_DEF("Test ReliableMessageMgr::CheckSendStandaloneAckMessage", CheckSendStandaloneAckMessage),
253 int Initialize(void * aContext);
254 int Finalize(void * aContext);
259 "Test-CHIP-ReliableMessageProtocol",
267 * Initialize the test suite.
269 int Initialize(void * aContext)
271 CHIP_ERROR err = chip::Platform::MemoryInit();
272 if (err != CHIP_NO_ERROR)
275 err = gTransportMgr.Init("LOOPBACK");
276 if (err != CHIP_NO_ERROR)
279 err = reinterpret_cast<TestContext *>(aContext)->Init(&sSuite, &gTransportMgr);
280 return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE;
284 * Finalize the test suite.
286 int Finalize(void * aContext)
288 CHIP_ERROR err = reinterpret_cast<TestContext *>(aContext)->Shutdown();
289 chip::Platform::MemoryShutdown();
290 return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE;
298 int TestReliableMessageProtocol()
300 // Run test suit against one context
301 nlTestRunner(&sSuite, &sContext);
303 return (nlTestRunnerStats(&sSuite));