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