#include #include #include #include #include "../Tests.hpp" #include "../src/ErrorSimulator.hpp" #include "core/Network.hpp" using Core::Client; using Core::InPacket; using Core::OutPacket; using Core::Server; #define TEST_READ(Type, type, value) \ { \ type u; \ TEST_FALSE(in.read##Type(u)); \ TEST_TRUE(u == value); \ } #define TEST_READ_FAIL(Type, type) \ { \ type u; \ TEST_TRUE(in.read##Type(u)); \ } static void testWriteRead() { OutPacket out; out.writeU8(200); out.writeU16(6656); out.writeU32(348'923'689); out.writeI8(90); out.writeI8(-35); out.writeI16(843); out.writeI16(-8961); out.writeI32(100'430'199); out.writeI32(-534'534); out.writeFloat(64564.5346f); const char s[] = "This is Great"; out.writeString(s); InPacket in(out.data.getData(), out.data.getLength()); TEST_READ(U8, u8, 200) TEST_READ(U16, u16, 6656) TEST_READ(U32, u32, 348'923'689) TEST_READ(I8, i8, 90) TEST_READ(I8, i8, -35) TEST_READ(I16, i16, 843) TEST_READ(I16, i16, -8961) TEST_READ(I32, i32, 100'430'199) TEST_READ(I32, i32, -534'534) float f; TEST_FALSE(in.readFloat(f)); TEST_FLOAT(64564.5346f, f, 0.00001f); char buffer[256]; size_t n = in.readString(buffer, sizeof(buffer)); TEST(14, n); TEST_STRING(s, buffer); TEST_READ_FAIL(U8, u8) TEST_READ_FAIL(U16, u16) TEST_READ_FAIL(U32, u32) TEST_READ_FAIL(I8, i8) TEST_READ_FAIL(I16, i16) TEST_READ_FAIL(I32, i32) TEST_READ_FAIL(Float, float) TEST(0, in.readString(nullptr, 0)); TEST(0, in.readString(buffer, sizeof(buffer))); } static void testTooShortBuffer() { OutPacket out; out.writeString("This is Great"); out.writeString("Well hoho"); InPacket in(out.data.getData(), out.data.getLength()); char buffer[8]; size_t n = in.readString(buffer, sizeof(buffer)); TEST(14, n); TEST_STRING("This is", buffer); char buffer2[6]; size_t n2 = in.readString(buffer2, sizeof(buffer2)); TEST(10, n2); TEST_STRING("Well ", buffer2); } struct PacketTest { u8 a; u8 b; }; static void testBinaryData() { OutPacket out; PacketTest data = {56, 3}; out.write(&data, sizeof(data)); InPacket in(out.data.getData(), out.data.getLength()); PacketTest inData; TEST_FALSE(in.read(&inData, sizeof(inData))); TEST_TRUE(memcmp(&inData, &data, sizeof(inData)) == 0); } static void testShortString() { OutPacket out; out.writeU16(200); out.writeU16(65'535); InPacket in(out.data.getData(), out.data.getLength()); char buffer[256]; size_t n = in.readString(buffer, sizeof(buffer)); TEST(200, n); TEST_STRING("", buffer); } using BoolFunction = bool (*)(void*); static void tick(Server& s, Client& c, BoolFunction f, void* fd) { for(int i = 0; i < 100'000 && f(fd); i++) { c.tick(); s.tick(); } } static void tickUntilConnected(Server& s, Client& c) { tick( s, c, [](void* v) { return !static_cast(v)->isConnected(); }, &c); } static bool clientConnected = false; static bool clientDisconnected = false; static bool clientPackage = false; static int packageCounter = 0; static bool serverConnected = false; static bool serverDisconnect = false; static u8 data1 = 0; static u16 data2 = 0; static u32 data3 = 0; static i8 data4 = 0; static i16 data5 = 0; static i32 data6 = 0; static i8 data7 = 0; static i16 data8 = 0; static i32 data9 = 0; static char data10[20]; static float data11 = 0.0f; static void onServerConnect(Server&, Core::ClientHandle) { serverConnected = true; } static void onServerDisconnect(Server&, Core::ClientHandle) { serverDisconnect = true; } static void onServerPacket(Server& s, Core::ClientHandle client, InPacket& in) { TEST_FALSE(in.readU8(data1)); TEST_FALSE(in.readU16(data2)); TEST_FALSE(in.readU32(data3)); TEST_FALSE(in.readI8(data4)); TEST_FALSE(in.readI16(data5)); TEST_FALSE(in.readI32(data6)); TEST_FALSE(in.readI8(data7)); TEST_FALSE(in.readI16(data8)); TEST_FALSE(in.readI32(data9)); TEST(9, in.readString(data10, sizeof(data10))); TEST_FALSE(in.readFloat(data11)); OutPacket out; if(packageCounter == 0) { s.sendPacket(client, out, Core::PacketSendMode::RELIABLE); } else if(packageCounter == 1) { s.sendPacket(client, out, Core::PacketSendMode::SEQUENCED); } else if(packageCounter == 2) { s.sendPacket(client, out, Core::PacketSendMode::UNSEQUENCED); } packageCounter++; } static void onClientConnect() { clientConnected = true; } static void onClientDisconnect() { clientDisconnected = true; } static void onClientPacket(InPacket&) { clientPackage = true; } static void testConnect(Core::PacketSendMode mode) { clientConnected = false; clientDisconnected = false; clientPackage = false; serverConnected = false; serverDisconnect = false; data1 = 0; data2 = 0; data3 = 0; data4 = 0; data5 = 0; data6 = 0; data7 = 0; data8 = 0; data9 = 0; *data10 = '\0'; data11 = 0.0f; Server s; s.resetHandler(); s.setConnectHandler(onServerConnect); s.setDisconnectHandler(onServerDisconnect); s.setPacketHandler(onServerPacket); Client c; c.resetHandler(); c.setConnectHandler(onClientConnect); c.setDisconnectHandler(onClientDisconnect); c.setPacketHandler(onClientPacket); if(!TEST_FALSE(s.start(54'321, 5))) { return; } else if(!TEST_FALSE(c.start())) { return; } else if(!TEST_FALSE(c.connect("127.0.0.1", 54'321, 90))) { return; } TEST_FALSE(c.isConnected()); TEST_TRUE(c.isConnecting()); tickUntilConnected(s, c); TEST_TRUE(clientConnected); TEST_TRUE(c.isConnected()); TEST_FALSE(c.isConnecting()); OutPacket out; out.writeU8(0xF1); out.writeU16(0xF123); out.writeU32(0xF123'4567); out.writeI8(-0x71); out.writeI16(-0x7123); out.writeI32(-0x7123'4567); out.writeI8(0x71); out.writeI16(0x7123); out.writeI32(0x7123'4567); const char st[] = "Hi there"; out.writeString(st); out.writeFloat(252345.983f); c.sendPacket(out, mode); tick(s, c, [](void*) { return !clientPackage || !serverConnected; }, &c); TEST_TRUE(clientPackage); TEST_TRUE(serverConnected); TEST(0xF1, data1); TEST(0xF123, data2); TEST(0xF123'4567, data3); TEST(-0x71, data4); TEST(-0x7123, data5); TEST(-0x7123'4567, data6); TEST(0x71, data7); TEST(0x7123, data8); TEST(0x7123'4567, data9); TEST_STRING(st, data10); TEST_FLOAT(252345.983f, data11, 0.01f); c.disconnect(90); TEST_FALSE(c.isConnected()); TEST_FALSE(c.isConnecting()); tick( s, c, [](void*) { return !clientDisconnected || !serverDisconnect; }, &c); TEST_TRUE(clientDisconnected); TEST_TRUE(serverDisconnect); c.stop(); s.stop(); } static bool disconnected = false; static void testStopDisconnect() { disconnected = true; } static void testDisconnect() { disconnected = false; Client c; c.resetHandler(); c.setDisconnectHandler(testStopDisconnect); if(!TEST_FALSE(c.start())) { return; } else if(!TEST_FALSE(c.connect("127.0.0.1", 54'321, 90))) { return; } TEST_FALSE(c.isConnected()); TEST_TRUE(c.isConnecting()); c.disconnect(50); Server s; tick(s, c, [](void*) { return !disconnected; }, &c); TEST_FALSE(c.isConnected()); TEST_FALSE(c.isConnecting()); TEST_TRUE(disconnected); c.stop(); } static void testStop() { disconnected = false; Client c; c.resetHandler(); c.setDisconnectHandler(testStopDisconnect); if(!TEST_FALSE(c.start())) { return; } else if(!TEST_FALSE(c.connect("127.0.0.1", 54'321, 90))) { return; } TEST_FALSE(c.isConnected()); TEST_TRUE(c.isConnecting()); c.stop(); TEST_FALSE(c.isConnected()); TEST_FALSE(c.isConnecting()); TEST_TRUE(disconnected); } static void testClientStartFails() { Client c; TEST_FALSE(c.start()); useReport = false; TEST_TRUE(c.start()); c.stop(); #ifdef ERROR_SIMULATOR failCounter = 0; TEST_TRUE(c.start()); failCounter = 1; TEST_TRUE(c.start()); failCounter = -1; #endif useReport = true; } static void testClientConnectionFails() { Client c; c.resetHandler(); useReport = false; TEST_TRUE(c.connect("", 54'321, 100)); TEST_FALSE(c.start()); #ifdef ERROR_SIMULATOR failCounter = 0; TEST_TRUE(c.connect("", 54'321, 100)); failCounter = -1; #endif TEST_FALSE(c.connect("", 54'321, 100)); TEST_TRUE(c.connect("", 54'321, 100)); useReport = true; for(int i = 0; i < 100; i++) { c.tick(); } c.stop(); } static void testInvalidClientAccess() { Client c; c.disconnect(0); OutPacket out; c.sendPacket(out, Core::PacketSendMode::RELIABLE); c.tick(); } static void testServerStartFails() { useReport = false; Server s; TEST_TRUE(s.start(54'321, 0)); #ifdef ERROR_SIMULATOR failCounter = 0; TEST_TRUE(s.start(54'321, 5)); failCounter = 1; TEST_TRUE(s.start(54'321, 5)); failCounter = -1; #endif TEST_FALSE(s.start(54'321, 5)); TEST_TRUE(s.start(54'321, 5)); useReport = true; s.stop(); } static void testServerClosesOnConnected() { Server s; Client c; clientDisconnected = false; TEST_FALSE(s.start(54'321, 5)); TEST_FALSE(c.start()); c.setDisconnectHandler(onClientDisconnect); TEST_FALSE(c.connect("127.0.0.1", 54'321, 50)); tickUntilConnected(s, c); TEST_TRUE(c.isConnected()); s.stop(); c.setTimeout(500, 500, 500); for(int i = 0; i < 500 && c.isConnected(); i++) { c.tick(); Core::Clock::sleepMillis(10); } TEST_FALSE(c.isConnected()); TEST_TRUE(clientDisconnected); c.stop(); } static Core::ClientHandle clientId = 0; static void onConnectSetClient(Server&, Core::ClientHandle client) { clientId = client; } static void testServerDisconnectsClient() { clientDisconnected = false; Server s; Client c; TEST_FALSE(s.start(54'321, 5)); TEST_FALSE(c.start()); c.setDisconnectHandler(onClientDisconnect); s.setConnectHandler(onConnectSetClient); TEST_FALSE(c.connect("127.0.0.1", 54'321, 50)); tickUntilConnected(s, c); TEST_TRUE(c.isConnected()); s.disconnectClient(clientId); for(int i = 0; i < 500 && c.isConnected(); i++) { c.tick(); s.tick(); Core::Clock::sleepMillis(10); } TEST_FALSE(c.isConnected()); TEST_TRUE(clientDisconnected); c.stop(); s.stop(); } static void onConnectSetTimeout(Server& s, Core::ClientHandle client) { s.setTimeout(client, 500, 500, 500); } static void testClientClosesOnConnected() { serverDisconnect = false; Server s; Client c; TEST_FALSE(s.start(54'321, 5)); TEST_FALSE(c.start()); s.setDisconnectHandler(onServerDisconnect); s.setConnectHandler(onConnectSetTimeout); TEST_FALSE(c.connect("127.0.0.1", 54'321, 50)); tickUntilConnected(s, c); TEST_TRUE(c.isConnected()); #ifdef ERROR_SIMULATOR failCounter = 0; #endif c.stop(); #ifdef ERROR_SIMULATOR failCounter = -1; #endif for(int i = 0; i < 500 && !serverDisconnect; i++) { s.tick(); Core::Clock::sleepMillis(10); } TEST_TRUE(serverDisconnect); s.stop(); } static void testInvalidServerAccess() { Server s; s.tick(); OutPacket out; s.sendPacket(0, out, Core::PacketSendMode::RELIABLE); s.setTimeout(0, 500, 500, 500); s.disconnectClient(0); } static void testDummyCallbacks() { Server s; Client c; c.resetHandler(); s.resetHandler(); TEST_FALSE(s.start(54'321, 5)); TEST_FALSE(c.start()); TEST_FALSE(c.connect("127.0.0.1", 54'321, 50)); tickUntilConnected(s, c); TEST_TRUE(c.isConnected()); OutPacket out; s.sendPacketBroadcast(out, Core::PacketSendMode::RELIABLE); c.sendPacket(out, Core::PacketSendMode::RELIABLE); for(int i = 0; i < 100; i++) { c.tick(); s.tick(); } c.stop(); s.stop(); } void testNetwork() { testWriteRead(); testTooShortBuffer(); testBinaryData(); testShortString(); testConnect(Core::PacketSendMode::UNSEQUENCED); testConnect(Core::PacketSendMode::SEQUENCED); testConnect(Core::PacketSendMode::RELIABLE); testDisconnect(); testStop(); testClientStartFails(); testClientConnectionFails(); testInvalidClientAccess(); testServerStartFails(); testServerClosesOnConnected(); testServerDisconnectsClient(); testClientClosesOnConnected(); testInvalidServerAccess(); testDummyCallbacks(); }