/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#include "lib/self_test.h"
#include "network/NetFileTransfer.h"
#include "network/NetMessage.h"
#include "network/NetSession.h"
#include
#include
namespace
{
constexpr const char* MESSAGECONTENT{"Some example message content"};
class MessageQueues final : public INetSession
{
public:
~MessageQueues() final = default;
bool SendMessage(const CNetMessage* message) final
{
switch (message->GetType())
{
case NMT_FILE_TRANSFER_REQUEST:
requests.push_back(*static_cast(message));
break;
case NMT_FILE_TRANSFER_RESPONSE:
responses.push_back(*static_cast(message));
break;
case NMT_FILE_TRANSFER_DATA:
data.push_back(*static_cast(message));
break;
case NMT_FILE_TRANSFER_ACK:
acknowledgements.push_back(*static_cast(message));
break;
default:
TS_FAIL("Unhandeled message type");
}
return true;
}
std::vector requests;
std::vector responses;
std::vector data;
std::vector acknowledgements;
};
void CheckSizes(MessageQueues& queues, size_t requestSize, size_t responseSize, size_t dataSize,
size_t acknowledgementSize)
{
TS_ASSERT_EQUALS(queues.requests.size(), requestSize);
TS_ASSERT_EQUALS(queues.responses.size(), responseSize);
TS_ASSERT_EQUALS(queues.data.size(), dataSize);
TS_ASSERT_EQUALS(queues.acknowledgements.size(), acknowledgementSize);
}
struct Participant
{
MessageQueues queues;
CNetFileTransferer transferer{&queues};
};
}
class TestFileTransfer : public CxxTest::TestSuite
{
public:
void test_transfer()
{
// The client requests some data from the server.
Participant server;
Participant client;
bool complete{false};
client.transferer.StartTask([&complete](std::string buffer)
{
// This callback is executed exactly once.
const bool previousComplete{std::exchange(complete, true)};
TS_ASSERT(!previousComplete);
TS_ASSERT_STR_EQUALS(buffer, MESSAGECONTENT);
});
CheckSizes(client.queues, 1, 0, 0, 0);
server.transferer.StartResponse(client.queues.requests.at(0).m_RequestID, MESSAGECONTENT);
CheckSizes(server.queues, 0, 1, 0, 0);
client.transferer.HandleMessageReceive(server.queues.responses.at(0));
CheckSizes(client.queues, 1, 0, 0, 0);
server.transferer.Poll();
CheckSizes(server.queues, 0, 1, 1, 0);
server.transferer.Poll();
// If `MESSAGECONTENT` would be longer another message would be sent.
CheckSizes(server.queues, 0, 1, 1, 0);
TS_ASSERT(!complete);
client.transferer.HandleMessageReceive(server.queues.data.at(0));
CheckSizes(client.queues, 1, 0, 0, 1);
TS_ASSERT(complete);
server.transferer.HandleMessageReceive(client.queues.acknowledgements.at(0));
CheckSizes(server.queues, 0, 1, 1, 0);
}
};