Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / transport / tests / TestPeerConnections.cpp
1 /*
2  *
3  *    Copyright (c) 2020 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 a process to effect a functional test for
22  *      the PeerConnections class within the transport layer
23  *
24  */
25 #include <support/CodeUtils.h>
26 #include <support/ErrorStr.h>
27 #include <support/UnitTestRegistration.h>
28 #include <transport/PeerConnections.h>
29
30 #include <nlunit-test.h>
31
32 namespace {
33
34 using namespace chip;
35 using namespace chip::Transport;
36
37 PeerAddress AddressFromString(const char * str)
38 {
39     Inet::IPAddress addr;
40
41     VerifyOrDie(Inet::IPAddress::FromString(str, addr));
42
43     return PeerAddress::UDP(addr);
44 }
45
46 const PeerAddress kPeer1Addr = AddressFromString("10.1.2.3");
47 const PeerAddress kPeer2Addr = AddressFromString("10.0.0.32");
48 const PeerAddress kPeer3Addr = AddressFromString("100.200.0.1");
49
50 const NodeId kPeer1NodeId = 123;
51 const NodeId kPeer2NodeId = 6;
52 const NodeId kPeer3NodeId = 81;
53
54 void TestBasicFunctionality(nlTestSuite * inSuite, void * inContext)
55 {
56     CHIP_ERROR err;
57     PeerConnectionState * statePtr;
58     PeerConnections<2, Time::Source::kTest> connections;
59     connections.GetTimeSource().SetCurrentMonotonicTimeMs(100);
60
61     err = connections.CreateNewPeerConnectionState(kPeer1Addr, nullptr);
62     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
63
64     err = connections.CreateNewPeerConnectionState(kPeer2Addr, &statePtr);
65     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
66     NL_TEST_ASSERT(inSuite, statePtr != nullptr);
67     NL_TEST_ASSERT(inSuite, statePtr->GetPeerAddress() == kPeer2Addr);
68     NL_TEST_ASSERT(inSuite, statePtr->GetLastActivityTimeMs() == 100);
69
70     // Insufficient space for new connections. Object is max size 2
71     err = connections.CreateNewPeerConnectionState(kPeer3Addr, &statePtr);
72     NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR);
73 }
74
75 void TestFindByAddress(nlTestSuite * inSuite, void * inContext)
76 {
77     CHIP_ERROR err;
78     PeerConnectionState * statePtr;
79     PeerConnections<3, Time::Source::kTest> connections;
80
81     PeerConnectionState * state1 = nullptr;
82     PeerConnectionState * state2 = nullptr;
83     PeerConnectionState * state3 = nullptr;
84
85     err = connections.CreateNewPeerConnectionState(kPeer1Addr, &state1);
86     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
87
88     err = connections.CreateNewPeerConnectionState(kPeer1Addr, &state2);
89     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
90
91     err = connections.CreateNewPeerConnectionState(kPeer2Addr, &state3);
92     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
93
94     NL_TEST_ASSERT(inSuite, state1 != state2);
95     NL_TEST_ASSERT(inSuite, state1 != state3);
96     NL_TEST_ASSERT(inSuite, state2 != state3);
97
98     NL_TEST_ASSERT(inSuite, statePtr = connections.FindPeerConnectionState(kPeer1Addr, nullptr));
99     NL_TEST_ASSERT(inSuite, statePtr->GetPeerAddress() == kPeer1Addr);
100
101     NL_TEST_ASSERT(inSuite, statePtr = connections.FindPeerConnectionState(kPeer1Addr, statePtr));
102     NL_TEST_ASSERT(inSuite, statePtr->GetPeerAddress() == kPeer1Addr);
103
104     NL_TEST_ASSERT(inSuite, (statePtr = connections.FindPeerConnectionState(kPeer1Addr, statePtr)) == nullptr);
105
106     NL_TEST_ASSERT(inSuite, statePtr = connections.FindPeerConnectionState(kPeer2Addr, nullptr));
107     NL_TEST_ASSERT(inSuite, statePtr->GetPeerAddress() == kPeer2Addr);
108     NL_TEST_ASSERT(inSuite, !connections.FindPeerConnectionState(kPeer3Addr, nullptr));
109 }
110
111 void TestFindByNodeId(nlTestSuite * inSuite, void * inContext)
112 {
113     CHIP_ERROR err;
114     PeerConnectionState * statePtr;
115     PeerConnections<3, Time::Source::kTest> connections;
116
117     err = connections.CreateNewPeerConnectionState(kPeer1Addr, &statePtr);
118     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
119     statePtr->SetPeerNodeId(kPeer1NodeId);
120
121     err = connections.CreateNewPeerConnectionState(kPeer2Addr, &statePtr);
122     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
123     statePtr->SetPeerNodeId(kPeer2NodeId);
124
125     err = connections.CreateNewPeerConnectionState(kPeer2Addr, &statePtr);
126     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
127     statePtr->SetPeerNodeId(kPeer1NodeId);
128
129     NL_TEST_ASSERT(inSuite, statePtr = connections.FindPeerConnectionState(kPeer1NodeId, nullptr));
130     char buf[100];
131     statePtr->GetPeerAddress().ToString(buf);
132     NL_TEST_ASSERT(inSuite, statePtr->GetPeerAddress() == kPeer1Addr);
133     NL_TEST_ASSERT(inSuite, statePtr->GetPeerNodeId() == kPeer1NodeId);
134
135     NL_TEST_ASSERT(inSuite, statePtr = connections.FindPeerConnectionState(kPeer1NodeId, statePtr));
136     statePtr->GetPeerAddress().ToString(buf);
137     NL_TEST_ASSERT(inSuite, statePtr->GetPeerAddress() == kPeer2Addr);
138     NL_TEST_ASSERT(inSuite, statePtr->GetPeerNodeId() == kPeer1NodeId);
139
140     NL_TEST_ASSERT(inSuite, (statePtr = connections.FindPeerConnectionState(kPeer1NodeId, statePtr)) == nullptr);
141
142     NL_TEST_ASSERT(inSuite, statePtr = connections.FindPeerConnectionState(kPeer2NodeId, nullptr));
143     NL_TEST_ASSERT(inSuite, statePtr->GetPeerAddress() == kPeer2Addr);
144     NL_TEST_ASSERT(inSuite, statePtr->GetPeerNodeId() == kPeer2NodeId);
145
146     NL_TEST_ASSERT(inSuite, !connections.FindPeerConnectionState(kPeer3NodeId, nullptr));
147 }
148
149 void TestFindByKeyId(nlTestSuite * inSuite, void * inContext)
150 {
151     CHIP_ERROR err;
152     PeerConnectionState * statePtr;
153     PeerConnections<2, Time::Source::kTest> connections;
154
155     // No Node ID, peer key 1, local key 2
156     err = connections.CreateNewPeerConnectionState(Optional<NodeId>::Missing(), 1, 2, &statePtr);
157     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
158
159     // Lookup using no node, and peer key
160     NL_TEST_ASSERT(inSuite, connections.FindPeerConnectionState(Optional<NodeId>::Missing(), 1, nullptr));
161     // Lookup using no node, and local key
162     NL_TEST_ASSERT(inSuite, connections.FindPeerConnectionStateByLocalKey(Optional<NodeId>::Missing(), 2, nullptr));
163
164     // Lookup using no node, and incorrect peer key
165     NL_TEST_ASSERT(inSuite, !connections.FindPeerConnectionState(Optional<NodeId>::Missing(), 2, nullptr));
166
167     // Lookup using no node, and incorrect local key
168     NL_TEST_ASSERT(inSuite, !connections.FindPeerConnectionStateByLocalKey(Optional<NodeId>::Missing(), 1, nullptr));
169
170     // Lookup using a node ID, and peer key
171     NL_TEST_ASSERT(inSuite, connections.FindPeerConnectionState(Optional<NodeId>::Value(kPeer1NodeId), 1, nullptr));
172
173     // Lookup using a node ID, and local key
174     NL_TEST_ASSERT(inSuite, connections.FindPeerConnectionStateByLocalKey(Optional<NodeId>::Value(kPeer1NodeId), 2, nullptr));
175
176     // Some Node ID, peer key 3, local key 4
177     err = connections.CreateNewPeerConnectionState(Optional<NodeId>::Value(kPeer1NodeId), 3, 4, &statePtr);
178     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
179
180     // Lookup using correct node (or no node), and correct keys
181     NL_TEST_ASSERT(inSuite, connections.FindPeerConnectionState(Optional<NodeId>::Value(kPeer1NodeId), 3, nullptr));
182     NL_TEST_ASSERT(inSuite, connections.FindPeerConnectionStateByLocalKey(Optional<NodeId>::Value(kPeer1NodeId), 4, nullptr));
183     NL_TEST_ASSERT(inSuite, connections.FindPeerConnectionState(Optional<NodeId>::Missing(), 3, nullptr));
184     NL_TEST_ASSERT(inSuite, connections.FindPeerConnectionStateByLocalKey(Optional<NodeId>::Missing(), 4, nullptr));
185
186     // Lookup using incorrect keys
187     NL_TEST_ASSERT(inSuite, !connections.FindPeerConnectionState(Optional<NodeId>::Value(kPeer1NodeId), 4, nullptr));
188     NL_TEST_ASSERT(inSuite, !connections.FindPeerConnectionStateByLocalKey(Optional<NodeId>::Value(kPeer1NodeId), 3, nullptr));
189
190     // Lookup using incorrect node, but correct keys
191     NL_TEST_ASSERT(inSuite, !connections.FindPeerConnectionState(Optional<NodeId>::Value(kPeer2NodeId), 3, nullptr));
192     NL_TEST_ASSERT(inSuite, !connections.FindPeerConnectionStateByLocalKey(Optional<NodeId>::Value(kPeer2NodeId), 4, nullptr));
193 }
194
195 struct ExpiredCallInfo
196 {
197     int callCount                   = 0;
198     NodeId lastCallNodeId           = 0;
199     PeerAddress lastCallPeerAddress = PeerAddress::Uninitialized();
200 };
201
202 void TestExpireConnections(nlTestSuite * inSuite, void * inContext)
203 {
204     CHIP_ERROR err;
205     ExpiredCallInfo callInfo;
206     PeerConnectionState * statePtr;
207     PeerConnections<2, Time::Source::kTest> connections;
208
209     connections.GetTimeSource().SetCurrentMonotonicTimeMs(100);
210
211     err = connections.CreateNewPeerConnectionState(kPeer1Addr, nullptr);
212     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
213
214     connections.GetTimeSource().SetCurrentMonotonicTimeMs(200);
215     err = connections.CreateNewPeerConnectionState(kPeer2Addr, &statePtr);
216     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
217     statePtr->SetPeerNodeId(kPeer2NodeId);
218
219     // cannot add before expiry
220     connections.GetTimeSource().SetCurrentMonotonicTimeMs(300);
221     err = connections.CreateNewPeerConnectionState(kPeer3Addr, &statePtr);
222     NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR);
223
224     // at time 300, this expires ip addr 1
225     connections.ExpireInactiveConnections(150, [&callInfo](const PeerConnectionState & state) {
226         callInfo.callCount++;
227         callInfo.lastCallNodeId      = state.GetPeerNodeId();
228         callInfo.lastCallPeerAddress = state.GetPeerAddress();
229     });
230     NL_TEST_ASSERT(inSuite, callInfo.callCount == 1);
231     NL_TEST_ASSERT(inSuite, callInfo.lastCallNodeId == kUndefinedNodeId);
232     NL_TEST_ASSERT(inSuite, callInfo.lastCallPeerAddress == kPeer1Addr);
233     NL_TEST_ASSERT(inSuite, !connections.FindPeerConnectionState(kPeer1NodeId, nullptr));
234
235     // now that the connections were expired, we can add peer3
236     connections.GetTimeSource().SetCurrentMonotonicTimeMs(300);
237     err = connections.CreateNewPeerConnectionState(kPeer3Addr, &statePtr);
238     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
239     statePtr->SetPeerNodeId(kPeer3NodeId);
240
241     connections.GetTimeSource().SetCurrentMonotonicTimeMs(400);
242     NL_TEST_ASSERT(inSuite, statePtr = connections.FindPeerConnectionState(kPeer2NodeId, nullptr));
243
244     connections.MarkConnectionActive(statePtr);
245     NL_TEST_ASSERT(inSuite, statePtr->GetLastActivityTimeMs() == connections.GetTimeSource().GetCurrentMonotonicTimeMs());
246
247     // At this time:
248     //   Peer 3 active at time 300
249     //   Peer 2 active at time 400
250
251     connections.GetTimeSource().SetCurrentMonotonicTimeMs(500);
252     callInfo.callCount = 0;
253     connections.ExpireInactiveConnections(150, [&callInfo](const PeerConnectionState & state) {
254         callInfo.callCount++;
255         callInfo.lastCallNodeId      = state.GetPeerNodeId();
256         callInfo.lastCallPeerAddress = state.GetPeerAddress();
257     });
258
259     // peer 2 stays active
260     NL_TEST_ASSERT(inSuite, callInfo.callCount == 1);
261     NL_TEST_ASSERT(inSuite, callInfo.lastCallNodeId == kPeer3NodeId);
262     NL_TEST_ASSERT(inSuite, callInfo.lastCallPeerAddress == kPeer3Addr);
263     NL_TEST_ASSERT(inSuite, !connections.FindPeerConnectionState(kPeer1Addr, nullptr));
264     NL_TEST_ASSERT(inSuite, connections.FindPeerConnectionState(kPeer2Addr, nullptr));
265     NL_TEST_ASSERT(inSuite, !connections.FindPeerConnectionState(kPeer3Addr, nullptr));
266
267     err = connections.CreateNewPeerConnectionState(kPeer1Addr, nullptr);
268     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
269     NL_TEST_ASSERT(inSuite, connections.FindPeerConnectionState(kPeer1Addr, nullptr));
270     NL_TEST_ASSERT(inSuite, connections.FindPeerConnectionState(kPeer2Addr, nullptr));
271     NL_TEST_ASSERT(inSuite, !connections.FindPeerConnectionState(kPeer3Addr, nullptr));
272
273     // peer 1 and 2 are active
274     connections.GetTimeSource().SetCurrentMonotonicTimeMs(1000);
275     callInfo.callCount = 0;
276     connections.ExpireInactiveConnections(100, [&callInfo](const PeerConnectionState & state) {
277         callInfo.callCount++;
278         callInfo.lastCallNodeId      = state.GetPeerNodeId();
279         callInfo.lastCallPeerAddress = state.GetPeerAddress();
280     });
281     NL_TEST_ASSERT(inSuite, callInfo.callCount == 2); // everything expired
282     NL_TEST_ASSERT(inSuite, !connections.FindPeerConnectionState(kPeer1Addr, nullptr));
283     NL_TEST_ASSERT(inSuite, !connections.FindPeerConnectionState(kPeer2Addr, nullptr));
284     NL_TEST_ASSERT(inSuite, !connections.FindPeerConnectionState(kPeer3Addr, nullptr));
285 }
286
287 } // namespace
288
289 // clang-format off
290 static const nlTest sTests[] =
291 {
292     NL_TEST_DEF("BasicFunctionality", TestBasicFunctionality),
293     NL_TEST_DEF("FindByPeerAddress", TestFindByAddress),
294     NL_TEST_DEF("FindByNodeId", TestFindByNodeId),
295     NL_TEST_DEF("FindByKeyId", TestFindByKeyId),
296     NL_TEST_DEF("ExpireConnections", TestExpireConnections),
297     NL_TEST_SENTINEL()
298 };
299 // clang-format on
300
301 int TestPeerConnectionsFn(void)
302 {
303     nlTestSuite theSuite = { "Transport-PeerConnections", &sTests[0], nullptr, nullptr };
304     nlTestRunner(&theSuite, nullptr);
305     return nlTestRunnerStats(&theSuite);
306 }
307
308 CHIP_REGISTER_TEST_SUITE(TestPeerConnectionsFn)