Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Byko-Ianko <v.bykoianko@corp.mail.ru>2015-02-06 17:07:00 +0300
committerAlex Zolotarev <alex@maps.me>2015-09-23 02:37:32 +0300
commit33e6349c122f4f886ddf830fd94aeeb94be63b19 (patch)
tree342614a334d134cbfb4ff9e97f1a96fdf2f3f6d9
parent5ebba22d264f9b816644916e67c23a10ecf425a7 (diff)
Integration tests implementation
-rw-r--r--integration_tests/integration_tests.pro32
-rw-r--r--integration_tests/osrm_route_test.cpp22
-rw-r--r--integration_tests/osrm_test_tools.cpp221
-rw-r--r--integration_tests/osrm_test_tools.hpp58
-rw-r--r--integration_tests/osrm_turn_test.cpp50
-rw-r--r--omim.pro3
-rw-r--r--routing/osrm_router.hpp10
-rw-r--r--routing/route.hpp1
-rw-r--r--std/new.hpp15
9 files changed, 411 insertions, 1 deletions
diff --git a/integration_tests/integration_tests.pro b/integration_tests/integration_tests.pro
new file mode 100644
index 0000000000..5babe1bf5e
--- /dev/null
+++ b/integration_tests/integration_tests.pro
@@ -0,0 +1,32 @@
+# This subproject implements integration tests.
+# This tests are launched on the whole world dataset.
+
+# It is recommended to place tests here in the following cases:
+# - tests are written to be launch on the whole world dataset;
+# - tests covers significant number of subsystems;
+
+TARGET = integration_tests
+CONFIG += console warn_on
+CONFIG -= app_bundle
+TEMPLATE = app
+
+ROOT_DIR = ../
+DEPENDENCIES = map routing search storage indexer platform geometry coding base osrm jansson protobuf tomcrypt
+
+macx-*: LIBS *= "-framework Foundation" "-framework IOKit"
+
+include($$ROOT_DIR/common.pri)
+
+QT *= core
+
+win32* : LIBS *= -lShell32
+
+
+SOURCES += \
+ ../testing/testingmain.cpp \
+ osrm_route_test.cpp \
+ osrm_turn_test.cpp \
+ osrm_test_tools.cpp \
+
+HEADERS += \
+ osrm_test_tools.hpp \
diff --git a/integration_tests/osrm_route_test.cpp b/integration_tests/osrm_route_test.cpp
new file mode 100644
index 0000000000..745b279785
--- /dev/null
+++ b/integration_tests/osrm_route_test.cpp
@@ -0,0 +1,22 @@
+#include "../../testing/testing.hpp"
+
+#include "osrm_test_tools.hpp"
+
+using namespace routing;
+
+namespace
+{
+ UNIT_TEST(RussiaMoscowLenigradskiy39GerPanfilovtsev22RouteTest)
+ {
+ shared_ptr<integration::OsrmRouterComponents> routerComponents = integration::GetAllMaps();
+ TEST(integration::CalculateRouteAndTestRouteLength(routerComponents, {37.53758809983519, 67.536162466434234},
+ {0., 0.}, {37.40993977728661, 67.644784047393685}, 14296.), ());
+ }
+
+ UNIT_TEST(RussiaMoscowGerPanfilovtsev22SolodshaPravdiRouteTest)
+ {
+ shared_ptr<integration::OsrmRouterComponents> routerComponents = integration::GetAllMaps();
+ TEST(integration::CalculateRouteAndTestRouteLength(routerComponents, {37.409929478750627, 67.644798619710073},
+ {0., 0.}, {39.836562407458047, 65.774372510437971}, 253275.), ());
+ }
+}
diff --git a/integration_tests/osrm_test_tools.cpp b/integration_tests/osrm_test_tools.cpp
new file mode 100644
index 0000000000..7291d4335e
--- /dev/null
+++ b/integration_tests/osrm_test_tools.cpp
@@ -0,0 +1,221 @@
+#include "osrm_test_tools.hpp"
+
+#include "../std/new.hpp"
+
+#include "../indexer/index.hpp"
+
+#include "../geometry/distance_on_sphere.hpp"
+
+#include "../routing/route.hpp"
+
+#include "../map/feature_vec_model.hpp"
+
+#include "../platform/platform.hpp"
+#include "../platform/preferred_languages.hpp"
+
+#include "../search/search_engine.hpp"
+
+
+using namespace routing;
+
+namespace integration
+{
+ class OsrmRouterWrapper : public OsrmRouter
+ {
+ public:
+ OsrmRouterWrapper(Index const * index, CountryFileFnT const & fn) :
+ OsrmRouter(index, fn) {}
+ ResultCode SyncCalculateRoute(m2::PointD const & startPt, m2::PointD const & startDr, m2::PointD const & finalPt, Route & route)
+ {
+ m_startPt = startPt;
+ m_startDr = startDr;
+ m_finalPt = finalPt;
+ m_cachedFinalNodes.clear();
+ m_isFinalChanged = false;
+ m_requestCancel = false;
+
+ return OsrmRouter::CalculateRouteImpl(startPt, startDr, finalPt, route);
+ }
+ };
+
+ shared_ptr<search::Engine> CreateSearchEngine(search::Engine::IndexType const * pIndex)
+ {
+ ASSERT(pIndex, ());
+ Platform const & pl = GetPlatform();
+ try
+ {
+ shared_ptr<search::Engine> searchEngine(new search::Engine(
+ pIndex,
+ pl.GetReader(SEARCH_CATEGORIES_FILE_NAME),
+ pl.GetReader(PACKED_POLYGONS_FILE),
+ pl.GetReader(COUNTRIES_FILE),
+ languages::GetCurrentOrig()));
+ return searchEngine;
+ }
+ catch (RootException const &)
+ {
+ ASSERT(false, ());
+ return nullptr;
+ }
+ }
+
+ shared_ptr<model::FeaturesFetcher> CreateFeaturesFetcher(vector<string> const & mapNames)
+ {
+ shared_ptr<model::FeaturesFetcher> featuresFetcher(new model::FeaturesFetcher);
+ featuresFetcher->InitClassificator();
+
+ for (auto const mapName : mapNames)
+ {
+ if (featuresFetcher->AddMap(mapName) == -1)
+ {
+ ASSERT(false, ());
+ return nullptr;
+ }
+ }
+ return featuresFetcher;
+ }
+
+ shared_ptr<search::Engine> CreateSearchEngine(shared_ptr<model::FeaturesFetcher> featuresFetcher)
+ {
+ shared_ptr<search::Engine> searchEngine = CreateSearchEngine(&featuresFetcher->GetIndex());
+ if (!searchEngine.get())
+ ASSERT(false, ());
+ return searchEngine;
+ }
+
+ shared_ptr<OsrmRouterWrapper> CreateOsrmRouter(shared_ptr<model::FeaturesFetcher> featuresFetcher,
+ shared_ptr<search::Engine> searchEngine)
+ {
+ shared_ptr<OsrmRouterWrapper> osrmRouter(new OsrmRouterWrapper(&featuresFetcher->GetIndex(),
+ [searchEngine] (m2::PointD const & pt)
+ {
+ return searchEngine->GetCountryFile(pt);
+ }));
+ return osrmRouter;
+ }
+
+ class OsrmRouterComponents
+ {
+ public:
+ OsrmRouterComponents(vector<string> const & mapNames) :
+ m_featuresFetcher(CreateFeaturesFetcher(mapNames)),
+ m_searchEngine(CreateSearchEngine(m_featuresFetcher)),
+ m_osrmRouter(CreateOsrmRouter(m_featuresFetcher, m_searchEngine)) {}
+ OsrmRouterWrapper * GetOsrmRouter() const { return m_osrmRouter.get(); }
+ private:
+ shared_ptr<model::FeaturesFetcher> m_featuresFetcher;
+ shared_ptr<search::Engine> m_searchEngine;
+ shared_ptr<OsrmRouterWrapper> m_osrmRouter;
+ };
+
+ void GetMapNames(vector<string> & maps)
+ {
+ Platform const & pl = GetPlatform();
+
+ pl.GetFilesByExt(pl.ResourcesDir(), DATA_FILE_EXTENSION, maps);
+ pl.GetFilesByExt(pl.WritableDir(), DATA_FILE_EXTENSION, maps);
+
+ sort(maps.begin(), maps.end());
+ maps.erase(unique(maps.begin(), maps.end()), maps.end());
+ }
+
+ shared_ptr<OsrmRouterComponents> LoadMaps(vector<string> const & mapNames)
+ {
+ try{
+ return shared_ptr<OsrmRouterComponents>(new OsrmRouterComponents(mapNames));
+ }
+ catch(bad_alloc &)
+ {
+ ASSERT(false, ());
+ return nullptr;
+ }
+ }
+
+ shared_ptr<OsrmRouterComponents> LoadAllMaps()
+ {
+ vector<string> maps;
+ GetMapNames(maps);
+ ASSERT(!maps.empty(), ());
+ return LoadMaps(maps);
+ }
+
+ shared_ptr<OsrmRouterComponents> GetAllMaps()
+ {
+ static shared_ptr<OsrmRouterComponents> inst = LoadAllMaps();
+ ASSERT(inst.get(), ());
+ return inst;
+ }
+
+ RouteResultT CalculateRoute(shared_ptr<OsrmRouterComponents> routerComponents,
+ m2::PointD const & startPt, m2::PointD const & startDr, m2::PointD const & finalPt)
+ {
+ try
+ {
+ ASSERT(routerComponents.get(), ());
+ OsrmRouterWrapper * osrmRouter = routerComponents->GetOsrmRouter();
+ ASSERT(osrmRouter, ());
+ shared_ptr<Route> route(new Route("mapsme"));
+ OsrmRouter::ResultCode result = osrmRouter->SyncCalculateRoute(startPt, startDr, finalPt, *route.get());
+ return RouteResultT(route, result);
+ }
+ catch(bad_alloc &)
+ {
+ ASSERT(false, ());
+ return RouteResultT(nullptr, OsrmRouter::InternalError);
+ }
+ }
+
+ bool TestTurn(shared_ptr<Route> const route, uint32_t etalonTurnNumber, m2::PointD const & etalonTurnPnt,
+ turns::TurnDirection etalonTurnDirection, uint32_t etalonRoundAboutExitNum)
+ {
+ ASSERT(route.get(), ());
+ turns::TurnsGeomT const & turnsGeom = route->GetTurnsGeometry();
+ if (etalonTurnNumber >= turnsGeom.size())
+ return false;
+
+ Route::TurnsT const & turns = route->GetTurns();
+ ASSERT_LESS(etalonTurnNumber, turns.size(), ());
+ Route::TurnItem const & turn = turns[etalonTurnNumber];
+ if (turn.m_turn != etalonTurnDirection)
+ return false;
+ if (turn.m_exitNum != etalonRoundAboutExitNum)
+ return false;
+
+ turns::TurnGeom const & turnGeom = turnsGeom[etalonTurnNumber];
+ ASSERT_LESS(turnGeom.m_turnIndex, turnGeom.m_points.size(), ());
+ m2::PointD turnGeomPnt = turnGeom.m_points[turnGeom.m_turnIndex];
+
+ double const dist = ms::DistanceOnEarth(etalonTurnPnt.y, etalonTurnPnt.x, turnGeomPnt.y, turnGeomPnt.x);
+ if (dist > turnInaccuracy)
+ return false;
+ return true;
+ }
+
+ bool TestTurnCount(shared_ptr<routing::Route> const route, uint32_t etalonTurnCount)
+ {
+ ASSERT(route.get(), ());
+ return route->GetTurnsGeometry().size() == etalonTurnCount;
+ }
+
+ bool TestRouteLength(shared_ptr<Route> const route, double etalonRouteLength)
+ {
+ ASSERT(route.get(), ());
+ double const delta = etalonRouteLength * routeLengthInaccurace;
+ double const routeLength = route->GetDistance();
+ if (routeLength - delta <= etalonRouteLength && routeLength + delta >= etalonRouteLength)
+ return true;
+ else
+ return false;
+ }
+
+ bool CalculateRouteAndTestRouteLength(shared_ptr<OsrmRouterComponents> routerComponents, m2::PointD const & startPt,
+ m2::PointD const & startDr, m2::PointD const & finalPt, double etalonRouteLength)
+ {
+ RouteResultT routeResult = CalculateRoute(routerComponents, startPt, startDr, finalPt);
+ shared_ptr<Route> const route = routeResult.first;
+ OsrmRouter::ResultCode const result = routeResult.second;
+ if (result != OsrmRouter::NoError)
+ return false;
+ return TestRouteLength(route, etalonRouteLength);
+ }
+}
diff --git a/integration_tests/osrm_test_tools.hpp b/integration_tests/osrm_test_tools.hpp
new file mode 100644
index 0000000000..476a271f71
--- /dev/null
+++ b/integration_tests/osrm_test_tools.hpp
@@ -0,0 +1,58 @@
+#pragma once
+
+#include "../std/shared_ptr.hpp"
+#include "../std/string.hpp"
+#include "../std/vector.hpp"
+
+#include "../routing/osrm_router.hpp"
+
+/*
+ * These tests are developed to simplify routing integration tests writing.
+ * You can use the interface bellow however you want but there are some hints.
+ * 1. Most likely you want to use GetAllMaps() to get shared_ptr<OsrmRouterComponents>.
+ * It loads all the maps from directories Platform::WritableDir()
+ * and Platform::ResourcesDir() only once and then reuse it.
+ * Use LoadMaps() only if you want to test something on a special map set.
+ * 2. Loading maps and calculating routes is a time consumption process.
+ * Do this only if you really need it.
+ * 3. If you want to check that a turn is absent use TestTurnCount.
+ * 4. The easiest way to gather all the information for writing an integration test is
+ * - to put a break point in OsrmRouter::CalculateRouteImpl;
+ * - to make a route with MapWithMe desktop application;
+ * - to get all necessary parameters and result of route calculation;
+ * - to place them into the test you're writing.
+ * 5. The recommended way for naming tests for route from one place to another one is
+ * <Country><City><Street1><House1><Street2><House2><Test time. TurnTest or RouteTest for the time being>
+ */
+
+/// Inaccuracy of turn point in meters
+double const turnInaccuracy = 2.;
+/// Inaccurace of the route length. It is used for checking if routes have etalon(sample) length.
+/// So the a created route has etalon length if
+/// etalonLength - etalonRouteLength * routeLengthInaccurace <= route->GetDistance()
+/// && etalonRouteLength + etalonRouteLength * routeLengthInaccurace >= route->GetDistance()
+/// is equal to true.
+double const routeLengthInaccurace = .01;
+
+typedef pair<shared_ptr<routing::Route>, routing::OsrmRouter::ResultCode> RouteResultT;
+
+namespace integration
+{
+ class OsrmRouterComponents;
+
+ shared_ptr<OsrmRouterComponents> GetAllMaps();
+ shared_ptr<OsrmRouterComponents> LoadMaps(vector<string> const & mapNames);
+
+ RouteResultT CalculateRoute(shared_ptr<OsrmRouterComponents> routerComponents,
+ m2::PointD const & startPt, m2::PointD const & startDr, m2::PointD const & finalPt);
+
+ bool TestTurn(shared_ptr<routing::Route> const route, uint32_t etalonTurnNumber, m2::PointD const & etalonTurnPnt,
+ routing::turns::TurnDirection etalonTurnDirection, uint32_t etalonRoundAboutExitNum = 0);
+
+ bool TestTurnCount(shared_ptr<routing::Route> const route, uint32_t etalonTurnCount);
+
+ bool TestRouteLength(shared_ptr<routing::Route> const route, double etalonRouteLength);
+
+ bool CalculateRouteAndTestRouteLength(shared_ptr<OsrmRouterComponents> routerComponents, m2::PointD const & startPt,
+ m2::PointD const & startDr, m2::PointD const & finalPt, double etalonRouteLength);
+}
diff --git a/integration_tests/osrm_turn_test.cpp b/integration_tests/osrm_turn_test.cpp
new file mode 100644
index 0000000000..5c7ebde715
--- /dev/null
+++ b/integration_tests/osrm_turn_test.cpp
@@ -0,0 +1,50 @@
+#include "../../testing/testing.hpp"
+
+#include "osrm_test_tools.hpp"
+
+#include "../routing/route.hpp"
+
+using namespace routing;
+
+UNIT_TEST(RussiaMoscowLenigradskiy39UturnTurnTest)
+{
+ shared_ptr<integration::OsrmRouterComponents> routerComponents = integration::GetAllMaps();
+
+ RouteResultT const routeResult = integration::CalculateRoute(routerComponents, {37.537544383032568, 67.536216737893028},
+ {0., 0.}, {37.538908531885973, 67.54544090660923});
+
+ shared_ptr<Route> const route = routeResult.first;
+ OsrmRouter::ResultCode const result = routeResult.second;
+ TEST_EQUAL(result, OsrmRouter::NoError, ());
+
+ TEST(integration::TestTurn(route, 0, {37.545981835916507, 67.530713137468041}, turns::TurnLeft), ());
+ TEST(integration::TestTurn(route, 1, {37.546738218864334, 67.531659957257347}, turns::TurnLeft), ());
+ TEST(integration::TestTurn(route, 2, {37.539925407915746, 67.537083383925875}, turns::TurnRight), ());
+ TEST(!integration::TestTurn(route, 2, {37., 67.}, turns::TurnRight), ());
+
+ TEST(integration::TestRouteLength(route, 2033.), ());
+ TEST(!integration::TestRouteLength(route, 2533.), ());
+ TEST(!integration::TestRouteLength(route, 1533.), ());
+}
+
+UNIT_TEST(RussiaMoscowSalameiNerisUturnTurnTest)
+{
+ shared_ptr<integration::OsrmRouterComponents> routerComponents = integration::GetAllMaps();
+ RouteResultT const routeResult = integration::CalculateRoute(routerComponents, {37.395332276656617, 67.633925439079519},
+ {0., 0.}, {37.392503720352721, 67.61975260731343});
+ shared_ptr<Route> const route = routeResult.first;
+ OsrmRouter::ResultCode const result = routeResult.second;
+
+ TEST_EQUAL(result, OsrmRouter::NoError, ());
+
+ TEST(integration::TestTurn(route, 0, {37.388482521388539, 67.633382734905041}, turns::TurnSlightRight), ());
+ TEST(integration::TestTurn(route, 1, {37.387117276989784, 67.633369323859881}, turns::TurnLeft), ());
+ TEST(integration::TestTurn(route, 2, {37.387380133475205, 67.632781920081243}, turns::TurnLeft), ());
+ TEST(integration::TestTurn(route, 3, {37.390526364673121, 67.633106467374461}, turns::TurnRight), ());
+
+ TEST(integration::TestTurnCount(route, 4), ());
+
+ TEST(integration::TestRouteLength(route, 1637.), ());
+
+}
+
diff --git a/omim.pro b/omim.pro
index 61a094d44d..6ef70df949 100644
--- a/omim.pro
+++ b/omim.pro
@@ -43,7 +43,8 @@ SUBDIRS = 3party \
gui/gui_tests \
qt \
drape_head \
- map_server
+ map_server \
+ integration_tests \
} else:drape_device {
# libraries which are used on mobile devices with drape engine
SUBDIRS = 3party \
diff --git a/routing/osrm_router.hpp b/routing/osrm_router.hpp
index dd11b17c4d..a3918e5b30 100644
--- a/routing/osrm_router.hpp
+++ b/routing/osrm_router.hpp
@@ -22,6 +22,12 @@ struct PhantomNode;
struct PathData;
class FeatureType;
struct RawRouteData;
+
+namespace integration
+{
+ class OsrmRouterWrapper;
+}
+
namespace routing
{
@@ -131,6 +137,10 @@ public:
RoutingMappingPtrT GetMappingByName(string const & fName, Index const * pIndex);
+ friend class integration::OsrmRouterWrapper;
+ typedef function<string (m2::PointD const &)> CountryFileFnT;
+ CountryFileFnT m_countryFn;
+
void Clear()
{
m_mapping.clear();
diff --git a/routing/route.hpp b/routing/route.hpp
index 02beffc70e..f415d6e721 100644
--- a/routing/route.hpp
+++ b/routing/route.hpp
@@ -78,6 +78,7 @@ public:
string const & GetRouterId() const { return m_router; }
m2::PolylineD const & GetPoly() const { return m_poly; }
turns::TurnsGeomT const & GetTurnsGeometry() const { return m_turnsGeom; }
+ TurnsT const & GetTurns() const { return m_turns; }
string const & GetName() const { return m_name; }
bool IsValid() const { return (m_poly.GetSize() > 1); }
diff --git a/std/new.hpp b/std/new.hpp
new file mode 100644
index 0000000000..fc519b585f
--- /dev/null
+++ b/std/new.hpp
@@ -0,0 +1,15 @@
+#pragma once
+#include "common_defines.hpp"
+
+#ifdef new
+#undef new
+#endif
+
+#include <new>
+
+using std::bad_alloc;
+using std::bad_array_new_length;
+
+#ifdef DEBUG_NEW
+#define new DEBUG_NEW
+#endif