Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / messaging / tests / TestReliableMessageProtocol.cpp
1 /*
2  *
3  *    Copyright (c) 2020-2021 Project CHIP Authors
4  *    All rights reserved.
5  *
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
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19 /**
20  *    @file
21  *      This file implements unit tests for the ReliableMessageProtocol
22  *      implementation.
23  */
24
25 #include "TestMessagingLayer.h"
26
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>
35
36 #include <nlbyteorder.h>
37 #include <nlunit-test.h>
38
39 #include <errno.h>
40
41 #include <messaging/ExchangeContext.h>
42 #include <messaging/ExchangeMgr.h>
43 #include <messaging/Flags.h>
44 #include <messaging/tests/MessagingContext.h>
45
46 namespace {
47
48 using namespace chip;
49 using namespace chip::Inet;
50 using namespace chip::Transport;
51 using namespace chip::Messaging;
52 using namespace chip::Protocols;
53
54 using TestContext = chip::Test::MessagingContext;
55
56 TestContext sContext;
57
58 const char PAYLOAD[] = "Hello!";
59
60 int gSendMessageCount = 0;
61
62 class OutgoingTransport : public Transport::Base
63 {
64 public:
65     /// Transports are required to have a constructor that takes exactly one argument
66     CHIP_ERROR Init(const char * unused) { return CHIP_NO_ERROR; }
67
68     CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBufferHandle msgBuf) override
69     {
70         ReturnErrorOnFailure(header.EncodeBeforeData(msgBuf));
71
72         gSendMessageCount++;
73
74         return CHIP_NO_ERROR;
75     }
76
77     bool CanSendToPeer(const PeerAddress & address) override { return true; }
78 };
79
80 TransportMgr<OutgoingTransport> gTransportMgr;
81
82 class MockAppDelegate : public ExchangeDelegate
83 {
84 public:
85     void OnMessageReceived(ExchangeContext * ec, const PacketHeader & packetHeader, const PayloadHeader & payloadHeader,
86                            System::PacketBufferHandle buffer) override
87     {
88         IsOnMessageReceivedCalled = true;
89     }
90
91     void OnResponseTimeout(ExchangeContext * ec) override {}
92
93     bool IsOnMessageReceivedCalled = false;
94 };
95
96 void test_os_sleep_ms(uint64_t millisecs)
97 {
98     struct timespec sleep_time;
99     uint64_t s = millisecs / 1000;
100
101     millisecs -= s * 1000;
102     sleep_time.tv_sec  = static_cast<time_t>(s);
103     sleep_time.tv_nsec = static_cast<long>(millisecs * 1000000);
104
105     nanosleep(&sleep_time, nullptr);
106 }
107
108 class ReliableMessageDelegateObject : public ReliableMessageDelegate
109 {
110 public:
111     ~ReliableMessageDelegateObject() override {}
112
113     /* Application callbacks */
114     void OnSendError(CHIP_ERROR err) override { SendErrorCalled = true; }
115     void OnAckRcvd() override {}
116
117     bool SendErrorCalled = false;
118 };
119
120 void CheckAddClearRetrans(nlTestSuite * inSuite, void * inContext)
121 {
122     TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
123
124     MockAppDelegate mockAppDelegate;
125     ExchangeContext * exchange = ctx.NewExchangeToPeer(&mockAppDelegate);
126     NL_TEST_ASSERT(inSuite, exchange != nullptr);
127
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);
132
133     ReliableMessageMgr::RetransTableEntry * entry;
134
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);
139 }
140
141 void CheckFailRetrans(nlTestSuite * inSuite, void * inContext)
142 {
143     TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
144
145     ctx.GetInetLayer().SystemLayer()->Init(nullptr);
146
147     MockAppDelegate mockAppDelegate;
148     ExchangeContext * exchange = ctx.NewExchangeToPeer(&mockAppDelegate);
149     NL_TEST_ASSERT(inSuite, exchange != nullptr);
150
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);
155
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);
165 }
166
167 void CheckResendMessage(nlTestSuite * inSuite, void * inContext)
168 {
169     TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
170
171     ctx.GetInetLayer().SystemLayer()->Init(nullptr);
172
173     chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, sizeof(PAYLOAD));
174     NL_TEST_ASSERT(inSuite, !buffer.IsNull());
175
176     IPAddress addr;
177     IPAddress::FromString("127.0.0.1", addr);
178
179     CHIP_ERROR err = CHIP_NO_ERROR;
180
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);
185
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);
190
191     rc->SetConfig({
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
196     });
197
198     gSendMessageCount = 0;
199
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);
203
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);
208
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);
213 }
214
215 void CheckSendStandaloneAckMessage(nlTestSuite * inSuite, void * inContext)
216 {
217     TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
218
219     ctx.GetInetLayer().SystemLayer()->Init(nullptr);
220
221     MockAppDelegate mockAppDelegate;
222     ExchangeContext * exchange = ctx.NewExchangeToPeer(&mockAppDelegate);
223     NL_TEST_ASSERT(inSuite, exchange != nullptr);
224
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);
229
230     ReliableMessageDelegateObject delegate;
231     rc->SetDelegate(&delegate);
232
233     NL_TEST_ASSERT(inSuite, rc->SendStandaloneAckMessage() == CHIP_NO_ERROR);
234 }
235
236 // Test Suite
237
238 /**
239  *  Test Suite that lists all the test functions.
240  */
241 // clang-format off
242 const nlTest sTests[] =
243 {
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),
248
249     NL_TEST_SENTINEL()
250 };
251 // clang-format on
252
253 int Initialize(void * aContext);
254 int Finalize(void * aContext);
255
256 // clang-format off
257 nlTestSuite sSuite =
258 {
259     "Test-CHIP-ReliableMessageProtocol",
260     &sTests[0],
261     Initialize,
262     Finalize
263 };
264 // clang-format on
265
266 /**
267  *  Initialize the test suite.
268  */
269 int Initialize(void * aContext)
270 {
271     CHIP_ERROR err = chip::Platform::MemoryInit();
272     if (err != CHIP_NO_ERROR)
273         return FAILURE;
274
275     err = gTransportMgr.Init("LOOPBACK");
276     if (err != CHIP_NO_ERROR)
277         return FAILURE;
278
279     err = reinterpret_cast<TestContext *>(aContext)->Init(&sSuite, &gTransportMgr);
280     return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE;
281 }
282
283 /**
284  *  Finalize the test suite.
285  */
286 int Finalize(void * aContext)
287 {
288     CHIP_ERROR err = reinterpret_cast<TestContext *>(aContext)->Shutdown();
289     chip::Platform::MemoryShutdown();
290     return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE;
291 }
292
293 } // namespace
294
295 /**
296  *  Main
297  */
298 int TestReliableMessageProtocol()
299 {
300     // Run test suit against one context
301     nlTestRunner(&sSuite, &sContext);
302
303     return (nlTestRunnerStats(&sSuite));
304 }