Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 13:58:55 +01:00
parent 4af19165ec
commit 68073add76
12458 changed files with 12350765 additions and 2 deletions

View file

@ -0,0 +1,29 @@
project(map_tests)
set(SRC
address_tests.cpp
bookmarks_test.cpp
chart_generator_tests.cpp
check_mwms.cpp
countries_names_tests.cpp
extrapolator_tests.cpp
feature_getters_tests.cpp
gps_track_collection_test.cpp
gps_track_storage_test.cpp
gps_track_test.cpp
kmz_unarchive_test.cpp
mwm_url_tests.cpp
power_manager_tests.cpp
search_api_tests.cpp
transliteration_test.cpp
elevation_info_tests.cpp
track_statistics_tests.cpp
)
omim_add_test(${PROJECT_NAME} ${SRC} REQUIRE_QT REQUIRE_SERVER)
target_link_libraries(${PROJECT_NAME}
search_tests_support
generator_tests_support
map
)

View file

@ -0,0 +1,106 @@
#include "testing/testing.hpp"
#include "search/reverse_geocoder.hpp"
#include "indexer/classificator_loader.hpp"
#include "indexer/data_source.hpp"
#include "indexer/feature_utils.hpp"
#include "indexer/mwm_set.hpp"
#include "indexer/search_string_utils.hpp"
#include "platform/preferred_languages.hpp"
#include "coding/string_utf8_multilang.hpp"
#include <memory>
#include <string>
namespace address_tests
{
using namespace search;
using namespace platform;
void TestAddress(ReverseGeocoder & coder, ms::LatLon const & ll, std::string_view street,
std::string const & houseNumber)
{
ReverseGeocoder::Address addr;
coder.GetNearbyAddress(mercator::FromLatLon(ll), addr);
std::string const expectedKey = strings::ToUtf8(GetStreetNameAsKey(street, false /* ignoreStreetSynonyms */));
std::string const resultKey =
strings::ToUtf8(GetStreetNameAsKey(addr.m_street.m_name, false /* ignoreStreetSynonyms */));
TEST_EQUAL(resultKey, expectedKey, (addr));
TEST_EQUAL(houseNumber, addr.GetHouseNumber(), (addr));
}
void TestAddress(ReverseGeocoder & coder, std::shared_ptr<MwmInfo> mwmInfo, ms::LatLon const & ll,
StringUtf8Multilang const & streetNames, std::string const & houseNumber)
{
feature::NameParamsOut out;
feature::GetReadableName(
{streetNames, mwmInfo->GetRegionData(), languages::GetCurrentMapLanguage(), false /* allowTranslit */}, out);
TestAddress(coder, ll, out.primary, houseNumber);
}
UNIT_TEST(ReverseGeocoder_Smoke)
{
classificator::Load();
LocalCountryFile file = LocalCountryFile::MakeForTesting("minsk-pass");
FrozenDataSource dataSource;
auto const regResult = dataSource.RegisterMap(file);
TEST_EQUAL(regResult.second, MwmSet::RegResult::Success, ());
auto mwmInfo = regResult.first.GetInfo();
TEST(mwmInfo != nullptr, ());
ReverseGeocoder coder(dataSource);
auto const currentLocale = languages::GetCurrentMapLanguage();
{
StringUtf8Multilang streetNames;
streetNames.AddString("default", "улица Мясникова");
streetNames.AddString("int_name", "vulica Miasnikova");
streetNames.AddString("be", "вуліца Мяснікова");
streetNames.AddString("ru", "улица Мясникова");
TestAddress(coder, mwmInfo, {53.89815, 27.54265}, streetNames, "32");
}
{
StringUtf8Multilang streetNames;
streetNames.AddString("default", "улица Немига");
streetNames.AddString("int_name", "vulica Niamiha");
streetNames.AddString("be", "вуліца Няміга");
streetNames.AddString("ru", "улица Немига");
TestAddress(coder, mwmInfo, {53.8997617, 27.5429365}, streetNames, "40");
}
{
StringUtf8Multilang streetNames;
streetNames.AddString("default", "Советская улица");
streetNames.AddString("int_name", "Savieckaja vulica");
streetNames.AddString("be", "Савецкая вуліца");
streetNames.AddString("ru", "Советская улица");
TestAddress(coder, mwmInfo, {53.89666, 27.54904}, streetNames, "19");
}
{
StringUtf8Multilang streetNames;
streetNames.AddString("default", "проспект Независимости");
streetNames.AddString("int_name", "praspiekt Niezaliežnasci");
streetNames.AddString("be", "праспект Незалежнасці");
streetNames.AddString("ru", "проспект Независимости");
TestAddress(coder, mwmInfo, {53.89724, 27.54983}, streetNames, "11");
}
{
StringUtf8Multilang streetNames;
streetNames.AddString("int_name", "vulica Karla Marksa");
streetNames.AddString("default", "улица Карла Маркса");
streetNames.AddString("be", "вуліца Карла Маркса");
streetNames.AddString("ru", "улица Карла Маркса");
TestAddress(coder, mwmInfo, {53.89745, 27.55835}, streetNames, "18А");
}
}
} // namespace address_tests

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,263 @@
#include "testing/testing.hpp"
#include "map/chart_generator.hpp"
#include "base/math.hpp"
#include "geometry/point_with_altitude.hpp"
#include <cstdint>
#include <vector>
namespace chart_generator_tests
{
using maps::kAltitudeChartBPP;
using std::vector;
namespace
{
double constexpr kEpsilon = 0.00001;
bool AlmostEqualAbs(vector<double> const & v1, vector<double> const & v2)
{
if (v1.size() != v2.size())
return false;
for (size_t i = 0; i < v1.size(); ++i)
if (!::AlmostEqualAbs(v1[i], v2[i], kEpsilon))
return false;
return true;
}
bool IsColor(vector<uint8_t> const & frameBuffer, size_t startColorIdx, uint8_t expectedR, uint8_t expectedG,
uint8_t expectedB, uint8_t expectedA)
{
CHECK_LESS_OR_EQUAL(startColorIdx + kAltitudeChartBPP, frameBuffer.size(), ());
return frameBuffer[startColorIdx] == expectedR && frameBuffer[startColorIdx + 1] == expectedG &&
frameBuffer[startColorIdx + 2] == expectedB && frameBuffer[startColorIdx + 3] == expectedA;
}
void TestAngleColors(size_t width, size_t height, vector<uint8_t> const & frameBuffer, uint8_t expectedR,
uint8_t expectedG, uint8_t expectedB, uint8_t expectedA)
{
TEST_EQUAL(frameBuffer.size(), width * height * kAltitudeChartBPP, ());
TEST(IsColor(frameBuffer, 0 /* startColorIdx */, expectedR, expectedG, expectedB, expectedA), ());
TEST(IsColor(frameBuffer, kAltitudeChartBPP * (width - 1) /* startColorIdx */, expectedR, expectedG, expectedB,
expectedA),
());
TEST(IsColor(frameBuffer, kAltitudeChartBPP * height * (width - 1) /* startColorIdx */, expectedR, expectedG,
expectedB, expectedA),
());
TEST(IsColor(frameBuffer, kAltitudeChartBPP * height * width - kAltitudeChartBPP /* startColorIdx */, expectedR,
expectedG, expectedB, expectedA),
());
}
} // namespace
UNIT_TEST(ScaleChartData_Test)
{
vector<double> chartData = {0.0, -1.0, 2.0};
maps::ScaleChartData(chartData, 2.0 /* scale */);
vector<double> const expectedChartData = {0.0, -2.0, 4.0};
TEST_EQUAL(chartData, expectedChartData, ());
}
UNIT_TEST(ShiftChartData_Test)
{
vector<double> chartData = {0.0, -1.0, 2.0};
maps::ShiftChartData(chartData, 1 /* shift */);
vector<double> const expectedChartData = {1.0, 0.0, 3.0};
TEST_EQUAL(chartData, expectedChartData, ());
}
UNIT_TEST(ReflectChartData_Test)
{
vector<double> chartData = {0.0, -1.0, 2.0};
maps::ReflectChartData(chartData);
vector<double> const expectedChartData = {0.0, 1.0, -2.0};
TEST_EQUAL(chartData, expectedChartData, ());
}
UNIT_TEST(NormalizeChartData_SmokeTest)
{
vector<double> const distanceDataM = {0.0, 0.0, 0.0};
geometry::Altitudes const altitudeDataM = {0, 0, 0};
vector<double> uniformAltitudeDataM;
TEST(maps::NormalizeChartData(distanceDataM, altitudeDataM, 2 /* resultPointCount */, uniformAltitudeDataM), ());
vector<double> const expectedUniformAltitudeDataM = {0.0, 0.0};
TEST_EQUAL(expectedUniformAltitudeDataM, uniformAltitudeDataM, ());
}
UNIT_TEST(NormalizeChartData_NoResultPointTest)
{
vector<double> const distanceDataM = {0.0, 0.0, 0.0};
geometry::Altitudes const altitudeDataM = {0, 0, 0};
vector<double> uniformAltitudeDataM;
TEST(maps::NormalizeChartData(distanceDataM, altitudeDataM, 0 /* resultPointCount */, uniformAltitudeDataM), ());
TEST(uniformAltitudeDataM.empty(), ());
}
UNIT_TEST(NormalizeChartData_NoPointTest)
{
vector<double> const distanceDataM = {};
geometry::Altitudes const altitudeDataM = {};
vector<double> uniformAltitudeDataM;
TEST(maps::NormalizeChartData(distanceDataM, altitudeDataM, 2 /* resultPointCount */, uniformAltitudeDataM), ());
TEST(uniformAltitudeDataM.empty(), ());
}
UNIT_TEST(NormalizeChartData_Test)
{
vector<double> const distanceDataM = {0.0, 2.0, 4.0, 6.0};
geometry::Altitudes const altitudeDataM = {-9, 0, 9, 18};
vector<double> uniformAltitudeDataM;
TEST(maps::NormalizeChartData(distanceDataM, altitudeDataM, 10 /* resultPointCount */, uniformAltitudeDataM), ());
vector<double> const expectedUniformAltitudeDataM = {-9.0, -6.0, -3.0, 0.0, 3.0, 6.0, 9.0, 12.0, 15.0, 18.0};
TEST(AlmostEqualAbs(uniformAltitudeDataM, expectedUniformAltitudeDataM), ());
}
UNIT_TEST(GenerateYAxisChartData_SmokeTest)
{
vector<double> const altitudeDataM = {0.0, 0.0};
vector<double> yAxisDataPxl;
TEST(maps::GenerateYAxisChartData(30 /* height */, 1.0 /* minMetersPerPxl */, altitudeDataM, yAxisDataPxl), ());
vector<double> expectedYAxisDataPxl = {15.0, 15.0};
TEST(AlmostEqualAbs(yAxisDataPxl, expectedYAxisDataPxl), ());
}
UNIT_TEST(GenerateYAxisChartData_EmptyAltitudeDataTest)
{
vector<double> const altitudeDataM = {};
vector<double> yAxisDataPxl;
TEST(maps::GenerateYAxisChartData(30 /* height */, 1.0 /* minMetersPerPxl */, altitudeDataM, yAxisDataPxl), ());
TEST(yAxisDataPxl.empty(), ());
}
UNIT_TEST(GenerateYAxisChartData_Test)
{
vector<double> const altitudeDataM = {0.0, 2.0, 0.0, -2.0, 1.0};
vector<double> yAxisDataPxl;
TEST(maps::GenerateYAxisChartData(100 /* height */, 1.0 /* minMetersPerPxl */, altitudeDataM, yAxisDataPxl), ());
vector<double> expectedYAxisDataPxl = {50.0, 48.0, 50.0, 52.0, 49.0};
TEST(AlmostEqualAbs(yAxisDataPxl, expectedYAxisDataPxl), ());
}
UNIT_TEST(GenerateChartByPoints_NoGeometryTest)
{
vector<m2::PointD> const geometry = {};
size_t constexpr width = 100;
size_t constexpr height = 40;
vector<uint8_t> frameBuffer;
TEST(maps::GenerateChartByPoints(width, height, geometry, MapStyleDefaultLight /* mapStyle */, frameBuffer), ());
TestAngleColors(width, height, frameBuffer, 255 /* expectedR */, 255 /* expectedG */, 255 /* expectedB */,
0 /* expectedA */);
}
UNIT_TEST(GenerateChartByPoints_OnePointTest)
{
vector<m2::PointD> const geometry = {{20.0, 20.0}};
size_t constexpr width = 40;
size_t constexpr height = 40;
vector<uint8_t> frameBuffer;
TEST(maps::GenerateChartByPoints(width, height, geometry, MapStyleDefaultLight /* mapStyle */, frameBuffer), ());
TestAngleColors(width, height, frameBuffer, 255 /* expectedR */, 255 /* expectedG */, 255 /* expectedB */,
0 /* expectedA */);
}
UNIT_TEST(GenerateChartByPoints_Test)
{
vector<m2::PointD> const geometry = {{0.0, 0.0}, {10.0, 10.0}};
size_t constexpr width = 40;
size_t constexpr height = 40;
vector<uint8_t> frameBuffer;
TEST(maps::GenerateChartByPoints(width, height, geometry, MapStyleDefaultLight /* mapStyle */, frameBuffer), ());
TEST_EQUAL(frameBuffer.size(), width * height * kAltitudeChartBPP, ());
TEST(IsColor(frameBuffer, 0 /* startColorIdx */, 30 /* expectedR */, 150 /* expectedG */, 240 /* expectedB */,
255 /* expectedA */),
());
TEST(IsColor(frameBuffer, kAltitudeChartBPP * (width - 1) /* startColorIdx */, 255 /* expectedR */,
255 /* expectedG */, 255 /* expectedB */, 0 /* expectedA */),
());
}
UNIT_TEST(GenerateChart_NoPointsTest)
{
size_t constexpr width = 50;
vector<double> const distanceDataM = {};
geometry::Altitudes const & altitudeDataM = {};
vector<uint8_t> frameBuffer;
TEST(maps::GenerateChart(width, 50 /* height */, distanceDataM, altitudeDataM, MapStyleDefaultDark /* mapStyle */,
frameBuffer),
());
TestAngleColors(width, 50 /* height */, frameBuffer, 255 /* expectedR */, 255 /* expectedG */, 255 /* expectedB */,
0 /* expectedA */);
}
UNIT_TEST(GenerateChart_OnePointTest)
{
size_t constexpr width = 50;
size_t constexpr height = 50;
vector<double> const distanceDataM = {0.0};
geometry::Altitudes const & altitudeDataM = {0};
vector<uint8_t> frameBuffer;
TEST(
maps::GenerateChart(width, height, distanceDataM, altitudeDataM, MapStyleDefaultDark /* mapStyle */, frameBuffer),
());
TEST_EQUAL(frameBuffer.size(), width * height * kAltitudeChartBPP, ());
TEST(IsColor(frameBuffer, 0 /* startColorIdx */, 255 /* expectedR */, 255 /* expectedG */, 255 /* expectedB */,
0 /* expectedA */),
());
TEST(IsColor(frameBuffer, kAltitudeChartBPP * (width - 1) /* startColorIdx */, 255 /* expectedR */,
255 /* expectedG */, 255 /* expectedB */, 0 /* expectedA */),
());
}
UNIT_TEST(GenerateChart_EmptyRectTest)
{
size_t constexpr width = 0;
vector<double> const distanceDataM = {};
geometry::Altitudes const & altitudeDataM = {};
vector<uint8_t> frameBuffer;
TEST(!maps::GenerateChart(width, 50 /* height */, distanceDataM, altitudeDataM, MapStyleDefaultDark /* mapStyle */,
frameBuffer),
());
TEST(frameBuffer.empty(), ());
}
UNIT_TEST(GenerateChart_Test)
{
size_t constexpr width = 50;
vector<double> const distanceDataM = {0.0, 100.0};
geometry::Altitudes const & altitudeDataM = {0, 1000};
vector<uint8_t> frameBuffer;
TEST(maps::GenerateChart(width, 50 /* height */, distanceDataM, altitudeDataM, MapStyleDefaultDark /* mapStyle */,
frameBuffer),
());
TEST(IsColor(frameBuffer, 0 /* startColorIdx */, 255 /* expectedR */, 255 /* expectedG */, 255 /* expectedB */,
0 /* expectedA */),
());
TEST(IsColor(frameBuffer, kAltitudeChartBPP * 3 * width - kAltitudeChartBPP /* startColorIdx */, 255 /* expectedR */,
230 /* expectedG */, 140 /* expectedB */, 255 /* expectedA */),
());
}
} // namespace chart_generator_tests

View file

@ -0,0 +1,88 @@
#include "testing/testing.hpp"
#include "map/features_fetcher.hpp"
#include "indexer/data_header.hpp"
#include "indexer/interval_index.hpp"
#include "platform/local_country_file.hpp"
#include "platform/local_country_file_utils.hpp"
#include "platform/platform.hpp"
#include "coding/var_serial_vector.hpp"
#include "base/logging.hpp"
#include <cstdint>
#include <map>
#include <memory>
#include <vector>
#include "defines.hpp"
namespace check_mwms
{
using namespace platform;
using namespace std;
UNIT_TEST(CheckMWM_LoadAll)
{
// Parse root WritableDir folder. Expect at least World, WorldCoasts, minsk-pass.
vector<LocalCountryFile> localFiles;
size_t const count = FindAllLocalMapsInDirectoryAndCleanup(GetPlatform().WritableDir(), 0 /* version */,
-1 /* latestVersion */, localFiles);
TEST_EQUAL(count, localFiles.size(), ());
TEST_GREATER_OR_EQUAL(count, 3, ());
FeaturesFetcher m;
m.InitClassificator();
for (auto const & localFile : localFiles)
{
LOG(LINFO, ("Found mwm:", localFile));
try
{
auto p = m.RegisterMap(localFile);
TEST(p.first.IsAlive(), ());
TEST_EQUAL(MwmSet::RegResult::Success, p.second, ());
}
catch (RootException const & ex)
{
TEST(false, ("Bad mwm file:", localFile));
}
}
}
UNIT_TEST(CheckMWM_GeomIndex)
{
// Open mwm file from data path.
FilesContainerR cont(GetPlatform().GetReader("minsk-pass.mwm"));
// Initialize index reader section inside mwm.
typedef ModelReaderPtr ReaderT;
ReaderT reader = cont.GetReader(INDEX_FILE_TAG);
ReaderSource<ReaderT> source(reader);
VarSerialVectorReader<ReaderT> treesReader(source);
// Make interval index objects for each scale bucket.
vector<unique_ptr<IntervalIndex<ReaderT, uint32_t>>> scale2Index;
for (size_t i = 0; i < treesReader.Size(); ++i)
{
scale2Index.emplace_back(
make_unique<IntervalIndex<ReaderT, uint32_t>>(treesReader.SubReader(static_cast<uint32_t>(i))));
}
// Pass full coverage as input for test.
uint64_t beg = 0;
uint64_t end = static_cast<uint64_t>((1ULL << 63) - 1);
// Count objects for each scale bucket.
map<size_t, uint64_t> resCount;
for (size_t i = 0; i < scale2Index.size(); ++i)
scale2Index[i]->ForEach([i, &resCount](uint64_t, uint32_t) { ++resCount[i]; }, beg, end);
// Print results.
LOG(LINFO, (resCount));
}
} // namespace check_mwms

View file

@ -0,0 +1,87 @@
#include "testing/testing.hpp"
#include "map/framework.hpp"
#include "search/categories_cache.hpp"
#include "search/downloader_search_callback.hpp"
#include "search/mwm_context.hpp"
#include "storage/storage.hpp"
#include "indexer/data_source.hpp"
#include "indexer/ftypes_matcher.hpp"
#include "indexer/mwm_set.hpp"
#include "indexer/utils.hpp"
#include "coding/string_utf8_multilang.hpp"
#include "base/cancellable.hpp"
#include "base/checked_cast.hpp"
#include <set>
#include <string>
UNIT_TEST(CountriesNamesTest)
{
using namespace platform;
using namespace storage;
using namespace std;
Framework f(FrameworkParams(false /* m_enableDiffs */));
auto & storage = f.GetStorage();
auto const & synonyms = storage.GetCountryNameSynonyms();
auto handle = indexer::FindWorld(f.GetDataSource());
TEST(handle.IsAlive(), ());
FeaturesLoaderGuard g(f.GetDataSource(), handle.GetId());
auto & value = *handle.GetValue();
TEST(value.HasSearchIndex(), ());
search::MwmContext const mwmContext(std::move(handle));
base::Cancellable const cancellable;
search::CategoriesCache cache(ftypes::IsLocalityChecker::Instance(), cancellable);
int8_t const langIndices[] = {StringUtf8Multilang::kEnglishCode, StringUtf8Multilang::kDefaultCode,
StringUtf8Multilang::kInternationalCode};
set<string> const kIgnoreList = {
"Northern Cyprus",
"Transnistria",
"Nagorno-Karabakh Republic",
"Republic of Artsakh",
"Saint Helena, Ascension and Tristan da Cunha",
"Somaliland",
};
auto const features = cache.Get(mwmContext);
features.ForEach([&](uint64_t fid)
{
auto ft = g.GetFeatureByIndex(base::asserted_cast<uint32_t>(fid));
TEST(ft, ());
ftypes::LocalityType const type = ftypes::IsLocalityChecker::Instance().GetType(*ft);
if (type != ftypes::LocalityType::Country)
return;
bool found = false;
for (auto const lang : langIndices)
{
std::string const name(ft->GetName(lang));
if (!name.empty())
{
auto const it = synonyms.find(name);
if (it == synonyms.end())
found = storage.IsNode(name) || kIgnoreList.count(name) != 0;
else
found = storage.IsNode(it->second);
if (found)
break;
}
}
// If this test fails, most likely somebody added fake place=country object into OSM.
TEST(found, ("Cannot find countries.txt record for country feature:", ft->DebugString()));
});
}

View file

@ -0,0 +1,93 @@
#include "testing/testing.hpp"
#include "map/elevation_info.hpp"
#include "geometry/mercator.hpp"
#include "geometry/point_with_altitude.hpp"
#include "kml/types.hpp"
namespace elevation_info_tests
{
using namespace geometry;
using namespace location;
GpsInfo const BuildGpsInfo(double latitude, double longitude, double altitude)
{
GpsInfo gpsInfo;
gpsInfo.m_latitude = latitude;
gpsInfo.m_longitude = longitude;
gpsInfo.m_altitude = altitude;
return gpsInfo;
}
UNIT_TEST(ElevationInfo_EmptyMultiGeometry)
{
ElevationInfo ei;
TEST_EQUAL(0, ei.GetSize(), ());
}
UNIT_TEST(ElevationInfo_FromMultiGeometry)
{
kml::MultiGeometry geometry;
auto const point1 = PointWithAltitude({0.0, 0.0}, 100);
auto const point2 = PointWithAltitude({1.0, 1.0}, 150);
auto const point3 = PointWithAltitude({2.0, 2.0}, 50);
geometry.AddLine({point1, point2, point3});
ElevationInfo ei(geometry.m_lines);
TEST_EQUAL(3, ei.GetSize(), ());
double distance = 0;
TEST_EQUAL(ei.GetPoints()[0].m_distance, distance, ());
distance += mercator::DistanceOnEarth(point1, point2);
TEST_EQUAL(ei.GetPoints()[1].m_distance, distance, ());
distance += mercator::DistanceOnEarth(point2, point3);
TEST_EQUAL(ei.GetPoints()[2].m_distance, distance, ());
}
UNIT_TEST(ElevationInfo_MultipleLines)
{
kml::MultiGeometry geometry;
geometry.AddLine(
{PointWithAltitude({0.0, 0.0}, 100), PointWithAltitude({1.0, 1.0}, 150), PointWithAltitude({1.0, 1.0}, 140)});
geometry.AddLine(
{PointWithAltitude({2.0, 2.0}, 50), PointWithAltitude({3.0, 3.0}, 75), PointWithAltitude({3.0, 3.0}, 60)});
geometry.AddLine({PointWithAltitude({4.0, 4.0}, 200), PointWithAltitude({5.0, 5.0}, 250)});
ElevationInfo ei(geometry.m_lines);
TEST_EQUAL(8, ei.GetSize(), ());
}
UNIT_TEST(ElevationInfo_SegmentDistances)
{
kml::MultiGeometry geometry;
geometry.AddLine({PointWithAltitude({0.0, 0.0}), PointWithAltitude({1.0, 0.0})});
geometry.AddLine({PointWithAltitude({2.0, 0.0}), PointWithAltitude({3.0, 0.0})});
geometry.AddLine({PointWithAltitude({4.0, 0.0}), PointWithAltitude({5.0, 0.0})});
ElevationInfo ei(geometry.m_lines);
auto const & segmentDistances = ei.GetSegmentsDistances();
auto const points = ei.GetPoints();
TEST_EQUAL(segmentDistances.size(), 2, ());
TEST_EQUAL(segmentDistances[0], ei.GetPoints()[2].m_distance, ());
TEST_EQUAL(segmentDistances[1], ei.GetPoints()[4].m_distance, ());
}
UNIT_TEST(ElevationInfo_BuildWithGpsPoints)
{
auto ei = ElevationInfo();
ei.AddGpsPoints({
BuildGpsInfo(0.0, 0.0, 0),
BuildGpsInfo(1.0, 1.0, 50),
BuildGpsInfo(2.0, 2.0, 100),
});
ei.AddGpsPoints({BuildGpsInfo(3.0, 3.0, -50)});
ei.AddGpsPoints({BuildGpsInfo(4.0, 4.0, 0)});
ei.AddGpsPoints({});
TEST_EQUAL(5, ei.GetSize(), ());
TEST_EQUAL(ei.GetSegmentsDistances().size(), 0, ());
}
} // namespace elevation_info_tests

View file

@ -0,0 +1,147 @@
#include "testing/testing.hpp"
#include "map/extrapolation/extrapolator.hpp"
#include "platform/location.hpp"
#include "base/math.hpp"
namespace
{
using namespace location;
using namespace extrapolation;
void TestGpsInfo(GpsInfo const & tested, GpsInfo const & expected)
{
double constexpr kEpsilon = 1e-5;
TEST_EQUAL(tested.m_source, expected.m_source, ());
TEST(AlmostEqualAbs(tested.m_latitude, expected.m_latitude, kEpsilon), ());
TEST(AlmostEqualAbs(tested.m_longitude, expected.m_longitude, kEpsilon), ());
TEST(AlmostEqualAbs(tested.m_horizontalAccuracy, expected.m_horizontalAccuracy, kEpsilon), ());
TEST(AlmostEqualAbs(tested.m_altitude, expected.m_altitude, kEpsilon), ());
TEST(AlmostEqualAbs(tested.m_verticalAccuracy, expected.m_verticalAccuracy, kEpsilon), ());
TEST(AlmostEqualAbs(tested.m_bearing, expected.m_bearing, kEpsilon), ());
TEST(AlmostEqualAbs(tested.m_speed, expected.m_speed, kEpsilon), ());
}
GpsInfo GetGpsInfo(double timestampS, double lat, double lon, double altitude, double speed)
{
return GpsInfo{EAppleNative,
timestampS,
lat,
lon,
10.0 /* m_horizontalAccuracy */,
altitude,
10.0 /* m_verticalAccuracy */,
0.0 /* m_bearing */,
speed};
}
UNIT_TEST(LinearExtrapolation)
{
GpsInfo const loc1 = GetGpsInfo(0.0 /* timestampS */, 1.0 /* m_latitude */, 1.0 /* m_longitude */,
1.0 /* m_altitude */, 10.0 /* m_speed */);
GpsInfo const loc2 = GetGpsInfo(1.0 /* timestampS */, 1.01 /* m_latitude */, 1.01 /* m_longitude */,
2.0 /* m_altitude */, 12.0 /* m_speed */);
// 0 ms after |point2|.
TestGpsInfo(LinearExtrapolation(loc1, loc2, 0 /* timeAfterPoint2Ms */), loc2);
// 100 ms after |point2|.
{
GpsInfo const expected = GetGpsInfo(1.1 /* timestampS */, 1.011 /* m_latitude */, 1.011 /* m_longitude */,
2.1 /* m_altitude */, 12.2 /* m_speed */);
TestGpsInfo(LinearExtrapolation(loc1, loc2, 100 /* timeAfterPoint2Ms */), expected);
}
// 200 ms after |point2|.
{
GpsInfo const expected = GetGpsInfo(1.2 /* timestampS */, 1.012 /* m_latitude */, 1.012 /* m_longitude */,
2.2 /* m_altitude */, 12.4 /* m_speed */);
TestGpsInfo(LinearExtrapolation(loc1, loc2, 200 /* timeAfterPoint2Ms */), expected);
}
// 1000 ms after |point2|.
{
GpsInfo const expected = GetGpsInfo(2.0 /* timestampS */, 1.02 /* m_latitude */, 1.02 /* m_longitude */,
3.0 /* m_altitude */, 14.0 /* m_speed */);
TestGpsInfo(LinearExtrapolation(loc1, loc2, 1000 /* timeAfterPoint2Ms */), expected);
}
}
UNIT_TEST(AreCoordsGoodForExtrapolation)
{
double constexpr kAltitude = 1.0;
double constexpr kSpeed = 10.0;
{
GpsInfo loc1;
GpsInfo loc2;
TEST(!AreCoordsGoodForExtrapolation(loc1, loc2), ("Locations are not valid."));
}
{
GpsInfo const loc1 = GetGpsInfo(0.0 /* timestamp */, 10.0 /* lat */, 179.999999 /* lon */, kAltitude, kSpeed);
GpsInfo const loc2 = GetGpsInfo(1.0 /* timestamp */, 10.0 /* lat */, -179.999999 /* lon */, kAltitude, kSpeed);
TEST(!AreCoordsGoodForExtrapolation(loc1, loc2), ("Crossing meridian 180."));
}
{
GpsInfo const loc1 = GetGpsInfo(0.0 /* timestamp */, 10.0 /* lat */, 179.999997 /* lon */, kAltitude, kSpeed);
GpsInfo const loc2 = GetGpsInfo(1.0 /* timestamp */, 10.0 /* lat */, 179.999999 /* lon */, kAltitude, kSpeed);
TEST(!AreCoordsGoodForExtrapolation(loc1, loc2), ("Near meridian 180."));
}
{
GpsInfo const loc1 = GetGpsInfo(0.0 /* timestamp */, 10.0 /* lat */, 179.999995 /* lon */, kAltitude, kSpeed);
GpsInfo const loc2 = GetGpsInfo(1.0 /* timestamp */, 10.0 /* lat */, 179.999996 /* lon */, kAltitude, kSpeed);
TEST(AreCoordsGoodForExtrapolation(loc1, loc2), ("Near meridian 180 but ok."));
}
{
GpsInfo const loc1 = GetGpsInfo(0.0 /* timestamp */, 10.0 /* lat */, -179.999997 /* lon */, kAltitude, kSpeed);
GpsInfo const loc2 = GetGpsInfo(1.0 /* timestamp */, 10.0 /* lat */, -179.999999 /* lon */, kAltitude, kSpeed);
TEST(!AreCoordsGoodForExtrapolation(loc1, loc2), ("Near meridian -180."));
}
{
GpsInfo const loc1 = GetGpsInfo(0.0 /* timestamp */, 89.9997 /* lat */, -10.0 /* lon */, kAltitude, kSpeed);
GpsInfo const loc2 = GetGpsInfo(1.0 /* timestamp */, 89.9999 /* lat */, -10.0 /* lon */, kAltitude, kSpeed);
TEST(!AreCoordsGoodForExtrapolation(loc1, loc2), ("Close to North Pole."));
}
{
GpsInfo const loc1 = GetGpsInfo(0.0 /* timestamp */, 89.9997 /* lat */, -10.0 /* lon */, kAltitude, kSpeed);
GpsInfo const loc2 = GetGpsInfo(1.0 /* timestamp */, 89.9998 /* lat */, -10.0 /* lon */, kAltitude, kSpeed);
TEST(AreCoordsGoodForExtrapolation(loc1, loc2), ("Close to North Pole but ok."));
}
{
GpsInfo const loc1 = GetGpsInfo(0.0 /* timestamp */, -89.9997 /* lat */, -10.0 /* lon */, kAltitude, kSpeed);
GpsInfo const loc2 = GetGpsInfo(1.0 /* timestamp */, -89.9999 /* lat */, -10.0 /* lon */, kAltitude, kSpeed);
TEST(!AreCoordsGoodForExtrapolation(loc1, loc2), ("Close to South Pole."));
}
{
GpsInfo const loc1 = GetGpsInfo(0.0 /* timestamp */, -89.9997 /* lat */, -10.0 /* lon */, kAltitude, kSpeed);
GpsInfo const loc2 = GetGpsInfo(1.0 /* timestamp */, -89.9998 /* lat */, -10.0 /* lon */, kAltitude, kSpeed);
TEST(AreCoordsGoodForExtrapolation(loc1, loc2), ("Close to South Pole but ok."));
}
{
GpsInfo const loc1 = GetGpsInfo(0.0 /* timestamp */, 10.0 /* lat */, -179.999995 /* lon */, kAltitude, kSpeed);
GpsInfo const loc2 = GetGpsInfo(1.0 /* timestamp */, 10.0 /* lat */, -179.999996 /* lon */, kAltitude, kSpeed);
TEST(AreCoordsGoodForExtrapolation(loc1, loc2), ("Near meridian -180 but ok."));
}
{
GpsInfo const loc1 = GetGpsInfo(0.0 /* timestamp */, 1.0 /* lat */, 10.0 /* lon */, kAltitude, kSpeed);
GpsInfo const loc2 = GetGpsInfo(1.0 /* timestamp */, 2.0 /* lat */, 10.0 /* lon */, kAltitude, kSpeed);
TEST(!AreCoordsGoodForExtrapolation(loc1, loc2), ("Locations are too far."));
}
{
GpsInfo const loc1 = GetGpsInfo(0.0 /* timestamp */, 1.0 /* lat */, 1.0 /* lon */, kAltitude, kSpeed);
GpsInfo const loc2 = GetGpsInfo(1.0 /* timestamp */, 1.0 /* lat */, 1.00001 /* lon */, kAltitude, kSpeed);
TEST(AreCoordsGoodForExtrapolation(loc1, loc2), ("Locations are close enough."));
}
{
GpsInfo const loc1 = GetGpsInfo(0.0 /* timestamp */, 1.0 /* lat */, 1.0 /* lon */, kAltitude, kSpeed);
GpsInfo const loc2 = GetGpsInfo(0.0 /* timestamp */, 1.0 /* lat */, 1.00001 /* lon */, kAltitude, kSpeed);
TEST(!AreCoordsGoodForExtrapolation(loc1, loc2), ("Time is the same."));
}
{
GpsInfo const loc1 = GetGpsInfo(0.0 /* timestamp */, 1.0 /* lat */, 1.0 /* lon */, kAltitude, kSpeed);
GpsInfo const loc2 = GetGpsInfo(3.0 /* timestamp */, 1.0 /* lat */, 1.00001 /* lon */, kAltitude, kSpeed);
TEST(!AreCoordsGoodForExtrapolation(loc1, loc2), ("Too rare locations."));
}
}
} // namespace

View file

@ -0,0 +1,65 @@
#include "testing/testing.hpp"
#include "map/framework.hpp"
#include "indexer/classificator.hpp"
#include "platform/local_country_file.hpp"
#include "coding/string_utf8_multilang.hpp"
#include "geometry/mercator.hpp"
#include <algorithm>
#include <cstdint>
#include <vector>
UNIT_TEST(Framework_ForEachFeatureAtPoint_And_Others)
{
using namespace std;
Framework frm(FrameworkParams(false /* m_enableDiffs */));
frm.DeregisterAllMaps();
frm.RegisterMap(platform::LocalCountryFile::MakeForTesting("minsk-pass"));
// May vary according to the new minsk-pass data.
vector<char const *> types = {
"highway|footway|", "hwtag|yesbicycle|", "psurface|paved_good|",
"highway|service|", "psurface|paved_good|",
"amenity|parking|",
"barrier|lift_gate|",
};
frm.ForEachFeatureAtPoint([&](FeatureType & ft)
{
ft.ForEachType([&types](uint32_t type)
{
string const strType = classif().GetFullObjectName(type);
auto found = find(types.begin(), types.end(), strType);
TEST(found != types.end(), (strType));
types.erase(found);
});
}, mercator::FromLatLon(53.8826576, 27.5378385));
TEST_EQUAL(0, types.size(), (types));
ftypes::IsBuildingChecker const & isBuilding = ftypes::IsBuildingChecker::Instance();
{
// Restaurant in the building.
auto const id = frm.GetFeatureAtPoint(mercator::FromLatLon(53.89395, 27.567365));
TEST(id.IsValid(), ());
frm.GetDataSource().ReadFeature([&](FeatureType & ft)
{
TEST_EQUAL("Родны Кут", ft.GetName(StringUtf8Multilang::kDefaultCode), ());
TEST(!isBuilding(ft), ());
}, id);
}
{
// Same building as above, very close to the restaurant.
auto const id = frm.GetFeatureAtPoint(mercator::FromLatLon(53.893603, 27.567032));
TEST(id.IsValid(), ());
frm.GetDataSource().ReadFeature([&](FeatureType & ft) { TEST(isBuilding(ft), ()); }, id);
}
}

View file

@ -0,0 +1,65 @@
#include "testing/testing.hpp"
#include "map/gps_track_collection.hpp"
#include "geometry/latlon.hpp"
#include "base/logging.hpp"
#include <chrono>
#include <ctime>
#include <map>
#include <utility>
namespace gps_track_collection_test
{
using namespace std::chrono;
location::GpsInfo MakeGpsTrackInfo(double timestamp, ms::LatLon const & ll, double speed)
{
location::GpsInfo info;
info.m_timestamp = timestamp;
info.m_speed = speed;
info.m_latitude = ll.m_lat;
info.m_longitude = ll.m_lon;
return info;
}
UNIT_TEST(GpsTrackCollection_Simple)
{
time_t const t = system_clock::to_time_t(system_clock::now());
double const timestamp = t;
LOG(LINFO, ("Timestamp", ctime(&t), timestamp));
GpsTrackCollection collection;
std::map<size_t, location::GpsInfo> data;
for (size_t i = 0; i < 50; ++i)
{
auto info = MakeGpsTrackInfo(timestamp + i, ms::LatLon(-90 + i, -180 + i), i);
std::pair<size_t, size_t> addedIds = collection.Add({info});
TEST_EQUAL(addedIds.second, i, ());
data[addedIds.second] = info;
}
TEST_EQUAL(50, collection.GetSize(), ());
collection.ForEach([&data](location::GpsInfo const & info, size_t id) -> bool
{
TEST(data.end() != data.find(id), ());
location::GpsInfo const & originInfo = data[id];
TEST_EQUAL(info.m_latitude, originInfo.m_latitude, ());
TEST_EQUAL(info.m_longitude, originInfo.m_longitude, ());
TEST_EQUAL(info.m_speed, originInfo.m_speed, ());
TEST_EQUAL(info.m_timestamp, originInfo.m_timestamp, ());
return true;
});
auto res = collection.Clear();
TEST_EQUAL(res.first, 0, ());
TEST_EQUAL(res.second, 49, ());
TEST_EQUAL(0, collection.GetSize(), ());
}
} // namespace gps_track_collection_test

View file

@ -0,0 +1,109 @@
#include "testing/testing.hpp"
#include "map/gps_track_storage.hpp"
#include "platform/platform.hpp"
#include "coding/file_writer.hpp"
#include "geometry/latlon.hpp"
#include "base/file_name_utils.hpp"
#include "base/logging.hpp"
#include "base/scope_guard.hpp"
#include <chrono>
#include <string>
#include <vector>
namespace gps_track_storage_test
{
using namespace std;
using namespace std::chrono;
location::GpsInfo Make(double timestamp, ms::LatLon const & ll, double speed)
{
location::GpsInfo info;
info.m_timestamp = timestamp;
info.m_speed = speed;
info.m_latitude = ll.m_lat;
info.m_longitude = ll.m_lon;
info.m_source = location::EAndroidNative;
return info;
}
inline string GetGpsTrackFilePath()
{
return base::JoinPath(GetPlatform().WritableDir(), "gpstrack_test.bin");
}
UNIT_TEST(GpsTrackStorage_WriteRead)
{
time_t const t = system_clock::to_time_t(system_clock::now());
double const timestamp = t;
LOG(LINFO, ("Timestamp", ctime(&t), timestamp));
string const filePath = GetGpsTrackFilePath();
SCOPE_GUARD(gpsTestFileDeleter, bind(FileWriter::DeleteFileX, filePath));
FileWriter::DeleteFileX(filePath);
size_t const itemCount = 100000;
vector<location::GpsInfo> points;
points.reserve(itemCount);
for (size_t i = 0; i < itemCount; ++i)
points.emplace_back(Make(timestamp + i, ms::LatLon(-90 + i, -180 + i), 60 + i));
// Open storage, write data and check written data
{
GpsTrackStorage stg(filePath);
stg.Append(points);
size_t i = 0;
stg.ForEach([&](location::GpsInfo const & point) -> bool
{
TEST_EQUAL(point.m_latitude, points[i].m_latitude, ());
TEST_EQUAL(point.m_longitude, points[i].m_longitude, ());
TEST_EQUAL(point.m_timestamp, points[i].m_timestamp, ());
TEST_EQUAL(point.m_speed, points[i].m_speed, ());
++i;
return true;
});
TEST_EQUAL(i, itemCount, ());
}
// Open storage and check previously written data
{
GpsTrackStorage stg(filePath);
size_t i = 0;
stg.ForEach([&](location::GpsInfo const & point) -> bool
{
TEST_EQUAL(point.m_latitude, points[i].m_latitude, ());
TEST_EQUAL(point.m_longitude, points[i].m_longitude, ());
TEST_EQUAL(point.m_timestamp, points[i].m_timestamp, ());
TEST_EQUAL(point.m_speed, points[i].m_speed, ());
++i;
return true;
});
TEST_EQUAL(i, itemCount, ());
// Clear data
stg.Clear();
}
// Open storage and check there is no data
{
GpsTrackStorage stg(filePath);
size_t i = 0;
stg.ForEach([&](location::GpsInfo const & point) -> bool
{
++i;
return true;
});
TEST_EQUAL(i, 0, ());
}
}
} // namespace gps_track_storage_test

View file

@ -0,0 +1,145 @@
#include "testing/testing.hpp"
#include "map/gps_track.hpp"
#include "platform/platform.hpp"
#include "coding/file_writer.hpp"
#include "geometry/latlon.hpp"
#include "base/file_name_utils.hpp"
#include "base/logging.hpp"
#include "base/scope_guard.hpp"
#include <chrono>
#include <functional>
#include <utility>
#include <vector>
namespace gps_track_test
{
using namespace std;
using namespace std::chrono;
inline location::GpsInfo Make(double timestamp, ms::LatLon const & ll, double speed)
{
location::GpsInfo info;
info.m_timestamp = timestamp;
info.m_speed = speed;
info.m_latitude = ll.m_lat;
info.m_longitude = ll.m_lon;
info.m_horizontalAccuracy = 15;
info.m_source = location::EAndroidNative;
return info;
}
inline string GetGpsTrackFilePath()
{
return base::JoinPath(GetPlatform().WritableDir(), "gpstrack_test.bin");
}
class GpsTrackCallback
{
public:
GpsTrackCallback() : m_toRemove(make_pair(GpsTrack::kInvalidId, GpsTrack::kInvalidId)), m_gotCallback(false) {}
void OnUpdate(vector<pair<size_t, location::GpsInfo>> && toAdd, pair<size_t, size_t> const & toRemove)
{
m_toAdd = std::move(toAdd);
m_toRemove = toRemove;
lock_guard<mutex> lg(m_mutex);
m_gotCallback = true;
m_cv.notify_one();
}
void Reset()
{
m_toAdd.clear();
m_toRemove = make_pair(GpsTrack::kInvalidId, GpsTrack::kInvalidId);
lock_guard<mutex> lg(m_mutex);
m_gotCallback = false;
}
bool WaitForCallback(seconds t)
{
unique_lock<mutex> ul(m_mutex);
return m_cv.wait_for(ul, t, [this]() -> bool { return m_gotCallback; });
}
vector<pair<size_t, location::GpsInfo>> m_toAdd;
pair<size_t, size_t> m_toRemove;
private:
mutex m_mutex;
condition_variable m_cv;
bool m_gotCallback;
};
seconds const kWaitForCallbackTimeout = seconds(5);
UNIT_TEST(GpsTrack_Simple)
{
string const filePath = GetGpsTrackFilePath();
SCOPE_GUARD(gpsTestFileDeleter, bind(FileWriter::DeleteFileX, filePath));
FileWriter::DeleteFileX(filePath);
time_t const t = system_clock::to_time_t(system_clock::now());
double const timestamp = t;
LOG(LINFO, ("Timestamp", ctime(&t), timestamp));
size_t const writeItemCount = 50000;
vector<location::GpsInfo> points;
points.reserve(writeItemCount);
for (size_t i = 0; i < writeItemCount; ++i)
points.emplace_back(Make(timestamp + i, ms::LatLon(-90.0 + i, -180.0 + i), 10 + i));
// Store points
{
GpsTrack track(filePath);
track.AddPoints(points);
GpsTrackCallback callback;
track.SetCallback(bind(&GpsTrackCallback::OnUpdate, &callback, placeholders::_1, placeholders::_2));
TEST(callback.WaitForCallback(kWaitForCallbackTimeout), ());
TEST_EQUAL(callback.m_toRemove.first, GpsTrack::kInvalidId, ());
TEST_EQUAL(callback.m_toRemove.second, GpsTrack::kInvalidId, ());
TEST_EQUAL(callback.m_toAdd.size(), writeItemCount, ());
for (size_t i = 0; i < writeItemCount; ++i)
{
TEST_EQUAL(i, callback.m_toAdd[i].first, ());
TEST_EQUAL(points[i].m_timestamp, callback.m_toAdd[i].second.m_timestamp, ());
TEST_EQUAL(points[i].m_speed, callback.m_toAdd[i].second.m_speed, ());
TEST_EQUAL(points[i].m_latitude, callback.m_toAdd[i].second.m_latitude, ());
TEST_EQUAL(points[i].m_longitude, callback.m_toAdd[i].second.m_longitude, ());
}
}
// Restore points
{
GpsTrack track(filePath);
GpsTrackCallback callback;
track.SetCallback(bind(&GpsTrackCallback::OnUpdate, &callback, placeholders::_1, placeholders::_2));
TEST(callback.WaitForCallback(kWaitForCallbackTimeout), ());
TEST_EQUAL(callback.m_toRemove.first, GpsTrack::kInvalidId, ());
TEST_EQUAL(callback.m_toRemove.second, GpsTrack::kInvalidId, ());
TEST_EQUAL(callback.m_toAdd.size(), writeItemCount, ());
for (size_t i = 0; i < writeItemCount; ++i)
{
TEST_EQUAL(i, callback.m_toAdd[i].first, ());
TEST_EQUAL(points[i].m_timestamp, callback.m_toAdd[i].second.m_timestamp, ());
TEST_EQUAL(points[i].m_speed, callback.m_toAdd[i].second.m_speed, ());
TEST_EQUAL(points[i].m_latitude, callback.m_toAdd[i].second.m_latitude, ());
TEST_EQUAL(points[i].m_longitude, callback.m_toAdd[i].second.m_longitude, ());
}
}
}
} // namespace gps_track_test

View file

@ -0,0 +1,68 @@
#include "testing/testing.hpp"
#include "map/bookmark_helpers.hpp"
#include "platform/platform.hpp"
#include "base/scope_guard.hpp"
UNIT_TEST(KMZ_UnzipTest)
{
std::string const kmzFile = GetPlatform().TestsDataPathForFile("test_data/kml/test.kmz");
auto const filePaths = GetKMLOrGPXFilesPathsToLoad(kmzFile);
TEST_EQUAL(1, filePaths.size(), ());
std::string const filePath = filePaths[0];
TEST(!filePath.empty(), ());
SCOPE_GUARD(fileGuard, std::bind(&base::DeleteFileX, filePath));
TEST(filePath.ends_with("doc.kml"), (filePath));
auto const kmlData = LoadKmlFile(filePath, KmlFileType::Text);
TEST(kmlData != nullptr, ());
TEST_EQUAL(kmlData->m_bookmarksData.size(), 6, ("Category wrong number of bookmarks"));
{
Bookmark const bm(std::move(kmlData->m_bookmarksData[0]));
TEST_EQUAL(kml::GetDefaultStr(bm.GetName()), ("Lahaina Breakwall"), ("KML wrong name!"));
TEST_EQUAL(bm.GetColor(), kml::PredefinedColor::Red, ("KML wrong type!"));
TEST_ALMOST_EQUAL_ULPS(bm.GetPivot().x, -156.6777046791284, ("KML wrong org x!"));
TEST_ALMOST_EQUAL_ULPS(bm.GetPivot().y, 21.34256685860084, ("KML wrong org y!"));
TEST_EQUAL(bm.GetScale(), 0, ("KML wrong scale!"));
}
{
Bookmark const bm(std::move(kmlData->m_bookmarksData[1]));
TEST_EQUAL(kml::GetDefaultStr(bm.GetName()), ("Seven Sacred Pools, Kipahulu"), ("KML wrong name!"));
TEST_EQUAL(bm.GetColor(), kml::PredefinedColor::Red, ("KML wrong type!"));
TEST_ALMOST_EQUAL_ULPS(bm.GetPivot().x, -156.0405130750025, ("KML wrong org x!"));
TEST_ALMOST_EQUAL_ULPS(bm.GetPivot().y, 21.12480639056074, ("KML wrong org y!"));
TEST_EQUAL(bm.GetScale(), 0, ("KML wrong scale!"));
}
}
UNIT_TEST(Multi_KML_KMZ_UnzipTest)
{
std::string const kmzFile = GetPlatform().TestsDataPathForFile("test_data/kml/BACRNKMZ.kmz");
auto const filePaths = GetKMLOrGPXFilesPathsToLoad(kmzFile);
std::vector<std::string> expectedFileNames = {
"BACRNKMZfilesCampgrounds 26may2022 green and tree icon",
"BACRNKMZfilesIndoor Accommodations 26may2022 placemark purple and bed icon",
"BACRNKMZfilesRoute 1 Canada - West-East Daily Segments",
"BACRNKMZfilesRoute 2 Canada - West-East Daily Segments",
"BACRNKMZfilesRoute Connector Canada - West-East Daily Segments",
"BACRNKMZdoc"
};
TEST_EQUAL(expectedFileNames.size(), filePaths.size(), ());
for (auto const & filePath : filePaths)
{
auto matched = false;
for (auto const & expectedFileName : expectedFileNames)
{
matched = filePath.find(expectedFileName) != std::string::npos;
if (matched)
break;
}
TEST(matched, ("Unexpected file path: " + filePath));
}
}

View file

@ -0,0 +1,60 @@
#include "testing/testing.hpp"
#include "indexer/data_source.hpp"
#include "platform/local_country_file_utils.hpp"
#include "platform/platform.hpp"
#include "base/scope_guard.hpp"
#ifndef OMIM_OS_WINDOWS
#include <sys/stat.h>
#endif
using namespace base;
using namespace platform;
/*
* This test is useless because of we don't build offsets index from now.
#ifndef OMIM_OS_WINDOWS
UNIT_TEST(MwmSet_FileSystemErrors)
{
string const dir = GetPlatform().WritableDir();
CountryFile file("minsk-pass");
LocalCountryFile localFile(dir, file, 0);
TEST(CountryIndexes::DeleteFromDisk(localFile), ());
// Maximum level to check exception handling logic.
LogLevel oldLevel = g_LogAbortLevel;
g_LogAbortLevel = LCRITICAL;
// Remove writable permission.
int const readOnlyMode = S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH;
TEST_EQUAL(chmod(dir.c_str(), readOnlyMode), 0, ());
auto restoreFn = [oldLevel, &dir, readOnlyMode] ()
{
g_LogAbortLevel = oldLevel;
TEST_EQUAL(chmod(dir.c_str(), readOnlyMode | S_IWUSR), 0, ());
};
SCOPE_GUARD(restoreGuard, restoreFn);
DataSource dataSource;
auto p = dataSource.RegisterMap(localFile);
TEST_EQUAL(p.second, DataSource::RegResult::Success, ());
// Registering should pass ok.
TEST(dataSource.GetMwmIdByCountryFile(file) != DataSource::MwmId(), ());
// Getting handle causes feature offsets index building which should fail
// because of write permissions.
TEST(!dataSource.GetMwmHandleById(p.first).IsAlive(), ());
// Map is automatically deregistered after the fail.
vector<shared_ptr<MwmInfo>> infos;
dataSource.GetMwmsInfo(infos);
TEST(infos.empty(), ());
}
#endif
*/

View file

@ -0,0 +1,577 @@
#include "testing/testing.hpp"
#include "map/mwm_url.hpp"
#include "geometry/mercator.hpp"
#include "coding/url.hpp"
#include "base/macros.hpp"
#include <random>
#include <string>
#include "defines.hpp"
namespace mwm_url_tests
{
using namespace std;
using namespace url_scheme;
using UrlType = ParsedMapApi::UrlType;
double const kEps = 1e-10;
UNIT_TEST(MapApiSmoke)
{
string urlString =
"mapswithme://"
"map?ll=38.970559,-9.419289&ignoreThisParam=Yes&z=17&n=Point%20Name&s=black&backurl=https%3A%2F%2Fcomaps.app";
TEST(url::Url(urlString).IsValid(), ());
ParsedMapApi test(urlString);
TEST_EQUAL(test.GetRequestType(), UrlType::Map, ());
TEST_EQUAL(test.GetMapPoints().size(), 1, ());
MapPoint const & p0 = test.GetMapPoints()[0];
TEST_ALMOST_EQUAL_ABS(p0.m_lat, 38.970559, kEps, ());
TEST_ALMOST_EQUAL_ABS(p0.m_lon, -9.419289, kEps, ());
TEST_EQUAL(p0.m_name, "Point Name", ());
TEST_EQUAL(p0.m_id, "", ());
TEST_EQUAL(p0.m_style, "black", ());
TEST_ALMOST_EQUAL_ABS(test.GetZoomLevel(), 17.0, kEps, ());
TEST_EQUAL(test.GetGlobalBackUrl(), "https://comaps.app", ());
}
UNIT_TEST(RouteApiSmoke)
{
string const urlString = "mapswithme://route?sll=1,1&saddr=name0&dll=2,2&daddr=name1&type=vehicle";
TEST(url::Url(urlString).IsValid(), ());
ParsedMapApi test(urlString);
TEST_EQUAL(test.GetRequestType(), UrlType::Route, ());
TEST_EQUAL(test.GetRoutePoints().size(), 2, ());
RoutePoint const & p0 = test.GetRoutePoints()[0];
RoutePoint const & p1 = test.GetRoutePoints()[1];
TEST_EQUAL(p0.m_org, mercator::FromLatLon(1, 1), ());
TEST_EQUAL(p0.m_name, "name0", ());
TEST_EQUAL(p1.m_org, mercator::FromLatLon(2, 2), ());
TEST_EQUAL(p1.m_name, "name1", ());
TEST_EQUAL(test.GetRoutingType(), "vehicle", ());
}
UNIT_TEST(SearchApiSmoke)
{
string const urlString =
"mapsme://search?query=Saint%20Hilarion&cll=35.3166654,33.2833322&locale=ru&map&appname=CoMaps";
TEST(url::Url(urlString).IsValid(), ());
ParsedMapApi test(urlString);
TEST_EQUAL(test.GetRequestType(), UrlType::Search, ());
auto const & request = test.GetSearchRequest();
ms::LatLon latlon = test.GetCenterLatLon();
TEST_EQUAL(request.m_query, "Saint Hilarion", ());
TEST_ALMOST_EQUAL_ABS(latlon.m_lat, 35.3166654, kEps, ());
TEST_ALMOST_EQUAL_ABS(latlon.m_lon, 33.2833322, kEps, ());
TEST_EQUAL(request.m_locale, "ru", ());
TEST_EQUAL(test.GetAppName(), "CoMaps", ());
TEST(request.m_isSearchOnMap, ());
}
UNIT_TEST(SearchApiAdvanced)
{
{
// Ignore wrong cll=.
ParsedMapApi test("cm://search?query=aaa&cll=1,1,1");
TEST_EQUAL(test.GetRequestType(), UrlType::Search, ());
auto const & request = test.GetSearchRequest();
ms::LatLon latlon = test.GetCenterLatLon();
TEST_EQUAL(request.m_query, "aaa", ());
TEST_EQUAL(request.m_locale, "", ());
TEST(!request.m_isSearchOnMap, ());
TEST_EQUAL(latlon.m_lat, ms::LatLon::kInvalid, ());
TEST_EQUAL(latlon.m_lon, ms::LatLon::kInvalid, ());
}
{
// Don't fail on unsupported parameters.
ParsedMapApi test("cm://search?query=aaa&ignoreThisParam=sure");
TEST_EQUAL(test.GetRequestType(), UrlType::Search, ());
auto const & request = test.GetSearchRequest();
ms::LatLon latlon = test.GetCenterLatLon();
TEST_EQUAL(request.m_query, "aaa", ());
TEST_EQUAL(request.m_locale, "", ());
TEST(!request.m_isSearchOnMap, ());
TEST_EQUAL(latlon.m_lat, ms::LatLon::kInvalid, ());
TEST_EQUAL(latlon.m_lon, ms::LatLon::kInvalid, ());
}
{
// Query parameter position doesn't matter
ParsedMapApi test("cm://search?cll=1,1&locale=ru&query=aaa");
TEST_EQUAL(test.GetRequestType(), UrlType::Search, ());
auto const & request = test.GetSearchRequest();
ms::LatLon latlon = test.GetCenterLatLon();
TEST_EQUAL(request.m_query, "aaa", ());
TEST_EQUAL(request.m_locale, "ru", ());
TEST(!request.m_isSearchOnMap, ());
TEST_ALMOST_EQUAL_ABS(latlon.m_lat, 1.0, kEps, ());
TEST_ALMOST_EQUAL_ABS(latlon.m_lon, 1.0, kEps, ());
}
}
UNIT_TEST(SearchApiInvalidUrl)
{
ParsedMapApi test;
TEST_EQUAL(test.SetUrlAndParse("mapsme://search?"), UrlType::Incorrect, ("Empty query string"));
TEST_EQUAL(test.SetUrlAndParse("mapsme://search?query"), UrlType::Incorrect, ("Search query can't be empty"));
TEST_EQUAL(test.SetUrlAndParse("mapsme://serch?cll=1,1&locale=ru&query=aaa"), UrlType::Incorrect,
("Incorrect url type"));
TEST_EQUAL(test.SetUrlAndParse("mapsme://search?Query=fff"), UrlType::Incorrect, ("The parser is case sensitive"));
TEST_EQUAL(test.SetUrlAndParse("incorrect://search?query=aaa"), UrlType::Incorrect, ("Wrong prefix"));
TEST_EQUAL(test.SetUrlAndParse("http://search?query=aaa"), UrlType::Incorrect, ("Wrong prefix"));
}
UNIT_TEST(LeadApiSmoke)
{
ParsedMapApi test;
TEST_EQUAL(test.SetUrlAndParse("mapsme://lead?utm_source=a&utm_medium=b&utm_campaign=c&utm_content=d&utm_term=e"),
UrlType::Incorrect, ("Lead API is not supported"));
}
UNIT_TEST(MapApiInvalidUrl)
{
ParsedMapApi test;
TEST_EQUAL(test.SetUrlAndParse("competitors://map?ll=12.3,34.54"), UrlType::Incorrect, ());
TEST_EQUAL(test.SetUrlAndParse("mapswithme://ggg?ll=12.3,34.54"), UrlType::Incorrect, ());
TEST_EQUAL(test.SetUrlAndParse("mwm://"), UrlType::Incorrect, ("No parameters"));
TEST_EQUAL(test.SetUrlAndParse("mapswithme://map?"), UrlType::Incorrect, ("No longtitude"));
TEST_EQUAL(test.SetUrlAndParse("mapswithme://map?ll=1,2,3"), UrlType::Incorrect, ("Too many values for ll"));
TEST_EQUAL(test.SetUrlAndParse("mapswithme://fffff://map?ll=1,2"), UrlType::Incorrect, ());
TEST_EQUAL(test.SetUrlAndParse("mapsme://map?LL=1,1"), UrlType::Incorrect, ("The parser is case sensitive"));
}
UNIT_TEST(RouteApiInvalidUrl)
{
ParsedMapApi test;
TEST_EQUAL(test.SetUrlAndParse("mapswithme://route?sll=1,1&saddr=name0&dll=2,2&daddr=name2"), UrlType::Incorrect,
("Route type doesn't exist"));
TEST_EQUAL(test.SetUrlAndParse("mapswithme://route?sll=1,1&saddr=name0"), UrlType::Incorrect,
("Destination doesn't exist"));
TEST_EQUAL(test.SetUrlAndParse("mapswithme://route?sll=1,1&dll=2,2&type=vehicle"), UrlType::Incorrect,
("Source or destination name doesn't exist"));
TEST_EQUAL(test.SetUrlAndParse("mapswithme://route?saddr=name0&daddr=name1&type=vehicle"), UrlType::Incorrect, ());
TEST_EQUAL(test.SetUrlAndParse("mapswithme://route?sll=1,1&sll=2.2&type=vehicle"), UrlType::Incorrect, ());
TEST_EQUAL(test.SetUrlAndParse("mapswithme://route?sll=1,1&dll=2.2&type=666"), UrlType::Incorrect, ());
TEST_EQUAL(test.SetUrlAndParse("mapswithme://route?sll=1,1&saddr=name0&sll=2,2&saddr=name1&type=vehicle"),
UrlType::Incorrect, ());
TEST_EQUAL(test.SetUrlAndParse("mapswithme://route?sll=1,1&type=vehicle"), UrlType::Incorrect, ());
TEST_EQUAL(test.SetUrlAndParse(
"mapswithme://route?sll=1,1&saddr=name0&sll=2,2&saddr=name1&sll=1,1&saddr=name0&type=vehicle"),
UrlType::Incorrect, ());
TEST_EQUAL(test.SetUrlAndParse("mapswithme://route?type=vehicle"), UrlType::Incorrect, ());
TEST_EQUAL(test.SetUrlAndParse("mapswithme://rout?sll=1,1&saddr=name0&dll=2,2&daddr=name1&type=vehicle"),
UrlType::Incorrect, ());
}
UNIT_TEST(MapApiLatLonLimits)
{
ParsedMapApi test;
TEST_EQUAL(test.SetUrlAndParse("mapswithme://map?ll=-91,10"), UrlType::Incorrect, ("Invalid latitude"));
TEST_EQUAL(test.SetUrlAndParse("mwm://map?ll=523.55,10"), UrlType::Incorrect, ("Invalid latitude"));
TEST_EQUAL(test.SetUrlAndParse("mapswithme://map?ll=23.55,450"), UrlType::Incorrect, ("Invalid longtitude"));
TEST_EQUAL(test.SetUrlAndParse("mapswithme://map?ll=23.55,-450"), UrlType::Incorrect, ("Invalid longtitude"));
}
UNIT_TEST(MapApiPointNameBeforeLatLon)
{
ParsedMapApi test("mapswithme://map?n=Name&ll=1,2");
TEST_EQUAL(test.GetRequestType(), UrlType::Incorrect, ());
}
UNIT_TEST(MapApiPointNameOverwritten)
{
{
ParsedMapApi api("mapswithme://map?ll=1,2&n=A&N=B");
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
TEST_EQUAL(api.GetMapPoints().size(), 1, ());
TEST_EQUAL(api.GetMapPoints()[0].m_name, "A", ());
}
{
ParsedMapApi api("mapswithme://map?ll=1,2&n=A&n=B");
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
TEST_EQUAL(api.GetMapPoints().size(), 1, ());
TEST_EQUAL(api.GetMapPoints()[0].m_name, "B", ());
}
}
UNIT_TEST(MapApiMultiplePoints)
{
ParsedMapApi api("mwm://map?ll=1.1,1.2&n=A&ll=2.1,2.2&ll=-3.1,-3.2&n=C");
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
TEST_EQUAL(api.GetMapPoints().size(), 3, ());
MapPoint const & p0 = api.GetMapPoints()[0];
TEST_ALMOST_EQUAL_ABS(p0.m_lat, 1.1, kEps, ());
TEST_ALMOST_EQUAL_ABS(p0.m_lon, 1.2, kEps, ());
TEST_EQUAL(p0.m_name, "A", ());
MapPoint const & p1 = api.GetMapPoints()[1];
TEST_ALMOST_EQUAL_ABS(p1.m_lat, 2.1, kEps, ());
TEST_ALMOST_EQUAL_ABS(p1.m_lon, 2.2, kEps, ());
TEST_EQUAL(p1.m_name, "", ());
MapPoint const & p2 = api.GetMapPoints()[2];
TEST_ALMOST_EQUAL_ABS(p2.m_lat, -3.1, kEps, ());
TEST_ALMOST_EQUAL_ABS(p2.m_lon, -3.2, kEps, ());
TEST_EQUAL(p2.m_name, "C", ());
}
UNIT_TEST(MapApiInvalidPointLatLonButValidOtherParts)
{
ParsedMapApi api("mapswithme://map?ll=1,1,1&n=A&ll=2,2&n=B&ll=3,3,3&n=C");
TEST_EQUAL(api.GetRequestType(), UrlType::Incorrect, ());
}
UNIT_TEST(MapApiPointURLEncoded)
{
ParsedMapApi api("mwm://map?ll=1,2&n=%D0%9C%D0%B8%D0%BD%D1%81%D0%BA&id=http%3A%2F%2Fmap%3Fll%3D1%2C2%26n%3Dtest");
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
TEST_EQUAL(api.GetMapPoints().size(), 1, ());
MapPoint const & p0 = api.GetMapPoints()[0];
TEST_EQUAL(p0.m_name, "\xd0\x9c\xd0\xb8\xd0\xbd\xd1\x81\xd0\xba", ());
TEST_EQUAL(p0.m_id, "http://map?ll=1,2&n=test", ());
}
UNIT_TEST(MapApiUrl)
{
{
ParsedMapApi api("https://www.google.com/maps?q=55.751809,37.6130029");
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
TEST_EQUAL(api.GetMapPoints().size(), 1, ());
MapPoint const & p0 = api.GetMapPoints()[0];
TEST_ALMOST_EQUAL_ABS(p0.m_lat, 55.751809, kEps, ());
TEST_ALMOST_EQUAL_ABS(p0.m_lon, 37.6130029, kEps, ());
}
{
ParsedMapApi api("https://www.openstreetmap.org/#map=16/33.89041/35.50664");
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
TEST_EQUAL(api.GetMapPoints().size(), 1, ());
MapPoint const & p0 = api.GetMapPoints()[0];
TEST_ALMOST_EQUAL_ABS(p0.m_lat, 33.89041, kEps, ());
TEST_ALMOST_EQUAL_ABS(p0.m_lon, 35.50664, kEps, ());
}
{
ParsedMapApi api("ftp://www.google.com/maps?q=55.751809,37.6130029");
TEST_EQUAL(api.GetRequestType(), UrlType::Incorrect, ());
}
}
UNIT_TEST(MapApiGe0)
{
{
ParsedMapApi api("cm://o4B4pYZsRs");
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
TEST_EQUAL(api.GetMapPoints().size(), 1, ());
MapPoint const & p0 = api.GetMapPoints()[0];
TEST_ALMOST_EQUAL_ABS(p0.m_lat, 47.3859, 1e-4, ());
TEST_ALMOST_EQUAL_ABS(p0.m_lon, 8.5766, 1e-4, ());
}
{
ParsedMapApi api("cm://o4B4pYZsRs/Zoo_Zürich");
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
TEST_EQUAL(api.GetMapPoints().size(), 1, ());
MapPoint const & p0 = api.GetMapPoints()[0];
TEST_ALMOST_EQUAL_ABS(p0.m_lat, 47.3859, 1e-4, ());
TEST_ALMOST_EQUAL_ABS(p0.m_lon, 8.5766, 1e-4, ());
TEST_EQUAL(p0.m_name, "Zoo Zürich", ());
}
{
ParsedMapApi api("http://comaps.at/o4B4pYZsRs/Zoo_Zürich");
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
}
{
ParsedMapApi api("https://comaps.at/o4B4pYZsRs/Zoo_Zürich");
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
}
{
ParsedMapApi api("ge0://o4B4pYZsRs/Zoo_Zürich");
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
}
{
ParsedMapApi api("http://ge0.me/o4B4pYZsRs/Zoo_Zürich");
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
}
{
ParsedMapApi api("https://ge0.me/o4B4pYZsRs/Zoo_Zürich");
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
}
{
ParsedMapApi api("mapsme://o4B4pYZsRs/Zoo_Zürich");
TEST_EQUAL(api.GetRequestType(), UrlType::Incorrect, ());
}
{
ParsedMapApi api("mwm://o4B4pYZsRs/Zoo_Zürich");
TEST_EQUAL(api.GetRequestType(), UrlType::Incorrect, ());
}
{
ParsedMapApi api("mapswithme://o4B4pYZsRs/Zoo_Zürich");
TEST_EQUAL(api.GetRequestType(), UrlType::Incorrect, ());
}
}
UNIT_TEST(MapApiGeoScheme)
{
{
ParsedMapApi api("geo:0,0?q=35.341714,33.32231 (Custom%20Title)");
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
TEST_EQUAL(api.GetMapPoints().size(), 1, ());
MapPoint const & p0 = api.GetMapPoints()[0];
TEST_ALMOST_EQUAL_ABS(p0.m_lat, 35.341714, kEps, ());
TEST_ALMOST_EQUAL_ABS(p0.m_lon, 33.32231, kEps, ());
TEST_EQUAL(p0.m_name, "Custom Title", ());
}
{
ParsedMapApi api("geo:0,0?q=");
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
TEST_EQUAL(api.GetMapPoints().size(), 1, ());
MapPoint const & p0 = api.GetMapPoints()[0];
TEST_ALMOST_EQUAL_ABS(p0.m_lat, 0.0, kEps, ());
TEST_ALMOST_EQUAL_ABS(p0.m_lon, 0.0, kEps, ());
}
{
ParsedMapApi api("geo:0,0");
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
TEST_EQUAL(api.GetMapPoints().size(), 1, ());
MapPoint const & p0 = api.GetMapPoints()[0];
TEST_ALMOST_EQUAL_ABS(p0.m_lat, 0.0, kEps, ());
TEST_ALMOST_EQUAL_ABS(p0.m_lon, 0.0, kEps, ());
}
}
UNIT_TEST(SearchApiGeoScheme)
{
{
ParsedMapApi api("geo:0,0?q=Kyrenia%20Castle");
TEST_EQUAL(api.GetRequestType(), UrlType::Search, ());
auto const & request = api.GetSearchRequest();
ms::LatLon latlon = api.GetCenterLatLon();
TEST(!latlon.IsValid(), ());
TEST_EQUAL(request.m_query, "Kyrenia Castle", ());
}
{
ParsedMapApi api("geo:35.3381607,33.3290564?q=Kyrenia%20Castle");
TEST_EQUAL(api.GetRequestType(), UrlType::Search, ());
auto const & request = api.GetSearchRequest();
ms::LatLon latlon = api.GetCenterLatLon();
TEST_EQUAL(request.m_query, "Kyrenia Castle", ());
TEST_ALMOST_EQUAL_ABS(latlon.m_lat, 35.3381607, kEps, ());
TEST_ALMOST_EQUAL_ABS(latlon.m_lon, 33.3290564, kEps, ());
}
{
ParsedMapApi api("geo:0,0?q=123+Main+St,+Seattle,+WA+98101");
TEST_EQUAL(api.GetRequestType(), UrlType::Search, ());
auto const & request = api.GetSearchRequest();
ms::LatLon latlon = api.GetCenterLatLon();
TEST(!latlon.IsValid(), ());
TEST_EQUAL(request.m_query, "123 Main St, Seattle, WA 98101", ());
}
}
UNIT_TEST(CrosshairApi)
{
{
ParsedMapApi api("cm://crosshair?cll=47.3813,8.5889&appname=Google%20Maps");
TEST_EQUAL(api.GetRequestType(), UrlType::Crosshair, ());
ms::LatLon latlon = api.GetCenterLatLon();
TEST_ALMOST_EQUAL_ABS(latlon.m_lat, 47.3813, kEps, ());
TEST_ALMOST_EQUAL_ABS(latlon.m_lon, 8.5889, kEps, ());
TEST_EQUAL(api.GetAppName(), "Google Maps", ());
}
{
ParsedMapApi api("https://comaps.at/crosshair?cll=47.3813,8.5889&appname=Google%20Maps");
TEST_EQUAL(api.GetRequestType(), UrlType::Crosshair, ());
ms::LatLon latlon = api.GetCenterLatLon();
TEST_ALMOST_EQUAL_ABS(latlon.m_lat, 47.3813, kEps, ());
TEST_ALMOST_EQUAL_ABS(latlon.m_lon, 8.5889, kEps, ());
TEST_EQUAL(api.GetAppName(), "Google Maps", ());
}
}
UNIT_TEST(GlobalBackUrl)
{
{
ParsedMapApi api("mwm://map?ll=1,2&n=PointName&backurl=someTestAppBackUrl");
TEST_EQUAL(api.GetGlobalBackUrl(), "someTestAppBackUrl://", ());
}
{
ParsedMapApi api("mwm://map?ll=1,2&n=PointName&backurl=ge0://");
TEST_EQUAL(api.GetGlobalBackUrl(), "ge0://", ());
}
{
ParsedMapApi api("cm://map?ll=1,2&n=PointName&backurl=cm://");
TEST_EQUAL(api.GetGlobalBackUrl(), "cm://", ());
}
{
ParsedMapApi api("mwm://map?ll=1,2&n=PointName&backurl=ge0%3A%2F%2F");
TEST_EQUAL(api.GetGlobalBackUrl(), "ge0://", ());
}
{
ParsedMapApi api("mwm://map?ll=1,2&n=PointName&backurl=http://mapswithme.com");
TEST_EQUAL(api.GetGlobalBackUrl(), "http://mapswithme.com", ());
}
{
ParsedMapApi api(
"mwm://map?ll=1,2&n=PointName&backurl=someapp://"
"%D0%9C%D0%BE%D0%B1%D0%B8%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5%20%D0%9A%D0%B0%D1%80%D1%82%D1%8B");
TEST_EQUAL(api.GetGlobalBackUrl(),
"someapp://\xd0\x9c\xd0\xbe\xd0\xb1\xd0\xb8\xd0\xbb\xd1\x8c\xd0\xbd\xd1\x8b\xd0\xb5 "
"\xd0\x9a\xd0\xb0\xd1\x80\xd1\x82\xd1\x8b",
());
}
{
ParsedMapApi api("mwm://map?ll=1,2&n=PointName");
TEST_EQUAL(api.GetGlobalBackUrl(), "", ());
}
{
ParsedMapApi api(
"mwm://"
"map?ll=1,2&n=PointName&backurl=%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5%3A%2F%2F%D0%BE%D1%"
"82%D0%BA%D1%80%D0%BE%D0%B9%D0%A1%D1%81%D1%8B%D0%BB%D0%BA%D1%83");
TEST_EQUAL(api.GetGlobalBackUrl(), "приложение://откройСсылку", ());
}
{
ParsedMapApi api(
"mwm://"
"map?ll=1,2&n=PointName&backurl=%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5%3A%2F%2F%D0%BE%D1%"
"82%D0%BA%D1%80%D0%BE%D0%B9%D0%A1%D1%81%D1%8B%D0%BB%D0%BA%D1%83");
TEST_EQUAL(api.GetGlobalBackUrl(), "приложение://откройСсылку", ());
}
{
ParsedMapApi api("mwm://map?ll=1,2&n=PointName&backurl=%E6%88%91%E6%84%9Bmapswithme");
TEST_EQUAL(api.GetGlobalBackUrl(), "我愛mapswithme://", ());
}
}
UNIT_TEST(VersionTest)
{
{
ParsedMapApi api("mwm://map?ll=1,2&v=1&n=PointName");
TEST_EQUAL(api.GetApiVersion(), 1, ());
}
{
ParsedMapApi api("mwm://map?ll=1,2&v=kotik&n=PointName");
TEST_EQUAL(api.GetApiVersion(), 0, ());
}
{
ParsedMapApi api("mwm://map?ll=1,2&v=APacanyVoobsheKotjata&n=PointName");
TEST_EQUAL(api.GetApiVersion(), 0, ());
}
{
ParsedMapApi api("mwm://map?ll=1,2&n=PointName");
TEST_EQUAL(api.GetApiVersion(), 0, ());
}
{
ParsedMapApi api("mwm://map?V=666&ll=1,2&n=PointName");
TEST_EQUAL(api.GetApiVersion(), 0, ());
}
{
ParsedMapApi api("mwm://map?v=666&ll=1,2&n=PointName");
TEST_EQUAL(api.GetApiVersion(), 666, ());
}
}
UNIT_TEST(AppNameTest)
{
{
ParsedMapApi api("mwm://map?ll=1,2&v=1&n=PointName&appname=Google");
TEST_EQUAL(api.GetAppName(), "Google", ());
}
{
ParsedMapApi api("mwm://map?ll=1,2&v=1&n=PointName&appname=%D0%AF%D0%BD%D0%B4%D0%B5%D0%BA%D1%81");
TEST_EQUAL(api.GetAppName(), "Яндекс", ());
}
{
ParsedMapApi api("mwm://map?ll=1,2&v=1&n=PointName");
TEST_EQUAL(api.GetAppName(), "", ());
}
}
UNIT_TEST(OAuth2Test)
{
{
ParsedMapApi api("cm://oauth2/osm/callback?code=THE_MEGA_CODE");
TEST_EQUAL(api.GetRequestType(), UrlType::OAuth2, ());
TEST_EQUAL(api.GetOAuth2Code(), "THE_MEGA_CODE", ());
}
{
ParsedMapApi api("cm://oauth2/google/callback?code=THE_MEGA_CODE");
TEST_EQUAL(api.GetRequestType(), UrlType::Incorrect, ());
}
{
ParsedMapApi api("cm://oauth2/osm/callback?code=");
TEST_EQUAL(api.GetRequestType(), UrlType::Incorrect, ());
}
}
namespace
{
string generatePartOfUrl(url_scheme::MapPoint const & point)
{
stringstream stream;
stream << "&ll=" << std::to_string(point.m_lat) << "," << std::to_string(point.m_lon) << "&n=" << point.m_name
<< "&id=" << point.m_id;
return stream.str();
}
string randomString(size_t size, uint32_t seed)
{
string result(size, '0');
mt19937 rng(seed);
for (size_t i = 0; i < size; ++i)
result[i] = 'a' + rng() % 26;
return result;
}
void generateRandomTest(uint32_t numberOfPoints, size_t stringLength)
{
vector<url_scheme::MapPoint> vect(numberOfPoints);
for (uint32_t i = 0; i < numberOfPoints; ++i)
{
url_scheme::MapPoint point;
mt19937 rng(i);
point.m_lat = rng() % 90;
point.m_lat *= rng() % 2 == 0 ? 1 : -1;
point.m_lon = rng() % 180;
point.m_lon *= rng() % 2 == 0 ? 1 : -1;
point.m_name = randomString(stringLength, i);
point.m_id = randomString(stringLength, i);
vect[i] = point;
}
string result = "mapswithme://map?v=1";
for (size_t i = 0; i < vect.size(); ++i)
result += generatePartOfUrl(vect[i]);
ParsedMapApi api(result);
TEST_EQUAL(api.GetRequestType(), UrlType::Map, ());
TEST_EQUAL(api.GetMapPoints().size(), vect.size(), ());
for (size_t i = 0; i < vect.size(); ++i)
{
MapPoint const & p = api.GetMapPoints()[i];
TEST_EQUAL(p.m_name, vect[i].m_name, ());
TEST_EQUAL(p.m_id, vect[i].m_id, ());
TEST(AlmostEqualULPs(p.m_lat, vect[i].m_lat), ());
TEST(AlmostEqualULPs(p.m_lon, vect[i].m_lon), ());
}
}
} // namespace
UNIT_TEST(100FullEnteriesRandomTest)
{
generateRandomTest(100, 10);
}
UNIT_TEST(StressTestRandomTest)
{
generateRandomTest(10000, 100);
}
} // namespace mwm_url_tests

View file

@ -0,0 +1,275 @@
#include "testing/testing.hpp"
#include "map/power_management/power_management_schemas.hpp"
#include "map/power_management/power_manager.hpp"
#include "platform//platform.hpp"
#include "coding/file_writer.hpp"
#include "base/scope_guard.hpp"
#include "base/stl_helpers.hpp"
#include <functional>
#include <vector>
using namespace power_management;
namespace
{
struct SubscriberForTesting : public PowerManager::Subscriber
{
public:
// PowerManager::Subscriber overrides:
void OnPowerFacilityChanged(Facility const facility, bool enabled) override
{
m_onFacilityEvents.push_back({facility, enabled});
}
void OnPowerSchemeChanged(Scheme const actualConfig) override { m_onShemeEvents.push_back(actualConfig); }
struct FacilityState
{
Facility m_facility;
bool m_state;
};
std::vector<FacilityState> m_onFacilityEvents;
std::vector<Scheme> m_onShemeEvents;
};
void TestIsAllFacilitiesInState(PowerManager const & manager, bool state)
{
auto const count = static_cast<size_t>(Facility::Count);
for (size_t i = 0; i < count; ++i)
TEST_EQUAL(manager.IsFacilityEnabled(static_cast<Facility>(i)), state, ());
}
void TestAllFacilitiesEnabledExcept(PowerManager const & manager, std::vector<Facility> const & disabledFacilities)
{
auto const count = static_cast<size_t>(Facility::Count);
for (size_t i = 0; i < count; ++i)
{
auto const facility = static_cast<Facility>(i);
TEST_EQUAL(manager.IsFacilityEnabled(facility), !base::IsExist(disabledFacilities, facility), ());
}
}
UNIT_TEST(PowerManager_SetFacility)
{
auto const configPath = PowerManager::GetConfigPath();
SCOPE_GUARD(deleteFileGuard, bind(&FileWriter::DeleteFileX, std::cref(configPath)));
PowerManager manager;
SubscriberForTesting subscriber;
manager.Subscribe(&subscriber);
TestIsAllFacilitiesInState(manager, true);
TEST_EQUAL(manager.GetScheme(), Scheme::Normal, ());
manager.SetFacility(Facility::Buildings3d, false);
TestAllFacilitiesEnabledExcept(manager, {Facility::Buildings3d});
TEST_EQUAL(manager.GetScheme(), Scheme::None, ());
TEST_EQUAL(subscriber.m_onFacilityEvents.size(), 1, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[0].m_facility, Facility::Buildings3d, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[0].m_state, false, ());
TEST_EQUAL(subscriber.m_onShemeEvents.size(), 1, ());
TEST_EQUAL(subscriber.m_onShemeEvents[0], Scheme::None, ());
subscriber.m_onFacilityEvents.clear();
subscriber.m_onShemeEvents.clear();
manager.SetFacility(Facility::MapDownloader, false);
TestAllFacilitiesEnabledExcept(manager, {Facility::Buildings3d, Facility::MapDownloader});
TEST_EQUAL(manager.GetScheme(), Scheme::None, ());
TEST_EQUAL(subscriber.m_onFacilityEvents.size(), 1, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[0].m_facility, Facility::MapDownloader, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[0].m_state, false, ());
TEST_EQUAL(subscriber.m_onShemeEvents.size(), 0, ());
}
UNIT_TEST(PowerManager_SetScheme)
{
auto const configPath = PowerManager::GetConfigPath();
SCOPE_GUARD(deleteFileGuard, bind(&FileWriter::DeleteFileX, std::cref(configPath)));
Platform::ThreadRunner m_runner;
PowerManager manager;
SubscriberForTesting subscriber;
manager.Subscribe(&subscriber);
TestIsAllFacilitiesInState(manager, true);
TEST_EQUAL(manager.GetScheme(), Scheme::Normal, ());
manager.SetScheme(Scheme::EconomyMaximum);
TEST_EQUAL(manager.GetScheme(), Scheme::EconomyMaximum, ());
TestAllFacilitiesEnabledExcept(
manager, {Facility::Buildings3d, Facility::PerspectiveView, Facility::TrackRecording, Facility::TrafficJams,
Facility::GpsTrackingForTraffic, Facility::OsmEditsUploading, Facility::UgcUploading,
Facility::BookmarkCloudUploading});
TEST_EQUAL(subscriber.m_onShemeEvents.size(), 1, ());
TEST_EQUAL(subscriber.m_onShemeEvents[0], Scheme::EconomyMaximum, ());
TEST_EQUAL(subscriber.m_onFacilityEvents.size(), 8, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[0].m_facility, Facility::Buildings3d, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[0].m_state, false, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[1].m_facility, Facility::PerspectiveView, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[1].m_state, false, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[2].m_facility, Facility::TrackRecording, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[2].m_state, false, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[3].m_facility, Facility::TrafficJams, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[3].m_state, false, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[4].m_facility, Facility::GpsTrackingForTraffic, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[4].m_state, false, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[5].m_facility, Facility::OsmEditsUploading, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[5].m_state, false, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[6].m_facility, Facility::UgcUploading, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[6].m_state, false, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[7].m_facility, Facility::BookmarkCloudUploading, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[7].m_state, false, ());
subscriber.m_onFacilityEvents.clear();
subscriber.m_onShemeEvents.clear();
manager.SetScheme(Scheme::EconomyMedium);
TEST_EQUAL(manager.GetScheme(), Scheme::EconomyMedium, ());
TestAllFacilitiesEnabledExcept(manager, {Facility::PerspectiveView, Facility::BookmarkCloudUploading});
TEST_EQUAL(subscriber.m_onShemeEvents.size(), 1, ());
TEST_EQUAL(subscriber.m_onShemeEvents[0], Scheme::EconomyMedium, ());
TEST_EQUAL(subscriber.m_onFacilityEvents.size(), 6, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[0].m_facility, Facility::Buildings3d, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[0].m_state, true, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[1].m_facility, Facility::TrackRecording, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[1].m_state, true, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[2].m_facility, Facility::TrafficJams, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[2].m_state, true, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[3].m_facility, Facility::GpsTrackingForTraffic, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[3].m_state, true, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[4].m_facility, Facility::OsmEditsUploading, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[4].m_state, true, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[5].m_facility, Facility::UgcUploading, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[5].m_state, true, ());
subscriber.m_onShemeEvents.clear();
subscriber.m_onFacilityEvents.clear();
manager.SetScheme(Scheme::Auto);
TEST_EQUAL(subscriber.m_onShemeEvents.size(), 1, ());
TEST_EQUAL(subscriber.m_onShemeEvents[0], Scheme::Auto, ());
subscriber.m_onShemeEvents.clear();
subscriber.m_onFacilityEvents.clear();
manager.SetScheme(Scheme::Normal);
TEST_EQUAL(subscriber.m_onShemeEvents.size(), 1, ());
TEST_EQUAL(subscriber.m_onShemeEvents[0], Scheme::Normal, ());
TEST_EQUAL(subscriber.m_onFacilityEvents.size(), 0, ());
}
UNIT_TEST(PowerManager_OnBatteryLevelChanged)
{
auto const configPath = PowerManager::GetConfigPath();
SCOPE_GUARD(deleteFileGuard, bind(&FileWriter::DeleteFileX, std::cref(configPath)));
Platform::ThreadRunner m_runner;
PowerManager manager;
SubscriberForTesting subscriber;
manager.Subscribe(&subscriber);
TestIsAllFacilitiesInState(manager, true);
TEST_EQUAL(manager.GetScheme(), Scheme::Normal, ());
manager.OnBatteryLevelReceived(50);
TestIsAllFacilitiesInState(manager, true);
TEST_EQUAL(manager.GetScheme(), Scheme::Normal, ());
TEST_EQUAL(subscriber.m_onShemeEvents.size(), 0, ());
TEST_EQUAL(subscriber.m_onFacilityEvents.size(), 0, ());
manager.OnBatteryLevelReceived(10);
TestIsAllFacilitiesInState(manager, true);
TEST_EQUAL(manager.GetScheme(), Scheme::Normal, ());
TEST_EQUAL(subscriber.m_onShemeEvents.size(), 0, ());
TEST_EQUAL(subscriber.m_onFacilityEvents.size(), 0, ());
manager.SetScheme(Scheme::Auto);
TEST_EQUAL(subscriber.m_onShemeEvents.size(), 1, ());
TEST_EQUAL(subscriber.m_onShemeEvents[0], Scheme::Auto, ());
TEST_EQUAL(subscriber.m_onFacilityEvents.size(), 0, ());
subscriber.m_onShemeEvents.clear();
subscriber.m_onFacilityEvents.clear();
manager.OnBatteryLevelReceived(50);
TestIsAllFacilitiesInState(manager, true);
TEST_EQUAL(manager.GetScheme(), Scheme::Auto, ());
TEST_EQUAL(subscriber.m_onShemeEvents.size(), 0, ());
TEST_EQUAL(subscriber.m_onFacilityEvents.size(), 0, ());
manager.OnBatteryLevelReceived(28);
TestAllFacilitiesEnabledExcept(manager, {Facility::PerspectiveView, Facility::GpsTrackingForTraffic,
Facility::BookmarkCloudUploading, Facility::MapDownloader});
TEST_EQUAL(manager.GetScheme(), Scheme::Auto, ());
TEST_EQUAL(subscriber.m_onShemeEvents.size(), 0, ());
TEST_EQUAL(subscriber.m_onFacilityEvents.size(), 4, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[0].m_facility, Facility::PerspectiveView, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[0].m_state, false, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[1].m_facility, Facility::GpsTrackingForTraffic, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[1].m_state, false, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[2].m_facility, Facility::BookmarkCloudUploading, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[2].m_state, false, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[3].m_facility, Facility::MapDownloader, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[3].m_state, false, ());
subscriber.m_onShemeEvents.clear();
subscriber.m_onFacilityEvents.clear();
manager.OnBatteryLevelReceived(10);
TestIsAllFacilitiesInState(manager, false);
TEST_EQUAL(manager.GetScheme(), Scheme::Auto, ());
TEST_EQUAL(subscriber.m_onShemeEvents.size(), 0, ());
TEST_EQUAL(subscriber.m_onFacilityEvents.size(), 5, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[0].m_facility, Facility::Buildings3d, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[0].m_state, false, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[1].m_facility, Facility::TrackRecording, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[1].m_state, false, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[2].m_facility, Facility::TrafficJams, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[2].m_state, false, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[3].m_facility, Facility::OsmEditsUploading, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[3].m_state, false, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[4].m_facility, Facility::UgcUploading, ());
TEST_EQUAL(subscriber.m_onFacilityEvents[4].m_state, false, ());
subscriber.m_onShemeEvents.clear();
subscriber.m_onFacilityEvents.clear();
manager.OnBatteryLevelReceived(100);
TestIsAllFacilitiesInState(manager, true);
TEST_EQUAL(manager.GetScheme(), Scheme::Auto, ());
TEST_EQUAL(subscriber.m_onShemeEvents.size(), 0, ());
TEST_EQUAL(subscriber.m_onFacilityEvents.size(), 9, ());
auto const & facilityEvents = subscriber.m_onFacilityEvents;
for (size_t i = 0; i < facilityEvents.size(); ++i)
{
TEST_EQUAL(facilityEvents[i].m_facility, static_cast<Facility>(i), ());
TEST_EQUAL(subscriber.m_onFacilityEvents[i].m_state, true, ());
}
}
} // namespace

View file

@ -0,0 +1,272 @@
// NOTE: the purpose of this test is to test interaction between
// SearchAPI and search engine. If you would like to test search
// engine behaviour, please, consider implementing another search
// integration test.
#include "testing/testing.hpp"
#include "generator/generator_tests_support/test_feature.hpp"
#include "search/search_tests_support/test_results_matching.hpp"
#include "search/search_tests_support/test_with_custom_mwms.hpp"
#include "map/bookmarks_search_params.hpp"
#include "map/search_api.hpp"
#include "map/search_product_info.hpp"
#include "map/viewport_search_params.hpp"
#include "storage/country_info_getter.hpp"
#include "storage/storage.hpp"
#include "indexer/classificator.hpp"
#include <atomic>
#include <functional>
#include <future>
#include <memory>
#include <string>
using namespace search::tests_support;
using namespace generator::tests_support;
using namespace search;
using namespace std;
using namespace storage;
namespace
{
using Rules = vector<shared_ptr<MatchingRule>>;
struct TestCafe : public TestPOI
{
public:
TestCafe(m2::PointD const & center, string const & name, string const & lang) : TestPOI(center, name, lang)
{
SetTypes({{"amenity", "cafe"}});
}
~TestCafe() override = default;
};
class Delegate : public SearchAPI::Delegate
{
public:
~Delegate() override = default;
// SearchAPI::Delegate overrides:
void RunUITask(function<void()> fn) override { fn(); }
};
class SearchAPITest : public generator::tests_support::TestWithCustomMwms
{
public:
SearchAPITest()
: m_infoGetter(CountryInfoReader::CreateCountryInfoGetter(GetPlatform()))
, m_api(m_dataSource, m_storage, *m_infoGetter, 1 /* numThreads */, m_delegate)
{}
protected:
Storage m_storage;
unique_ptr<CountryInfoGetter> m_infoGetter;
Delegate m_delegate;
SearchAPI m_api;
};
UNIT_CLASS_TEST(SearchAPITest, MultipleViewportsRequests)
{
TestCafe cafe1(m2::PointD(0, 0), "cafe 1", "en");
TestCafe cafe2(m2::PointD(0.5, 0.5), "cafe 2", "en");
TestCafe cafe3(m2::PointD(10, 10), "cafe 3", "en");
TestCafe cafe4(m2::PointD(10.5, 10.5), "cafe 4", "en");
auto const id = BuildCountry("Wonderland", [&](TestMwmBuilder & builder)
{
builder.Add(cafe1);
builder.Add(cafe2);
builder.Add(cafe3);
builder.Add(cafe4);
});
atomic<int> stage{0};
promise<void> promise0;
auto future0 = promise0.get_future();
promise<void> promise1;
auto future1 = promise1.get_future();
ViewportSearchParams params;
params.m_query = "cafe ";
params.m_inputLocale = "en";
params.m_onCompleted = [&](Results const & results)
{
TEST(!results.IsEndedCancelled(), ());
if (!results.IsEndMarker())
return;
if (stage == 0)
{
Rules const rules = {ExactMatch(id, cafe1), ExactMatch(id, cafe2)};
TEST(MatchResults(m_dataSource, rules, results), ());
promise0.set_value();
}
else
{
TEST_EQUAL(stage, 1, ());
Rules const rules = {ExactMatch(id, cafe3), ExactMatch(id, cafe4)};
TEST(MatchResults(m_dataSource, rules, results), ());
promise1.set_value();
}
};
m_api.OnViewportChanged(m2::RectD(-1, -1, 1, 1));
m_api.SearchInViewport(params);
future0.wait();
++stage;
m_api.OnViewportChanged(m2::RectD(9, 9, 11, 11));
future1.wait();
}
UNIT_CLASS_TEST(SearchAPITest, Cancellation)
{
TestCafe cafe(m2::PointD(0, 0), "cafe", "en");
auto const id = BuildCountry("Wonderland", [&](TestMwmBuilder & builder) { builder.Add(cafe); });
EverywhereSearchParams commonParams;
commonParams.m_query = "cafe ";
commonParams.m_inputLocale = "en";
{
auto params = commonParams;
promise<void> promise;
auto future = promise.get_future();
params.m_onResults = [&](Results const & results, vector<ProductInfo> const &)
{
TEST(!results.IsEndedCancelled(), ());
if (!results.IsEndMarker())
return;
Rules const rules = {ExactMatch(id, cafe)};
TEST(MatchResults(m_dataSource, rules, results), ());
promise.set_value();
};
m_api.OnViewportChanged(m2::RectD(0.0, 0.0, 1.0, 1.0));
m_api.SearchEverywhere(params);
future.wait();
}
{
auto params = commonParams;
promise<void> promise;
auto future = promise.get_future();
params.m_timeout = chrono::seconds(-1);
params.m_onResults = [&](Results const & results, vector<ProductInfo> const &)
{
// The deadline has fired but Search API does not expose it.
TEST(!results.IsEndedCancelled(), ());
if (!results.IsEndMarker())
return;
Rules const rules = {ExactMatch(id, cafe)};
TEST(MatchResults(m_dataSource, rules, results), ());
promise.set_value();
};
// Force the search by changing the viewport.
m_api.OnViewportChanged(m2::RectD(0.0, 0.0, 2.0, 2.0));
m_api.SearchEverywhere(params);
future.wait();
}
}
UNIT_CLASS_TEST(SearchAPITest, BookmarksSearch)
{
vector<BookmarkInfo> marks;
kml::BookmarkData data;
kml::SetDefaultStr(data.m_name, "R&R dinner");
kml::SetDefaultStr(data.m_description, "They've got a cherry pie there that'll kill ya!");
marks.emplace_back(0, data);
kml::SetDefaultStr(data.m_name, "Silver Mustang Casino");
kml::SetDefaultStr(data.m_description, "Joyful place, owners Bradley and Rodney are very friendly!");
marks.emplace_back(1, data);
kml::SetDefaultStr(data.m_name, "Great Northern Hotel");
kml::SetDefaultStr(data.m_description, "Clean place with a reasonable price");
marks.emplace_back(2, data);
m_api.EnableIndexingOfBookmarksDescriptions(true);
m_api.EnableIndexingOfBookmarkGroup(10, true /* enable */);
m_api.OnBookmarksCreated(marks);
m_api.OnViewportChanged(m2::RectD(-1, -1, 1, 1));
auto runTest = [&](string const & query, kml::MarkGroupId const & groupId, vector<kml::MarkId> const & expected)
{
promise<vector<kml::MarkId>> idsPromise;
auto idsFuture = idsPromise.get_future();
BookmarksSearchParams params;
params.m_query = query;
params.m_onResults = [&](vector<kml::MarkId> const & results, BookmarksSearchParams::Status status)
{
if (status != BookmarksSearchParams::Status::Completed)
return;
idsPromise.set_value(results);
};
params.m_groupId = groupId;
m_api.SearchInBookmarks(params);
auto const ids = idsFuture.get();
TEST_EQUAL(ids, expected, ());
};
string const query = "gread silver hotel";
runTest(query, kml::kInvalidMarkGroupId, vector<kml::MarkId>());
{
vector<BookmarkGroupInfo> groupInfos;
groupInfos.emplace_back(kml::MarkGroupId(10), vector<kml::MarkId>({0, 1}));
groupInfos.emplace_back(kml::MarkGroupId(11), vector<kml::MarkId>({2}));
m_api.OnBookmarksAttached(groupInfos);
}
runTest(query, kml::kInvalidMarkGroupId, vector<kml::MarkId>({1}));
runTest(query, kml::MarkGroupId(11), {});
m_api.EnableIndexingOfBookmarkGroup(11, true /* enable */);
runTest(query, kml::kInvalidMarkGroupId, vector<kml::MarkId>({2, 1}));
runTest(query, kml::MarkGroupId(11), vector<kml::MarkId>({2}));
m_api.EnableIndexingOfBookmarkGroup(11, false /* enable */);
runTest(query, kml::kInvalidMarkGroupId, vector<kml::MarkId>({1}));
runTest(query, kml::MarkGroupId(11), {});
m_api.EnableIndexingOfBookmarkGroup(11, true /* enable */);
{
vector<BookmarkGroupInfo> groupInfos;
groupInfos.emplace_back(kml::MarkGroupId(10), vector<kml::MarkId>({1}));
m_api.OnBookmarksDetached(groupInfos);
}
{
vector<BookmarkGroupInfo> groupInfos;
groupInfos.emplace_back(kml::MarkGroupId(11), vector<kml::MarkId>({1}));
m_api.OnBookmarksAttached(groupInfos);
}
runTest(query, kml::MarkGroupId(11), vector<kml::MarkId>({2, 1}));
m_api.ResetBookmarksEngine();
runTest(query, kml::MarkGroupId(11), {});
}
} // namespace

View file

@ -0,0 +1,158 @@
#include "testing/testing.hpp"
#include "map/track_statistics.hpp"
#include "geometry/mercator.hpp"
#include "geometry/point_with_altitude.hpp"
#include "kml/types.hpp"
namespace track_statistics_tests
{
using namespace geometry;
using namespace location;
GpsInfo const BuildGpsInfo(double latitude, double longitude, double altitude, double timestamp = 0)
{
GpsInfo gpsInfo;
gpsInfo.m_latitude = latitude;
gpsInfo.m_longitude = longitude;
gpsInfo.m_altitude = altitude;
gpsInfo.m_timestamp = timestamp;
return gpsInfo;
}
UNIT_TEST(TrackStatistics_EmptyMultiGeometry)
{
TrackStatistics ts;
TEST_EQUAL(0, ts.m_ascent, ());
TEST_EQUAL(0, ts.m_descent, ());
TEST_EQUAL(ts.m_minElevation, kDefaultAltitudeMeters, ());
TEST_EQUAL(ts.m_maxElevation, kDefaultAltitudeMeters, ());
}
UNIT_TEST(TrackStatistics_FromMultiGeometry)
{
kml::MultiGeometry geometry;
auto const point1 = PointWithAltitude({0.0, 0.0}, 100);
auto const point2 = PointWithAltitude({1.0, 1.0}, 150);
auto const point3 = PointWithAltitude({2.0, 2.0}, 50);
geometry.AddLine({point1, point2, point3});
geometry.AddTimestamps({0, 1, 2});
auto const ts = TrackStatistics(geometry);
TEST_EQUAL(ts.m_minElevation, 50, ());
TEST_EQUAL(ts.m_maxElevation, 150, ());
TEST_EQUAL(ts.m_ascent, 50, ()); // Ascent from 100 -> 150
TEST_EQUAL(ts.m_descent, 100, ()); // Descent from 150 -> 50
TEST_EQUAL(ts.m_duration, 2, ());
double distance = 0;
distance += mercator::DistanceOnEarth(point1, point2);
distance += mercator::DistanceOnEarth(point2, point3);
TEST_EQUAL(ts.m_length, distance, ());
}
UNIT_TEST(TrackStatistics_NoAltitudeAndTimestampPoints)
{
kml::MultiGeometry geometry;
geometry.AddLine({PointWithAltitude({0.0, 0.0}), PointWithAltitude({1.0, 1.0}), PointWithAltitude({2.0, 2.0})});
auto const ts = TrackStatistics(geometry);
TEST_EQUAL(ts.m_minElevation, kDefaultAltitudeMeters, ());
TEST_EQUAL(ts.m_maxElevation, kDefaultAltitudeMeters, ());
TEST_EQUAL(ts.m_ascent, 0, ());
TEST_EQUAL(ts.m_descent, 0, ());
TEST_EQUAL(ts.m_duration, 0, ());
}
UNIT_TEST(TrackStatistics_MultipleLines)
{
kml::MultiGeometry geometry;
geometry.AddLine(
{PointWithAltitude({0.0, 0.0}, 100), PointWithAltitude({1.0, 1.0}, 150), PointWithAltitude({1.0, 1.0}, 140)});
geometry.AddTimestamps({0, 1, 2});
geometry.AddLine(
{PointWithAltitude({2.0, 2.0}, 50), PointWithAltitude({3.0, 3.0}, 75), PointWithAltitude({3.0, 3.0}, 60)});
geometry.AddTimestamps({0, 0, 0});
geometry.AddLine({PointWithAltitude({4.0, 4.0}, 200), PointWithAltitude({5.0, 5.0}, 250)});
geometry.AddTimestamps({4, 5});
auto const ts = TrackStatistics(geometry);
TEST_EQUAL(ts.m_minElevation, 50, ());
TEST_EQUAL(ts.m_maxElevation, 250, ());
TEST_EQUAL(ts.m_ascent, 125, ()); // Ascent from 100 -> 150, 50 -> 75, 200 -> 250
TEST_EQUAL(ts.m_descent, 25, ()); // Descent from 150 -> 140, 75 -> 60
TEST_EQUAL(ts.m_duration, 3, ());
}
UNIT_TEST(TrackStatistics_WithGpsPoints)
{
std::vector<std::vector<GpsInfo>> const pointsData = {
{BuildGpsInfo(0.0, 0.0, 0, 0), BuildGpsInfo(1.0, 1.0, 50, 1), BuildGpsInfo(2.0, 2.0, 100, 2)},
{BuildGpsInfo(3.0, 3.0, -50, 5)},
{BuildGpsInfo(4.0, 4.0, 0, 10)}};
TrackStatistics ts;
for (auto const & pointsList : pointsData)
for (auto const & point : pointsList)
ts.AddGpsInfoPoint(point);
TEST_EQUAL(ts.m_minElevation, -50, ());
TEST_EQUAL(ts.m_maxElevation, 100, ());
TEST_EQUAL(ts.m_ascent, 150, ()); // Ascent from 0 -> 50, 50 -> 100, -50 -> 0
TEST_EQUAL(ts.m_descent, 150, ()); // Descent from 100 -> -50
TEST_EQUAL(ts.m_duration, 10, ());
}
UNIT_TEST(TrackStatistics_PositiveAndNegativeAltitudes)
{
kml::MultiGeometry geometry;
geometry.AddLine({PointWithAltitude({0.0, 0.0}, -10), PointWithAltitude({1.0, 1.0}, 20),
PointWithAltitude({2.0, 2.0}, -5), PointWithAltitude({3.0, 3.0}, 15)});
auto const ts = TrackStatistics(geometry);
TEST_EQUAL(ts.m_minElevation, -10, ());
TEST_EQUAL(ts.m_maxElevation, 20, ());
TEST_EQUAL(ts.m_ascent, 50, ()); // Ascent from -10 -> 20 and -5 -> 15
TEST_EQUAL(ts.m_descent, 25, ()); // Descent from 20 -> -5
}
UNIT_TEST(TrackStatistics_SmallAltitudeDelta)
{
std::vector<GpsInfo> const points = {BuildGpsInfo(0.0, 0.0, 0), BuildGpsInfo(1.0, 1.0, 0.2),
BuildGpsInfo(2.0, 2.0, 0.4), BuildGpsInfo(3.0, 3.0, 0.6),
BuildGpsInfo(4.0, 4.0, 0.8), BuildGpsInfo(5.0, 5.0, 1.0)};
TrackStatistics ts;
for (auto const & point : points)
ts.AddGpsInfoPoint(point);
TEST_EQUAL(ts.m_minElevation, 0, ());
TEST_EQUAL(ts.m_maxElevation, 1.0, ());
TEST_EQUAL(ts.m_ascent, 1.0, ());
TEST_EQUAL(ts.m_descent, 0, ());
}
UNIT_TEST(TrackStatistics_MixedMultiGeometryAndGpsPoints)
{
kml::MultiGeometry geometry;
auto const point1 = PointWithAltitude({0.0, 0.0}, 100);
auto const point2 = PointWithAltitude({1.0, 1.0}, 150);
auto const point3 = PointWithAltitude({2.0, 2.0}, 50);
geometry.AddLine({point1, point2, point3});
geometry.AddTimestamps({5, 6, 7});
auto ts = TrackStatistics(geometry);
std::vector<GpsInfo> const points = {BuildGpsInfo(3.0, 3.0, 60, 8), BuildGpsInfo(4.0, 4.0, 160, 10),
BuildGpsInfo(4.0, 4.0, 20, 15)};
for (auto const & point : points)
ts.AddGpsInfoPoint(point);
TEST_EQUAL(ts.m_minElevation, 20, ());
TEST_EQUAL(ts.m_maxElevation, 160, ());
TEST_EQUAL(ts.m_ascent, 160, ()); // 50 + 10 + 100
TEST_EQUAL(ts.m_descent, 240, ()); // 100 + 140
TEST_EQUAL(ts.m_duration, 10, ()); // 10
}
} // namespace track_statistics_tests

View file

@ -0,0 +1,48 @@
#include "testing/testing.hpp"
#include "coding/string_utf8_multilang.hpp"
#include "coding/transliteration.hpp"
#include "platform/platform.hpp"
namespace
{
void TestTransliteration(Transliteration const & translit, std::string const & locale, std::string const & original,
std::string const & expected)
{
std::string out;
translit.Transliterate(original, StringUtf8Multilang::GetLangIndex(locale), out);
TEST_EQUAL(expected, out, ());
}
} // namespace
// This test is inside of the map_tests because it uses Platform for obtaining the resource directory.
UNIT_TEST(Transliteration_CompareSamples)
{
Transliteration & translit = Transliteration::Instance();
translit.Init(GetPlatform().ResourcesDir());
TestTransliteration(translit, "ar", "العربية", "alrbyt");
TestTransliteration(translit, "ru", "Русский", "Russkiy");
TestTransliteration(translit, "zh", "中文", "zhong wen");
TestTransliteration(translit, "be", "Беларуская", "Byelaruskaya");
TestTransliteration(translit, "ka", "ქართული", "kartuli");
TestTransliteration(translit, "ko", "한국어", "hangug-eo");
TestTransliteration(translit, "he", "עברית", "bryt");
TestTransliteration(translit, "el", "Ελληνικά", "Ellenika");
TestTransliteration(translit, "zh_pinyin", "拼音", "pin yin");
TestTransliteration(translit, "th", "ไทย", ""); // Thai-Latin transliteration is off.
TestTransliteration(translit, "sr", "Српски", "Srpski");
TestTransliteration(translit, "uk", "Українська", "Ukrayinska");
TestTransliteration(translit, "fa", "فارسی", "farsy");
TestTransliteration(translit, "hy", "Հայերէն", "Hayeren");
TestTransliteration(translit, "am", "አማርኛ", "amarinya");
TestTransliteration(translit, "ja_kana", "カタカナ", "katakana");
TestTransliteration(translit, "ja_kana", "ひらがな", "hiragana");
TestTransliteration(translit, "ja_kana", "カタカナ ひらがな", "katakana hiragana");
TestTransliteration(translit, "bg", "Български", "Bulgarski");
TestTransliteration(translit, "kk", "Қазақ", "Qazaq");
TestTransliteration(translit, "mn", "Монгол хэл", "Mongol hel");
TestTransliteration(translit, "mk", "Македонски", "Makedonski");
TestTransliteration(translit, "hi", "हिन्दी", "hindi");
}