]> git.lizzy.rs Git - dragonfireclient.git/blob - src/unittest/test_connection.cpp
Revert "Make Lint Happy"
[dragonfireclient.git] / src / unittest / test_connection.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "test.h"
21
22 #include "log.h"
23 #include "porting.h"
24 #include "settings.h"
25 #include "util/serialize.h"
26 #include "network/connection.h"
27 #include "network/networkpacket.h"
28 #include "network/socket.h"
29
30 class TestConnection : public TestBase {
31 public:
32         TestConnection()
33         {
34                 if (INTERNET_SIMULATOR == false)
35                         TestManager::registerTestModule(this);
36         }
37
38         const char *getName() { return "TestConnection"; }
39
40         void runTests(IGameDef *gamedef);
41
42         void testHelpers();
43         void testConnectSendReceive();
44 };
45
46 static TestConnection g_test_instance;
47
48 void TestConnection::runTests(IGameDef *gamedef)
49 {
50         TEST(testHelpers);
51         TEST(testConnectSendReceive);
52 }
53
54 ////////////////////////////////////////////////////////////////////////////////
55
56 struct Handler : public con::PeerHandler
57 {
58         Handler(const char *a_name) : name(a_name) {}
59
60         void peerAdded(con::Peer *peer)
61         {
62                 infostream << "Handler(" << name << ")::peerAdded(): "
63                         "id=" << peer->id << std::endl;
64                 last_id = peer->id;
65                 count++;
66         }
67
68         void deletingPeer(con::Peer *peer, bool timeout)
69         {
70                 infostream << "Handler(" << name << ")::deletingPeer(): "
71                         "id=" << peer->id << ", timeout=" << timeout << std::endl;
72                 last_id = peer->id;
73                 count--;
74         }
75
76         s32 count = 0;
77         u16 last_id = 0;
78         const char *name;
79 };
80
81 void TestConnection::testHelpers()
82 {
83         // Some constants for testing
84         u32 proto_id = 0x12345678;
85         session_t peer_id = 123;
86         u8 channel = 2;
87         SharedBuffer<u8> data1(1);
88         data1[0] = 100;
89         Address a(127,0,0,1, 10);
90         const u16 seqnum = 34352;
91
92         con::BufferedPacket p1 = con::makePacket(a, data1,
93                         proto_id, peer_id, channel);
94         /*
95                 We should now have a packet with this data:
96                 Header:
97                         [0] u32 protocol_id
98                         [4] session_t sender_peer_id
99                         [6] u8 channel
100                 Data:
101                         [7] u8 data1[0]
102         */
103         UASSERT(readU32(&p1.data[0]) == proto_id);
104         UASSERT(readU16(&p1.data[4]) == peer_id);
105         UASSERT(readU8(&p1.data[6]) == channel);
106         UASSERT(readU8(&p1.data[7]) == data1[0]);
107
108         //infostream<<"initial data1[0]="<<((u32)data1[0]&0xff)<<std::endl;
109
110         SharedBuffer<u8> p2 = con::makeReliablePacket(data1, seqnum);
111
112         /*infostream<<"p2.getSize()="<<p2.getSize()<<", data1.getSize()="
113                         <<data1.getSize()<<std::endl;
114         infostream<<"readU8(&p2[3])="<<readU8(&p2[3])
115                         <<" p2[3]="<<((u32)p2[3]&0xff)<<std::endl;
116         infostream<<"data1[0]="<<((u32)data1[0]&0xff)<<std::endl;*/
117
118         UASSERT(p2.getSize() == 3 + data1.getSize());
119         UASSERT(readU8(&p2[0]) == con::PACKET_TYPE_RELIABLE);
120         UASSERT(readU16(&p2[1]) == seqnum);
121         UASSERT(readU8(&p2[3]) == data1[0]);
122 }
123
124
125 void TestConnection::testConnectSendReceive()
126 {
127         /*
128                 Test some real connections
129
130                 NOTE: This mostly tests the legacy interface.
131         */
132
133         u32 proto_id = 0xad26846a;
134
135         Handler hand_server("server");
136         Handler hand_client("client");
137
138         Address address(0, 0, 0, 0, 30001);
139         Address bind_addr(0, 0, 0, 0, 30001);
140         /*
141          * Try to use the bind_address for servers with no localhost address
142          * For example: FreeBSD jails
143          */
144         std::string bind_str = g_settings->get("bind_address");
145         try {
146                 bind_addr.Resolve(bind_str.c_str());
147
148                 if (!bind_addr.isIPv6()) {
149                         address = bind_addr;
150                 }
151         } catch (ResolveError &e) {
152         }
153
154         infostream << "** Creating server Connection" << std::endl;
155         con::Connection server(proto_id, 512, 5.0, false, &hand_server);
156         server.Serve(address);
157
158         infostream << "** Creating client Connection" << std::endl;
159         con::Connection client(proto_id, 512, 5.0, false, &hand_client);
160
161         UASSERT(hand_server.count == 0);
162         UASSERT(hand_client.count == 0);
163
164         sleep_ms(50);
165
166         Address server_address(127, 0, 0, 1, 30001);
167         if (address != Address(0, 0, 0, 0, 30001)) {
168                 server_address = bind_addr;
169         }
170
171         infostream << "** running client.Connect()" << std::endl;
172         client.Connect(server_address);
173
174         sleep_ms(50);
175
176         // Client should not have added client yet
177         UASSERT(hand_client.count == 0);
178
179         try {
180                 NetworkPacket pkt;
181                 infostream << "** running client.Receive()" << std::endl;
182                 client.Receive(&pkt);
183                 infostream << "** Client received: peer_id=" << pkt.getPeerId()
184                         << ", size=" << pkt.getSize() << std::endl;
185         } catch (con::NoIncomingDataException &e) {
186         }
187
188         // Client should have added server now
189         UASSERT(hand_client.count == 1);
190         UASSERT(hand_client.last_id == 1);
191         // Server should not have added client yet
192         UASSERT(hand_server.count == 0);
193
194         sleep_ms(100);
195
196         try {
197                 NetworkPacket pkt;
198                 infostream << "** running server.Receive()" << std::endl;
199                 server.Receive(&pkt);
200                 infostream << "** Server received: peer_id=" << pkt.getPeerId()
201                                 << ", size=" << pkt.getSize()
202                                 << std::endl;
203         } catch (con::NoIncomingDataException &e) {
204                 // No actual data received, but the client has
205                 // probably been connected
206         }
207
208         // Client should be the same
209         UASSERT(hand_client.count == 1);
210         UASSERT(hand_client.last_id == 1);
211         // Server should have the client
212         UASSERT(hand_server.count == 1);
213         UASSERT(hand_server.last_id == 2);
214
215         //sleep_ms(50);
216
217         while (client.Connected() == false) {
218                 try {
219                         NetworkPacket pkt;
220                         infostream << "** running client.Receive()" << std::endl;
221                         client.Receive(&pkt);
222                         infostream << "** Client received: peer_id=" << pkt.getPeerId()
223                                 << ", size=" << pkt.getSize() << std::endl;
224                 } catch (con::NoIncomingDataException &e) {
225                 }
226                 sleep_ms(50);
227         }
228
229         sleep_ms(50);
230
231         try {
232                 NetworkPacket pkt;
233                 infostream << "** running server.Receive()" << std::endl;
234                 server.Receive(&pkt);
235                 infostream << "** Server received: peer_id=" << pkt.getPeerId()
236                                 << ", size=" << pkt.getSize()
237                                 << std::endl;
238         } catch (con::NoIncomingDataException &e) {
239         }
240
241         /*
242                 Simple send-receive test
243         */
244         {
245                 NetworkPacket pkt;
246                 pkt.putRawPacket((u8*) "Hello World !", 14, 0);
247
248                 SharedBuffer<u8> sentdata = pkt.oldForgePacket();
249
250                 infostream<<"** running client.Send()"<<std::endl;
251                 client.Send(PEER_ID_SERVER, 0, &pkt, true);
252
253                 sleep_ms(50);
254
255                 NetworkPacket recvpacket;
256                 infostream << "** running server.Receive()" << std::endl;
257                 server.Receive(&recvpacket);
258                 infostream << "** Server received: peer_id=" << pkt.getPeerId()
259                                 << ", size=" << pkt.getSize()
260                                 << ", data=" << (const char*)pkt.getU8Ptr(0)
261                                 << std::endl;
262
263                 SharedBuffer<u8> recvdata = pkt.oldForgePacket();
264
265                 UASSERT(memcmp(*sentdata, *recvdata, recvdata.getSize()) == 0);
266         }
267
268         session_t peer_id_client = 2;
269         /*
270                 Send a large packet
271         */
272         {
273                 const int datasize = 30000;
274                 NetworkPacket pkt(0, datasize);
275                 for (u16 i=0; i<datasize; i++) {
276                         pkt << (u8) i/4;
277                 }
278
279                 infostream << "Sending data (size=" << datasize << "):";
280                 for (int i = 0; i < datasize && i < 20; i++) {
281                         if (i % 2 == 0)
282                                 infostream << " ";
283                         char buf[10];
284                         porting::mt_snprintf(buf, sizeof(buf), "%.2X",
285                                 ((int)((const char *)pkt.getU8Ptr(0))[i]) & 0xff);
286                         infostream<<buf;
287                 }
288                 if (datasize > 20)
289                         infostream << "...";
290                 infostream << std::endl;
291
292                 SharedBuffer<u8> sentdata = pkt.oldForgePacket();
293
294                 server.Send(peer_id_client, 0, &pkt, true);
295
296                 //sleep_ms(3000);
297
298                 SharedBuffer<u8> recvdata;
299                 infostream << "** running client.Receive()" << std::endl;
300                 session_t peer_id = 132;
301                 u16 size = 0;
302                 bool received = false;
303                 u64 timems0 = porting::getTimeMs();
304                 for (;;) {
305                         if (porting::getTimeMs() - timems0 > 5000 || received)
306                                 break;
307                         try {
308                                 NetworkPacket pkt;
309                                 client.Receive(&pkt);
310                                 size = pkt.getSize();
311                                 peer_id = pkt.getPeerId();
312                                 recvdata = pkt.oldForgePacket();
313                                 received = true;
314                         } catch (con::NoIncomingDataException &e) {
315                         }
316                         sleep_ms(10);
317                 }
318                 UASSERT(received);
319                 infostream << "** Client received: peer_id=" << peer_id
320                         << ", size=" << size << std::endl;
321
322                 infostream << "Received data (size=" << size << "): ";
323                 for (int i = 0; i < size && i < 20; i++) {
324                         if (i % 2 == 0)
325                                 infostream << " ";
326                         char buf[10];
327                         porting::mt_snprintf(buf, sizeof(buf), "%.2X", ((int)(recvdata[i])) & 0xff);
328                         infostream << buf;
329                 }
330                 if (size > 20)
331                         infostream << "...";
332                 infostream << std::endl;
333
334                 UASSERT(memcmp(*sentdata, *recvdata, recvdata.getSize()) == 0);
335                 UASSERT(peer_id == PEER_ID_SERVER);
336         }
337
338         // Check peer handlers
339         UASSERT(hand_client.count == 1);
340         UASSERT(hand_client.last_id == 1);
341         UASSERT(hand_server.count == 1);
342         UASSERT(hand_server.last_id == 2);
343 }