From 7feb03f7d47068e7c5e7ae0002bb91f4ec206f37 Mon Sep 17 00:00:00 2001 From: Mikhail Gorbushin Date: Thu, 10 Jan 2019 13:17:50 +0300 Subject: [PATCH] [routing] Fix crash because of transit cross mwm section, add routing_integration_tests for transit case, small refact routing_test_tools --- routing/cross_mwm_index_graph.hpp | 5 +- .../routing_integration_tests/CMakeLists.txt | 1 + .../routing_test_tools.cpp | 59 ++++++- .../routing_test_tools.hpp | 14 +- .../transit_route_test.cpp | 162 ++++++++++++++++++ 5 files changed, 231 insertions(+), 10 deletions(-) create mode 100644 routing/routing_integration_tests/transit_route_test.cpp diff --git a/routing/cross_mwm_index_graph.hpp b/routing/cross_mwm_index_graph.hpp index 979a30a2bc..8986a7224f 100644 --- a/routing/cross_mwm_index_graph.hpp +++ b/routing/cross_mwm_index_graph.hpp @@ -120,7 +120,7 @@ public: // There are same in common, but in case of different version of mwms // their's geometry can differ from each other. Because of this we can not // build the route, because we fail in astar_algorithm.hpp CHECK(invariant) sometimes. - if (s.IsRealSegment() || SegmentsAreEqualByGeometry(s, *twinSeg)) + if (SegmentsAreEqualByGeometry(s, *twinSeg)) twins.push_back(*twinSeg); else LOG(LINFO, ("Bad cross mwm feature, differ in geometry. Current:", s, ", twin:", *twinSeg)); @@ -188,6 +188,9 @@ private: /// \brief Checks segment for equality point by point. bool SegmentsAreEqualByGeometry(Segment const & one, Segment const & two) { + if (!one.IsRealSegment() || !two.IsRealSegment()) + return true; + std::vector geometryOne = GetFeaturePointsBySegment(one); std::vector geometryTwo = GetFeaturePointsBySegment(two); diff --git a/routing/routing_integration_tests/CMakeLists.txt b/routing/routing_integration_tests/CMakeLists.txt index b6ab0bb996..973091ae13 100644 --- a/routing/routing_integration_tests/CMakeLists.txt +++ b/routing/routing_integration_tests/CMakeLists.txt @@ -20,6 +20,7 @@ set( routing_test_tools.hpp speed_camera_notifications_tests.cpp street_names_test.cpp + transit_route_test.cpp turn_test.cpp ) diff --git a/routing/routing_integration_tests/routing_test_tools.cpp b/routing/routing_integration_tests/routing_test_tools.cpp index 75304b1b42..db25257e2a 100644 --- a/routing/routing_integration_tests/routing_test_tools.cpp +++ b/routing/routing_integration_tests/routing_test_tools.cpp @@ -29,11 +29,10 @@ #include "base/math.hpp" -#include "std/functional.hpp" -#include "std/limits.hpp" - #include "private.h" +#include +#include #include #include @@ -341,6 +340,60 @@ void TestOnlineCrosses(ms::LatLon const & startPoint, ms::LatLon const & finalPo ("Can't find ", mwmName)); foundMwms.insert(mwmName); } + TEST_EQUAL(expected.size(), foundMwms.size(), ()); } + +bool IsSubwayExists(Route const & route) +{ + auto const & routeSegments = route.GetRouteSegments(); + + bool intoSubway = false; + bool wasSubway = false; + + for (auto const & routeSegment : routeSegments) + { + if (!routeSegment.HasTransitInfo()) + { + intoSubway = false; + continue; + } + + switch (routeSegment.GetTransitInfo().GetType()) + { + case TransitInfo::Type::Gate: + { + if (intoSubway) + { + // Out from subway + intoSubway = false; + wasSubway = true; + } + else + { + // Enter into subway + intoSubway = true; + } + break; + } + case TransitInfo::Type::Edge: + case TransitInfo::Type::Transfer: + break; + } + } + + return wasSubway; +} + +void CheckSubwayAbsent(Route const & route) +{ + bool wasSubway = IsSubwayExists(route); + TEST(!wasSubway, ("Find subway subpath into route.")); +} + +void CheckSubwayExistence(Route const & route) +{ + bool wasSubway = IsSubwayExists(route); + TEST(wasSubway, ("Can not find subway subpath into route.")); +} } // namespace diff --git a/routing/routing_integration_tests/routing_test_tools.hpp b/routing/routing_integration_tests/routing_test_tools.hpp index 2b284bc71c..48640d06e6 100644 --- a/routing/routing_integration_tests/routing_test_tools.hpp +++ b/routing/routing_integration_tests/routing_test_tools.hpp @@ -9,12 +9,11 @@ #include "platform/local_country_file.hpp" -#include "std/set.hpp" -#include "std/shared_ptr.hpp" -#include "std/string.hpp" -#include "std/unique_ptr.hpp" -#include "std/utility.hpp" -#include "std/vector.hpp" +#include +#include +#include +#include +#include /* * These tests are developed to simplify routing integration tests writing. @@ -131,6 +130,9 @@ void CalculateRouteAndTestRouteLength(IRouterComponents const & routerComponents m2::PointD const & finalPoint, double expectedRouteMeters, double relativeError = 0.07); +void CheckSubwayExistence(Route const & route); +void CheckSubwayAbsent(Route const & route); + class TestTurn { friend TestTurn GetNthTurn(Route const & route, uint32_t turnNumber); diff --git a/routing/routing_integration_tests/transit_route_test.cpp b/routing/routing_integration_tests/transit_route_test.cpp new file mode 100644 index 0000000000..37b74e5468 --- /dev/null +++ b/routing/routing_integration_tests/transit_route_test.cpp @@ -0,0 +1,162 @@ +#include "testing/testing.hpp" + +#include "routing/routing_integration_tests/routing_test_tools.hpp" + +#include "geometry/mercator.hpp" + +using namespace routing; + +namespace +{ +UNIT_TEST(Moscow_CenterToKotelniki_CrossMwm) +{ + TRouteResult routeResult = + integration::CalculateRoute(integration::GetVehicleComponents(), + MercatorBounds::FromLatLon(55.75018, 37.60971), {0., 0.}, + MercatorBounds::FromLatLon(55.67245, 37.86130)); + TEST_EQUAL(routeResult.second, RouterResultCode::NoError, ()); + + integration::TestRouteLength(*routeResult.first, 22968.6); + + CHECK(routeResult.first, ()); + integration::CheckSubwayExistence(*routeResult.first); +} + +UNIT_TEST(Moscow_DubrovkaToTrtykovskya) +{ + TRouteResult routeResult = + integration::CalculateRoute(integration::GetVehicleComponents(), + MercatorBounds::FromLatLon(55.71813, 37.67756), {0., 0.}, + MercatorBounds::FromLatLon(55.74089, 37.62831)); + TEST_EQUAL(routeResult.second, RouterResultCode::NoError, ()); + + integration::TestRouteLength(*routeResult.first, 7622.19); + + CHECK(routeResult.first, ()); + integration::CheckSubwayExistence(*routeResult.first); +} + +UNIT_TEST(Moscow_NoSubwayTest) +{ + TRouteResult routeResult = + integration::CalculateRoute(integration::GetVehicleComponents(), + MercatorBounds::FromLatLon(55.73893, 37.62438), {0., 0.}, + MercatorBounds::FromLatLon(55.73470, 37.62617)); + TEST_EQUAL(routeResult.second, RouterResultCode::NoError, ()); + + integration::TestRouteLength(*routeResult.first, 604.847); + + CHECK(routeResult.first, ()); + integration::CheckSubwayAbsent(*routeResult.first); +} + +UNIT_TEST(Piter_FrunzenskyaToPlochadVosstaniya) +{ + TRouteResult routeResult = + integration::CalculateRoute(integration::GetVehicleComponents(), + MercatorBounds::FromLatLon(59.90511, 30.31425), {0., 0.}, + MercatorBounds::FromLatLon(59.93096, 30.35872)); + TEST_EQUAL(routeResult.second, RouterResultCode::NoError, ()); + + integration::TestRouteLength(*routeResult.first, 4952.43); + + CHECK(routeResult.first, ()); + integration::CheckSubwayExistence(*routeResult.first); +} + +UNIT_TEST(Piter_TooLongPedestrian) +{ + TRouteResult routeResult = + integration::CalculateRoute(integration::GetVehicleComponents(), + MercatorBounds::FromLatLon(59.90511, 30.31425), {0., 0.}, + MercatorBounds::FromLatLon(59.80677, 30.44749)); + + TEST_EQUAL(routeResult.second, RouterResultCode::TransitRouteNotFoundTooLongPedestrian, ()); +} + +UNIT_TEST(Vatikan_NotEnoughGraphDataAtThenEnd) +{ + TRouteResult routeResult = + integration::CalculateRoute(integration::GetVehicleComponents(), + MercatorBounds::FromLatLon(41.90052, 12.42642), {0., 0.}, + MercatorBounds::FromLatLon(41.90253, 12.45574)); + + // TODO (@gmoryes) here must be RouteNotFound. + TEST_EQUAL(routeResult.second, RouterResultCode::TransitRouteNotFoundTooLongPedestrian, ()); +} + +UNIT_TEST(Vatikan_CorneliaToOttaviano) +{ + TRouteResult routeResult = + integration::CalculateRoute(integration::GetVehicleComponents(), + MercatorBounds::FromLatLon(41.90052, 12.42642), {0., 0.}, + MercatorBounds::FromLatLon(41.90414, 12.45640)); + + TEST_EQUAL(routeResult.second, RouterResultCode::NoError, ()); + + integration::TestRouteLength(*routeResult.first, 4255.16); + + CHECK(routeResult.first, ()); + integration::CheckSubwayExistence(*routeResult.first); +} + +UNIT_TEST(London_PoplarToOval) +{ + TRouteResult routeResult = + integration::CalculateRoute(integration::GetVehicleComponents(), + MercatorBounds::FromLatLon(51.50818, -0.01634), {0., 0.}, + MercatorBounds::FromLatLon(51.48041, -0.10843)); + + TEST_EQUAL(routeResult.second, RouterResultCode::NoError, ()); + + integration::TestRouteLength(*routeResult.first, 9421.72); + + CHECK(routeResult.first, ()); + integration::CheckSubwayExistence(*routeResult.first); +} + +UNIT_TEST(London_DeptfordBridgeToCyprus) +{ + TRouteResult routeResult = + integration::CalculateRoute(integration::GetVehicleComponents(), + MercatorBounds::FromLatLon(51.47149, -0.030558), {0., 0.}, + MercatorBounds::FromLatLon(51.51242, 0.07101)); + + TEST_EQUAL(routeResult.second, RouterResultCode::NoError, ()); + + integration::TestRouteLength(*routeResult.first, 12293.4); + + CHECK(routeResult.first, ()); + integration::CheckSubwayExistence(*routeResult.first); +} + +UNIT_TEST(Vashington_FoggyToShaw) +{ + TRouteResult routeResult = + integration::CalculateRoute(integration::GetVehicleComponents(), + MercatorBounds::FromLatLon(38.89582, -77.04934), {0., 0.}, + MercatorBounds::FromLatLon(38.91516, -77.01513)); + + TEST_EQUAL(routeResult.second, RouterResultCode::NoError, ()); + + integration::TestRouteLength(*routeResult.first, 6102.92); + + CHECK(routeResult.first, ()); + integration::CheckSubwayExistence(*routeResult.first); +} + +UNIT_TEST(NewYork_GrassmereToPleasantPlains) +{ + TRouteResult routeResult = + integration::CalculateRoute(integration::GetVehicleComponents(), + MercatorBounds::FromLatLon(40.60536, -74.07736), {0., 0.}, + MercatorBounds::FromLatLon(40.53015, -74.21559)); + + TEST_EQUAL(routeResult.second, RouterResultCode::NoError, ()); + + integration::TestRouteLength(*routeResult.first, 17409.7); + + CHECK(routeResult.first, ()); + integration::CheckSubwayExistence(*routeResult.first); +} +} // namespace