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

routing_test_tools.hpp « routing_integration_tests « routing - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2b284bc71c88305d3549c34b1f997a7bca60734a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#pragma once

#include "routing/index_router.hpp"
#include "routing/routing_callbacks.hpp"

#include "storage/country_info_getter.hpp"

#include "map/feature_vec_model.hpp"

#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"

/*
 * 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 GetCarComponents() or GetPedestrianComponents() without parameter
 *    to get a reference to IRouterComponents.
 *    It loads all the maps from directories Platform::WritableDir()
 *    and Platform::ResourcesDir() only once and then reuse it.
 *    Use GetCarComponents() or GetPedestrianComponents() with vector of maps parameter
 *    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 CalculateRoute() method;
 *    - to make a route with MapWithMe desktop application;
 *    - to get all necessary parameters and result of the route calculation;
 *    - to place them into the test you're writing.
 * 5. The recommended way for naming tests for a route from one place to another one is
 *    <Country><City><Street1><House1><Street2><House2><Test time. TurnTest or RouteTest for the
 * time being>
 * 6. It's a good idea to use short routes for testing turns. The thing is geometry of long routes
 *    could be changed from one dataset to another. The shorter the route the less is the chance it's changed.
 */
using namespace routing;
using namespace turns;
using platform::LocalCountryFile;

typedef pair<shared_ptr<Route>, RouterResultCode> TRouteResult;

namespace integration
{
shared_ptr<model::FeaturesFetcher> CreateFeaturesFetcher(vector<LocalCountryFile> const & localFiles);

unique_ptr<storage::CountryInfoGetter> CreateCountryInfoGetter();

unique_ptr<IndexRouter> CreateVehicleRouter(DataSource & dataSource,
                                            storage::CountryInfoGetter const & infoGetter,
                                            traffic::TrafficCache const & trafficCache,
                                            vector<LocalCountryFile> const & localFiles,
                                            VehicleType vehicleType);

class IRouterComponents
{
public:
  IRouterComponents(vector<LocalCountryFile> const & localFiles)
    : m_featuresFetcher(CreateFeaturesFetcher(localFiles)), m_infoGetter(CreateCountryInfoGetter())
  {
  }

  virtual ~IRouterComponents() = default;

  virtual IRouter & GetRouter() const = 0;

  storage::CountryInfoGetter const & GetCountryInfoGetter() const noexcept { return *m_infoGetter; }

protected:
  shared_ptr<model::FeaturesFetcher> m_featuresFetcher;
  unique_ptr<storage::CountryInfoGetter> m_infoGetter;
};

class VehicleRouterComponents : public IRouterComponents
{
public:
  VehicleRouterComponents(vector<LocalCountryFile> const & localFiles, VehicleType vehicleType)
    : IRouterComponents(localFiles)
    , m_indexRouter(CreateVehicleRouter(m_featuresFetcher->GetDataSource(), *m_infoGetter, m_trafficCache,
                                        localFiles, vehicleType))
  {
  }

  IRouter & GetRouter() const override { return *m_indexRouter; }

private:
  traffic::TrafficCache m_trafficCache;
  unique_ptr<IndexRouter> m_indexRouter;
};

void GetAllLocalFiles(vector<LocalCountryFile> & localFiles);
void TestOnlineCrosses(ms::LatLon const & startPoint, ms::LatLon const & finalPoint,
                       vector<string> const & expected, IRouterComponents & routerComponents);
void TestOnlineFetcher(ms::LatLon const & startPoint, ms::LatLon const & finalPoint,
                       vector<string> const & expected, IRouterComponents & routerComponents);

shared_ptr<VehicleRouterComponents> CreateAllMapsComponents(VehicleType vehicleType);

template <VehicleType type>
IRouterComponents & GetVehicleComponents()
{
  static auto const instance = CreateAllMapsComponents(type);
  ASSERT(instance, ());
  return *instance;
}

TRouteResult CalculateRoute(IRouterComponents const & routerComponents,
                            m2::PointD const & startPoint, m2::PointD const & startDirection,
                            m2::PointD const & finalPoint);

void TestTurnCount(Route const & route, uint32_t expectedTurnCount);

/// Testing route length.
/// It is used for checking if routes have expected(sample) length.
/// A created route will pass the test iff
/// expectedRouteMeters - expectedRouteMeters * relativeError  <= route->GetDistance()
/// && expectedRouteMeters + expectedRouteMeters * relativeError >= route->GetDistance()
void TestRouteLength(Route const & route, double expectedRouteMeters, double relativeError = 0.01);
void TestRouteTime(Route const & route, double expectedRouteSeconds, double relativeError = 0.01);
void TestRoutePointsNumber(Route const & route, size_t expectedPointsNumber,
                           double relativeError = 0.1);

void CalculateRouteAndTestRouteLength(IRouterComponents const & routerComponents,
                                      m2::PointD const & startPoint,
                                      m2::PointD const & startDirection,
                                      m2::PointD const & finalPoint, double expectedRouteMeters,
                                      double relativeError = 0.07);

class TestTurn
{
  friend TestTurn GetNthTurn(Route const & route, uint32_t turnNumber);

  m2::PointD const m_point;
  CarDirection const m_direction;
  uint32_t const m_roundAboutExitNum;
  bool const m_isValid;

  TestTurn()
    : m_point({0.0, 0.0})
    , m_direction(CarDirection::None)
    , m_roundAboutExitNum(0)
    , m_isValid(false)
  {
  }
  TestTurn(m2::PointD const & pnt, CarDirection direction, uint32_t roundAboutExitNum)
    : m_point(pnt), m_direction(direction), m_roundAboutExitNum(roundAboutExitNum), m_isValid(true)
  {
  }

public:
  const TestTurn & TestValid() const;
  const TestTurn & TestNotValid() const;
  const TestTurn & TestPoint(m2::PointD const & expectedPoint, double inaccuracyMeters = 3.) const;
  const TestTurn & TestDirection(CarDirection expectedDirection) const;
  const TestTurn & TestOneOfDirections(set<CarDirection> const & expectedDirections) const;
  const TestTurn & TestRoundAboutExitNum(uint32_t expectedRoundAboutExitNum) const;
};

/// Extracting appropriate TestTurn if any. If not TestTurn::isValid() returns false.
/// inaccuracy is set in meters.
TestTurn GetNthTurn(Route const & route, uint32_t turnNumber);

void TestCurrentStreetName(routing::Route const & route, string const & expectedStreetName);

void TestNextStreetName(routing::Route const & route, string const & expectedStreetName);
}  // namespace integration