Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
340
libs/routing/routing_integration_tests/routing_test_tools.cpp
Normal file
340
libs/routing/routing_integration_tests/routing_test_tools.cpp
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
#include "routing/routing_integration_tests/routing_test_tools.hpp"
|
||||
|
||||
#include "routing/routing_tests/index_graph_tools.hpp"
|
||||
|
||||
#include "testing/testing.hpp"
|
||||
|
||||
#include "map/features_fetcher.hpp"
|
||||
|
||||
#include "routing/index_router.hpp"
|
||||
#include "routing/route.hpp"
|
||||
#include "routing/router_delegate.hpp"
|
||||
#include "routing/routing_callbacks.hpp"
|
||||
|
||||
#include "storage/country_parent_getter.hpp"
|
||||
#include "storage/routing_helpers.hpp"
|
||||
|
||||
#include "indexer/data_source.hpp"
|
||||
|
||||
#include "platform/platform_tests_support/helpers.hpp"
|
||||
|
||||
#include "platform/local_country_file.hpp"
|
||||
#include "platform/local_country_file_utils.hpp"
|
||||
#include "platform/platform.hpp"
|
||||
|
||||
#include "geometry/distance_on_sphere.hpp"
|
||||
|
||||
#include "base/math.hpp"
|
||||
#include "base/stl_helpers.hpp"
|
||||
|
||||
namespace integration
|
||||
{
|
||||
using namespace routing;
|
||||
using namespace routing_test;
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
double constexpr kErrorMeters = 1.0;
|
||||
double constexpr kErrorSeconds = 1.0;
|
||||
} // namespace
|
||||
|
||||
shared_ptr<FeaturesFetcher> CreateFeaturesFetcher(vector<LocalCountryFile> const & localFiles)
|
||||
{
|
||||
size_t const maxOpenFileNumber = 4096;
|
||||
platform::tests_support::ChangeMaxNumberOfOpenFiles(maxOpenFileNumber);
|
||||
shared_ptr<FeaturesFetcher> featuresFetcher(new FeaturesFetcher);
|
||||
featuresFetcher->InitClassificator();
|
||||
|
||||
for (LocalCountryFile const & localFile : localFiles)
|
||||
featuresFetcher->RegisterMap(localFile);
|
||||
|
||||
return featuresFetcher;
|
||||
}
|
||||
|
||||
unique_ptr<storage::CountryInfoGetter> CreateCountryInfoGetter()
|
||||
{
|
||||
Platform const & platform = GetPlatform();
|
||||
return storage::CountryInfoReader::CreateCountryInfoGetter(platform);
|
||||
}
|
||||
|
||||
unique_ptr<IndexRouter> CreateVehicleRouter(DataSource & dataSource, storage::CountryInfoGetter const & infoGetter,
|
||||
traffic::TrafficCache const & trafficCache,
|
||||
vector<LocalCountryFile> const & localFiles, VehicleType vehicleType)
|
||||
{
|
||||
auto const countryFileGetter = [&infoGetter](m2::PointD const & pt) { return infoGetter.GetRegionCountryId(pt); };
|
||||
|
||||
auto const getMwmRectByName = [&infoGetter](string const & countryId) -> m2::RectD
|
||||
{ return infoGetter.GetLimitRectForLeaf(countryId); };
|
||||
|
||||
auto countryParentGetter = std::make_unique<storage::CountryParentGetter>();
|
||||
CHECK(countryParentGetter, ());
|
||||
|
||||
auto numMwmIds = make_shared<NumMwmIds>();
|
||||
for (auto const & f : localFiles)
|
||||
{
|
||||
auto const & countryFile = f.GetCountryFile();
|
||||
auto const mwmId = dataSource.GetMwmIdByCountryFile(countryFile);
|
||||
|
||||
if (!mwmId.IsAlive())
|
||||
continue;
|
||||
|
||||
if (countryParentGetter->GetStorageForTesting().IsLeaf(countryFile.GetName()))
|
||||
numMwmIds->RegisterFile(countryFile);
|
||||
}
|
||||
|
||||
// You should have at least one country file to make further tests.
|
||||
TEST(!numMwmIds->IsEmpty(), ());
|
||||
|
||||
bool const loadAltitudes = vehicleType != VehicleType::Car;
|
||||
auto indexRouter =
|
||||
make_unique<IndexRouter>(vehicleType, loadAltitudes, *countryParentGetter, countryFileGetter, getMwmRectByName,
|
||||
numMwmIds, MakeNumMwmTree(*numMwmIds, infoGetter), trafficCache, dataSource);
|
||||
|
||||
return indexRouter;
|
||||
}
|
||||
|
||||
void GetAllLocalFiles(vector<LocalCountryFile> & localFiles)
|
||||
{
|
||||
platform::FindAllLocalMapsAndCleanup(numeric_limits<int64_t>::max() /* latestVersion */, localFiles);
|
||||
|
||||
// Leave only real country files for routing test.
|
||||
localFiles.erase(std::remove_if(localFiles.begin(), localFiles.end(),
|
||||
[](LocalCountryFile const & file)
|
||||
{
|
||||
auto const & name = file.GetCountryName();
|
||||
return name == WORLD_FILE_NAME || name == WORLD_COASTS_FILE_NAME;
|
||||
}),
|
||||
localFiles.end());
|
||||
|
||||
for (auto & file : localFiles)
|
||||
file.SyncWithDisk();
|
||||
}
|
||||
|
||||
shared_ptr<VehicleRouterComponents> CreateAllMapsComponents(VehicleType vehicleType,
|
||||
std::set<std::string> const & skipMaps)
|
||||
{
|
||||
vector<LocalCountryFile> localFiles;
|
||||
GetAllLocalFiles(localFiles);
|
||||
base::EraseIf(localFiles,
|
||||
[&skipMaps](LocalCountryFile const & cf) { return skipMaps.count(cf.GetCountryName()) > 0; });
|
||||
TEST(!localFiles.empty(), ());
|
||||
|
||||
return make_shared<VehicleRouterComponents>(localFiles, vehicleType);
|
||||
}
|
||||
|
||||
IRouterComponents & GetVehicleComponents(VehicleType vehicleType)
|
||||
{
|
||||
static map<VehicleType, shared_ptr<VehicleRouterComponents>> kVehicleComponents;
|
||||
|
||||
auto it = kVehicleComponents.find(vehicleType);
|
||||
if (it == kVehicleComponents.end())
|
||||
tie(it, ignore) = kVehicleComponents.emplace(vehicleType, CreateAllMapsComponents(vehicleType, {}));
|
||||
|
||||
CHECK(it->second, ());
|
||||
return *(it->second);
|
||||
}
|
||||
|
||||
TRouteResult CalculateRoute(IRouterComponents const & routerComponents, m2::PointD const & startPoint,
|
||||
m2::PointD const & startDirection, m2::PointD const & finalPoint)
|
||||
{
|
||||
RouterDelegate delegate;
|
||||
shared_ptr<Route> route = make_shared<Route>("mapsme", 0 /* route id */);
|
||||
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> route = make_shared<Route>("mapsme", 0 /* route id */);
|
||||
routerComponents.GetRouter().SetGuides(std::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);
|
||||
}
|
||||
|
||||
void TestTurnCount(routing::Route const & route, uint32_t expectedTurnCount)
|
||||
{
|
||||
// We use -1 for ignoring the "ReachedYourDestination" turn record.
|
||||
vector<turns::TurnItem> turns;
|
||||
route.GetTurnsForTesting(turns);
|
||||
TEST_EQUAL(turns.size() - 1, expectedTurnCount, ());
|
||||
}
|
||||
|
||||
void TestTurns(Route const & route, vector<CarDirection> const & expectedTurns)
|
||||
{
|
||||
vector<turns::TurnItem> turns;
|
||||
route.GetTurnsForTesting(turns);
|
||||
TEST_EQUAL(turns.size() - 1, expectedTurns.size(), ());
|
||||
|
||||
for (size_t i = 0; i < expectedTurns.size(); ++i)
|
||||
TEST_EQUAL(turns[i].m_turn, expectedTurns[i], ());
|
||||
}
|
||||
|
||||
void TestCurrentStreetName(Route const & route, string const & expectedStreetName)
|
||||
{
|
||||
RouteSegment::RoadNameInfo roadNameInfo;
|
||||
route.GetCurrentStreetName(roadNameInfo);
|
||||
TEST_EQUAL(roadNameInfo.m_name, expectedStreetName, ());
|
||||
}
|
||||
|
||||
void TestNextStreetName(Route const & route, string const & expectedStreetName)
|
||||
{
|
||||
RouteSegment::RoadNameInfo roadNameInfo;
|
||||
route.GetNextTurnStreetName(roadNameInfo);
|
||||
TEST_EQUAL(roadNameInfo.m_name, expectedStreetName, ());
|
||||
}
|
||||
|
||||
void TestRouteLength(Route const & route, double expectedRouteMeters, double relativeError)
|
||||
{
|
||||
double const delta = max(expectedRouteMeters * relativeError, kErrorMeters);
|
||||
double const routeMeters = route.GetTotalDistanceMeters();
|
||||
TEST(AlmostEqualAbs(routeMeters, expectedRouteMeters, delta),
|
||||
("Route length test failed. Expected:", expectedRouteMeters, "have:", routeMeters, "delta:", delta));
|
||||
}
|
||||
|
||||
void TestRouteTime(Route const & route, double expectedRouteSeconds, double relativeError)
|
||||
{
|
||||
double const delta = max(expectedRouteSeconds * relativeError, kErrorSeconds);
|
||||
double const routeSeconds = route.GetTotalTimeSec();
|
||||
TEST(AlmostEqualAbs(routeSeconds, expectedRouteSeconds, delta),
|
||||
("Route time test failed. Expected:", expectedRouteSeconds, "have:", routeSeconds, "delta:", delta));
|
||||
}
|
||||
|
||||
void TestRoutePointsNumber(Route const & route, size_t expectedPointsNumber, double relativeError)
|
||||
{
|
||||
CHECK_GREATER_OR_EQUAL(relativeError, 0.0, ());
|
||||
size_t const routePoints = route.GetPoly().GetSize();
|
||||
TEST(AlmostEqualRel(static_cast<double>(routePoints), static_cast<double>(expectedPointsNumber), relativeError),
|
||||
("Route points test failed. Expected:", expectedPointsNumber, "have:", routePoints,
|
||||
"relative error:", relativeError));
|
||||
}
|
||||
|
||||
void CalculateRouteAndTestRouteLength(IRouterComponents const & routerComponents, m2::PointD const & startPoint,
|
||||
m2::PointD const & startDirection, m2::PointD const & finalPoint,
|
||||
double expectedRouteMeters, double relativeError /* = 0.02 */)
|
||||
{
|
||||
TRouteResult routeResult = CalculateRoute(routerComponents, startPoint, startDirection, finalPoint);
|
||||
RouterResultCode const result = routeResult.second;
|
||||
TEST_EQUAL(result, RouterResultCode::NoError, ());
|
||||
CHECK(routeResult.first, ());
|
||||
TestRouteLength(*routeResult.first, expectedRouteMeters, relativeError);
|
||||
}
|
||||
|
||||
void CalculateRouteAndTestRouteTime(IRouterComponents const & routerComponents, m2::PointD const & startPoint,
|
||||
m2::PointD const & startDirection, m2::PointD const & finalPoint,
|
||||
double expectedTimeSeconds, double relativeError /* = 0.07 */)
|
||||
{
|
||||
TRouteResult routeResult = CalculateRoute(routerComponents, startPoint, startDirection, finalPoint);
|
||||
RouterResultCode const result = routeResult.second;
|
||||
TEST_EQUAL(result, RouterResultCode::NoError, ());
|
||||
CHECK(routeResult.first, ());
|
||||
TestRouteTime(*routeResult.first, expectedTimeSeconds, relativeError);
|
||||
}
|
||||
|
||||
TestTurn const & TestTurn::TestValid() const
|
||||
{
|
||||
TEST(m_isValid, ());
|
||||
return *this;
|
||||
}
|
||||
|
||||
TestTurn const & TestTurn::TestNotValid() const
|
||||
{
|
||||
TEST(!m_isValid, ());
|
||||
return *this;
|
||||
}
|
||||
|
||||
TestTurn const & TestTurn::TestPoint(m2::PointD const & expectedPoint, double inaccuracyMeters) const
|
||||
{
|
||||
double const distanceMeters = ms::DistanceOnEarth(expectedPoint.y, expectedPoint.x, m_point.y, m_point.x);
|
||||
TEST_LESS(distanceMeters, inaccuracyMeters, ());
|
||||
return *this;
|
||||
}
|
||||
|
||||
TestTurn const & TestTurn::TestDirection(routing::turns::CarDirection expectedDirection) const
|
||||
{
|
||||
TEST_EQUAL(m_direction, expectedDirection, ());
|
||||
return *this;
|
||||
}
|
||||
|
||||
TestTurn const & TestTurn::TestOneOfDirections(set<routing::turns::CarDirection> const & expectedDirections) const
|
||||
{
|
||||
TEST(expectedDirections.find(m_direction) != expectedDirections.cend(), (m_direction));
|
||||
return *this;
|
||||
}
|
||||
|
||||
TestTurn const & TestTurn::TestRoundAboutExitNum(uint32_t expectedRoundAboutExitNum) const
|
||||
{
|
||||
TEST_EQUAL(m_roundAboutExitNum, expectedRoundAboutExitNum, ());
|
||||
return *this;
|
||||
}
|
||||
|
||||
TestTurn GetNthTurn(routing::Route const & route, uint32_t turnNumber)
|
||||
{
|
||||
vector<turns::TurnItem> turns;
|
||||
route.GetTurnsForTesting(turns);
|
||||
if (turnNumber >= turns.size())
|
||||
{
|
||||
ASSERT(false, ());
|
||||
return TestTurn();
|
||||
}
|
||||
|
||||
TurnItem const & turn = turns[turnNumber];
|
||||
return TestTurn(route.GetPoly().GetPoint(turn.m_index), turn.m_turn, turn.m_exitNum);
|
||||
}
|
||||
|
||||
bool IsSubwayExists(Route const & route)
|
||||
{
|
||||
auto const & routeSegments = route.GetRouteSegments();
|
||||
bool intoSubway = false;
|
||||
|
||||
for (auto const & routeSegment : routeSegments)
|
||||
{
|
||||
if (!routeSegment.HasTransitInfo())
|
||||
{
|
||||
intoSubway = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (routeSegment.GetTransitInfo().GetType() != TransitInfo::Type::Gate)
|
||||
continue;
|
||||
|
||||
if (intoSubway)
|
||||
return true;
|
||||
|
||||
intoSubway = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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."));
|
||||
}
|
||||
|
||||
LocalCountryFile GetLocalCountryFileByCountryId(platform::CountryFile const & country)
|
||||
{
|
||||
vector<LocalCountryFile> localFiles;
|
||||
GetAllLocalFiles(localFiles);
|
||||
|
||||
for (auto const & lf : localFiles)
|
||||
if (lf.GetCountryFile() == country)
|
||||
return lf;
|
||||
return {};
|
||||
}
|
||||
} // namespace integration
|
||||
Loading…
Add table
Add a link
Reference in a new issue