From 54d7a46ab9aa1f58b6a518a2cea275d0b93afb89 Mon Sep 17 00:00:00 2001 From: Olga Khlopkova Date: Wed, 25 Mar 2020 17:47:51 +0300 Subject: [PATCH] [routing] Integration tests and unit tests for Guides. --- routing/index_router.cpp | 11 +- .../routing_integration_tests/CMakeLists.txt | 1 + .../guides_tests.cpp | 124 ++++++++++++++++++ .../routing_test_tools.cpp | 15 +++ .../routing_test_tools.hpp | 3 + routing/routing_tests/CMakeLists.txt | 1 + routing/routing_tests/async_router_test.cpp | 1 + routing/routing_tests/fake_graph_test.cpp | 48 ++++--- 8 files changed, 180 insertions(+), 24 deletions(-) create mode 100644 routing/routing_integration_tests/guides_tests.cpp diff --git a/routing/index_router.cpp b/routing/index_router.cpp index 04ac3d3191..76a4a34f20 100644 --- a/routing/index_router.cpp +++ b/routing/index_router.cpp @@ -515,12 +515,11 @@ void IndexRouter::AddGuidesOsmConnectionsToGraphStarter(size_t checkpointIdxFrom auto linksTo = m_guides.GetOsmConnections(checkpointIdxTo); for (auto const & link : linksTo) { - auto it = - std::find_if(linksFrom.begin(), linksFrom.end(), [&link](ConnectionToOsm const & cur) { - return link.m_fakeEnding.m_originJunction == cur.m_fakeEnding.m_originJunction && - link.m_fakeEnding.m_projections == cur.m_fakeEnding.m_projections && - link.m_realSegment == cur.m_realSegment && link.m_realTo == cur.m_realTo; - }); + auto it = find_if(linksFrom.begin(), linksFrom.end(), [&link](ConnectionToOsm const & cur) { + return link.m_fakeEnding.m_originJunction == cur.m_fakeEnding.m_originJunction && + link.m_fakeEnding.m_projections == cur.m_fakeEnding.m_projections && + link.m_realSegment == cur.m_realSegment && link.m_realTo == cur.m_realTo; + }); if (it == linksFrom.end()) { diff --git a/routing/routing_integration_tests/CMakeLists.txt b/routing/routing_integration_tests/CMakeLists.txt index 25775d1a84..054fe86482 100644 --- a/routing/routing_integration_tests/CMakeLists.txt +++ b/routing/routing_integration_tests/CMakeLists.txt @@ -20,6 +20,7 @@ set( bicycle_route_test.cpp bicycle_turn_test.cpp get_altitude_test.cpp + guides_tests.cpp online_cross_tests.cpp pedestrian_route_test.cpp road_graph_tests.cpp diff --git a/routing/routing_integration_tests/guides_tests.cpp b/routing/routing_integration_tests/guides_tests.cpp new file mode 100644 index 0000000000..acc90959b7 --- /dev/null +++ b/routing/routing_integration_tests/guides_tests.cpp @@ -0,0 +1,124 @@ +#include "routing/routing_integration_tests/routing_test_tools.hpp" + +#include "testing/testing.hpp" + +#include "routing/route.hpp" +#include "routing/routing_callbacks.hpp" + +#include "geometry/latlon.hpp" + +#include + +using namespace routing; + +namespace +{ +// Test guide track is laid crosswise the OSM road graph. It doesn't match the OSM roads so we +// can test route length, time and points number and it is enough to guarantee that the route +// built during the test is the route through the guide which we expect. +GuidesTracks GetTestGuides() +{ + // Guide with single track. + GuidesTracks guides; + guides[10] = {{{mercator::FromLatLon(48.13999, 11.56873), 10}, + {mercator::FromLatLon(48.14096, 11.57246), 10}, + {mercator::FromLatLon(48.14487, 11.57259), 10}}}; + return guides; +} + +void TestGuideRoute(Checkpoints const & checkpoints, double expectedDistM, double expectedTimeS, + size_t expectedPointsCount) +{ + TRouteResult const routeResult = integration::CalculateRoute( + integration::GetVehicleComponents(VehicleType::Pedestrian), checkpoints, GetTestGuides()); + + TEST_EQUAL(routeResult.second, RouterResultCode::NoError, ()); + + integration::TestRouteLength(*routeResult.first, expectedDistM); + integration::TestRouteTime(*routeResult.first, expectedTimeS); + integration::TestRoutePointsNumber(*routeResult.first, expectedPointsCount); +} + +void ReverseCheckpoints(Checkpoints const & checkpoints) +{ + auto points = checkpoints.GetPoints(); + std::reverse(points.begin(), points.end()); +} + +// Start and finish checkpoints are connected to the track via single fake edge. +UNIT_TEST(Guides_TwoPointsOnTrack) +{ + // Checkpoints lie on the track. + Checkpoints const checkpoints{mercator::FromLatLon(48.14367, 11.57257), + mercator::FromLatLon(48.13999, 11.56873)}; + + double const expectedDistM = 600.8; + double const expectedTimeS = 721.0; + size_t const expectedPointsCount = 7; + + TestGuideRoute(checkpoints, expectedDistM, expectedTimeS, expectedPointsCount); + ReverseCheckpoints(checkpoints); + TestGuideRoute(checkpoints, expectedDistM, expectedTimeS, expectedPointsCount); +} + +// One checkpoint is connected to the track projection via OSM, +// other checkpoint is connected to the track projection via single fake edge. +UNIT_TEST(Guides_TwoPointsOnTrackOneViaOsm) +{ + // Start is further from track then |kEqDistToTrackPointM|, but finish is closer. + Checkpoints const checkpoints{mercator::FromLatLon(48.13998, 11.56982), + mercator::FromLatLon(48.14448, 11.57259)}; + + double const expectedDistM = 702.4; + double const expectedTimeS = 821.6; + size_t const expectedPointsCount = 11; + + TestGuideRoute(checkpoints, expectedDistM, expectedTimeS, expectedPointsCount); + ReverseCheckpoints(checkpoints); + TestGuideRoute(checkpoints, expectedDistM, expectedTimeS, expectedPointsCount); +} + +// Start checkpoint is far away from the track, finish checkpoint lies in meters from +// the middle of the track. We build the first part of the route from start to the terminal +// track point, second part - from the terminal point to the finish. +UNIT_TEST(Guides_FinishPointOnTrack) +{ + Checkpoints const checkpoints{mercator::FromLatLon(48.1394659, 11.575924), + mercator::FromLatLon(48.1407632, 11.5716992)}; + + double const expectedDistM = 840.1; + double const expectedTimeS = 771.3; + size_t const expectedPointsCount = 37; + + TestGuideRoute(checkpoints, expectedDistM, expectedTimeS, expectedPointsCount); +} + +// Start checkpoint is on the track, finish checkpoint is far away. We build the first part of the +// route through the track and the second part - through the OSM roads. +UNIT_TEST(Guides_StartPointOnTrack) +{ + Checkpoints const checkpoints{mercator::FromLatLon(48.14168, 11.57244), + mercator::FromLatLon(48.13741, 11.56095)}; + + double const expectedDistM = 1272.3; + double const expectedTimeS = 1192.0; + size_t const expectedPointsCount = 67; + + TestGuideRoute(checkpoints, expectedDistM, expectedTimeS, expectedPointsCount); +} + +// Start and finish lie on the track; 3 intermediate points are far away from the track. +UNIT_TEST(Guides_MultipleIntermediatePoints) +{ + Checkpoints const checkpoints( + {mercator::FromLatLon(48.14403, 11.57259), mercator::FromLatLon(48.14439, 11.57480), + mercator::FromLatLon(48.14192, 11.57548), mercator::FromLatLon(48.14106, 11.57279), + mercator::FromLatLon(48.14044, 11.57061)}); + + double const expectedDistM = 1221.11; + double const expectedTimeS = 1096.6; + size_t const expectedPointsCount = 67; + + TestGuideRoute(checkpoints, expectedDistM, expectedTimeS, expectedPointsCount); +} +} // namespace diff --git a/routing/routing_integration_tests/routing_test_tools.cpp b/routing/routing_integration_tests/routing_test_tools.cpp index f55eab5f62..c570bd9eb4 100644 --- a/routing/routing_integration_tests/routing_test_tools.cpp +++ b/routing/routing_integration_tests/routing_test_tools.cpp @@ -39,6 +39,7 @@ #include #include #include +#include using namespace routing; using namespace routing_test; @@ -159,6 +160,20 @@ TRouteResult CalculateRoute(IRouterComponents const & routerComponents, RouterResultCode result = routerComponents.GetRouter().CalculateRoute( Checkpoints(startPoint, finalPoint), startDirection, false /* adjust */, delegate, *route); ASSERT(route, ()); + routerComponents.GetRouter().SetGuides({}); + return TRouteResult(route, result); +} + +TRouteResult CalculateRoute(IRouterComponents const & routerComponents, + Checkpoints const & checkpoints, GuidesTracks && guides) +{ + RouterDelegate delegate; + shared_ptr route = make_shared("mapsme", 0 /* route id */); + routerComponents.GetRouter().SetGuides(move(guides)); + RouterResultCode result = routerComponents.GetRouter().CalculateRoute( + checkpoints, m2::PointD::Zero() /* startDirection */, false /* adjust */, delegate, *route); + ASSERT(route, ()); + routerComponents.GetRouter().SetGuides({}); return TRouteResult(route, result); } diff --git a/routing/routing_integration_tests/routing_test_tools.hpp b/routing/routing_integration_tests/routing_test_tools.hpp index ccf915d26f..682daefb0f 100644 --- a/routing/routing_integration_tests/routing_test_tools.hpp +++ b/routing/routing_integration_tests/routing_test_tools.hpp @@ -109,6 +109,9 @@ TRouteResult CalculateRoute(IRouterComponents const & routerComponents, m2::PointD const & startPoint, m2::PointD const & startDirection, m2::PointD const & finalPoint); +TRouteResult CalculateRoute(IRouterComponents const & routerComponents, + Checkpoints const & checkpoints, GuidesTracks && guides); + void TestTurnCount(Route const & route, uint32_t expectedTurnCount); /// Testing route length. diff --git a/routing/routing_tests/CMakeLists.txt b/routing/routing_tests/CMakeLists.txt index 45cebce6e1..2ef6c53a3d 100644 --- a/routing/routing_tests/CMakeLists.txt +++ b/routing/routing_tests/CMakeLists.txt @@ -15,6 +15,7 @@ set( edge_estimator_tests.cpp fake_graph_test.cpp followed_polyline_test.cpp + guides_tests.cpp index_graph_test.cpp index_graph_tools.cpp index_graph_tools.hpp diff --git a/routing/routing_tests/async_router_test.cpp b/routing/routing_tests/async_router_test.cpp index 0b0fd8f26e..0d0cf7b840 100644 --- a/routing/routing_tests/async_router_test.cpp +++ b/routing/routing_tests/async_router_test.cpp @@ -36,6 +36,7 @@ public: // IRouter overrides: string GetName() const override { return "Dummy"; } + void SetGuides(GuidesTracks && /* guides */) override {} RouterResultCode CalculateRoute(Checkpoints const & checkpoints, m2::PointD const & startDirection, bool adjustToPrevRoute, RouterDelegate const & delegate, Route & route) override diff --git a/routing/routing_tests/fake_graph_test.cpp b/routing/routing_tests/fake_graph_test.cpp index 75827e2f13..85c244bdc3 100644 --- a/routing/routing_tests/fake_graph_test.cpp +++ b/routing/routing_tests/fake_graph_test.cpp @@ -1,6 +1,10 @@ #include "testing/testing.hpp" +#include "routing/fake_feature_ids.hpp" #include "routing/fake_graph.hpp" +#include "routing/segment.hpp" + +#include "routing_common/num_mwm_id.hpp" #include "geometry/point2d.hpp" @@ -12,13 +16,21 @@ using namespace std; namespace { +Segment GetSegment(uint32_t segmentIdx, bool isReal = false) +{ + static NumMwmId constexpr kFakeNumMwmId = std::numeric_limits::max(); + static uint32_t constexpr kFakeFeatureId = FakeFeatureIds::kIndexGraphStarterId; + if (isReal) + return Segment(0 /* mwmId */, 0 /* featureId */, segmentIdx, true /* isForward */); + return Segment(kFakeNumMwmId, kFakeFeatureId, segmentIdx, true /* isForward */); +} // Constructs simple fake graph where vertex (i + 1) is child of vertex (i) with |numFake| fake // vertices and |numReal| real vertices. Checks vetex-to-segment, segment-to-vertex, fake-to-real, // real-to-fake mappings for each vertex. Checks ingoing and outgoing sets. -FakeGraph +FakeGraph ConstructFakeGraph(uint32_t numerationStart, uint32_t numFake, uint32_t numReal) { - FakeGraph fakeGraph; + FakeGraph fakeGraph; TEST_EQUAL(fakeGraph.GetSize(), 0, ("Constructed fake graph not empty")); if (numFake < 1) @@ -28,19 +40,19 @@ ConstructFakeGraph(uint32_t numerationStart, uint32_t numFake, uint32_t numReal) return fakeGraph; } - int32_t const startSegment = numerationStart; - auto const startVertex = m2::PointD(numerationStart, numerationStart); + auto const startSegment = GetSegment(numerationStart); + m2::PointD const startVertex(numerationStart, numerationStart); fakeGraph.AddStandaloneVertex(startSegment, startVertex); // Add pure fake. for (uint32_t prevNumber = numerationStart; prevNumber + 1 < numerationStart + numFake + numReal; ++prevNumber) { - bool const newIsReal = prevNumber + 1 < numerationStart + numFake ? false : true; - int32_t const prevSegment = prevNumber; - int32_t const newSegment = prevNumber + 1; - auto const newVertex = m2::PointD(prevNumber + 1, prevNumber + 1); - int32_t const realSegment = -(prevNumber + 1); + bool const newIsReal = prevNumber + 1 >= numerationStart + numFake; + auto const prevSegment = GetSegment(prevNumber); + auto const newSegment = GetSegment(prevNumber + 1); + m2::PointD const newVertex(prevNumber + 1, prevNumber + 1); + auto const realSegment = GetSegment(prevNumber + 1, true /* isReal */); fakeGraph.AddVertex(prevSegment, newSegment, newVertex, true /* isOutgoing */, newIsReal /* isPartOfReal */, realSegment); @@ -48,21 +60,21 @@ ConstructFakeGraph(uint32_t numerationStart, uint32_t numFake, uint32_t numReal) // Test segment to vertex mapping. TEST_EQUAL(fakeGraph.GetVertex(newSegment), newVertex, ("Wrong segment to vertex mapping.")); // Test outgoing edge. - TEST_EQUAL(fakeGraph.GetEdges(newSegment, false /* isOutgoing */), set{prevSegment}, + TEST_EQUAL(fakeGraph.GetEdges(newSegment, false /* isOutgoing */), set{prevSegment}, ("Wrong ingoing edges set.")); // Test ingoing edge. - TEST_EQUAL(fakeGraph.GetEdges(prevSegment, true /* isOutgoing */), set{newSegment}, + TEST_EQUAL(fakeGraph.GetEdges(prevSegment, true /* isOutgoing */), set{newSegment}, ("Wrong ingoing edges set.")); // Test graph size TEST_EQUAL(fakeGraph.GetSize() + numerationStart, prevNumber + 2, ("Wrong fake graph size.")); // Test fake to real and real to fake mapping. - int32_t realFound; + Segment realFound; if (newIsReal) { TEST_EQUAL(fakeGraph.FindReal(newSegment, realFound), true, ("Unexpected real segment found.")); TEST_EQUAL(realSegment, realFound, ("Wrong fake to real mapping.")); - TEST_EQUAL(fakeGraph.GetFake(realSegment), set{newSegment}, + TEST_EQUAL(fakeGraph.GetFake(realSegment), set{newSegment}, ("Unexpected fake segment found.")); } else @@ -79,7 +91,7 @@ ConstructFakeGraph(uint32_t numerationStart, uint32_t numFake, uint32_t numReal) namespace routing { // Test constructs two fake graphs, performs checks during construction, merges graphs -// using FakeGraph::Append and checks topology of merged graph. +// Calls FakeGraph::Append and checks topology of the merged graph. UNIT_TEST(FakeGraphTest) { uint32_t const fake0 = 5; @@ -99,8 +111,8 @@ UNIT_TEST(FakeGraphTest) // Test merged graph. for (uint32_t i = 0; i + 1 < fakeGraph0.GetSize(); ++i) { - int32_t const segmentFrom = i; - int32_t const segmentTo = i + 1; + auto const segmentFrom = GetSegment(i); + auto const segmentTo = GetSegment(i + 1); TEST_EQUAL(fakeGraph0.GetVertex(segmentFrom), m2::PointD(i, i), ("Wrong segment to vertex mapping.")); TEST_EQUAL(fakeGraph0.GetVertex(segmentTo), m2::PointD(i + 1, i + 1), ("Wrong segment to vertex mapping.")); @@ -114,10 +126,10 @@ UNIT_TEST(FakeGraphTest) } else { - TEST_EQUAL(fakeGraph0.GetEdges(segmentFrom, true /* isOutgoing */), set{segmentTo}, + TEST_EQUAL(fakeGraph0.GetEdges(segmentFrom, true /* isOutgoing */), set{segmentTo}, ("Wrong ingoing edges set.")); TEST_EQUAL(fakeGraph0.GetEdges(segmentTo, false /* isOutgoing */), - set{segmentFrom}, ("Wrong ingoing edges set.")); + set{segmentFrom}, ("Wrong ingoing edges set.")); } } }