diff --git a/unit_tests/engine/offline_facade.cpp b/unit_tests/engine/offline_facade.cpp new file mode 100644 index 000000000..57cd9e358 --- /dev/null +++ b/unit_tests/engine/offline_facade.cpp @@ -0,0 +1,429 @@ +#include "engine/routing_algorithms/routing_base_mld.hpp" +#include "engine/routing_algorithms/shortest_path_impl.hpp" +#include "engine/search_engine_data.hpp" +#include "util/integer_range.hpp" + +#include + +namespace osrm +{ +namespace engine +{ +namespace routing_algorithms +{ + +// Declare offline data facade algorithm +namespace offline +{ +struct Algorithm final +{ +}; +} + +} // routing_algorithms + +// Define engine data for offline data facade +template <> struct SearchEngineData +{ + using QueryHeap = SearchEngineData::QueryHeap; + + using SearchEngineHeapPtr = std::unique_ptr; + + SearchEngineHeapPtr forward_heap_1; + SearchEngineHeapPtr reverse_heap_1; + + void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes) + { + if (forward_heap_1.get()) + { + forward_heap_1->Clear(); + } + else + { + forward_heap_1.reset(new QueryHeap(number_of_nodes)); + } + + if (reverse_heap_1.get()) + { + reverse_heap_1->Clear(); + } + else + { + reverse_heap_1.reset(new QueryHeap(number_of_nodes)); + } + } +}; + +// Define offline multilevel partition +namespace datafacade +{ +struct ExternalMultiLevelPartition +{ + CellID GetCell(LevelID /*l*/, NodeID /*node*/) const { return 0; } + LevelID GetQueryLevel(NodeID /*start*/, NodeID /*target*/, NodeID /*node*/) const { return 0; } + LevelID GetHighestDifferentLevel(NodeID /*first*/, NodeID /*second*/) const { return 0; } + std::uint8_t GetNumberOfLevels() const { return 0; } + std::uint32_t GetNumberOfCells(LevelID /*level*/) const { return 0; } + CellID BeginChildren(LevelID /*level*/, CellID /*cell*/) const { return 0; } + CellID EndChildren(LevelID /*level*/, CellID /*cell*/) const { return 0; } +}; + +// Define external cell storage +struct ExternalCellStorage +{ + struct CellImpl + { + auto GetOutWeight(NodeID /*node*/) const + { + return boost::make_iterator_range((EdgeWeight *)0, (EdgeWeight *)0); + } + + auto GetInWeight(NodeID /*node*/) const + { + return boost::make_iterator_range((EdgeWeight *)0, (EdgeWeight *)0); + } + + auto GetSourceNodes() const + { + return boost::make_iterator_range((EdgeWeight *)0, (EdgeWeight *)0); + } + + auto GetDestinationNodes() const + { + return boost::make_iterator_range((EdgeWeight *)0, (EdgeWeight *)0); + } + }; + + using Cell = CellImpl; + using ConstCell = const CellImpl; + + ConstCell GetCell(LevelID /*level*/, CellID /*id*/) const { return Cell{}; } + Cell GetCell(LevelID /*level*/, CellID /*id*/) { return Cell{}; } +}; + +// Define external data facade +template <> +class ContiguousInternalMemoryDataFacade final + : public BaseDataFacade +{ + ExternalMultiLevelPartition external_partition; + ExternalCellStorage external_cell_storage; + + public: + using EdgeData = extractor::EdgeBasedEdge::EdgeData; + // using RTreeLeaf = extractor::EdgeBasedNode; + + ContiguousInternalMemoryDataFacade() {} + + ~ContiguousInternalMemoryDataFacade() {} + + unsigned GetNumberOfNodes() const { return 0; } + + NodeID GetTarget(const EdgeID /*edgeID*/) const { return 0; } + + const EdgeData &GetEdgeData(const EdgeID /*edgeID*/) const + { + static EdgeData outData; + return outData; + } + + const auto &GetMultiLevelPartition() const { return external_partition; } + + const auto &GetCellStorage() const { return external_cell_storage; } + + auto GetBorderEdgeRange(const LevelID /*level*/, const NodeID /*node*/) const + { + return util::irange(0, 0); + } + + EdgeID FindEdge(const NodeID /*from*/, const NodeID /*to*/) const { return SPECIAL_EDGEID; } + + unsigned GetCheckSum() const override { return 0; } + + // node and edge information access + util::Coordinate GetCoordinateOfNode(const NodeID /*id*/) const override + { + return {osrm::util::FloatLongitude{7.437069}, osrm::util::FloatLatitude{43.749249}}; + } + + OSMNodeID GetOSMNodeIDOfNode(const NodeID /*id*/) const override { return OSMNodeID(); } + + GeometryID GetGeometryIndex(const NodeID /*id*/) const override { return GeometryID{0, false}; } + + std::vector GetUncompressedForwardGeometry(const EdgeID /*id*/) const override + { + return {}; + } + + std::vector GetUncompressedReverseGeometry(const EdgeID /*id*/) const override + { + return {}; + } + + TurnPenalty GetWeightPenaltyForEdgeID(const unsigned /*id*/) const override + { + return INVALID_TURN_PENALTY; + } + + TurnPenalty GetDurationPenaltyForEdgeID(const unsigned /*id*/) const override + { + return INVALID_TURN_PENALTY; + } + + std::vector GetUncompressedForwardWeights(const EdgeID /*id*/) const override + { + return {}; + } + + std::vector GetUncompressedReverseWeights(const EdgeID /*id*/) const override + { + return {}; + } + + std::vector GetUncompressedForwardDurations(const EdgeID /*geomID*/) const override + { + return {}; + } + + std::vector GetUncompressedReverseDurations(const EdgeID /*geomID*/) const override + { + return {}; + } + + std::vector GetUncompressedForwardDatasources(const EdgeID /*id*/) const override + { + return {}; + } + + std::vector GetUncompressedReverseDatasources(const EdgeID /*id*/) const override + { + return {}; + } + + StringView GetDatasourceName(const DatasourceID /*id*/) const override { return StringView{}; } + + extractor::guidance::TurnInstruction + GetTurnInstructionForEdgeID(const EdgeID /*id*/) const override + { + return extractor::guidance::TurnInstruction{}; + } + + extractor::TravelMode GetTravelMode(const NodeID /*id*/) const override + { + return TRAVEL_MODE_DRIVING; + } + + std::vector GetEdgesInBox(const util::Coordinate /*south_west*/, + const util::Coordinate /*north_east*/) const override + { + return {}; + } + + std::vector + NearestPhantomNodesInRange(const util::Coordinate /*input_coordinate*/, + const float /*max_distance*/, + const int /*bearing*/, + const int /*bearing_range*/, + const Approach /*approach*/) const override + { + return {}; + } + + std::vector + NearestPhantomNodesInRange(const util::Coordinate /*input_coordinate*/, + const float /*max_distance*/, + const Approach /*approach*/) const override + { + return {}; + } + + std::vector + NearestPhantomNodes(const util::Coordinate /*input_coordinate*/, + const unsigned /*max_results*/, + const double /*max_distance*/, + const int /*bearing*/, + const int /*bearing_range*/, + const Approach /*approach*/) const override + { + return {}; + } + + std::vector + NearestPhantomNodes(const util::Coordinate /*input_coordinate*/, + const unsigned /*max_results*/, + const int /*bearing*/, + const int /*bearing_range*/, + const Approach /*approach*/) const override + { + return {}; + } + + std::vector + NearestPhantomNodes(const util::Coordinate /*input_coordinate*/, + const unsigned /*max_results*/, + const Approach /*approach*/) const override + { + return {}; + } + + std::vector + NearestPhantomNodes(const util::Coordinate /*input_coordinate*/, + const unsigned /*max_results*/, + const double /*max_distance*/, + const Approach /*approach*/) const override + { + return {}; + } + + std::pair + NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/, + const Approach /*approach*/) const override + { + return {}; + } + + std::pair + NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/, + const double /*max_distance*/, + const Approach /*approach*/) const override + { + return {}; + } + + std::pair + NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/, + const double /*max_distance*/, + const int /*bearing*/, + const int /*bearing_range*/, + const Approach /*approach*/) const override + { + return {}; + } + + std::pair + NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/, + const int /*bearing*/, + const int /*bearing_range*/, + const Approach /*approach*/) const override + { + return {}; + } + + util::guidance::LaneTupleIdPair GetLaneData(const EdgeID /*id*/) const override + { + return util::guidance::LaneTupleIdPair{}; + } + + extractor::guidance::TurnLaneDescription + GetTurnDescription(const LaneDescriptionID /*laneDescriptionID*/) const override + { + return {}; + } + + bool HasLaneData(const EdgeID /*id*/) const override { return false; } + NameID GetNameIndex(const NodeID /*nodeID*/) const { return EMPTY_NAMEID; } + StringView GetNameForID(const NameID /*id*/) const override { return StringView{}; } + StringView GetRefForID(const NameID /*id*/) const override { return StringView{}; } + StringView GetPronunciationForID(const NameID /*id*/) const override { return StringView{}; } + StringView GetDestinationsForID(const NameID /*id*/) const override { return StringView{}; } + StringView GetExitsForID(const NameID /*id*/) const override { return StringView{}; } + std::string GetTimestamp() const override { return std::string(); } + bool GetContinueStraightDefault() const override { return false; } + double GetMapMatchingMaxSpeed() const override { return 0; } + const char *GetWeightName() const override { return ""; } + unsigned GetWeightPrecision() const override { return 0; } + double GetWeightMultiplier() const override { return 1; } + ComponentID GetComponentID(NodeID) const override { return ComponentID{}; } + + util::guidance::TurnBearing PreTurnBearing(const EdgeID /*eid*/) const override + { + return util::guidance::TurnBearing(0); + } + + util::guidance::TurnBearing PostTurnBearing(const EdgeID /*eid*/) const override + { + return util::guidance::TurnBearing(0); + } + + util::guidance::BearingClass + GetBearingClass(const BearingClassID /*bearing_class_id*/) const override + { + return util::guidance::BearingClass{}; + } + + osrm::extractor::ClassData GetClassData(const NodeID /*id*/) const override { return 0; } + std::vector GetClasses(const extractor::ClassData /*class_data*/) const override + { + return {}; + } + + util::guidance::EntryClass GetEntryClass(const EdgeID /*turn_id*/) const override { return {}; } + bool IsLeftHandDriving() const override { return false; } +}; + +} // datafacade + +// Fallback to MLD algorithm: requires from data facade MLD specific members +namespace routing_algorithms +{ +namespace offline +{ + +inline void search(SearchEngineData &engine_working_data, + const datafacade::ContiguousInternalMemoryDataFacade &facade, + typename SearchEngineData::QueryHeap &forward_heap, + typename SearchEngineData::QueryHeap &reverse_heap, + EdgeWeight &weight, + std::vector &packed_leg, + const bool force_loop_forward, + const bool force_loop_reverse, + const PhantomNodes &phantom_nodes, + const EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT) +{ + mld::search(engine_working_data, + facade, + forward_heap, + reverse_heap, + weight, + packed_leg, + force_loop_forward, + force_loop_reverse, + phantom_nodes, + weight_upper_bound); +} + +template +void unpackPath(const FacadeT &facade, + RandomIter packed_path_begin, + RandomIter packed_path_end, + const PhantomNodes &phantom_nodes, + std::vector &unpacked_path) +{ + mld::unpackPath(facade, packed_path_begin, packed_path_end, phantom_nodes, unpacked_path); +} + +} // offline +} // routing_algorithms + +} // engine +} // osrm + +BOOST_AUTO_TEST_SUITE(offline_facade) + +BOOST_AUTO_TEST_CASE(shortest_path) +{ + using Algorithm = osrm::engine::routing_algorithms::offline::Algorithm; + + osrm::engine::SearchEngineData heaps; + osrm::engine::datafacade::ContiguousInternalMemoryDataFacade facade; + + std::vector phantom_nodes; + phantom_nodes.push_back({osrm::engine::PhantomNode{}, osrm::engine::PhantomNode{}}); + + auto route = + osrm::engine::routing_algorithms::shortestPathSearch(heaps, facade, phantom_nodes, false); + + BOOST_CHECK_EQUAL(route.shortest_path_weight, INVALID_EDGE_WEIGHT); +} + +BOOST_AUTO_TEST_SUITE_END()