aboutsummaryrefslogtreecommitdiff
path: root/src/unittest/test_connection.cpp
diff options
context:
space:
mode:
authorkwolekr <kwolekr@minetest.net>2015-04-26 01:24:19 -0400
committerkwolekr <kwolekr@minetest.net>2015-04-26 15:08:54 -0400
commit7220ca906dfc804bd508336f5bed252bcec62ae0 (patch)
tree6a61f536227510a57b023019271084450042a7ad /src/unittest/test_connection.cpp
parent45a77c8bf1a744edc1642d717579281cf988f8dd (diff)
downloadminetest-7220ca906dfc804bd508336f5bed252bcec62ae0.tar.gz
minetest-7220ca906dfc804bd508336f5bed252bcec62ae0.tar.bz2
minetest-7220ca906dfc804bd508336f5bed252bcec62ae0.zip
Tests: Modularize unit testing
Split unit tests into separate files under src/unittest/ Give better unittest diagnostics Clean up some code
Diffstat (limited to 'src/unittest/test_connection.cpp')
-rw-r--r--src/unittest/test_connection.cpp348
1 files changed, 348 insertions, 0 deletions
diff --git a/src/unittest/test_connection.cpp b/src/unittest/test_connection.cpp
new file mode 100644
index 000000000..49e412fc8
--- /dev/null
+++ b/src/unittest/test_connection.cpp
@@ -0,0 +1,348 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "test.h"
+
+#include "log.h"
+#include "socket.h"
+#include "settings.h"
+#include "util/serialize.h"
+#include "network/connection.h"
+
+class TestConnection : public TestBase {
+public:
+ TestConnection()
+ {
+ if (INTERNET_SIMULATOR == false)
+ TestManager::registerTestModule(this);
+ }
+
+ const char *getName() { return "TestConnection"; }
+
+ void runTests(IGameDef *gamedef);
+
+ void testHelpers();
+ void testConnectSendReceive();
+};
+
+static TestConnection g_test_instance;
+
+void TestConnection::runTests(IGameDef *gamedef)
+{
+ TEST(testHelpers);
+ TEST(testConnectSendReceive);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct Handler : public con::PeerHandler
+{
+ Handler(const char *a_name)
+ {
+ count = 0;
+ last_id = 0;
+ name = a_name;
+ }
+
+ void peerAdded(con::Peer *peer)
+ {
+ infostream << "Handler(" << name << ")::peerAdded(): "
+ "id=" << peer->id << std::endl;
+ last_id = peer->id;
+ count++;
+ }
+
+ void deletingPeer(con::Peer *peer, bool timeout)
+ {
+ infostream << "Handler(" << name << ")::deletingPeer(): "
+ "id=" << peer->id << ", timeout=" << timeout << std::endl;
+ last_id = peer->id;
+ count--;
+ }
+
+ s32 count;
+ u16 last_id;
+ const char *name;
+};
+
+void TestConnection::testHelpers()
+{
+ // Some constants for testing
+ u32 proto_id = 0x12345678;
+ u16 peer_id = 123;
+ u8 channel = 2;
+ SharedBuffer<u8> data1(1);
+ data1[0] = 100;
+ Address a(127,0,0,1, 10);
+ const u16 seqnum = 34352;
+
+ con::BufferedPacket p1 = con::makePacket(a, data1,
+ proto_id, peer_id, channel);
+ /*
+ We should now have a packet with this data:
+ Header:
+ [0] u32 protocol_id
+ [4] u16 sender_peer_id
+ [6] u8 channel
+ Data:
+ [7] u8 data1[0]
+ */
+ UASSERT(readU32(&p1.data[0]) == proto_id);
+ UASSERT(readU16(&p1.data[4]) == peer_id);
+ UASSERT(readU8(&p1.data[6]) == channel);
+ UASSERT(readU8(&p1.data[7]) == data1[0]);
+
+ //infostream<<"initial data1[0]="<<((u32)data1[0]&0xff)<<std::endl;
+
+ SharedBuffer<u8> p2 = con::makeReliablePacket(data1, seqnum);
+
+ /*infostream<<"p2.getSize()="<<p2.getSize()<<", data1.getSize()="
+ <<data1.getSize()<<std::endl;
+ infostream<<"readU8(&p2[3])="<<readU8(&p2[3])
+ <<" p2[3]="<<((u32)p2[3]&0xff)<<std::endl;
+ infostream<<"data1[0]="<<((u32)data1[0]&0xff)<<std::endl;*/
+
+ UASSERT(p2.getSize() == 3 + data1.getSize());
+ UASSERT(readU8(&p2[0]) == TYPE_RELIABLE);
+ UASSERT(readU16(&p2[1]) == seqnum);
+ UASSERT(readU8(&p2[3]) == data1[0]);
+}
+
+
+void TestConnection::testConnectSendReceive()
+{
+ DSTACK("TestConnection::Run");
+
+ /*
+ Test some real connections
+
+ NOTE: This mostly tests the legacy interface.
+ */
+
+ u32 proto_id = 0xad26846a;
+
+ Handler hand_server("server");
+ Handler hand_client("client");
+
+ Address address(0, 0, 0, 0, 30001);
+ Address bind_addr(0, 0, 0, 0, 30001);
+ /*
+ * Try to use the bind_address for servers with no localhost address
+ * For example: FreeBSD jails
+ */
+ std::string bind_str = g_settings->get("bind_address");
+ try {
+ bind_addr.Resolve(bind_str.c_str());
+
+ if (!bind_addr.isIPv6()) {
+ address = bind_addr;
+ }
+ } catch (ResolveError &e) {
+ }
+
+ infostream << "** Creating server Connection" << std::endl;
+ con::Connection server(proto_id, 512, 5.0, false, &hand_server);
+ server.Serve(address);
+
+ infostream << "** Creating client Connection" << std::endl;
+ con::Connection client(proto_id, 512, 5.0, false, &hand_client);
+
+ UASSERT(hand_server.count == 0);
+ UASSERT(hand_client.count == 0);
+
+ sleep_ms(50);
+
+ Address server_address(127, 0, 0, 1, 30001);
+ if (address != Address(0, 0, 0, 0, 30001)) {
+ server_address = bind_addr;
+ }
+
+ infostream << "** running client.Connect()" << std::endl;
+ client.Connect(server_address);
+
+ sleep_ms(50);
+
+ // Client should not have added client yet
+ UASSERT(hand_client.count == 0);
+
+ try {
+ NetworkPacket pkt;
+ infostream << "** running client.Receive()" << std::endl;
+ client.Receive(&pkt);
+ infostream << "** Client received: peer_id=" << pkt.getPeerId()
+ << ", size=" << pkt.getSize() << std::endl;
+ } catch (con::NoIncomingDataException &e) {
+ }
+
+ // Client should have added server now
+ UASSERT(hand_client.count == 1);
+ UASSERT(hand_client.last_id == 1);
+ // Server should not have added client yet
+ UASSERT(hand_server.count == 0);
+
+ sleep_ms(100);
+
+ try {
+ NetworkPacket pkt;
+ infostream << "** running server.Receive()" << std::endl;
+ server.Receive(&pkt);
+ infostream << "** Server received: peer_id=" << pkt.getPeerId()
+ << ", size=" << pkt.getSize()
+ << std::endl;
+ } catch (con::NoIncomingDataException &e) {
+ // No actual data received, but the client has
+ // probably been connected
+ }
+
+ // Client should be the same
+ UASSERT(hand_client.count == 1);
+ UASSERT(hand_client.last_id == 1);
+ // Server should have the client
+ UASSERT(hand_server.count == 1);
+ UASSERT(hand_server.last_id == 2);
+
+ //sleep_ms(50);
+
+ while (client.Connected() == false) {
+ try {
+ NetworkPacket pkt;
+ infostream << "** running client.Receive()" << std::endl;
+ client.Receive(&pkt);
+ infostream << "** Client received: peer_id=" << pkt.getPeerId()
+ << ", size=" << pkt.getSize() << std::endl;
+ } catch (con::NoIncomingDataException &e) {
+ }
+ sleep_ms(50);
+ }
+
+ sleep_ms(50);
+
+ try {
+ NetworkPacket pkt;
+ infostream << "** running server.Receive()" << std::endl;
+ server.Receive(&pkt);
+ infostream << "** Server received: peer_id=" << pkt.getPeerId()
+ << ", size=" << pkt.getSize()
+ << std::endl;
+ } catch (con::NoIncomingDataException &e) {
+ }
+
+ /*
+ Simple send-receive test
+ */
+ {
+ NetworkPacket pkt;
+ pkt.putRawPacket((u8*) "Hello World !", 14, 0);
+
+ Buffer<u8> sentdata = pkt.oldForgePacket();
+
+ infostream<<"** running client.Send()"<<std::endl;
+ client.Send(PEER_ID_SERVER, 0, &pkt, true);
+
+ sleep_ms(50);
+
+ NetworkPacket recvpacket;
+ infostream << "** running server.Receive()" << std::endl;
+ server.Receive(&recvpacket);
+ infostream << "** Server received: peer_id=" << pkt.getPeerId()
+ << ", size=" << pkt.getSize()
+ << ", data=" << (const char*)pkt.getU8Ptr(0)
+ << std::endl;
+
+ Buffer<u8> recvdata = pkt.oldForgePacket();
+
+ UASSERT(memcmp(*sentdata, *recvdata, recvdata.getSize()) == 0);
+ }
+
+ u16 peer_id_client = 2;
+ /*
+ Send a large packet
+ */
+ {
+ const int datasize = 30000;
+ NetworkPacket pkt(0, datasize);
+ for (u16 i=0; i<datasize; i++) {
+ pkt << (u8) i/4;
+ }
+
+ infostream << "Sending data (size=" << datasize << "):";
+ for (int i = 0; i < datasize && i < 20; i++) {
+ if (i % 2 == 0)
+ infostream << " ";
+ char buf[10];
+ snprintf(buf, 10, "%.2X",
+ ((int)((const char *)pkt.getU8Ptr(0))[i]) & 0xff);
+ infostream<<buf;
+ }
+ if (datasize > 20)
+ infostream << "...";
+ infostream << std::endl;
+
+ Buffer<u8> sentdata = pkt.oldForgePacket();
+
+ server.Send(peer_id_client, 0, &pkt, true);
+
+ //sleep_ms(3000);
+
+ Buffer<u8> recvdata;
+ infostream << "** running client.Receive()" << std::endl;
+ u16 peer_id = 132;
+ u16 size = 0;
+ bool received = false;
+ u32 timems0 = porting::getTimeMs();
+ for (;;) {
+ if (porting::getTimeMs() - timems0 > 5000 || received)
+ break;
+ try {
+ NetworkPacket pkt;
+ client.Receive(&pkt);
+ size = pkt.getSize();
+ peer_id = pkt.getPeerId();
+ recvdata = pkt.oldForgePacket();
+ received = true;
+ } catch (con::NoIncomingDataException &e) {
+ }
+ sleep_ms(10);
+ }
+ UASSERT(received);
+ infostream << "** Client received: peer_id=" << peer_id
+ << ", size=" << size << std::endl;
+
+ infostream << "Received data (size=" << size << "): ";
+ for (int i = 0; i < size && i < 20; i++) {
+ if (i % 2 == 0)
+ infostream << " ";
+ char buf[10];
+ snprintf(buf, 10, "%.2X", ((int)(recvdata[i])) & 0xff);
+ infostream << buf;
+ }
+ if (size > 20)
+ infostream << "...";
+ infostream << std::endl;
+
+ UASSERT(memcmp(*sentdata, *recvdata, recvdata.getSize()) == 0);
+ UASSERT(peer_id == PEER_ID_SERVER);
+ }
+
+ // Check peer handlers
+ UASSERT(hand_client.count == 1);
+ UASSERT(hand_client.last_id == 1);
+ UASSERT(hand_server.count == 1);
+ UASSERT(hand_server.last_id == 2);
+}