mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-11 12:33:25 -08:00
[Tests] Add a shared in-memory server test fixture
Add tests/support/server_test_fixture as a built-but-unshipped static target: an InMemoryServer_DatabaseInterface with configurable auth, a user table, session bookkeeping, ban state, id counters, and chat-log capture, plus FakeServer and ServerTestFixture. Migrate server_game_join_test to it, removing the first private copy of the mock.
This commit is contained in:
parent
3b379618c3
commit
2187e47a60
4 changed files with 266 additions and 44 deletions
|
|
@ -171,6 +171,11 @@ endfunction()
|
||||||
|
|
||||||
# --- Unit tests ------------------------------------------------------------------
|
# --- Unit tests ------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Test-only server double and fixture, shared by the server tests. Built, never installed.
|
||||||
|
add_library(testsupport_server STATIC support/server_test_fixture.cpp)
|
||||||
|
target_link_libraries(testsupport_server PUBLIC libcockatrice_network_server_remote)
|
||||||
|
target_include_directories(testsupport_server PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
cockatrice_add_test(NAME image_request_queue_test SOURCES image_request_queue_test.cpp)
|
cockatrice_add_test(NAME image_request_queue_test SOURCES image_request_queue_test.cpp)
|
||||||
cockatrice_add_test(NAME image_redirect_chain_test SOURCES image_redirect_chain_test.cpp)
|
cockatrice_add_test(NAME image_redirect_chain_test SOURCES image_redirect_chain_test.cpp)
|
||||||
cockatrice_add_test(NAME expression_test SOURCES expression_test.cpp LIBS libcockatrice_utility)
|
cockatrice_add_test(NAME expression_test SOURCES expression_test.cpp LIBS libcockatrice_utility)
|
||||||
|
|
@ -377,6 +382,9 @@ cockatrice_add_test(
|
||||||
LIBS
|
LIBS
|
||||||
libcockatrice_network_server_remote
|
libcockatrice_network_server_remote
|
||||||
libcockatrice_rng
|
libcockatrice_rng
|
||||||
|
testsupport_server
|
||||||
|
INCLUDE_DIRS
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
LABELS
|
LABELS
|
||||||
server
|
server
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,8 @@
|
||||||
#include "game/role_info.h"
|
#include "game/role_info.h"
|
||||||
#include "game/server_game.h"
|
#include "game/server_game.h"
|
||||||
#include "libcockatrice/protocol/pb/response.pb.h"
|
#include "libcockatrice/protocol/pb/response.pb.h"
|
||||||
#include "server.h"
|
|
||||||
#include "server_database_interface.h"
|
|
||||||
#include "server_room.h"
|
#include "server_room.h"
|
||||||
|
#include "support/server_test_fixture.h"
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
@ -23,50 +22,9 @@ RNG_Abstract *rng = nullptr; // referenced by the server_remote library
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
class MockDatabaseInterface : public Server_DatabaseInterface
|
class GameJoinOverrideTest : public ServerTestFixture
|
||||||
{
|
|
||||||
public:
|
|
||||||
AuthenticationResult checkUserPassword(Server_ProtocolHandler *,
|
|
||||||
const QString &,
|
|
||||||
const QString &,
|
|
||||||
const QString &,
|
|
||||||
QString &,
|
|
||||||
int &,
|
|
||||||
bool) override
|
|
||||||
{
|
|
||||||
return NotLoggedIn;
|
|
||||||
}
|
|
||||||
int getNextReplayId() override
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int getNextGameId() override
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int getActiveUserCount(QString) override
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ServerInfo_User getUserData(const QString &, bool) override
|
|
||||||
{
|
|
||||||
return ServerInfo_User();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class FakeServer : public Server
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FakeServer()
|
|
||||||
{
|
|
||||||
setDatabaseInterface(new MockDatabaseInterface());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class GameJoinOverrideTest : public ::testing::Test
|
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
FakeServer server;
|
|
||||||
Server_Room room{0, 0, "", "", "", "", false, "", {}, &server};
|
Server_Room room{0, 0, "", "", "", "", false, "", {}, &server};
|
||||||
ServerInfo_User creator;
|
ServerInfo_User creator;
|
||||||
ServerInfo_User plainUser;
|
ServerInfo_User plainUser;
|
||||||
|
|
|
||||||
139
tests/support/server_test_fixture.cpp
Normal file
139
tests/support/server_test_fixture.cpp
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
/** @file server_test_fixture.cpp
|
||||||
|
* @brief Shared in-memory server database double and gtest fixture for server tests.
|
||||||
|
* @ingroup Tests
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "support/server_test_fixture.h"
|
||||||
|
|
||||||
|
#include "server_room.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
InMemoryServer_DatabaseInterface::InMemoryServer_DatabaseInterface(QObject *parent) : Server_DatabaseInterface(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void InMemoryServer_DatabaseInterface::addUser(const ServerInfo_User &user)
|
||||||
|
{
|
||||||
|
users.insert(QString::fromStdString(user.name()), user);
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthenticationResult InMemoryServer_DatabaseInterface::checkUserPassword(Server_ProtocolHandler *,
|
||||||
|
const QString &,
|
||||||
|
const QString &,
|
||||||
|
const QString &,
|
||||||
|
QString &,
|
||||||
|
int &,
|
||||||
|
bool)
|
||||||
|
{
|
||||||
|
return authenticationResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InMemoryServer_DatabaseInterface::checkUserIsBanned(const QString &,
|
||||||
|
const QString &,
|
||||||
|
const QString &,
|
||||||
|
QString &reason,
|
||||||
|
int &seconds)
|
||||||
|
{
|
||||||
|
reason = banReason;
|
||||||
|
seconds = banSecondsRemaining;
|
||||||
|
return userIsBanned;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InMemoryServer_DatabaseInterface::checkUserIsBanned(Server_ProtocolHandler *, QString &reason, int &seconds)
|
||||||
|
{
|
||||||
|
reason = banReason;
|
||||||
|
seconds = banSecondsRemaining;
|
||||||
|
return userIsBanned;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InMemoryServer_DatabaseInterface::activeUserExists(const QString &user)
|
||||||
|
{
|
||||||
|
for (const QString &sessionUser : std::as_const(sessions)) {
|
||||||
|
if (sessionUser == user) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerInfo_User InMemoryServer_DatabaseInterface::getUserData(const QString &name, bool withId)
|
||||||
|
{
|
||||||
|
ServerInfo_User user = users.value(name);
|
||||||
|
if (!withId) {
|
||||||
|
user.clear_id();
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 InMemoryServer_DatabaseInterface::startSession(const QString &userName,
|
||||||
|
const QString &,
|
||||||
|
const QString &,
|
||||||
|
const QString &)
|
||||||
|
{
|
||||||
|
const qint64 sessionId = nextSessionId++;
|
||||||
|
sessions.insert(sessionId, userName);
|
||||||
|
return sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InMemoryServer_DatabaseInterface::endSession(qint64 sessionId)
|
||||||
|
{
|
||||||
|
sessions.remove(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InMemoryServer_DatabaseInterface::userSessionExists(const QString &userName)
|
||||||
|
{
|
||||||
|
return activeUserExists(userName);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InMemoryServer_DatabaseInterface::getRequireRegistration()
|
||||||
|
{
|
||||||
|
return requireRegistration;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InMemoryServer_DatabaseInterface::getNextGameId()
|
||||||
|
{
|
||||||
|
return nextGameId;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InMemoryServer_DatabaseInterface::getNextReplayId()
|
||||||
|
{
|
||||||
|
return nextReplayId;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InMemoryServer_DatabaseInterface::getActiveUserCount(QString)
|
||||||
|
{
|
||||||
|
return activeUserCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InMemoryServer_DatabaseInterface::logMessage(const int,
|
||||||
|
const QString &senderName,
|
||||||
|
const QString &,
|
||||||
|
const QString &message,
|
||||||
|
LogMessage_TargetType targetType,
|
||||||
|
const int targetId,
|
||||||
|
const QString &targetName,
|
||||||
|
const QString &channel)
|
||||||
|
{
|
||||||
|
logEntries.append(LogEntry{.senderName = senderName,
|
||||||
|
.message = message,
|
||||||
|
.targetType = targetType,
|
||||||
|
.targetId = targetId,
|
||||||
|
.targetName = targetName,
|
||||||
|
.channel = channel});
|
||||||
|
}
|
||||||
|
|
||||||
|
FakeServer::FakeServer()
|
||||||
|
{
|
||||||
|
setDatabaseInterface(new InMemoryServer_DatabaseInterface(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
InMemoryServer_DatabaseInterface *FakeServer::database() const
|
||||||
|
{
|
||||||
|
return static_cast<InMemoryServer_DatabaseInterface *>(getDatabaseInterface());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FakeServer::insertRoom(Server_Room *newRoom)
|
||||||
|
{
|
||||||
|
addRoom(newRoom);
|
||||||
|
}
|
||||||
117
tests/support/server_test_fixture.h
Normal file
117
tests/support/server_test_fixture.h
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
/** @file server_test_fixture.h
|
||||||
|
* @brief Shared in-memory server database double and gtest fixture for server tests.
|
||||||
|
* @ingroup Tests
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COCKATRICE_TESTS_SUPPORT_SERVER_TEST_FIXTURE_H
|
||||||
|
#define COCKATRICE_TESTS_SUPPORT_SERVER_TEST_FIXTURE_H
|
||||||
|
|
||||||
|
#include "server.h"
|
||||||
|
#include "server_database_interface.h"
|
||||||
|
|
||||||
|
#include <QHash>
|
||||||
|
#include <QList>
|
||||||
|
#include <QString>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <libcockatrice/protocol/pb/serverinfo_user.pb.h>
|
||||||
|
|
||||||
|
class Server_Room;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A Server_DatabaseInterface backed by in-memory state.
|
||||||
|
*
|
||||||
|
* Only the methods the server tests need are overridden; everything else keeps
|
||||||
|
* the abstract interface's defaults. The public members are the knobs a test
|
||||||
|
* turns to describe the state it wants.
|
||||||
|
*/
|
||||||
|
class InMemoryServer_DatabaseInterface : public Server_DatabaseInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit InMemoryServer_DatabaseInterface(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
struct LogEntry
|
||||||
|
{
|
||||||
|
QString senderName;
|
||||||
|
QString message;
|
||||||
|
LogMessage_TargetType targetType;
|
||||||
|
int targetId;
|
||||||
|
QString targetName;
|
||||||
|
QString channel;
|
||||||
|
};
|
||||||
|
|
||||||
|
AuthenticationResult authenticationResult = NotLoggedIn;
|
||||||
|
QHash<QString, ServerInfo_User> users;
|
||||||
|
bool userIsBanned = false;
|
||||||
|
QString banReason;
|
||||||
|
int banSecondsRemaining = 0;
|
||||||
|
int activeUserCount = 0;
|
||||||
|
int nextGameId = 1;
|
||||||
|
int nextReplayId = 1;
|
||||||
|
bool requireRegistration = false;
|
||||||
|
QList<LogEntry> logEntries;
|
||||||
|
|
||||||
|
void addUser(const ServerInfo_User &user);
|
||||||
|
|
||||||
|
AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler,
|
||||||
|
const QString &user,
|
||||||
|
const QString &password,
|
||||||
|
const QString &clientId,
|
||||||
|
QString &reasonStr,
|
||||||
|
int &secondsLeft,
|
||||||
|
bool passwordNeedsHash) override;
|
||||||
|
bool checkUserIsBanned(const QString &ipAddress,
|
||||||
|
const QString &userName,
|
||||||
|
const QString &clientId,
|
||||||
|
QString &reason,
|
||||||
|
int &seconds) override;
|
||||||
|
bool checkUserIsBanned(Server_ProtocolHandler *session, QString &reason, int &seconds) override;
|
||||||
|
bool activeUserExists(const QString &user) override;
|
||||||
|
ServerInfo_User getUserData(const QString &name, bool withId = false) override;
|
||||||
|
qint64 startSession(const QString &userName,
|
||||||
|
const QString &address,
|
||||||
|
const QString &clientId,
|
||||||
|
const QString &connectionType) override;
|
||||||
|
void endSession(qint64 sessionId) override;
|
||||||
|
bool userSessionExists(const QString &userName) override;
|
||||||
|
bool getRequireRegistration() override;
|
||||||
|
int getNextGameId() override;
|
||||||
|
int getNextReplayId() override;
|
||||||
|
int getActiveUserCount(QString connectionType = QString()) override;
|
||||||
|
void logMessage(const int senderId,
|
||||||
|
const QString &senderName,
|
||||||
|
const QString &senderIp,
|
||||||
|
const QString &message,
|
||||||
|
LogMessage_TargetType targetType,
|
||||||
|
const int targetId,
|
||||||
|
const QString &targetName,
|
||||||
|
const QString &channel = QString()) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QHash<qint64, QString> sessions;
|
||||||
|
qint64 nextSessionId = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A Server that always has its own InMemoryServer_DatabaseInterface attached.
|
||||||
|
class FakeServer : public Server
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FakeServer();
|
||||||
|
|
||||||
|
InMemoryServer_DatabaseInterface *database() const;
|
||||||
|
|
||||||
|
void insertRoom(Server_Room *newRoom);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A gtest fixture with a FakeServer and direct access to its database.
|
||||||
|
class ServerTestFixture : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
FakeServer server;
|
||||||
|
|
||||||
|
InMemoryServer_DatabaseInterface *database() const
|
||||||
|
{
|
||||||
|
return server.database();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
Add table
Add a link
Reference in a new issue