Skip to content

Commit

Permalink
feat: send initialisation data to integrations
Browse files Browse the repository at this point in the history
  • Loading branch information
AndyTWF committed Apr 1, 2023
1 parent 5cb793e commit 3227a36
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 20 deletions.
21 changes: 15 additions & 6 deletions src/plugin/integration/ClientInitialisationManager.cpp
Expand Up @@ -4,18 +4,23 @@
#include "IntegrationClient.h"
#include "IntegrationClientManager.h"
#include "IntegrationConnection.h"
#include "IntegrationDataInitialisers.h"
#include "time/SystemClock.h"

namespace UKControllerPlugin::Integration {

ClientInitialisationManager::ClientInitialisationManager(std::shared_ptr<IntegrationClientManager> clientManager)
: clientManager(std::move(clientManager))
ClientInitialisationManager::ClientInitialisationManager(
std::shared_ptr<IntegrationClientManager> clientManager,
std::shared_ptr<IntegrationDataInitialisers> dataInitialisers)
: clientManager(std::move(clientManager)), dataInitialisers(std::move(dataInitialisers))
{
assert(this.clientManager && "Client manager not set in ClientInitialisationManager");
assert(this.dataInitialisers && "Data initialisers not set in ClientInitialisationManager");
}

void ClientInitialisationManager::AddConnection(std::shared_ptr<IntegrationConnection> connection)
{
if (this->connections.count(connection) > 0) {
if (this->connections.contains(connection)) {
LogWarning("A duplicate integration client was added");
return;
}
Expand Down Expand Up @@ -69,8 +74,10 @@ namespace UKControllerPlugin::Integration {
continue;
}

this->UpgradeToClient(connection, incomingMessages.front());
const auto client = this->UpgradeToClient(connection, incomingMessages.front());
SendInitialisationSuccessMessage(connection, incomingMessages.front());
this->dataInitialisers->InitialiseClient(*client);

return true;
}

Expand Down Expand Up @@ -157,9 +164,9 @@ namespace UKControllerPlugin::Integration {
return errors;
}

void ClientInitialisationManager::UpgradeToClient(
auto ClientInitialisationManager::UpgradeToClient(
const std::shared_ptr<IntegrationConnection>& connection,
const std::shared_ptr<MessageInterface>& initialisationMessage)
const std::shared_ptr<MessageInterface>& initialisationMessage) -> std::shared_ptr<IntegrationClient>
{
auto data = initialisationMessage->GetMessageData();
auto client = std::make_shared<IntegrationClient>(
Expand All @@ -172,6 +179,8 @@ namespace UKControllerPlugin::Integration {
MessageType{interestedEvent.at("type").get<std::string>(), interestedEvent.at("version").get<int>()}));
}
this->clientManager->AddClient(client);

return client;
}

void ClientInitialisationManager::SendInitialisationSuccessMessage(
Expand Down
13 changes: 10 additions & 3 deletions src/plugin/integration/ClientInitialisationManager.h
Expand Up @@ -3,7 +3,9 @@

namespace UKControllerPlugin::Integration {
class IntegrationConnection;
class IntegrationClient;
class IntegrationClientManager;
class IntegrationDataInitialisers;
class MessageInterface;

/*
Expand All @@ -14,7 +16,9 @@ namespace UKControllerPlugin::Integration {
class ClientInitialisationManager : public TimedEvent::AbstractTimedEvent
{
public:
explicit ClientInitialisationManager(std::shared_ptr<IntegrationClientManager> clientManager);
explicit ClientInitialisationManager(
std::shared_ptr<IntegrationClientManager> clientManager,
std::shared_ptr<IntegrationDataInitialisers> dataInitialisers);
void AddConnection(std::shared_ptr<IntegrationConnection> connection);
void TimedEventTrigger() override;
[[nodiscard]] auto CountConnections() const -> size_t;
Expand Down Expand Up @@ -48,9 +52,9 @@ namespace UKControllerPlugin::Integration {
static auto ValidateMessageData(const std::shared_ptr<MessageInterface>& message) -> std::vector<std::string>;
static auto ValidateIntegrationDetails(const nlohmann::json& data) -> std::vector<std::string>;
static auto ValidateEventSubscriptions(const nlohmann::json& data) -> std::vector<std::string>;
void UpgradeToClient(
[[nodiscard]] auto UpgradeToClient(
const std::shared_ptr<IntegrationConnection>& connection,
const std::shared_ptr<MessageInterface>& initialisationMessage);
const std::shared_ptr<MessageInterface>& initialisationMessage) -> std::shared_ptr<IntegrationClient>;
static void SendInitialisationSuccessMessage(
const std::shared_ptr<IntegrationConnection>& connection,
const std::shared_ptr<MessageInterface>& initialisationMessage);
Expand All @@ -62,6 +66,9 @@ namespace UKControllerPlugin::Integration {
// Manages clients once fully initialised
std::shared_ptr<IntegrationClientManager> clientManager;

// Handles data initialisation
std::shared_ptr<IntegrationDataInitialisers> dataInitialisers;

// Clients that are fully initialised
std::map<std::shared_ptr<IntegrationConnection>, std::chrono::system_clock::time_point> connections;

Expand Down
9 changes: 6 additions & 3 deletions src/plugin/integration/IntegrationModule.cpp
Expand Up @@ -3,6 +3,7 @@
#include "ExternalMessageEventHandler.h"
#include "InboundIntegrationMessageHandler.h"
#include "IntegrationClientManager.h"
#include "IntegrationDataInitialisers.h"
#include "IntegrationModule.h"
#include "IntegrationPersistenceContainer.h"
#include "IntegrationServer.h"
Expand All @@ -22,12 +23,14 @@ namespace UKControllerPlugin::Integration {
container.externalEventHandler = std::make_shared<ExternalMessageEventHandler>(duplicatePlugin);
auto clientManager = std::make_shared<IntegrationClientManager>();
auto inboundMessageProcessors = std::make_shared<InboundIntegrationMessageHandler>(clientManager);
auto dataInitialisers = std::make_shared<IntegrationDataInitialisers>();

if (duplicatePlugin || !winsockInitialised) {
container.integrationModuleContainer = std::make_unique<IntegrationPersistenceContainer>(
std::make_shared<DummyOutboundIntegrationMessageHandler>(),
std::move(inboundMessageProcessors),
nullptr);
nullptr,
std::move(dataInitialisers));
return;
}

Expand All @@ -37,12 +40,12 @@ namespace UKControllerPlugin::Integration {
container.timedHandler->RegisterEvent(container.externalEventHandler, 1);

// Setup the new server
auto initialisationManager = std::make_shared<ClientInitialisationManager>(clientManager);
auto initialisationManager = std::make_shared<ClientInitialisationManager>(clientManager, dataInitialisers);
auto server = std::make_unique<IntegrationServer>(initialisationManager);
container.timedHandler->RegisterEvent(initialisationManager, 1);
const auto outboundHandler = std::make_shared<OutboundIntegrationMessageHandler>(clientManager);

container.integrationModuleContainer = std::make_unique<IntegrationPersistenceContainer>(
outboundHandler, std::move(inboundMessageProcessors), std::move(server));
outboundHandler, std::move(inboundMessageProcessors), std::move(server), std::move(dataInitialisers));
}
} // namespace UKControllerPlugin::Integration
6 changes: 4 additions & 2 deletions src/plugin/integration/IntegrationPersistenceContainer.cpp
Expand Up @@ -8,9 +8,11 @@ namespace UKControllerPlugin::Integration {
IntegrationPersistenceContainer::IntegrationPersistenceContainer(
std::shared_ptr<OutboundIntegrationEventHandler> outboundMessageHandler,
std::shared_ptr<InboundIntegrationMessageHandler> inboundMessageHandler,
std::unique_ptr<IntegrationServer> server)
std::unique_ptr<IntegrationServer> server,
std::shared_ptr<IntegrationDataInitialisers> dataInitialisers)
: outboundMessageHandler(std::move(outboundMessageHandler)),
inboundMessageHandler(std::move(inboundMessageHandler)), server(std::move(server))
inboundMessageHandler(std::move(inboundMessageHandler)), server(std::move(server)),
dataInitialisers(std::move(dataInitialisers))
{
}

Expand Down
7 changes: 6 additions & 1 deletion src/plugin/integration/IntegrationPersistenceContainer.h
Expand Up @@ -5,6 +5,7 @@ namespace UKControllerPlugin::Integration {
class OutboundIntegrationEventHandler;
class InboundIntegrationMessageHandler;
class IntegrationServer;
class IntegrationDataInitialisers;

/*
* Persists things relating to the integration
Expand All @@ -16,7 +17,8 @@ namespace UKControllerPlugin::Integration {
IntegrationPersistenceContainer(
std::shared_ptr<OutboundIntegrationEventHandler> outboundMessageHandler,
std::shared_ptr<InboundIntegrationMessageHandler> inboundMessageHandler,
std::unique_ptr<IntegrationServer> server);
std::unique_ptr<IntegrationServer> server,
std::shared_ptr<IntegrationDataInitialisers> dataInitialisers);
~IntegrationPersistenceContainer();
IntegrationPersistenceContainer(const IntegrationPersistenceContainer&) = delete;
IntegrationPersistenceContainer(IntegrationPersistenceContainer&&) noexcept;
Expand All @@ -31,5 +33,8 @@ namespace UKControllerPlugin::Integration {

// The server that listens for connections
std::unique_ptr<IntegrationServer> server{};

// Initialises integrations with data
std::shared_ptr<IntegrationDataInitialisers> dataInitialisers{};
};
} // namespace UKControllerPlugin::Integration
2 changes: 1 addition & 1 deletion test/plugin/handoff/HandoffModuleTest.cpp
Expand Up @@ -30,7 +30,7 @@ namespace UKControllerPluginTest::Handoff {
this->container.activeCallsigns = std::make_shared<ActiveCallsignCollection>();
this->container.runwayDialogEventHandlers = std::make_unique<RunwayDialogAwareCollection>();
this->container.integrationModuleContainer =
std::make_unique<IntegrationPersistenceContainer>(nullptr, nullptr, nullptr);
std::make_unique<IntegrationPersistenceContainer>(nullptr, nullptr, nullptr, nullptr);
}

PersistenceContainer container;
Expand Down
44 changes: 43 additions & 1 deletion test/plugin/integration/ClientInitialisationManagerTest.cpp
Expand Up @@ -4,25 +4,36 @@
#include "integration/IntegrationClient.h"
#include "integration/IntegrationClientManager.h"
#include "integration/IntegrationConnection.h"
#include "integration/IntegrationDataInitialisers.h"
#include "integration/MessageType.h"
#include "mock/MockIntegrationDataInitialiser.h"
#include "time/SystemClock.h"
#include <gmock/gmock-actions.h>

using UKControllerPlugin::Integration::ClientInitialisationManager;
using UKControllerPlugin::Integration::InitialisationFailureMessage;
using UKControllerPlugin::Integration::IntegrationClientManager;
using UKControllerPlugin::Integration::IntegrationDataInitialisers;
using UKControllerPlugin::Time::SetTestNow;

namespace UKControllerPluginTest::Integration {
class ClientInitialisationManagerTest : public testing::Test
{
public:
ClientInitialisationManagerTest()
: clientManager(new IntegrationClientManager), initialisationManager(clientManager)
: clientManager(new IntegrationClientManager),
initialisers(std::make_shared<IntegrationDataInitialisers>()),
initialisationManager(clientManager, initialisers)
{
mockConnection1 = std::make_shared<testing::NiceMock<MockConnection>>();
mockConnection2 = std::make_shared<testing::NiceMock<MockConnection>>();
integration1 = std::make_shared<UKControllerPlugin::Integration::IntegrationConnection>(mockConnection1);
integration2 = std::make_shared<UKControllerPlugin::Integration::IntegrationConnection>(mockConnection2);

mockInitialiser = std::make_shared<testing::NiceMock<MockIntegrationDataInitialiser>>();
initialisers->Add(mockInitialiser);

testing::DefaultValue<UKControllerPlugin::Integration::MessageType>::Set({"nope", 0});
}

void SetUp() override
Expand All @@ -40,6 +51,8 @@ namespace UKControllerPluginTest::Integration {
std::shared_ptr<testing::NiceMock<MockConnection>> mockConnection1;
std::shared_ptr<testing::NiceMock<MockConnection>> mockConnection2;
std::shared_ptr<IntegrationClientManager> clientManager;
std::shared_ptr<IntegrationDataInitialisers> initialisers;
std::shared_ptr<testing::NiceMock<MockIntegrationDataInitialiser>> mockInitialiser;
ClientInitialisationManager initialisationManager;
};

Expand Down Expand Up @@ -242,6 +255,35 @@ namespace UKControllerPluginTest::Integration {
initialisationManager.TimedEventTrigger();
}

TEST_F(ClientInitialisationManagerTest, ItInitialisesAClientAndSendsDataInitialisers)
{
initialisationManager.AddConnection(integration1);

nlohmann::json integrationMessage = {
{"type", "initialise"},
{"version", 1},
{"id", "foo"},
{"data",
nlohmann::json::object(
{{"integration_name", "UKCPTEST"},
{"integration_version", "1.5"},
{"event_subscriptions",
nlohmann::json::array(
{nlohmann::json::object({{"type", "foo"}, {"version", 1}}),
nlohmann::json::object({{"type", "bar"}, {"version", 2}})})}})}};

std::queue<std::string> returnedMessages;
returnedMessages.push(integrationMessage.dump());
ON_CALL(*this->mockConnection1, Receive).WillByDefault(testing::Return(returnedMessages));

// Make sure the data initialiser is called
UKControllerPlugin::Integration::MessageType messageType{"foo", 1};
EXPECT_CALL(*mockInitialiser, InitialisesFor()).Times(1).WillOnce(testing::Return(messageType));
EXPECT_CALL(*mockInitialiser, Initialise(testing::_)).Times(1);

initialisationManager.TimedEventTrigger();
}

TEST_F(ClientInitialisationManagerTest, ItRejectsIniitialisationMessageWithNoType)
{
initialisationManager.AddConnection(integration1);
Expand Down
13 changes: 13 additions & 0 deletions test/plugin/integration/IntegrationModuleTest.cpp
Expand Up @@ -3,6 +3,7 @@
#include "integration/ExternalMessageEventHandler.h"
#include "integration/InitialisationSuccessMessage.h"
#include "integration/InboundIntegrationMessageHandler.h"
#include "integration/IntegrationDataInitialisers.h"
#include "integration/IntegrationModule.h"
#include "integration/IntegrationPersistenceContainer.h"
#include "integration/OutboundIntegrationEventHandler.h"
Expand Down Expand Up @@ -59,6 +60,12 @@ namespace UKControllerPluginTest::Integration {
EXPECT_NO_THROW(container.integrationModuleContainer->outboundMessageHandler->SendEvent(testEvent));
}

TEST_F(IntegrationModuleTest, ItSetsUpDataInitialisersRegardlessOfDuplicatePlugin)
{
BootstrapPlugin(container, true, true);
EXPECT_EQ(0, container.integrationModuleContainer->dataInitialisers->Count());
}

TEST_F(IntegrationModuleTest, ItSetsUpExternalEventHandlerRegardlessOfDuplicatePlugin)
{
BootstrapPlugin(container, true, true);
Expand All @@ -83,6 +90,12 @@ namespace UKControllerPluginTest::Integration {
EXPECT_EQ(0, container.externalEventHandler->CountHandlers());
}

TEST_F(IntegrationModuleTest, ItSetsUpDataInitialisersRegardlessOfWinsockInitialisation)
{
BootstrapPlugin(container, false, false);
EXPECT_EQ(0, container.integrationModuleContainer->dataInitialisers->Count());
}

TEST_F(IntegrationModuleTest, ItRegistersForCommands)
{
BootstrapPlugin(container, false, true);
Expand Down
3 changes: 2 additions & 1 deletion test/plugin/intention/IntentionCodeBootstrapProviderTest.cpp
Expand Up @@ -21,7 +21,8 @@ namespace UKControllerPluginTest::IntentionCode {
container.dependencyLoader = std::make_unique<testing::NiceMock<Dependency::MockDependencyLoader>>();
container.integrationModuleContainer =
std::unique_ptr<UKControllerPlugin::Integration::IntegrationPersistenceContainer>(
new UKControllerPlugin::Integration::IntegrationPersistenceContainer(nullptr, nullptr, nullptr));
new UKControllerPlugin::Integration::IntegrationPersistenceContainer(
nullptr, nullptr, nullptr, nullptr));
container.integrationModuleContainer->outboundMessageHandler =
std::make_unique<testing::NiceMock<Integration::MockOutboundIntegrationEventHandler>>();
container.activeCallsigns = std::make_shared<ActiveCallsignCollection>();
Expand Down
2 changes: 1 addition & 1 deletion test/plugin/missedapproach/MissedApproachModuleTest.cpp
Expand Up @@ -44,7 +44,7 @@ namespace UKControllerPluginTest::MissedApproach {
container.dialogManager = std::make_unique<DialogManager>(mockProvider);
container.airfields = std::make_unique<AirfieldCollection>();
container.integrationModuleContainer = std::make_unique<IntegrationPersistenceContainer>(
nullptr, std::make_shared<InboundIntegrationMessageHandler>(nullptr), nullptr);
nullptr, std::make_shared<InboundIntegrationMessageHandler>(nullptr), nullptr, nullptr);
container.tagHandler = std::make_unique<TagItemCollection>();
}

Expand Down
2 changes: 1 addition & 1 deletion test/plugin/stands/StandModuleTest.cpp
Expand Up @@ -38,7 +38,7 @@ namespace UKControllerPluginTest::Stands {
container.pluginFunctionHandlers = std::make_unique<FunctionCallEventHandler>();
container.externalEventHandler = std::make_shared<ExternalMessageEventHandler>(true);
container.integrationModuleContainer =
std::make_unique<IntegrationPersistenceContainer>(nullptr, nullptr, nullptr);
std::make_unique<IntegrationPersistenceContainer>(nullptr, nullptr, nullptr, nullptr);
container.integrationModuleContainer->inboundMessageHandler =
std::make_shared<InboundIntegrationMessageHandler>(nullptr);

Expand Down

0 comments on commit 3227a36

Please sign in to comment.