diff --git a/src/plugin/handoff/ClearCacheOnActiveCallsignChanges.cpp b/src/plugin/handoff/ClearCacheOnActiveCallsignChanges.cpp deleted file mode 100644 index 39de4d3bc..000000000 --- a/src/plugin/handoff/ClearCacheOnActiveCallsignChanges.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "ClearCacheOnActiveCallsignChanges.h" -#include "HandoffCache.h" -#include "ResolvedHandoff.h" -#include "controller/ActiveCallsign.h" -#include "controller/ControllerPosition.h" -#include "controller/ControllerPositionHierarchy.h" - -namespace UKControllerPlugin::Handoff { - - ClearCacheOnActiveCallsignChanges::ClearCacheOnActiveCallsignChanges(HandoffCache& cache) : cache(cache) - { - } - - /** - * When new controllers come online, we need to evict from the cache any controller who preceeds them - * in the hierarchy. - */ - void ClearCacheOnActiveCallsignChanges::ActiveCallsignAdded(const Controller::ActiveCallsign& callsign) - { - this->cache.DeleteWhere([&callsign](const std::shared_ptr& handoff) -> bool { - /* - * The SID hierarchy has the highest priority. So if the resolved controller is from the SIDs hierarchy, - * then the controller coming online must preceed it. - */ - if (handoff->sidHierarchy->PositionInHierarchy(*handoff->resolvedController)) { - return handoff->sidHierarchy->PositionPreceeds( - callsign.GetNormalisedPosition(), *handoff->resolvedController); - } - - /* - * If the resolved controller isn't int he SID hierarchy, but the controller logging on is, then - * this takes precedence. - */ - if (handoff->sidHierarchy->PositionInHierarchy(callsign.GetNormalisedPosition())) { - return true; - } - - /* - * If the resolved controller is in the airfield fallback hierarchy, then the controller coming online must - * preceed them in that. - */ - if (handoff->airfieldHierarchy->PositionInHierarchy(*handoff->resolvedController)) { - return handoff->airfieldHierarchy->PositionPreceeds( - callsign.GetNormalisedPosition(), *handoff->resolvedController); - } - - /* - * Finally, if the resolved controller isn't from a hierarchy, it must be unicom. - * - * The last check here is to see if the controller in question is in the airfield hierarchy. - */ - return handoff->airfieldHierarchy->PositionInHierarchy(callsign.GetNormalisedPosition()); - }); - } - - /** - * If we have a controller that logs off, we only need to evict from the cache instances where - * this controller is the resolved controller. - */ - void ClearCacheOnActiveCallsignChanges::ActiveCallsignRemoved(const Controller::ActiveCallsign& callsign) - { - this->cache.DeleteWhere([&callsign](const std::shared_ptr& handoff) -> bool { - return *handoff->resolvedController == callsign.GetNormalisedPosition(); - }); - } - - /** - * If we lose track of who's online alltogether, time to clear the cache. - */ - void ClearCacheOnActiveCallsignChanges::CallsignsFlushed() - { - this->cache.Clear(); - } -} // namespace UKControllerPlugin::Handoff diff --git a/src/plugin/handoff/ClearCacheOnActiveCallsignChanges.h b/src/plugin/handoff/ClearCacheOnActiveCallsignChanges.h deleted file mode 100644 index 7473d1d6c..000000000 --- a/src/plugin/handoff/ClearCacheOnActiveCallsignChanges.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "controller/ActiveCallsignEventHandlerInterface.h" - -namespace UKControllerPlugin::Handoff { - class HandoffCache; - - class ClearCacheOnActiveCallsignChanges : public Controller::ActiveCallsignEventHandlerInterface - { - public: - ClearCacheOnActiveCallsignChanges(HandoffCache& cache); - void ActiveCallsignAdded(const Controller::ActiveCallsign& callsign) override; - void ActiveCallsignRemoved(const Controller::ActiveCallsign& callsign) override; - void CallsignsFlushed() override; - - private: - // The cache to clear - HandoffCache& cache; - }; -} // namespace UKControllerPlugin::Handoff diff --git a/src/plugin/handoff/ClearCacheOnRunwayDialogSave.cpp b/src/plugin/handoff/ClearCacheOnRunwayDialogSave.cpp deleted file mode 100644 index 6073fc43b..000000000 --- a/src/plugin/handoff/ClearCacheOnRunwayDialogSave.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "ClearCacheOnRunwayDialogSave.h" -#include "HandoffCache.h" - -namespace UKControllerPlugin::Handoff { - - ClearCacheOnRunwayDialogSave::ClearCacheOnRunwayDialogSave(std::shared_ptr cache) : cache(cache) - { - assert(cache && "Handoff cache not set in ctor"); - } - - void ClearCacheOnRunwayDialogSave::RunwayDialogSaved() - { - cache->Clear(); - } -} // namespace UKControllerPlugin::Handoff diff --git a/src/plugin/handoff/ClearCacheOnRunwayDialogSave.h b/src/plugin/handoff/ClearCacheOnRunwayDialogSave.h deleted file mode 100644 index 25ace18b3..000000000 --- a/src/plugin/handoff/ClearCacheOnRunwayDialogSave.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include "euroscope/RunwayDialogAwareInterface.h" - -namespace UKControllerPlugin::Handoff { - - class HandoffCache; - - class ClearCacheOnRunwayDialogSave : public Euroscope::RunwayDialogAwareInterface - { - public: - ClearCacheOnRunwayDialogSave(std::shared_ptr cache); - void RunwayDialogSaved() override; - - private: - // The cache - const std::shared_ptr cache; - }; -} // namespace UKControllerPlugin::Handoff diff --git a/src/plugin/handoff/DepartureHandoffResolver.cpp b/src/plugin/handoff/DefaultDepartureHandoffResolutionStrategy.cpp similarity index 87% rename from src/plugin/handoff/DepartureHandoffResolver.cpp rename to src/plugin/handoff/DefaultDepartureHandoffResolutionStrategy.cpp index e35a09115..03f3263db 100644 --- a/src/plugin/handoff/DepartureHandoffResolver.cpp +++ b/src/plugin/handoff/DefaultDepartureHandoffResolutionStrategy.cpp @@ -1,4 +1,4 @@ -#include "DepartureHandoffResolver.h" +#include "DefaultDepartureHandoffResolutionStrategy.h" #include "FlightplanAirfieldHandoffMapper.h" #include "FlightplanSidHandoffMapper.h" #include "HandoffOrder.h" @@ -13,7 +13,7 @@ using UKControllerPlugin::Controller::ControllerPositionHierarchy; namespace UKControllerPlugin::Handoff { - DepartureHandoffResolver::DepartureHandoffResolver( + DefaultDepartureHandoffResolutionStrategy::DefaultDepartureHandoffResolutionStrategy( const FlightplanSidHandoffMapper& sidMapper, const FlightplanAirfieldHandoffMapper& airfieldMapper, const Controller::ActiveCallsignCollection& activeCallsigns) @@ -28,7 +28,8 @@ namespace UKControllerPlugin::Handoff { * nothing to map to, resolve to unicom anyway... We'll need a flightplan change to be able to attempt * it again. */ - auto DepartureHandoffResolver::Resolve(const Euroscope::EuroScopeCFlightPlanInterface& flightplan) const + auto + DefaultDepartureHandoffResolutionStrategy::Resolve(const Euroscope::EuroScopeCFlightPlanInterface& flightplan) const -> std::shared_ptr { std::shared_ptr controller = nullptr; @@ -68,7 +69,7 @@ namespace UKControllerPlugin::Handoff { /** * For a given handoff, resolve it to a particular controller position. */ - auto DepartureHandoffResolver::ResolveController(const HandoffOrder& handoff) const + auto DefaultDepartureHandoffResolutionStrategy::ResolveController(const HandoffOrder& handoff) const -> std::shared_ptr { for (auto& controller : *handoff.order) { diff --git a/src/plugin/handoff/DepartureHandoffResolver.h b/src/plugin/handoff/DefaultDepartureHandoffResolutionStrategy.h similarity index 88% rename from src/plugin/handoff/DepartureHandoffResolver.h rename to src/plugin/handoff/DefaultDepartureHandoffResolutionStrategy.h index d04a59cd3..fa1edcfce 100644 --- a/src/plugin/handoff/DepartureHandoffResolver.h +++ b/src/plugin/handoff/DefaultDepartureHandoffResolutionStrategy.h @@ -1,4 +1,5 @@ #pragma once +#include "DepartureHandoffResolverInterface.h" namespace UKControllerPlugin { namespace Controller { @@ -22,7 +23,7 @@ namespace UKControllerPlugin::Handoff { * Given a flightplan, resolves the handoff frequency * that should be used for the after departure TAG item. */ - class DepartureHandoffResolver + class DepartureHandoffResolver : public DepartureHandoffResolverInterface { public: DepartureHandoffResolver( @@ -31,7 +32,7 @@ namespace UKControllerPlugin::Handoff { const Controller::ActiveCallsignCollection& activeCallsigns); [[nodiscard]] auto Resolve(const Euroscope::EuroScopeCFlightPlanInterface& flightplan) const - -> std::shared_ptr; + -> std::shared_ptr override; private: [[nodiscard]] auto ResolveController(const HandoffOrder& handoff) const diff --git a/src/plugin/handoff/HandoffCache.cpp b/src/plugin/handoff/HandoffCache.cpp deleted file mode 100644 index 6d9874b19..000000000 --- a/src/plugin/handoff/HandoffCache.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "HandoffCache.h" -#include "ResolvedHandoff.h" - -namespace UKControllerPlugin::Handoff { - - void HandoffCache::Add(const std::shared_ptr& handoff) - { - if (this->handoffs.count(handoff->callsign) != 0) { - LogWarning("Duplicate cached handoff detected for " + handoff->callsign); - } - - this->handoffs[handoff->callsign] = handoff; - } - - auto HandoffCache::Count() const -> size_t - { - return this->handoffs.size(); - } - - auto HandoffCache::Get(const std::string& callsign) const -> std::shared_ptr - { - return this->handoffs.count(callsign) == 0 ? nullptr : this->handoffs.at(callsign); - } - - void HandoffCache::Delete(const std::string& callsign) - { - this->handoffs.erase(callsign); - } - - void HandoffCache::Clear() - { - this->handoffs.clear(); - } - - void HandoffCache::DeleteWhere(const std::function)>& predicate) - { - for (auto handoff = this->handoffs.cbegin(); handoff != this->handoffs.cend();) { - if (predicate(handoff->second)) { - handoff = this->handoffs.erase(handoff); - } else { - ++handoff; - } - } - } -} // namespace UKControllerPlugin::Handoff diff --git a/src/plugin/handoff/HandoffCache.h b/src/plugin/handoff/HandoffCache.h deleted file mode 100644 index a4669e6e5..000000000 --- a/src/plugin/handoff/HandoffCache.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -namespace UKControllerPlugin::Handoff { - struct ResolvedHandoff; - - /* - * Contains all the handoffs that have been generated. - */ - class HandoffCache - { - public: - void Add(const std::shared_ptr& handoff); - void Clear(); - [[nodiscard]] auto Count() const -> size_t; - [[nodiscard]] auto Get(const std::string& callsign) const -> std::shared_ptr; - void Delete(const std::string& callsign); - void DeleteWhere(const std::function handoff)>& predicate); - - private: - // All the handoffs - std::map> handoffs; - }; -} // namespace UKControllerPlugin::Handoff diff --git a/src/plugin/handoff/HandoffEventHandler.cpp b/src/plugin/handoff/HandoffEventHandler.cpp index 772dd8b03..ced48abfa 100644 --- a/src/plugin/handoff/HandoffEventHandler.cpp +++ b/src/plugin/handoff/HandoffEventHandler.cpp @@ -43,8 +43,7 @@ namespace UKControllerPlugin::Handoff { } // Resolve the handoff and return - const auto resolvedHandoff = this->resolver->Resolve(flightplan); - this->cache->Add(resolvedHandoff); + const auto resolvedHandoff = ResolveHandoffAndCache(flightplan); tagData.SetItemString(FormatFrequency(resolvedHandoff)); this->FireHandoffUpdatedEvent(flightplan.GetCallsign()); } @@ -53,6 +52,7 @@ namespace UKControllerPlugin::Handoff { EuroScopeCFlightPlanInterface& flightPlan, EuroScopeCRadarTargetInterface& radarTarget) { this->cache->Delete(flightPlan.GetCallsign()); + static_cast(ResolveHandoffAndCache(flightPlan)); } void HandoffEventHandler::FlightPlanDisconnectEvent(EuroScopeCFlightPlanInterface& flightPlan) @@ -82,4 +82,13 @@ namespace UKControllerPlugin::Handoff { sprintf_s(frequencyString, "%.3f", handoff->resolvedController->GetFrequency()); // NOLINT return frequencyString; // NOLINT } + + auto HandoffEventHandler::ResolveHandoffAndCache(const EuroScopeCFlightPlanInterface& flightplan) const + -> std::shared_ptr + { + const auto resolvedHandoff = this->resolver->Resolve(flightplan); + this->cache->Add(resolvedHandoff); + + return std::move(resolvedHandoff); + } } // namespace UKControllerPlugin::Handoff diff --git a/src/plugin/handoff/HandoffEventHandler.h b/src/plugin/handoff/HandoffEventHandler.h index 22fef6990..5b2123bb1 100644 --- a/src/plugin/handoff/HandoffEventHandler.h +++ b/src/plugin/handoff/HandoffEventHandler.h @@ -44,6 +44,8 @@ namespace UKControllerPlugin::Handoff { private: void FireHandoffUpdatedEvent(const std::string& callsign); [[nodiscard]] static auto FormatFrequency(const std::shared_ptr& handoff) -> std::string; + [[nodiscard]] auto ResolveHandoffAndCache(const Euroscope::EuroScopeCFlightPlanInterface& flightplan) const + -> std::shared_ptr; // Resolves handoffs const std::shared_ptr resolver; diff --git a/src/plugin/handoff/InvalidateHandoffsOnActiveCallsignChanges.cpp b/src/plugin/handoff/InvalidateHandoffsOnActiveCallsignChanges.cpp new file mode 100644 index 000000000..09ef9a9ec --- /dev/null +++ b/src/plugin/handoff/InvalidateHandoffsOnActiveCallsignChanges.cpp @@ -0,0 +1,98 @@ +#include "ClearCacheOnActiveCallsignChanges.h" +#include "DepartureHandoffResolver.h" +#include "ResolvedHandoff.h" +#include "controller/ActiveCallsign.h" +#include "controller/ControllerPosition.h" +#include "controller/ControllerPositionHierarchy.h" +#include "euroscope/EuroscopePluginLoopbackInterface.h" + +namespace UKControllerPlugin::Handoff { + + ClearCacheOnActiveCallsignChanges::ClearCacheOnActiveCallsignChanges( + const std::shared_ptr& resolver, Euroscope::EuroscopePluginLoopbackInterface& plugin) + : resolver(std::move(resolver)), plugin(plugin) + { + assert(this->resolver != nullptr && "Resolver must not be null"); + } + + /** + * When new controllers come online, we need to evict from the cache any controller who preceeds them + * in the hierarchy. + */ + void ClearCacheOnActiveCallsignChanges::ActiveCallsignAdded(const Controller::ActiveCallsign& callsign) + { + plugin.ApplyFunctionToAllFlightplans([&callsign, this](const auto& fp, const auto& rt) -> void { + auto resolvedHandoff = this->resolver->Resolve(*fp); + + if (!ShouldInvalidateOnCallsignAdded(*resolvedHandoff, callsign)) { + return; + } + + this->resolver->Invalidate(*fp); + static_cast(this->resolver->Resolve(*fp)); + }); + } + + /** + * If we have a controller that logs off, we only need to evict from the cache instances where + * this controller is the resolved controller. + */ + void ClearCacheOnActiveCallsignChanges::ActiveCallsignRemoved(const Controller::ActiveCallsign& callsign) + { + plugin.ApplyFunctionToAllFlightplans([&callsign, this](const auto& fp, const auto& rt) -> void { + auto resolvedHandoff = this->resolver->Resolve(*fp); + if (*resolvedHandoff->resolvedController != callsign.GetNormalisedPosition()) { + return; + } + + this->resolver->Invalidate(*fp); + static_cast(this->resolver->Resolve(*fp)); + }); + } + + /** + * If we lose track of who's online alltogether, time to clear the cache. + */ + void ClearCacheOnActiveCallsignChanges::CallsignsFlushed() + { + plugin.ApplyFunctionToAllFlightplans( + [this](const auto& fp, const auto& rt) -> void { this->resolver->Invalidate(*fp); }); + } + + auto ClearCacheOnActiveCallsignChanges::ShouldInvalidateOnCallsignAdded( + const ResolvedHandoff& handoff, const Controller::ActiveCallsign& callsign) -> bool + { + /* + * The SID hierarchy has the highest priority. So if the resolved controller is from the SIDs hierarchy, + * then the controller coming online must preceed it. + */ + if (handoff.sidHierarchy->PositionInHierarchy(*handoff.resolvedController)) { + return handoff.sidHierarchy->PositionPreceeds( + callsign.GetNormalisedPosition(), *handoff.resolvedController); + } + + /* + * If the resolved controller isn't int he SID hierarchy, but the controller logging on is, then + * this takes precedence. + */ + if (handoff.sidHierarchy->PositionInHierarchy(callsign.GetNormalisedPosition())) { + return true; + } + + /* + * If the resolved controller is in the airfield fallback hierarchy, then the controller coming online must + * preceed them in that. + */ + if (handoff.airfieldHierarchy->PositionInHierarchy(*handoff.resolvedController)) { + return handoff.airfieldHierarchy->PositionPreceeds( + callsign.GetNormalisedPosition(), *handoff.resolvedController); + } + + /* + * Finally, if the resolved controller isn't from a hierarchy, it must be unicom. + * + * The last check here is to see if the controller in question is in the airfield hierarchy. + */ + return handoff.airfieldHierarchy->PositionInHierarchy(callsign.GetNormalisedPosition()); + } +} // namespace UKControllerPlugin::Handoff diff --git a/src/plugin/handoff/InvalidateHandoffsOnActiveCallsignChanges.h b/src/plugin/handoff/InvalidateHandoffsOnActiveCallsignChanges.h new file mode 100644 index 000000000..afbbdb966 --- /dev/null +++ b/src/plugin/handoff/InvalidateHandoffsOnActiveCallsignChanges.h @@ -0,0 +1,33 @@ +#pragma once +#include "controller/ActiveCallsignEventHandlerInterface.h" + +namespace UKControllerPlugin::Euroscope { + class EuroscopePluginLoopbackInterface; +} // namespace UKControllerPlugin::Euroscope + +namespace UKControllerPlugin::Handoff { + class DepartureHandoffResolver; + class ResolvedHandoff; + + class InvalidateHandoffsOnActiveCallsignChanges : public Controller::ActiveCallsignEventHandlerInterface + { + public: + InvalidateHandoffsOnActiveCallsignChanges( + const std::shared_ptr& resolver, + Euroscope::EuroscopePluginLoopbackInterface& plugin); + void ActiveCallsignAdded(const Controller::ActiveCallsign& callsign) override; + void ActiveCallsignRemoved(const Controller::ActiveCallsign& callsign) override; + void CallsignsFlushed() override; + + private: + [[nodiscard]] static auto + ShouldInvalidateOnCallsignAdded(const ResolvedHandoff& handoff, const Controller::ActiveCallsign& callsign) + -> bool; + + // The resolver + std::shared_ptr resolver; + + // The plugin for flightplan looping + Euroscope::EuroscopePluginLoopbackInterface& plugin; + }; +} // namespace UKControllerPlugin::Handoff diff --git a/src/plugin/handoff/InvalidateHandoffsOnRunwayDialogSave.cpp b/src/plugin/handoff/InvalidateHandoffsOnRunwayDialogSave.cpp new file mode 100644 index 000000000..0a0f80b04 --- /dev/null +++ b/src/plugin/handoff/InvalidateHandoffsOnRunwayDialogSave.cpp @@ -0,0 +1,27 @@ +#include "ClearCacheOnRunwayDialogSave.h" +#include "DepartureHandoffResolver.h" +#include "euroscope/EuroscopePluginLoopbackInterface.h" + +namespace UKControllerPlugin::Handoff { + + InvalidateHandoffsOnRunwayDialogSave::InvalidateHandoffsOnRunwayDialogSave( + std::shared_ptr resolver, Euroscope::EuroscopePluginLoopbackInterface& plugin) + : resolver(std::move(resolver)), plugin(plugin) + { + assert(resolver && "Resolver not set in ctor"); + } + + /** + * If the runway dialog changes, we have to assume all resolutions are bad, but we can re-resolve + * them as soon as we invalidate them. + */ + void InvalidateHandoffsOnRunwayDialogSave::RunwayDialogSaved() + { + plugin.ApplyFunctionToAllFlightplans([this]( + const std::shared_ptr& fp, + const std::shared_ptr& rt) { + resolver->Invalidate(*fp); + static_cast(resolver->Resolve(*fp)); + }); + } +} // namespace UKControllerPlugin::Handoff diff --git a/src/plugin/handoff/InvalidateHandoffsOnRunwayDialogSave.h b/src/plugin/handoff/InvalidateHandoffsOnRunwayDialogSave.h new file mode 100644 index 000000000..241e85b32 --- /dev/null +++ b/src/plugin/handoff/InvalidateHandoffsOnRunwayDialogSave.h @@ -0,0 +1,26 @@ +#pragma once +#include "euroscope/RunwayDialogAwareInterface.h" + +namespace UKControllerPlugin::Euroscope { + class EuroscopePluginLoopbackInterface; +} // namespace UKControllerPlugin::Euroscope + +namespace UKControllerPlugin::Handoff { + + class DepartureHandoffResolver; + + class InvalidateHandoffsOnRunwayDialogSave : public Euroscope::RunwayDialogAwareInterface + { + public: + InvalidateHandoffsOnRunwayDialogSave( + std::shared_ptr resolver, Euroscope::EuroscopePluginLoopbackInterface& plugin); + void RunwayDialogSaved() override; + + private: + // The resolver + const std::shared_ptr resolver; + + // The plugin + Euroscope::EuroscopePluginLoopbackInterface& plugin; + }; +} // namespace UKControllerPlugin::Handoff diff --git a/src/plugin/intention/IntentionCodeIntegrationDataInitialiser.cpp b/src/plugin/intention/IntentionCodeIntegrationDataInitialiser.cpp index 38df1780b..72d55077d 100644 --- a/src/plugin/intention/IntentionCodeIntegrationDataInitialiser.cpp +++ b/src/plugin/intention/IntentionCodeIntegrationDataInitialiser.cpp @@ -3,8 +3,6 @@ #include "FirExitPoint.h" #include "FirExitPointCollection.h" #include "IntentionCodeIntegrationDataInitialiser.h" - -#include #include "IntentionCodeMetadata.h" #include "IntentionCodeModel.h" #include "IntentionCodeUpdatedMessage.h" diff --git a/test/plugin/handoff/ClearCacheOnActiveCallsignChangesTest.cpp b/test/plugin/handoff/ClearCacheOnActiveCallsignChangesTest.cpp deleted file mode 100644 index 65ba46404..000000000 --- a/test/plugin/handoff/ClearCacheOnActiveCallsignChangesTest.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include "controller/ActiveCallsign.h" -#include "controller/ControllerPosition.h" -#include "controller/ControllerPositionHierarchy.h" -#include "handoff/ClearCacheOnActiveCallsignChanges.h" -#include "handoff/HandoffCache.h" -#include "handoff/ResolvedHandoff.h" - -using UKControllerPlugin::Controller::ActiveCallsign; -using UKControllerPlugin::Controller::ControllerPosition; -using UKControllerPlugin::Controller::ControllerPositionHierarchy; -using UKControllerPlugin::Handoff::ClearCacheOnActiveCallsignChanges; -using UKControllerPlugin::Handoff::HandoffCache; -using UKControllerPlugin::Handoff::ResolvedHandoff; - -namespace UKControllerPluginTest::Handoff { - class ClearCacheOnActiveCallsignChangesTest : public testing::Test - { - public: - ClearCacheOnActiveCallsignChangesTest() - : position1(std::make_shared( - 1, "LON_S_CTR", 129.420, std::vector{}, true, false)), - position2(std::make_shared( - 2, "LON_SC_CTR", 132.6, std::vector{}, true, false)), - position3( - std::make_shared(-1, "UNICOM", 122.800, std::vector{}, true, false)), - hierarchy1(std::make_shared()), - hierarchy2(std::make_shared()), - hierarchy3(std::make_shared()), - hierarchy4(std::make_shared()), - callsign("LON_S_CTR", "Test", *position1, true), changes(cache) - { - hierarchy1->AddPosition(position1); - hierarchy1->AddPosition(position2); - hierarchy2->AddPosition(position2); - hierarchy2->AddPosition(position1); - hierarchy4->AddPosition(position2); - } - - std::shared_ptr position1; - std::shared_ptr position2; - std::shared_ptr position3; - std::shared_ptr hierarchy1; - std::shared_ptr hierarchy2; - std::shared_ptr hierarchy3; - std::shared_ptr hierarchy4; - ActiveCallsign callsign; - HandoffCache cache; - ClearCacheOnActiveCallsignChanges changes; - }; - - TEST_F(ClearCacheOnActiveCallsignChangesTest, FlushingCallsignsClearsCache) - { - cache.Add(std::make_shared("BAW123", nullptr, nullptr, nullptr)); - cache.Add(std::make_shared("BAW456", nullptr, nullptr, nullptr)); - changes.CallsignsFlushed(); - EXPECT_EQ(0, cache.Count()); - } - - TEST_F(ClearCacheOnActiveCallsignChangesTest, CallsignsLoggingOffEvictOnResolvedControllerMatch) - { - cache.Add(std::make_shared("BAW123", position1, nullptr, nullptr)); - cache.Add(std::make_shared("BAW456", position1, nullptr, nullptr)); - cache.Add(std::make_shared("BAW789", position2, nullptr, nullptr)); - changes.ActiveCallsignRemoved(callsign); - EXPECT_EQ(1, cache.Count()); - EXPECT_EQ(nullptr, cache.Get("BAW123")); - EXPECT_EQ(nullptr, cache.Get("BAW456")); - EXPECT_NE(nullptr, cache.Get("BAW789")); - } - - TEST_F(ClearCacheOnActiveCallsignChangesTest, CallsignsLoggingOnClearsCacheIfControllerPreceedsInSidHierarchy) - { - // Resolved to LON_SC, LON_S comes on and precedes in SID hierarchy - cache.Add(std::make_shared("BAW123", position2, hierarchy1, hierarchy2)); - changes.ActiveCallsignAdded(callsign); - EXPECT_EQ(nullptr, cache.Get("BAW123")); - } - - TEST_F(ClearCacheOnActiveCallsignChangesTest, CallsignsLoggingOnDoesntClearCacheIfControllerAfterInSidHierarchy) - { - // Resolved to LON_SC, LON_S comes on but is after SC in the hierarchy - cache.Add(std::make_shared("BAW123", position2, hierarchy2, hierarchy1)); - changes.ActiveCallsignAdded(callsign); - EXPECT_NE(nullptr, cache.Get("BAW123")); - } - - TEST_F(ClearCacheOnActiveCallsignChangesTest, CallsignLoggingOnClearsCacheIfControllerPreceedsInAirfieldHierarchy) - { - // Resolve to LON_SC, LON_S comes on and preceeds in hierarchy - cache.Add(std::make_shared("BAW123", position2, hierarchy3, hierarchy1)); - changes.ActiveCallsignAdded(callsign); - EXPECT_EQ(nullptr, cache.Get("BAW123")); - } - - TEST_F( - ClearCacheOnActiveCallsignChangesTest, - CallsignLoggingOnClearsCacheIfResolvedControllerInAirfieldHierarchyButControllerLoggingOnIsInSidHierarchy) - { - // Resolve to LON_SC on the airfield hierarchy, LON_S comes on, is not in the airfield hierarchy but is - // in the SID one, should clear. - cache.Add(std::make_shared("BAW123", position2, hierarchy1, hierarchy4)); - changes.ActiveCallsignAdded(callsign); - EXPECT_EQ(nullptr, cache.Get("BAW123")); - } - - TEST_F(ClearCacheOnActiveCallsignChangesTest, CallsignLoggingOnDoesntClearCacheIfControllerAfterInAirfieldHierarchy) - { - // Resolve to LON_SC, LON_S comes on but is after SC in the hierarchy - cache.Add(std::make_shared("BAW123", position2, hierarchy3, hierarchy2)); - changes.ActiveCallsignAdded(callsign); - EXPECT_NE(nullptr, cache.Get("BAW123")); - } - - TEST_F( - ClearCacheOnActiveCallsignChangesTest, - CallsignLoggingOnClearsCacheIfResolvedControllerNotInHierarchyButControllerInSidHierarchy) - { - // Resolve to unicom, LON_S comes on and is in SID hierarchy - cache.Add(std::make_shared("BAW123", position3, hierarchy1, hierarchy3)); - changes.ActiveCallsignAdded(callsign); - EXPECT_EQ(nullptr, cache.Get("BAW123")); - } - - TEST_F( - ClearCacheOnActiveCallsignChangesTest, - CallsignLoggingOnClearsCacheIfResolvedControllerNotInHierarchyButControllerInAirfieldHierarchy) - { - // Resolve to unicom, LON_S comes on and is in airfield hierarchy - cache.Add(std::make_shared("BAW123", position3, hierarchy3, hierarchy1)); - changes.ActiveCallsignAdded(callsign); - EXPECT_EQ(nullptr, cache.Get("BAW123")); - } - - TEST_F( - ClearCacheOnActiveCallsignChangesTest, - CallsignLoggingOnDoesntClearCacheIfResolvedControllerNotInHierarchyButControllerNotInHierarchy) - { - // Resolve to unicom, LON_S comes on and is in neither hierarchy - cache.Add(std::make_shared("BAW123", position3, hierarchy3, hierarchy3)); - changes.ActiveCallsignAdded(callsign); - EXPECT_NE(nullptr, cache.Get("BAW123")); - } -} // namespace UKControllerPluginTest::Handoff diff --git a/test/plugin/handoff/ClearCacheOnRunwayDialogSaveTest.cpp b/test/plugin/handoff/ClearCacheOnRunwayDialogSaveTest.cpp deleted file mode 100644 index 4474e6a9f..000000000 --- a/test/plugin/handoff/ClearCacheOnRunwayDialogSaveTest.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "handoff/ClearCacheOnRunwayDialogSave.h" -#include "handoff/HandoffCache.h" -#include "handoff/ResolvedHandoff.h" - -using UKControllerPlugin::Handoff::ClearCacheOnRunwayDialogSave; -using UKControllerPlugin::Handoff::HandoffCache; -using UKControllerPlugin::Handoff::ResolvedHandoff; - -namespace UKControllerPluginTest::Handoff { - - class ClearCacheOnRunwayDialogSaveTest : public testing::Test - { - }; - - TEST_F(ClearCacheOnRunwayDialogSaveTest, FlushingCallsignsClearsCache) - { - auto cache = std::make_shared(); - ClearCacheOnRunwayDialogSave clear(cache); - - cache->Add(std::make_shared("BAW123", nullptr, nullptr, nullptr)); - cache->Add(std::make_shared("BAW456", nullptr, nullptr, nullptr)); - cache->Add(std::make_shared("BAW789", nullptr, nullptr, nullptr)); - - EXPECT_EQ(3, cache->Count()); - clear.RunwayDialogSaved(); - EXPECT_EQ(0, cache->Count()); - } -} // namespace UKControllerPluginTest::Handoff diff --git a/test/plugin/handoff/DepartureHandoffResolverTest.cpp b/test/plugin/handoff/DefaultDepartureHandoffResolutionStrategyTest.cpp similarity index 95% rename from test/plugin/handoff/DepartureHandoffResolverTest.cpp rename to test/plugin/handoff/DefaultDepartureHandoffResolutionStrategyTest.cpp index 634e2b7bf..568bd1963 100644 --- a/test/plugin/handoff/DepartureHandoffResolverTest.cpp +++ b/test/plugin/handoff/DefaultDepartureHandoffResolutionStrategyTest.cpp @@ -3,7 +3,7 @@ #include "controller/ActiveCallsignCollection.h" #include "controller/ControllerPosition.h" #include "controller/ControllerPositionHierarchy.h" -#include "handoff/DepartureHandoffResolver.h" +#include "handoff/DefaultDepartureHandoffResolutionStrategy.h" #include "handoff/FlightplanAirfieldHandoffMapper.h" #include "handoff/FlightplanSidHandoffMapper.h" #include "handoff/HandoffCollection.h" @@ -18,7 +18,7 @@ using UKControllerPlugin::Controller::ActiveCallsign; using UKControllerPlugin::Controller::ActiveCallsignCollection; using UKControllerPlugin::Controller::ControllerPosition; using UKControllerPlugin::Controller::ControllerPositionHierarchy; -using UKControllerPlugin::Handoff::DepartureHandoffResolver; +using UKControllerPlugin::Handoff::DefaultDepartureHandoffResolutionStrategy; using UKControllerPlugin::Handoff::FlightplanAirfieldHandoffMapper; using UKControllerPlugin::Handoff::FlightplanSidHandoffMapper; using UKControllerPlugin::Handoff::HandoffCollection; @@ -67,7 +67,7 @@ namespace UKControllerPluginTest::Handoff { HandoffCollection handoffs; FlightplanSidHandoffMapper sidMapper; FlightplanAirfieldHandoffMapper airfieldMapper; - DepartureHandoffResolver resolver; + DefaultDepartureHandoffResolutionStrategy resolver; }; TEST_F(DepartureHandoffResolverTest, ItReturnsUnicomIfNoHandoffFound) diff --git a/test/plugin/handoff/HandoffCacheTest.cpp b/test/plugin/handoff/HandoffCacheTest.cpp deleted file mode 100644 index 8a80e248f..000000000 --- a/test/plugin/handoff/HandoffCacheTest.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "handoff/HandoffCache.h" -#include "handoff/ResolvedHandoff.h" - -using UKControllerPlugin::Handoff::HandoffCache; -using UKControllerPlugin::Handoff::ResolvedHandoff; - -namespace UKControllerPluginTest::Handoff { - class HandoffCacheTest : public testing::Test - { - public: - HandoffCacheTest() - : handoff1(std::make_shared("BAW123", nullptr, nullptr, nullptr)), - handoff2(std::make_shared("BAW456", nullptr, nullptr, nullptr)) - { - } - - std::shared_ptr handoff1; - std::shared_ptr handoff2; - HandoffCache cache; - }; - - TEST_F(HandoffCacheTest, ItStartsEmpty) - { - EXPECT_EQ(0, cache.Count()); - } - - TEST_F(HandoffCacheTest, ItAddsResolvedHandoffs) - { - cache.Add(handoff1); - cache.Add(handoff2); - - EXPECT_EQ(2, cache.Count()); - EXPECT_EQ(handoff1, cache.Get("BAW123")); - EXPECT_EQ(handoff2, cache.Get("BAW456")); - } - - TEST_F(HandoffCacheTest, ItDoesntAddDuplicateCallsigns) - { - cache.Add(handoff1); - cache.Add(handoff1); - cache.Add(handoff1); - cache.Add(handoff2); - cache.Add(handoff2); - cache.Add(handoff2); - - EXPECT_EQ(2, cache.Count()); - } - - TEST_F(HandoffCacheTest, ItReturnsNullptrOnHandoffNotFound) - { - cache.Add(handoff1); - cache.Add(handoff2); - - EXPECT_EQ(nullptr, cache.Get("BAW999")); - } - - TEST_F(HandoffCacheTest, ItRemovesHandoffs) - { - cache.Add(handoff1); - cache.Add(handoff2); - cache.Delete("BAW123"); - - EXPECT_EQ(1, cache.Count()); - EXPECT_EQ(nullptr, cache.Get("BAW123")); - EXPECT_EQ(handoff2, cache.Get("BAW456")); - } - - TEST_F(HandoffCacheTest, ItHandlesNonExistantHandoffRemoval) - { - EXPECT_NO_THROW(cache.Delete("BAW123")); - } - - TEST_F(HandoffCacheTest, ItClearsTheCache) - { - cache.Add(handoff1); - cache.Add(handoff2); - cache.Clear(); - - EXPECT_EQ(0, cache.Count()); - } - - TEST_F(HandoffCacheTest, ItRemovesHandoffsBasedOnPredicate) - { - cache.Add(handoff1); - cache.Add(handoff2); - cache.DeleteWhere( - [](const std::shared_ptr& handoff) -> bool { return handoff->callsign == "BAW123"; }); - - EXPECT_EQ(1, cache.Count()); - EXPECT_EQ(nullptr, cache.Get("BAW123")); - EXPECT_EQ(handoff2, cache.Get("BAW456")); - } -} // namespace UKControllerPluginTest::Handoff diff --git a/test/plugin/handoff/HandoffEventHandlerTest.cpp b/test/plugin/handoff/HandoffEventHandlerTest.cpp index f70527baa..fe1f495fe 100644 --- a/test/plugin/handoff/HandoffEventHandlerTest.cpp +++ b/test/plugin/handoff/HandoffEventHandlerTest.cpp @@ -187,13 +187,15 @@ namespace UKControllerPluginTest::Handoff { EXPECT_EQ(122.800, this->cache->Get("BAW123")->resolvedController->GetFrequency()); } - TEST_F(HandoffEventHandlerTest, TestItClearsCacheOnFlightplanUpdate) + TEST_F(HandoffEventHandlerTest, TestItRepopulatesCacheOnFlightplanUpdate) { + this->AddHandoffOrders(); + this->activeCallsigns.AddUserCallsign(ActiveCallsign("LON_SC_CTR", "Testy McTestFace", *this->position2, true)); this->cache->Add(std::make_shared("BAW123", position2, nullptr, nullptr)); this->cache->Add(std::make_shared("BAW456", position2, nullptr, nullptr)); this->handler.FlightPlanEvent(this->mockFlightplan, this->mockRadarTarget); - EXPECT_EQ(nullptr, this->cache->Get("BAW123")); EXPECT_NE(nullptr, this->cache->Get("BAW456")); + EXPECT_EQ(122.800, this->cache->Get("BAW123")->resolvedController->GetFrequency()); } TEST_F(HandoffEventHandlerTest, TestItClearsCacheOnFlightplanDisconnect) diff --git a/test/plugin/handoff/InvalidateHandoffsOnActiveCallsignChangesTest.cpp b/test/plugin/handoff/InvalidateHandoffsOnActiveCallsignChangesTest.cpp new file mode 100644 index 000000000..a043ed9a1 --- /dev/null +++ b/test/plugin/handoff/InvalidateHandoffsOnActiveCallsignChangesTest.cpp @@ -0,0 +1,259 @@ +#include "controller/ActiveCallsign.h" +#include "controller/ControllerPosition.h" +#include "controller/ControllerPositionHierarchy.h" +#include "handoff/InvalidateHandoffsOnActiveCallsignChanges.h" +#include "handoff/ResolvedHandoff.h" +#include "mock/MockDepartureHandoffResolver.h" +#include "mock/MockEuroScopeCFlightplanInterface.h" +#include "mock/MockEuroscopePluginLoopbackInterface.h" + +using UKControllerPlugin::Controller::ActiveCallsign; +using UKControllerPlugin::Controller::ControllerPosition; +using UKControllerPlugin::Controller::ControllerPositionHierarchy; +using UKControllerPlugin::Handoff::HandoffCache; +using UKControllerPlugin::Handoff::ResolvedHandoff; + +namespace UKControllerPluginTest::Handoff { + class ClearCacheOnActiveCallsignChangesTest : public testing::Test + { + public: + ClearCacheOnActiveCallsignChangesTest() + : position1(std::make_shared( + 1, "LON_S_CTR", 129.420, std::vector{}, true, false)), + position2(std::make_shared( + 2, "LON_SC_CTR", 132.6, std::vector{}, true, false)), + position3( + std::make_shared(-1, "UNICOM", 122.800, std::vector{}, true, false)), + hierarchy1(std::make_shared()), + hierarchy2(std::make_shared()), + hierarchy3(std::make_shared()), + hierarchy4(std::make_shared()), + callsign("LON_S_CTR", "Test", *position1, true), + mockResolver(std::make_shared>()), + changes(mockResolver, mockPlugin) + { + hierarchy1->AddPosition(position1); + hierarchy1->AddPosition(position2); + hierarchy2->AddPosition(position2); + hierarchy2->AddPosition(position1); + hierarchy4->AddPosition(position2); + } + + std::shared_ptr position1; + std::shared_ptr position2; + std::shared_ptr position3; + std::shared_ptr hierarchy1; + std::shared_ptr hierarchy2; + std::shared_ptr hierarchy3; + std::shared_ptr hierarchy4; + ActiveCallsign callsign; + testing::NiceMock mockPlugin; + std::shared_ptr> mockResolver; + InvalidateHandoffsOnActiveCallsignChanges changes; + }; + + TEST_F(ClearCacheOnActiveCallsignChangesTest, FlushingCallsignsInvalidatesAllFlightplans) + { + auto mockFlightplan1 = std::make_shared>(); + auto mockRadarTarget1 = std::make_shared>(); + auto mockFlightplan2 = std::make_shared>(); + auto mockRadarTarget2 = std::make_shared>(); + auto mockFlightplan3 = std::make_shared>(); + auto mockRadarTarget3 = std::make_shared>(); + + mockPlugin.AddAllFlightplansItem({mockFlightplan1, mockRadarTarget1}); + mockPlugin.AddAllFlightplansItem({mockFlightplan2, mockRadarTarget2}); + mockPlugin.AddAllFlightplansItem({mockFlightplan3, mockRadarTarget3}); + + EXPECT_CALL(*mockResolver, Invalidate(testing::Ref(*mockFlightplan1))).Times(1); + EXPECT_CALL(*mockResolver, Invalidate(testing::Ref(*mockFlightplan2))).Times(1); + EXPECT_CALL(*mockResolver, Invalidate(testing::Ref(*mockFlightplan3))).Times(1); + + changes.CallsignsFlushed(); + } + + TEST_F(ClearCacheOnActiveCallsignChangesTest, CallsignsLoggingOffEvictOnResolvedControllerMatch) + { + auto mockFlightplan1 = std::make_shared>(); + auto mockRadarTarget1 = std::make_shared>(); + auto mockFlightplan2 = std::make_shared>(); + auto mockRadarTarget2 = std::make_shared>(); + auto mockFlightplan3 = std::make_shared>(); + auto mockRadarTarget3 = std::make_shared>(); + + mockPlugin.AddAllFlightplansItem({mockFlightplan1, mockRadarTarget1}); + mockPlugin.AddAllFlightplansItem({mockFlightplan2, mockRadarTarget2}); + mockPlugin.AddAllFlightplansItem({mockFlightplan3, mockRadarTarget3}); + + auto handoffFlightplan1 = std::make_shared("BAW123", position1, nullptr, nullptr); + auto handoffFlightplan2 = std::make_shared("BAW456", position1, nullptr, nullptr); + auto handoffFlightplan3 = std::make_shared("BAW789", position2, nullptr, nullptr); + + EXPECT_CALL(*mockResolver, Invalidate(testing::Ref(*mockFlightplan1))).Times(1); + EXPECT_CALL(*mockResolver, Resolve(testing::Ref(*mockFlightplan1))).Times(1); + EXPECT_CALL(*mockResolver, Invalidate(testing::Ref(*mockFlightplan2))).Times(1); + EXPECT_CALL(*mockResolver, Resolve(testing::Ref(*mockFlightplan2))).Times(1); + EXPECT_CALL(*mockResolver, Invalidate(testing::Ref(*mockFlightplan3))).Times(0); + EXPECT_CALL(*mockResolver, Resolve(testing::Ref(*mockFlightplan3))).Times(1); + + changes.ActiveCallsignRemoved(callsign); + } + + TEST_F( + ClearCacheOnActiveCallsignChangesTest, + CallsignsLoggingOnInvalidatesAndResolvesIfControllerPreceedsInSidHierarchy) + { + auto mockFlightplan1 = std::make_shared>(); + auto mockRadarTarget1 = std::make_shared>(); + mockPlugin.AddAllFlightplansItem({mockFlightplan1, mockRadarTarget1}); + + // Make sure we resolve and get the handoff first time + auto resolvedHandoff = std::make_shared("BAW123", position2, hierarchy1, hierarchy2); + EXPECT_CALL(*mockResolver, Resolve(testing::Ref(*mockFlightplan1))).WillOnce(testing::Return(resolvedHandoff)); + + // Subsequent times, we should invalidate and resolve + EXPECT_CALL(*mockResolver, Invalidate(testing::Ref(*mockFlightplan1))).Times(1); + EXPECT_CALL(*mockResolver, Resolve(testing::Ref(*mockFlightplan1))).Times(1); + + // Resolved to LON_SC, LON_S comes on and precedes in SID hierarchy + changes.ActiveCallsignAdded(callsign); + } + + TEST_F( + ClearCacheOnActiveCallsignChangesTest, + CallsignsLoggingOnDoesntInvalidateAndResolveIfControllerAfterInSidHierarchy) + { + auto mockFlightplan1 = std::make_shared>(); + auto mockRadarTarget1 = std::make_shared>(); + mockPlugin.AddAllFlightplansItem({mockFlightplan1, mockRadarTarget1}); + + // Make sure we resolve and get the handoff first time + auto resolvedHandoff = std::make_shared("BAW123", position2, hierarchy2, hierarchy1); + EXPECT_CALL(*mockResolver, Resolve(testing::Ref(*mockFlightplan1))).WillOnce(testing::Return(resolvedHandoff)); + + // Subsequent times, we should invalidate and resolve + EXPECT_CALL(*mockResolver, Invalidate(testing::Ref(*mockFlightplan1))).Times(0); + + // Resolved to LON_SC, LON_S comes on but is after SC in the hierarchy + changes.ActiveCallsignAdded(callsign); + } + + TEST_F( + ClearCacheOnActiveCallsignChangesTest, + CallsignLoggingOnInvalidatesAndResolvesIfControllerPreceedsInAirfieldHierarchy) + { + auto mockFlightplan1 = std::make_shared>(); + auto mockRadarTarget1 = std::make_shared>(); + mockPlugin.AddAllFlightplansItem({mockFlightplan1, mockRadarTarget1}); + + // Make sure we resolve and get the handoff first time + auto resolvedHandoff = std::make_shared("BAW123", position2, hierarchy3, hierarchy1); + EXPECT_CALL(*mockResolver, Resolve(testing::Ref(*mockFlightplan1))).WillOnce(testing::Return(resolvedHandoff)); + + // Subsequent times, we should invalidate and resolve + EXPECT_CALL(*mockResolver, Invalidate(testing::Ref(*mockFlightplan1))).Times(1); + EXPECT_CALL(*mockResolver, Resolve(testing::Ref(*mockFlightplan1))).Times(1); + + // Resolve to LON_SC, LON_S comes on and preceeds in hierarchy + changes.ActiveCallsignAdded(callsign); + } + + TEST_F( + ClearCacheOnActiveCallsignChangesTest, + CallsignLoggingOnInvalidatesAndResolvesIfResolvedControllerInAirfieldHierarchyButControllerLoggingOnIsInSidHierarchy) + { + auto mockFlightplan1 = std::make_shared>(); + auto mockRadarTarget1 = std::make_shared>(); + mockPlugin.AddAllFlightplansItem({mockFlightplan1, mockRadarTarget1}); + + // Make sure we resolve and get the handoff first time + auto resolvedHandoff = std::make_shared("BAW123", position2, hierarchy1, hierarchy4); + EXPECT_CALL(*mockResolver, Resolve(testing::Ref(*mockFlightplan1))).WillOnce(testing::Return(resolvedHandoff)); + + // Subsequent times, we should invalidate and resolve + EXPECT_CALL(*mockResolver, Invalidate(testing::Ref(*mockFlightplan1))).Times(1); + EXPECT_CALL(*mockResolver, Resolve(testing::Ref(*mockFlightplan1))).Times(1); + + // Resolve to LON_SC on the airfield hierarchy, LON_S comes on, is not in the airfield hierarchy but is + // in the SID one, should clear. + changes.ActiveCallsignAdded(callsign); + } + + TEST_F( + ClearCacheOnActiveCallsignChangesTest, + CallsignLoggingOnDoesntInvalidateAndResolveIfControllerAfterInAirfieldHierarchy) + { + auto mockFlightplan1 = std::make_shared>(); + auto mockRadarTarget1 = std::make_shared>(); + mockPlugin.AddAllFlightplansItem({mockFlightplan1, mockRadarTarget1}); + + // Make sure we resolve and get the handoff first time + auto resolvedHandoff = std::make_shared("BAW123", position2, hierarchy3, hierarchy2); + EXPECT_CALL(*mockResolver, Resolve(testing::Ref(*mockFlightplan1))).WillOnce(testing::Return(resolvedHandoff)); + + // Subsequent times, we should invalidate and resolve + EXPECT_CALL(*mockResolver, Invalidate(testing::Ref(*mockFlightplan1))).Times(0); + + // Resolve to LON_SC, LON_S comes on but is after SC in the hierarchy + changes.ActiveCallsignAdded(callsign); + } + + TEST_F( + ClearCacheOnActiveCallsignChangesTest, + CallsignLoggingOnInvalidatesAndResolvesIfResolvedControllerNotInHierarchyButControllerInSidHierarchy) + { + auto mockFlightplan1 = std::make_shared>(); + auto mockRadarTarget1 = std::make_shared>(); + mockPlugin.AddAllFlightplansItem({mockFlightplan1, mockRadarTarget1}); + + // Make sure we resolve and get the handoff first time + auto resolvedHandoff = std::make_shared("BAW123", position3, hierarchy1, hierarchy3); + EXPECT_CALL(*mockResolver, Resolve(testing::Ref(*mockFlightplan1))).WillOnce(testing::Return(resolvedHandoff)); + + // Subsequent times, we should invalidate and resolve + EXPECT_CALL(*mockResolver, Invalidate(testing::Ref(*mockFlightplan1))).Times(1); + EXPECT_CALL(*mockResolver, Resolve(testing::Ref(*mockFlightplan1))).Times(1); + + // Resolve to unicom, LON_S comes on and is in SID hierarchy + changes.ActiveCallsignAdded(callsign); + } + + TEST_F( + ClearCacheOnActiveCallsignChangesTest, + CallsignLoggingOnInvalidatesAndResolvesIfResolvedControllerNotInHierarchyButControllerInAirfieldHierarchy) + { + auto mockFlightplan1 = std::make_shared>(); + auto mockRadarTarget1 = std::make_shared>(); + mockPlugin.AddAllFlightplansItem({mockFlightplan1, mockRadarTarget1}); + + // Make sure we resolve and get the handoff first time + auto resolvedHandoff = std::make_shared("BAW123", position3, hierarchy3, hierarchy1); + EXPECT_CALL(*mockResolver, Resolve(testing::Ref(*mockFlightplan1))).WillOnce(testing::Return(resolvedHandoff)); + + // Subsequent times, we should invalidate and resolve + EXPECT_CALL(*mockResolver, Invalidate(testing::Ref(*mockFlightplan1))).Times(1); + EXPECT_CALL(*mockResolver, Resolve(testing::Ref(*mockFlightplan1))).Times(1); + + // Resolve to unicom, LON_S comes on and is in airfield hierarchy + changes.ActiveCallsignAdded(callsign); + } + + TEST_F( + ClearCacheOnActiveCallsignChangesTest, + CallsignLoggingOnDoesntInvalidateAndResolveIfResolvedControllerNotInHierarchyButControllerNotInHierarchy) + { + auto mockFlightplan1 = std::make_shared>(); + auto mockRadarTarget1 = std::make_shared>(); + mockPlugin.AddAllFlightplansItem({mockFlightplan1, mockRadarTarget1}); + + // Make sure we resolve and get the handoff first time + auto resolvedHandoff = std::make_shared("BAW123", position3, hierarchy3, hierarchy3); + EXPECT_CALL(*mockResolver, Resolve(testing::Ref(*mockFlightplan1))).WillOnce(testing::Return(resolvedHandoff)); + + // Subsequent times, we should invalidate and resolve + EXPECT_CALL(*mockResolver, Invalidate(testing::Ref(*mockFlightplan1))).Times(0); + + // Resolve to unicom, LON_S comes on and is in neither hierarchy + changes.ActiveCallsignAdded(callsign); + } +} // namespace UKControllerPluginTest::Handoff diff --git a/test/plugin/handoff/InvalidateHandoffsOnRunwayDialogSaveTest.cpp b/test/plugin/handoff/InvalidateHandoffsOnRunwayDialogSaveTest.cpp new file mode 100644 index 000000000..9a0b77472 --- /dev/null +++ b/test/plugin/handoff/InvalidateHandoffsOnRunwayDialogSaveTest.cpp @@ -0,0 +1,43 @@ +#include "handoff/ClearCacheOnRunwayDialogSave.h" + +using UKControllerPlugin::Handoff::ClearCacheOnRunwayDialogSave; +using UKControllerPlugin::Handoff::ResolvedHandoff; + +namespace UKControllerPluginTest::Handoff { + + class ClearCacheOnRunwayDialogSaveTest : public testing::Test + { + public: + ClearCacheOnRunwayDialogSaveTest() + : resolver(std::make_shared>()), clear(resolver, plugin) + { + } + + std::shared_ptr> resolver; + testing::NiceMock plugin; + ClearCacheOnRunwayDialogSave clear; + }; + + TEST_F(ClearCacheOnRunwayDialogSaveTest, SavingTheRunwayDialogInvalidatesAndReResolvesFlightplans) + { + auto fp1 = std::make_shared(); + auto rt1 = std::make_shared(); + auto fp2 = std::make_shared(); + auto rt2 = std::make_shared(); + auto fp3 = std::make_shared(); + auto rt3 = std::make_shared(); + + plugin.AddAllFlightplansItem({fp1, rt1}); + plugin.AddAllFlightplansItem({fp2, rt2}); + plugin.AddAllFlightplansItem({fp3, rt3}); + + EXPECT_CALL(*resolver, Invalidate(testing::Ref(*fp1))); + EXPECT_CALL(*resolver, Resolve(testing::Ref(*fp1))); + EXPECT_CALL(*resolver, Invalidate(testing::Ref(*fp2))); + EXPECT_CALL(*resolver, Resolve(testing::Ref(*fp2))); + EXPECT_CALL(*resolver, Invalidate(testing::Ref(*fp3))); + EXPECT_CALL(*resolver, Resolve(testing::Ref(*fp3))); + + clear.RunwayDialogSaved(); + } +} // namespace UKControllerPluginTest::Handoff