diff --git a/.github/workflows/linux-check.yaml b/.github/workflows/linux-check.yaml index 7a955fc0b3..7e6aff5206 100644 --- a/.github/workflows/linux-check.yaml +++ b/.github/workflows/linux-check.yaml @@ -143,6 +143,7 @@ jobs: -e generator_integration_tests \ -e routing_integration_tests \ -e routing_quality_tests \ + -e search_quality_tests \ -e world_feed_integration_tests \ -e drape_tests \ -e shaders_tests \ diff --git a/generator/generator_tests/collector_building_parts_tests.cpp b/generator/generator_tests/collector_building_parts_tests.cpp index 3ff73efc73..8f5dc09761 100644 --- a/generator/generator_tests/collector_building_parts_tests.cpp +++ b/generator/generator_tests/collector_building_parts_tests.cpp @@ -8,12 +8,9 @@ #include "generator/osm_element.hpp" #include "indexer/classificator.hpp" -#include "indexer/classificator_loader.hpp" #include "platform/platform_tests_support/scoped_file.hpp" -#include "geometry/point2d.hpp" - #include #include @@ -30,8 +27,9 @@ public: } // OSMElementCacheReaderInterface overrides: - [[noreturn]] bool Read(generator::cache::Key /* id */, WayElement & /* value */) override { - CHECK(false, ("Should not be called")); + bool Read(generator::cache::Key /* id */, WayElement & /* value */) override + { + UNREACHABLE(); } bool Read(generator::cache::Key id, RelationElement & value) override diff --git a/generator/generator_tests/relation_tags_tests.cpp b/generator/generator_tests/relation_tags_tests.cpp index ca832d8b37..4f41f1237c 100644 --- a/generator/generator_tests/relation_tags_tests.cpp +++ b/generator/generator_tests/relation_tags_tests.cpp @@ -22,8 +22,9 @@ public: } // OSMElementCacheReaderInterface overrides: - [[noreturn]] bool Read(Key /* id */, WayElement & /* value */) override { - CHECK(false, ("Should not be called")); + bool Read(Key /* id */, WayElement & /* value */) override + { + UNREACHABLE(); } bool Read(Key id, RelationElement & value) override @@ -242,4 +243,4 @@ UNIT_TEST(Process_boundary) TEST_EQUAL(outerWay6.GetTag("wikidata"), "Q145694", ()); } -} \ No newline at end of file +} // namespace relation_tags_tests diff --git a/generator/generator_tests_support/test_mwm_builder.cpp b/generator/generator_tests_support/test_mwm_builder.cpp index 6790aeda63..a35e599dfd 100644 --- a/generator/generator_tests_support/test_mwm_builder.cpp +++ b/generator/generator_tests_support/test_mwm_builder.cpp @@ -104,6 +104,9 @@ bool TestMwmBuilder::Add(FeatureBuilder & fb) if (!feature::PreprocessForWorldMap(fb)) return false; break; + case DataHeader::MapType::WorldCoasts: + CHECK(false, ("Coasts are not supported in test builder")); + break; } auto const & isCityTownOrVillage = ftypes::IsCityTownOrVillageChecker::Instance(); diff --git a/generator/generator_tests_support/test_with_custom_mwms.cpp b/generator/generator_tests_support/test_with_custom_mwms.cpp index 1ac517251d..bd840c2582 100644 --- a/generator/generator_tests_support/test_with_custom_mwms.cpp +++ b/generator/generator_tests_support/test_with_custom_mwms.cpp @@ -1,5 +1,7 @@ #include "generator/generator_tests_support/test_with_custom_mwms.hpp" +#include "storage/country_info_getter.hpp" + #include "platform/local_country_file_utils.hpp" #include "base/stl_helpers.hpp" @@ -9,6 +11,8 @@ namespace generator { namespace tests_support { +using namespace platform; + TestWithCustomMwms::TestWithCustomMwms() { m_version = base::GenerateYYMMDD(base::SecondsSinceEpoch()); @@ -21,12 +25,49 @@ TestWithCustomMwms::~TestWithCustomMwms() } // static -void TestWithCustomMwms::Cleanup(platform::LocalCountryFile const & file) +void TestWithCustomMwms::Cleanup(LocalCountryFile const & file) { - platform::CountryIndexes::DeleteFromDisk(file); + CountryIndexes::DeleteFromDisk(file); file.DeleteFromDisk(MapFileType::Map); } -void TestWithCustomMwms::SetMwmVersion(uint32_t version) { m_version = version; } +void TestWithCustomMwms::DeregisterMap(std::string const & name) +{ + auto const file = CountryFile(name); + auto it = base::FindIf(m_files, [&file](LocalCountryFile const & f) + { + return f.GetCountryFile() == file; + }); + + if (it == m_files.end()) + return; + + m_dataSource.DeregisterMap(file); + Cleanup(*it); + m_files.erase(it); +} + +void TestWithCustomMwms::RegisterLocalMapsInViewport(m2::RectD const & viewport) +{ + auto const countriesInfo = storage::CountryInfoReader::CreateCountryInfoGetter(GetPlatform()); + + std::vector localFiles; + FindAllLocalMapsAndCleanup(std::numeric_limits::max() /* latestVersion */, localFiles); + + for (auto const & file : localFiles) + { + // Always load World.mwm, important for search. + auto const & name = file.GetCountryName(); + if (name != WORLD_FILE_NAME && !countriesInfo->GetLimitRectForLeaf(name).IsIntersect(viewport)) + continue; + + auto const res = m_dataSource.RegisterMap(file); + CHECK_EQUAL(res.second, MwmSet::RegResult::Success, ()); + + auto const & info = res.first.GetInfo(); + OnMwmBuilt(*info); + } +} + } // namespace tests_support } // namespace generator diff --git a/generator/generator_tests_support/test_with_custom_mwms.hpp b/generator/generator_tests_support/test_with_custom_mwms.hpp index 2598abc9e0..f10b35511d 100644 --- a/generator/generator_tests_support/test_with_custom_mwms.hpp +++ b/generator/generator_tests_support/test_with_custom_mwms.hpp @@ -6,7 +6,6 @@ #include "editor/editable_data_source.hpp" #include "indexer/data_header.hpp" -#include "indexer/feature.hpp" #include "indexer/mwm_set.hpp" #include "platform/country_file.hpp" @@ -28,16 +27,12 @@ class TestWithCustomMwms : public TestWithClassificator { public: TestWithCustomMwms(); - ~TestWithCustomMwms() override; // Creates a physical country file on a disk, which will be removed // at the end of the test. |fn| is a delegate that accepts a single // argument - TestMwmBuilder and adds all necessary features to the // country file. - // - // *NOTE* when |type| is feature::DataHeader::MapType::Country, the country - // with |name| will be automatically registered. template MwmSet::MwmId BuildMwm(std::string name, feature::DataHeader::MapType type, BuildFn && fn) { @@ -60,34 +55,23 @@ public: return id; } - void DeregisterMap(std::string const & name) - { - auto const file = platform::CountryFile(name); - auto it = base::FindIf(m_files, [&file](platform::LocalCountryFile const & f) { - return f.GetCountryFile() == file; - }); - - if (it == m_files.end()) - return; - - m_dataSource.DeregisterMap(file); - Cleanup(*it); - m_files.erase(it); - } + void DeregisterMap(std::string const & name); template MwmSet::MwmId BuildWorld(BuildFn && fn) { - return BuildMwm("testWorld", feature::DataHeader::MapType::World, std::forward(fn)); + return BuildMwm("testWorld", feature::DataHeader::MapType::World, fn); } template MwmSet::MwmId BuildCountry(std::string_view name, BuildFn && fn) { - return BuildMwm(std::string(name), feature::DataHeader::MapType::Country, std::forward(fn)); + return BuildMwm(std::string(name), feature::DataHeader::MapType::Country, fn); } - void SetMwmVersion(uint32_t version); + void SetMwmVersion(uint32_t version) { m_version = version; } + + void RegisterLocalMapsInViewport(m2::RectD const & viewport); protected: static void Cleanup(platform::LocalCountryFile const & file); diff --git a/search/processor.cpp b/search/processor.cpp index b166e10ec3..f403310681 100644 --- a/search/processor.cpp +++ b/search/processor.cpp @@ -632,10 +632,8 @@ void Processor::Search(SearchParams const & params) case Mode::Count: ASSERT(false, ("Invalid mode")); break; } - if (!viewportSearch && cancellationStatus != Cancellable::Status::CancelCalled) - { - LOG(LWARNING, ("Search cancelled by timeout")); - } + if (!viewportSearch && cancellationStatus == Cancellable::Status::DeadlineExceeded) + LOG(LWARNING, ("Search stopped by timeout")); } void Processor::SearchDebug() diff --git a/search/search_integration_tests/pre_ranker_test.cpp b/search/search_integration_tests/pre_ranker_test.cpp index e06085551c..5ad98a6728 100644 --- a/search/search_integration_tests/pre_ranker_test.cpp +++ b/search/search_integration_tests/pre_ranker_test.cpp @@ -79,7 +79,7 @@ private: bool m_finished = false; }; -class PreRankerTest : public SearchTest +class PreRankerTest : public search::tests_support::SearchTest { public: vector m_suggests; diff --git a/search/search_integration_tests/processor_test.cpp b/search/search_integration_tests/processor_test.cpp index 0a1fa7261c..41517eeba7 100644 --- a/search/search_integration_tests/processor_test.cpp +++ b/search/search_integration_tests/processor_test.cpp @@ -24,12 +24,10 @@ #include "geometry/point2d.hpp" #include "geometry/rect2d.hpp" -#include "base/assert.hpp" #include "base/checked_cast.hpp" #include "base/scope_guard.hpp" #include "base/string_utils.hpp" -#include #include #include #include @@ -281,7 +279,9 @@ UNIT_CLASS_TEST(ProcessorTest, SearchInWorld) builder.Add(wonderland); builder.Add(losAlamos); }); - RegisterCountry(countryName, m2::RectD(-1.0, -1.0, 1.0, 1.0)); + + // Manually call RegisterCountry, because we don't call BuildCountry. + RegisterCountry(countryName, {-1.0, -1.0, 1.0, 1.0}); SetViewport(m2::RectD(-1.0, -1.0, -0.5, -0.5)); { @@ -328,11 +328,11 @@ UNIT_CLASS_TEST(ProcessorTest, SearchByName) SetViewport(m2::RectD(0.5, 0.5, 1.5, 1.5)); { Rules rules = {ExactMatch(worldId, london)}; - TEST(ResultsMatch("london", Mode::Downloader, rules), ()); + TEST(ResultsMatch("london", rules, "en", Mode::Downloader), ()); } { Rules rules = {ExactMatch(worldId, london), ExactMatch(wonderlandId, cafe)}; - TEST(ResultsMatch("london", Mode::Everywhere, rules), ()); + TEST(ResultsMatch("london", rules, "en", Mode::Everywhere), ()); } } @@ -555,27 +555,27 @@ UNIT_CLASS_TEST(ProcessorTest, TestHouseNumbers) { Rules rules{ExactMatch(countryId, building100), ExactMatch(countryId, street)}; - TEST(ResultsMatch("Зеленоград генералова к100 ", "ru", rules), ()); + TEST(ResultsMatch("Зеленоград генералова к100 ", rules, "ru"), ()); } { Rules rules{ExactMatch(countryId, building200), ExactMatch(countryId, street)}; - TEST(ResultsMatch("Зеленоград генералова к200 ", "ru", rules), ()); + TEST(ResultsMatch("Зеленоград генералова к200 ", rules, "ru"), ()); } { Rules rules{ExactMatch(countryId, building200), ExactMatch(countryId, street)}; - TEST(ResultsMatch("Зеленоград к200 генералова ", "ru", rules), ()); + TEST(ResultsMatch("Зеленоград к200 генералова ", rules, "ru"), ()); } { Rules rules{ExactMatch(countryId, building300), ExactMatch(countryId, street)}; - TEST(ResultsMatch("Зеленоград 300 строение 400 генералова ", "ru", rules), ()); + TEST(ResultsMatch("Зеленоград 300 строение 400 генералова ", rules, "ru"), ()); } { Rules rules{ExactMatch(countryId, street)}; - TEST(ResultsMatch("Зеленоград генералова строе 300", "ru", rules), ()); + TEST(ResultsMatch("Зеленоград генералова строе 300", rules, "ru"), ()); } { Rules rules{ExactMatch(countryId, building300), ExactMatch(countryId, street)}; - TEST(ResultsMatch("Зеленоград генералова 300 строе", "ru", rules), ()); + TEST(ResultsMatch("Зеленоград генералова 300 строе", rules, "ru"), ()); } { auto request = MakeRequest("Зеленоград Генерала Генералова 115 ", "ru"); @@ -583,7 +583,7 @@ UNIT_CLASS_TEST(ProcessorTest, TestHouseNumbers) // Test exact matching result ranked first. auto const & results = request->Results(); TEST_GREATER(results.size(), 0, (results)); - TEST(ResultMatches(results[0], ExactMatch(countryId, building115)), (results)); + TEST(IsResultMatches(results[0], ExactMatch(countryId, building115)), (results)); Rules rules{ExactMatch(countryId, building115), ExactMatch(countryId, building115k1), ExactMatch(countryId, street)}; @@ -595,7 +595,7 @@ UNIT_CLASS_TEST(ProcessorTest, TestHouseNumbers) // Test exact matching result ranked first. auto const & results = request->Results(); TEST_GREATER(results.size(), 0, (results)); - TEST(ResultMatches(results[0], ExactMatch(countryId, building115k1)), (results)); + TEST(IsResultMatches(results[0], ExactMatch(countryId, building115k1)), (results)); Rules rules{ExactMatch(countryId, building115k1), ExactMatch(countryId, building115), ExactMatch(countryId, street)}; @@ -603,7 +603,7 @@ UNIT_CLASS_TEST(ProcessorTest, TestHouseNumbers) } { Rules rules{ExactMatch(countryId, building115), ExactMatch(countryId, street)}; - TEST(ResultsMatch("Зеленоград Генерала Генералова 115к2 ", "ru", rules), ()); + TEST(ResultsMatch("Зеленоград Генерала Генералова 115к2 ", rules, "ru"), ()); } } @@ -679,29 +679,29 @@ UNIT_CLASS_TEST(ProcessorTest, TestPostcodes) { Rules rules{ExactMatch(countryId, building28), ExactMatch(countryId, street)}; - TEST(ResultsMatch("Долгопрудный первомайская 28а ", "ru", rules), ()); + TEST(ResultsMatch("Долгопрудный первомайская 28а ", rules, "ru"), ()); } { Rules rules{ExactMatch(countryId, building28), ExactMatch(countryId, street)}; - TEST(ResultsMatch("Долгопрудный первомайская 28а, 141701", "ru", rules), ()); + TEST(ResultsMatch("Долгопрудный первомайская 28а, 141701", rules, "ru"), ()); } { Rules rules{ExactMatch(countryId, building28), ExactMatch(countryId, building29), ExactMatch(countryId, building30), ExactMatch(countryId, street)}; - TEST(ResultsMatch("Долгопрудный первомайская 141701", "ru", rules), ()); + TEST(ResultsMatch("Долгопрудный первомайская 141701", rules, "ru"), ()); } { Rules rules{ExactMatch(countryId, building31), ExactMatch(countryId, street)}; - TEST(ResultsMatch("Долгопрудный первомайская 141702", "ru", rules), ()); + TEST(ResultsMatch("Долгопрудный первомайская 141702", rules, "ru"), ()); } { Rules rules{ExactMatch(countryId, building28), ExactMatch(countryId, building29), ExactMatch(countryId, building30), ExactMatch(countryId, street)}; - TEST(ResultsMatch("Долгопрудный 141701", "ru", rules), ()); + TEST(ResultsMatch("Долгопрудный 141701", rules, "ru"), ()); } { Rules rules{ExactMatch(countryId, building31)}; - TEST(ResultsMatch("Долгопрудный 141702", "ru", rules), ()); + TEST(ResultsMatch("Долгопрудный 141702", rules, "ru"), ()); } { @@ -787,7 +787,7 @@ UNIT_CLASS_TEST(ProcessorTest, TestCategories) TEST(ResultsMatch("wifi", {ExactMatch(wonderlandId, cafe)}), ()); TEST(ResultsMatch("wi-fi", {ExactMatch(wonderlandId, cafe)}), ()); - TEST(ResultsMatch("wai-fai", Rules{}), ()); + TEST(ResultsMatch("wai-fai", {}), ()); TEST(ResultsMatch("toilet", {ExactMatch(wonderlandId, toi)}), ()); TEST(ResultsMatch("beach ", {ExactMatch(wonderlandId, nonameBeach), ExactMatch(wonderlandId, namedBeach)}), @@ -932,7 +932,6 @@ UNIT_CLASS_TEST(ProcessorTest, SearchDebug) builder.Add(hotel); builder.Add(cafe); }); - RegisterCountry(countryName, m2::RectD(-100.0, -100.0, 100.0, 100.0)); auto const ruleCity = ExactMatch(testWorldId, debugville); auto const ruleCafe = ExactMatch(wonderlandId, cafe); @@ -1033,28 +1032,28 @@ UNIT_CLASS_TEST(ProcessorTest, FuzzyMatch) { Rules rulesWithoutStreet = {ExactMatch(id, bar)}; Rules rules = {ExactMatch(id, bar), ExactMatch(id, street)}; - TEST(ResultsMatch("москва черчилль", "ru", rulesWithoutStreet), ()); - TEST(ResultsMatch("москва ленинградский черчилль", "ru", rules), ()); - TEST(ResultsMatch("москва ленинградский паб черчилль", "ru", rules), ()); + TEST(ResultsMatch("москва черчилль", rulesWithoutStreet, "ru"), ()); + TEST(ResultsMatch("москва ленинградский черчилль", rules, "ru"), ()); + TEST(ResultsMatch("москва ленинградский паб черчилль", rules, "ru"), ()); - TEST(ResultsMatch("масква лининградский черчиль", "ru", rules), ()); - TEST(ResultsMatch("масква ленинргадский черчиль", "ru", rules), ()); + TEST(ResultsMatch("масква лининградский черчиль", rules, "ru"), ()); + TEST(ResultsMatch("масква ленинргадский черчиль", rules, "ru"), ()); // Too many errors, can't do anything. - TEST(ResultsMatch("маcсква лениноргадсский чирчиль", "ru", Rules{}), ()); + TEST(ResultsMatch("маcсква лениноргадсский чирчиль", {}, "ru"), ()); - TEST(ResultsMatch("моксва ленинргадский черчиль", "ru", rules), ()); + TEST(ResultsMatch("моксва ленинргадский черчиль", rules, "ru"), ()); - TEST(ResultsMatch("food", "ru", rulesWithoutStreet), ()); - TEST(ResultsMatch("foood", "ru", rulesWithoutStreet), ()); - TEST(ResultsMatch("fod", "ru", Rules{}), ()); + TEST(ResultsMatch("food", rulesWithoutStreet, "ru"), ()); + TEST(ResultsMatch("foood", rulesWithoutStreet, "ru"), ()); + TEST(ResultsMatch("fod", {}, "ru"), ()); Rules rulesMetro = {ExactMatch(id, metro)}; - TEST(ResultsMatch("transporte", "es", rulesMetro), ()); - TEST(ResultsMatch("transport", "es", rulesMetro), ()); - TEST(ResultsMatch("transpurt", "en", rulesMetro), ()); - TEST(ResultsMatch("transpurrt", "es", rulesMetro), ()); - TEST(ResultsMatch("transportation", "en", Rules{}), ()); + TEST(ResultsMatch("transporte", rulesMetro, "es"), ()); + TEST(ResultsMatch("transport", rulesMetro, "es"), ()); + TEST(ResultsMatch("transpurt", rulesMetro, "en"), ()); + TEST(ResultsMatch("transpurrt", rulesMetro, "es"), ()); + TEST(ResultsMatch("transportation", {}, "en"), ()); } } @@ -1079,10 +1078,10 @@ UNIT_CLASS_TEST(ProcessorTest, SpacesInCategories) { Rules rules = {ExactMatch(id, nightclub)}; - TEST(ResultsMatch("nightclub", "en", rules), ()); - TEST(ResultsMatch("night club", "en", rules), ()); - TEST(ResultsMatch("n i g h t c l u b", "en", Rules{}), ()); - TEST(ResultsMatch("Москва ночной клуб", "ru", rules), ()); + TEST(ResultsMatch("nightclub", rules), ()); + TEST(ResultsMatch("night club", rules), ()); + TEST(ResultsMatch("n i g h t c l u b", {}), ()); + TEST(ResultsMatch("Москва ночной клуб", rules, "ru"), ()); } } @@ -1122,13 +1121,13 @@ UNIT_CLASS_TEST(ProcessorTest, StopWords) { Rules rules = {ExactMatch(id, bakery)}; - TEST(ResultsMatch("la boulangerie ", "fr", rules), ()); + TEST(ResultsMatch("la boulangerie ", rules, "fr"), ()); } { - TEST(ResultsMatch("la motviderie ", "fr", Rules{}), ()); - TEST(ResultsMatch("la la le la la la ", "fr", {ExactMatch(id, street)}), ()); - TEST(ResultsMatch("la la le la la la", "fr", Rules{}), ()); + TEST(ResultsMatch("la motviderie ", {}, "fr"), ()); + TEST(ResultsMatch("la la le la la la ", {ExactMatch(id, street)}, "fr"), ()); + TEST(ResultsMatch("la la le la la la", {}, "fr"), ()); } } @@ -1141,16 +1140,16 @@ UNIT_CLASS_TEST(ProcessorTest, Numerals) auto id = BuildCountry(country.GetName("ru"), [&](TestMwmBuilder & builder) { builder.Add(school); -}); + }); SetViewport(m2::RectD(-1.0, -1.0, 1.0, 1.0)); { Rules rules{ExactMatch(id, school)}; - TEST(ResultsMatch("Школа 61", "ru", rules), ()); - TEST(ResultsMatch("Школа # 61", "ru", rules), ()); - TEST(ResultsMatch("school #61", "ru", rules), ()); - TEST(ResultsMatch("сш №61", "ru", rules), ()); - TEST(ResultsMatch("школа", "ru", rules), ()); + TEST(ResultsMatch("Школа 61", rules, "ru"), ()); + TEST(ResultsMatch("Школа # 61", rules, "ru"), ()); + TEST(ResultsMatch("school #61", rules, "ru"), ()); + TEST(ResultsMatch("сш №61", rules, "ru"), ()); + TEST(ResultsMatch("школа", rules, "ru"), ()); } } @@ -1179,26 +1178,26 @@ UNIT_CLASS_TEST(ProcessorTest, TestWeirdTypes) { Rules rules{ExactMatch(countryId, defibrillator1), ExactMatch(countryId, defibrillator2)}; - TEST(ResultsMatch("defibrillator", "en", rules), ()); - TEST(ResultsMatch("除細動器", "ja", rules), ()); + TEST(ResultsMatch("defibrillator", rules, "en"), ()); + TEST(ResultsMatch("除細動器", rules, "ja"), ()); Rules onlyFirst{ExactMatch(countryId, defibrillator1)}; Rules firstWithStreet{ExactMatch(countryId, defibrillator1), ExactMatch(countryId, street)}; // City + category. Only the first defibrillator is inside. - TEST(ResultsMatch("東京 除細動器 ", "ja", onlyFirst), ()); + TEST(ResultsMatch("東京 除細動器 ", onlyFirst, "ja"), ()); // City + street + category. - TEST(ResultsMatch("東京 竹下通り 除細動器 ", "ja", firstWithStreet), ()); + TEST(ResultsMatch("東京 竹下通り 除細動器 ", firstWithStreet, "ja"), ()); } { Rules rules{ExactMatch(countryId, fireHydrant)}; - TEST(ResultsMatch("fire hydrant", "en", rules), ()); - TEST(ResultsMatch("гидрант", "ru", rules), ()); - TEST(ResultsMatch("пожарный гидрант", "ru", rules), ()); + TEST(ResultsMatch("fire hydrant", rules, "en"), ()); + TEST(ResultsMatch("гидрант", rules, "ru"), ()); + TEST(ResultsMatch("пожарный гидрант", rules, "ru"), ()); - TEST(ResultsMatch("fire station", "en", Rules{}), ()); + TEST(ResultsMatch("fire station", {}, "en"), ()); } } @@ -1210,7 +1209,7 @@ UNIT_CLASS_TEST(ProcessorTest, CityBoundaryLoad) SetViewport(m2::RectD(-1.0, -1.0, 1.0, 1.0)); { Rules const rules{ExactMatch(id, city)}; - TEST(ResultsMatch("moscow", "en", rules), ()); + TEST(ResultsMatch("moscow", rules), ()); } CitiesBoundariesTable table(m_dataSource); @@ -1264,13 +1263,13 @@ UNIT_CLASS_TEST(ProcessorTest, CityBoundarySmoke) for (auto const & result : results) { - if (ResultMatches(result, ExactMatch(countryId, cafeMoscow))) + if (IsResultMatches(result, ExactMatch(countryId, cafeMoscow))) { TEST_EQUAL(result.GetAddress(), "Москва, Россия", ()); } else { - TEST(ResultMatches(result, ExactMatch(countryId, cafeKhimki)), ()); + TEST(IsResultMatches(result, ExactMatch(countryId, cafeKhimki)), ()); TEST_EQUAL(result.GetAddress(), "Химки, Россия", ()); } } @@ -1302,6 +1301,12 @@ UNIT_CLASS_TEST(ProcessorTest, RelaxedRetrieval) TestPOI poi2({2.0, 0.0}, "Post box", "en"); poi2.SetTypes({{"amenity", "post_box"}}); + auto worldId = BuildWorld([&](TestMwmBuilder & builder) + { + builder.Add(country); + builder.Add(city); + }); + auto countryId = BuildCountry(countryName, [&](TestMwmBuilder & builder) { builder.Add(street); @@ -1309,13 +1314,9 @@ UNIT_CLASS_TEST(ProcessorTest, RelaxedRetrieval) builder.Add(building1); builder.Add(poi0); }); - RegisterCountry(countryName, m2::RectD(-10.0, -10.0, 10.0, 10.0)); - auto worldId = BuildWorld([&](TestMwmBuilder & builder) - { - builder.Add(country); - builder.Add(city); - }); + // Manually call RegisterCountry because it should include |country| by rect. + RegisterCountry(countryName, {-10.0, -10.0, 10.0, 10.0}); { Rules rulesStrict = {ExactMatch(countryId, building0)}; @@ -1393,7 +1394,6 @@ UNIT_CLASS_TEST(ProcessorTest, PathsThroughLayers) builder.Add(scienceCountry); builder.Add(mathTown); }); - RegisterCountry(countryName, m2::RectD(-100.0, -100.0, 100.0, 100.0)); auto countryId = BuildCountry(countryName, [&](TestMwmBuilder & builder) { @@ -1453,7 +1453,7 @@ UNIT_CLASS_TEST(ProcessorTest, PathsThroughLayers) // BUILDING TEST(ResultsMatch("statistical learning ", {ruleBuilding}), ()); // Cannot find anything only by a house number. - TEST(ResultsMatch("0 ", Rules{}), ()); + TEST(ResultsMatch("0 ", {}), ()); // STREET TEST(ResultsMatch("computing street ", {ruleStreet}), ()); @@ -1534,13 +1534,13 @@ UNIT_CLASS_TEST(ProcessorTest, CuisineTest) { Rules rules{ExactMatch(countryId, vegan)}; - TEST(ResultsMatch("vegan ", "en", rules), ()); + TEST(ResultsMatch("vegan ", rules), ()); } { Rules rules{ExactMatch(countryId, pizza)}; - TEST(ResultsMatch("pizza ", "en", rules), ()); - TEST(ResultsMatch("pizzeria ", "en", rules), ()); + TEST(ResultsMatch("pizza ", rules), ()); + TEST(ResultsMatch("pizzeria ", rules), ()); } } @@ -1562,15 +1562,15 @@ UNIT_CLASS_TEST(ProcessorTest, OrganicTest) { Rules rules{ExactMatch(countryId, cafe), ExactMatch(countryId, shop)}; - TEST(ResultsMatch("органическая ", "ru", rules), ()); + TEST(ResultsMatch("органическая ", rules, "ru"), ()); } { Rules rules{ExactMatch(countryId, shop)}; - TEST(ResultsMatch("органический магазин", "ru", rules), ()); + TEST(ResultsMatch("органический магазин", rules, "ru"), ()); } { Rules rules{ExactMatch(countryId, cafe)}; - TEST(ResultsMatch("органическое кафе", "ru", rules), ()); + TEST(ResultsMatch("органическое кафе", rules, "ru"), ()); } TEST_EQUAL(GetResultsNumber("органическая обувь", "ru"), 0, ()); } @@ -1593,11 +1593,11 @@ UNIT_CLASS_TEST(ProcessorTest, RecyclingTest) { Rules rules{ExactMatch(countryId, paper), ExactMatch(countryId, metal)}; - TEST(ResultsMatch("прием вторсырья", "ru", rules), ()); + TEST(ResultsMatch("прием вторсырья", rules, "ru"), ()); } { Rules rules{ExactMatch(countryId, paper)}; - TEST(ResultsMatch("прием бумаги", "ru", rules), ()); + TEST(ResultsMatch("прием бумаги", rules, "ru"), ()); } TEST_EQUAL(GetResultsNumber("прием обуви", "ru"), 0, ()); } @@ -1617,12 +1617,12 @@ UNIT_CLASS_TEST(ProcessorTest, AirportTest) { Rules rules{ExactMatch(countryId, vko)}; - TEST(ResultsMatch("vko ", "en", rules), ()); + TEST(ResultsMatch("vko ", rules), ()); } { Rules rules{ExactMatch(countryId, svo)}; - TEST(ResultsMatch("svo ", "en", rules), ()); + TEST(ResultsMatch("svo ", rules), ()); } } @@ -1641,18 +1641,18 @@ UNIT_CLASS_TEST(ProcessorTest, OperatorTest) { Rules rules{ExactMatch(countryId, sber)}; - TEST(ResultsMatch("sberbank ", "en", rules), ()); - TEST(ResultsMatch("sberbank atm ", "en", rules), ()); - TEST(ResultsMatch("atm sberbank ", "en", rules), ()); + TEST(ResultsMatch("sberbank ", rules), ()); + TEST(ResultsMatch("sberbank atm ", rules), ()); + TEST(ResultsMatch("atm sberbank ", rules), ()); } { Rules rules{ExactMatch(countryId, alfa)}; - TEST(ResultsMatch("alfa bank ", "en", rules), ()); - TEST(ResultsMatch("alfa bank atm ", "en", rules), ()); - TEST(ResultsMatch("alfa atm ", "en", rules), ()); - TEST(ResultsMatch("atm alfa bank ", "en", rules), ()); - TEST(ResultsMatch("atm alfa ", "en", rules), ()); + TEST(ResultsMatch("alfa bank ", rules), ()); + TEST(ResultsMatch("alfa bank atm ", rules), ()); + TEST(ResultsMatch("alfa atm ", rules), ()); + TEST(ResultsMatch("atm alfa bank ", rules), ()); + TEST(ResultsMatch("atm alfa ", rules), ()); } } @@ -1671,18 +1671,18 @@ UNIT_CLASS_TEST(ProcessorTest, BrandTest) { Rules rules{ExactMatch(countryId, mac)}; - TEST(ResultsMatch("McDonald's", "en", rules), ()); - TEST(ResultsMatch("Mc Donalds", "en", rules), ()); - TEST(ResultsMatch("МакДональд'с", "ru", rules), ()); - TEST(ResultsMatch("Мак Доналдс", "ru", rules), ()); - TEST(ResultsMatch("マクドナルド", "ja", rules), ()); + TEST(ResultsMatch("McDonald's", rules, "en"), ()); + TEST(ResultsMatch("Mc Donalds", rules, "en"), ()); + TEST(ResultsMatch("МакДональд'с", rules, "ru"), ()); + TEST(ResultsMatch("Мак Доналдс", rules, "ru"), ()); + TEST(ResultsMatch("マクドナルド", rules, "ja"), ()); } { Rules rules{ExactMatch(countryId, sw)}; - TEST(ResultsMatch("Subway cafe", "en", rules), ()); - TEST(ResultsMatch("Сабвэй", "ru", rules), ()); - TEST(ResultsMatch("サブウェイ", "ja", rules), ()); + TEST(ResultsMatch("Subway cafe", rules, "en"), ()); + TEST(ResultsMatch("Сабвэй", rules, "ru"), ()); + TEST(ResultsMatch("サブウェイ", rules, "ja"), ()); } } @@ -1987,12 +1987,14 @@ UNIT_CLASS_TEST(ProcessorTest, Strasse) TestStreet s1({{-1.0, -1.0},{1.0, 1.0}}, "abcdstraße", "en"); TestStreet s2({{1.0, -1.0}, {-1.0, 1.0}}, "xyz strasse", "en"); - auto countryId = BuildCountry("Wonderland", [&](TestMwmBuilder & builder) { + auto countryId = BuildCountry("Wonderland", [&](TestMwmBuilder & builder) + { builder.Add(s1); builder.Add(s2); }); - auto checkNoErrors = [&](string const & query, Rules const & rules) { + auto checkNoErrors = [&](string const & query, Rules const & rules) + { auto request = MakeRequest(query, "en"); auto const & results = request->Results(); @@ -2258,7 +2260,7 @@ UNIT_CLASS_TEST(ProcessorTest, StreetPostcodes) { Rules rules{ExactMatch(countryId, building4), ExactMatch(countryId, street)}; // Test that we do not require the building to have a postcode if the street has. - TEST(ResultsMatch("4 Rue des Serpents 67390 ", "ru", rules), ()); + TEST(ResultsMatch("4 Rue des Serpents 67390 ", rules, "ru"), ()); } { Rules rules{ExactMatch(countryId, street)}; @@ -2371,28 +2373,28 @@ UNIT_CLASS_TEST(ProcessorTest, OrderCountries) TestCafe cambridgeCafe({-10.02, 14.01}, "Cambridge Wheeling cafe", "en"); auto worldId = BuildWorld([&](TestMwmBuilder & builder) { builder.Add(london); }); - auto UkId = BuildCountry(UkCountryName, [&](TestMwmBuilder & builder) { + auto UkId = BuildCountry(UkCountryName, [&](TestMwmBuilder & builder) + { builder.Add(london); builder.Add(piccadilly); builder.Add(cambridge); builder.Add(wheeling); }); - auto const UkCountryRect = m2::RectD(0.5, 0.5, 3.5, 3.5); - RegisterCountry(UkCountryName, UkCountryRect); - auto cafeLandId = BuildCountry(cafeLandName, [&](TestMwmBuilder & builder) { + auto cafeLandId = BuildCountry(cafeLandName, [&](TestMwmBuilder & builder) + { builder.Add(dummyPoi); builder.Add(londonCafe); builder.Add(cambridgeCafe); }); + auto const UkCountryRect = m2::RectD(0.5, 0.5, 3.5, 3.5); auto const cafeLandRect = m2::RectD(-10.5, 4.0, 0.0, 14.5); - RegisterCountry(cafeLandName, cafeLandRect); - auto const viewportRect = m2::RectD(-1.0, 4.0, 0.0, 5.0); SetViewport(viewportRect); - CHECK(!viewportRect.IsIntersect(UkCountryRect), ()); - CHECK(viewportRect.IsIntersect(cafeLandRect), ()); + TEST(!viewportRect.IsIntersect(UkCountryRect), ()); + TEST(viewportRect.IsIntersect(cafeLandRect), ()); + { auto request = MakeRequest("London Piccadilly"); auto const & results = request->Results(); @@ -2442,7 +2444,7 @@ UNIT_CLASS_TEST(ProcessorTest, Suburbs) auto request = MakeRequest(query); auto const & results = request->Results(); TEST_GREATER(results.size(), 0, (results)); - TEST(ResultMatches(results[0], expected), (query, results)); + TEST(IsResultMatches(results[0], expected), (query, results)); auto const & info = results[0].GetRankingInfo(); TEST(info.m_exactMatch, ()); @@ -2923,7 +2925,8 @@ UNIT_CLASS_TEST(ProcessorTest, TestRankingInfo_IsAltOrOldName) SetViewport(m2::RectD(-1, -1, 1, 1)); - auto checkIsAltOrOldName = [&](string const & query, bool isAltOrOldName) { + auto checkIsAltOrOldName = [&](string const & query, bool isAltOrOldName) + { auto request = MakeRequest(query, "ru"); auto const & results = request->Results(); @@ -3063,7 +3066,7 @@ UNIT_CLASS_TEST(ProcessorTest, PostCategoryTest) { Rules rules{ExactMatch(countryId, office), ExactMatch(countryId, box), ExactMatch(countryId, locker)}; - TEST(ResultsMatch("Oficina de correos", "es", rules), ()); + TEST(ResultsMatch("Oficina de correos", rules, "es"), ()); } { @@ -3090,12 +3093,12 @@ UNIT_CLASS_TEST(ProcessorTest, SportTest) { Rules rules{ExactMatch(countryId, tennis), ExactMatch(countryId, soccer)}; - TEST(ResultsMatch("sportplatz", "de", rules), ()); + TEST(ResultsMatch("sportplatz", rules, "de"), ()); } { Rules rules{ExactMatch(countryId, tennis)}; - TEST(ResultsMatch("теннис", "ru", rules), ()); + TEST(ResultsMatch("теннис", rules, "ru"), ()); } { @@ -3138,8 +3141,6 @@ UNIT_CLASS_TEST(ProcessorTest, PoiStreetCity_FancyMatch) SetViewport(RectByCenterLatLonAndSizeInMeters(53.8861373, 27.5492881, 100)); // Minsk - base::ScopedLogLevelChanger const enableDebug(LDEBUG); - auto request = MakeRequest("улица Толстого Молодечно"); auto const & results = request->Results(); diff --git a/search/search_integration_tests/search_edited_features_test.cpp b/search/search_integration_tests/search_edited_features_test.cpp index be4c3c6d1f..7910f2834f 100644 --- a/search/search_integration_tests/search_edited_features_test.cpp +++ b/search/search_integration_tests/search_edited_features_test.cpp @@ -11,16 +11,14 @@ #include "coding/string_utf8_multilang.hpp" +namespace search_edited_features_test +{ using namespace generator::tests_support; using namespace search::tests_support; using namespace search; using namespace std; -namespace -{ -class SearchEditedFeaturesTest : public SearchTest -{ -}; +using SearchEditedFeaturesTest = SearchTest; UNIT_CLASS_TEST(SearchEditedFeaturesTest, Smoke) { @@ -90,7 +88,8 @@ UNIT_CLASS_TEST(SearchEditedFeaturesTest, SearchInViewport) BuildWorld([&](TestMwmBuilder & builder) { builder.Add(city); }); - auto const countryId = BuildCountry("Equestria", [&](TestMwmBuilder & builder) { + auto const countryId = BuildCountry("Equestria", [&](TestMwmBuilder & builder) + { builder.Add(bakery0); builder.Add(cornerPost); }); @@ -106,43 +105,38 @@ UNIT_CLASS_TEST(SearchEditedFeaturesTest, SearchInViewport) FeatureID const & id3 = tmp3.second; UNUSED_VALUE(id2); - SetViewport(m2::RectD(-1.0, -1.0, 4.0, 4.0)); + SetViewport({-1.0, -1.0, 4.0, 4.0}); { Rules const rules = {ExactMatch(countryId, bakery0), ExactMatch(countryId, bakery1), ExactMatch(countryId, bakery2), ExactMatch(countryId, bakery3)}; - TEST(ResultsMatch("french bakery", Mode::Viewport, rules), ()); + TEST(ResultsMatch("french bakery", rules, "en", Mode::Viewport), ()); } - SetViewport(m2::RectD(-2.0, -2.0, -1.0, -1.0)); + SetViewport({-2.0, -2.0, -1.0, -1.0}); { - Rules const rules = {}; - - TEST(ResultsMatch("french bakery", Mode::Viewport, rules), ()); + TEST(ResultsMatch("french bakery", {}, "en", Mode::Viewport), ()); } - SetViewport(m2::RectD(-1.0, -1.0, 1.5, 1.5)); + SetViewport({-1.0, -1.0, 1.5, 1.5}); { Rules const rules = {ExactMatch(countryId, bakery0), ExactMatch(countryId, bakery1)}; - - TEST(ResultsMatch("french bakery", Mode::Viewport, rules), ()); + TEST(ResultsMatch("french bakery", rules, "en", Mode::Viewport), ()); } - SetViewport(m2::RectD(1.5, 1.5, 4.0, 4.0)); + SetViewport({1.5, 1.5, 4.0, 4.0}); { Rules const rules = {ExactMatch(countryId, bakery2), ExactMatch(countryId, bakery3)}; - - TEST(ResultsMatch("french bakery", Mode::Viewport, rules), ()); + TEST(ResultsMatch("french bakery", rules, "en", Mode::Viewport), ()); } editor.DeleteFeature(id1); editor.DeleteFeature(id3); - SetViewport(m2::RectD(-1.0, -1.0, 4.0, 4.0)); + SetViewport({-1.0, -1.0, 4.0, 4.0}); { Rules const rules = {ExactMatch(countryId, bakery0), ExactMatch(countryId, bakery2)}; - - TEST(ResultsMatch("french bakery", Mode::Viewport, rules), ()); + TEST(ResultsMatch("french bakery", rules, "en", Mode::Viewport), ()); } } @@ -153,7 +147,8 @@ UNIT_CLASS_TEST(SearchEditedFeaturesTest, ViewportFilter) TestPOI dummy(m2::PointD(1.0, 1.0), "dummy", "default"); auto & editor = osm::Editor::Instance(); - auto const countryId = BuildCountry("Wounderland", [&](TestMwmBuilder & builder) { + auto const countryId = BuildCountry("Wounderland", [&](TestMwmBuilder & builder) + { builder.Add(restaurant); builder.Add(dummy); }); @@ -161,13 +156,14 @@ UNIT_CLASS_TEST(SearchEditedFeaturesTest, ViewportFilter) auto const tmp = TestPOI::AddWithEditor(editor, countryId, "Pushkin cafe", {0.01, 0.01}); TestPOI const & cafe = tmp.first; + SearchParams params; + params.m_query = "pushkin"; + params.m_inputLocale = "en"; + params.m_viewport = { -1.0, -1.0, 1.0, 1.0 }; + params.m_mode = Mode::Viewport; + // Test center for created feature loaded and filter for viewport works. { - SearchParams params; - params.m_query = "pushkin"; - params.m_inputLocale = "en"; - params.m_viewport = { -1.0, -1.0, 1.0, 1.0 }; - params.m_mode = Mode::Viewport; params.m_minDistanceOnMapBetweenResults = { 0.02, 0.02 }; // Min distance on map between results is 0.02, distance between results is 0.01. @@ -180,11 +176,6 @@ UNIT_CLASS_TEST(SearchEditedFeaturesTest, ViewportFilter) } { - SearchParams params; - params.m_query = "pushkin"; - params.m_inputLocale = "en"; - params.m_viewport = { -1.0, -1.0, 1.0, 1.0 }; - params.m_mode = Mode::Viewport; params.m_minDistanceOnMapBetweenResults = { 0.005, 0.005 }; // Min distance on map between results is 0.005, distance between results is 0.01. @@ -196,12 +187,8 @@ UNIT_CLASS_TEST(SearchEditedFeaturesTest, ViewportFilter) TEST(ResultsMatch(request.Results(), rulesViewport), ()); } - SetViewport(m2::RectD(-1.0, -1.0, 1.0, 1.0)); + SetViewport({-1.0, -1.0, 1.0, 1.0}); { - SearchParams params; - params.m_query = "pushkin"; - params.m_inputLocale = "en"; - params.m_viewport = { -1.0, -1.0, 1.0, 1.0 }; params.m_mode = Mode::Everywhere; params.m_minDistanceOnMapBetweenResults = { 0.02, 0.02 }; @@ -213,4 +200,4 @@ UNIT_CLASS_TEST(SearchEditedFeaturesTest, ViewportFilter) TEST(ResultsMatch(request.Results(), rulesEverywhere), ()); } } -} // namespace +} // namespace search_edited_features_test diff --git a/search/search_integration_tests/utils_test.cpp b/search/search_integration_tests/utils_test.cpp index ecda46f556..bd047367aa 100644 --- a/search/search_integration_tests/utils_test.cpp +++ b/search/search_integration_tests/utils_test.cpp @@ -2,7 +2,6 @@ #include "search/search_tests_support/helpers.hpp" -#include "generator/feature_builder.hpp" #include "generator/generator_tests_support/test_feature.hpp" #include "generator/generator_tests_support/test_mwm_builder.hpp" @@ -23,7 +22,7 @@ using namespace generator::tests_support; using namespace search; using namespace std; -class SearchUtilsTest : public SearchTest +class SearchUtilsTest : public search::tests_support::SearchTest { public: DataSource const & GetDataSource() const { return m_dataSource; } diff --git a/search/search_quality/search_quality_tests/CMakeLists.txt b/search/search_quality/search_quality_tests/CMakeLists.txt index d29699e8e9..d9b6834717 100644 --- a/search/search_quality/search_quality_tests/CMakeLists.txt +++ b/search/search_quality/search_quality_tests/CMakeLists.txt @@ -2,6 +2,7 @@ project(search_quality_tests) set(SRC benchmark_tests.cpp + real_mwm_tests.cpp sample_test.cpp ) diff --git a/search/search_quality/search_quality_tests/benchmark_tests.cpp b/search/search_quality/search_quality_tests/benchmark_tests.cpp index d04bdd6048..b079d60301 100644 --- a/search/search_quality/search_quality_tests/benchmark_tests.cpp +++ b/search/search_quality/search_quality_tests/benchmark_tests.cpp @@ -1,81 +1,20 @@ #include "testing/testing.hpp" -#include "generator/generator_tests_support/test_with_classificator.hpp" - -#include "search/search_tests_support/test_search_engine.hpp" -#include "search/search_tests_support/test_search_request.hpp" - -#include "indexer/classificator_loader.hpp" -#include "indexer/data_source.hpp" - -#include "platform/local_country_file_utils.hpp" +#include "search/search_tests_support/helpers.hpp" namespace benchmark_tests { -using namespace search; -using namespace std::chrono; -class DataSourceTestFixture : public generator::tests_support::TestWithClassificator +using BenchmarkFixture = search::tests_support::SearchTest; + +UNIT_CLASS_TEST(BenchmarkFixture, Smoke) { -protected: - FrozenDataSource m_dataSource; - std::unique_ptr m_countryInfo; + RegisterLocalMapsInViewport(mercator::Bounds::FullRect()); -public: - DataSourceTestFixture() - : m_countryInfo(std::make_unique()) - { - using namespace platform; - std::vector localFiles; - FindAllLocalMapsAndCleanup(std::numeric_limits::max() /* latestVersion */, localFiles); + SetViewport({50.1052, 8.6868}, 10000); // Frankfurt am Main - bool hasWorld = false; - for (auto const & file : localFiles) - { - auto const res = m_dataSource.RegisterMap(file); - TEST_EQUAL(res.second, MwmSet::RegResult::Success, ()); - - auto const & info = res.first.GetInfo(); - TEST_EQUAL(file.GetCountryName(), info->GetCountryName(), ()); - if (file.GetCountryName() == WORLD_FILE_NAME) - { - TEST_EQUAL(info->GetType(), MwmInfo::WORLD, ()); - hasWorld = true; - } - - m_countryInfo->AddCountry({ info->GetCountryName(), info->m_bordersRect }); - } - - TEST(hasWorld, ()); - } -}; - -class SearchBenchmarkFixture : public DataSourceTestFixture -{ - tests_support::TestSearchEngine m_engine; - m2::RectD m_viewport; - -public: - SearchBenchmarkFixture() : m_engine(m_dataSource, std::move(m_countryInfo), {}) - { - } - - void SetCenter(ms::LatLon ll) - { - m_viewport = mercator::MetersToXY(ll.m_lon, ll.m_lat, 1.0E4); - } - - uint64_t Run(std::string const & query) - { - tests_support::TestSearchRequest request(m_engine, query, "en", Mode::Everywhere, m_viewport); - request.Run(); - return request.ResponseTime().count(); - } -}; - -UNIT_CLASS_TEST(SearchBenchmarkFixture, Smoke) -{ - SetCenter({ 50.1052, 8.6868 }); // Frankfurt am Main - LOG(LINFO, (Run("b"))); + auto request = MakeRequest("b"); + LOG(LINFO, (request->ResponseTime().count())); } + } // namespace benchmark_tests diff --git a/search/search_quality/search_quality_tests/real_mwm_tests.cpp b/search/search_quality/search_quality_tests/real_mwm_tests.cpp new file mode 100644 index 0000000000..58bcc918ba --- /dev/null +++ b/search/search_quality/search_quality_tests/real_mwm_tests.cpp @@ -0,0 +1,273 @@ +#include "testing/testing.hpp" + +#include "search/search_tests_support/helpers.hpp" + +#include "geometry/distance_on_sphere.hpp" + +namespace real_mwm_tests +{ + +class MwmTestsFixture : public search::tests_support::SearchTest +{ +public: + // Pass LDEBUG to verbose logs for debugging. + MwmTestsFixture() : search::tests_support::SearchTest(LINFO) {} + + // Default top POIs count to check types or distances. + static size_t constexpr kTopPoiResultsCount = 5; + // Feature's centers table is created with low coordinates precision for better compression, + // so distance-to-pivot is not precise and real meters distance may differ. + static double constexpr kDistanceEpsilon = 5; + static double constexpr kDefaultViewportRadiusM = 10000; + static double constexpr kLoadMwmRadiusM = 200000; + + void SetViewportAndLoadMaps(ms::LatLon const & center, double radiusM = kDefaultViewportRadiusM) + { + RegisterLocalMapsInViewport(mercator::MetersToXY(center.m_lon, center.m_lat, kLoadMwmRadiusM)); + + SetViewport(center, radiusM); + } + + using ResultsT = std::vector; + + class Range + { + ResultsT const & m_v; + size_t m_beg, m_end; + + public: + explicit Range(ResultsT const & v) : m_v(v), m_beg(0), m_end(kTopPoiResultsCount) {} + Range(ResultsT const & v, size_t beg, size_t end = kTopPoiResultsCount) : m_v(v), m_beg(beg), m_end(end) {} + + size_t size() const { return m_end - m_beg; } + auto begin() const { return m_v.begin() + m_beg; } + auto end() const { return m_v.begin() + m_end; } + auto const & operator[](size_t i) const { return *(begin() + i); } + }; + + /// @return First (minimal) distance in meters. + static double SortedByDistance(Range const & results, ms::LatLon const & center) + { + double const firstDist = ms::DistanceOnEarth(center, mercator::ToLatLon(results[0].GetFeatureCenter())); + + double prevDist = firstDist; + for (size_t i = 1; i < results.size(); ++i) + { + double const dist = ms::DistanceOnEarth(center, mercator::ToLatLon(results[i].GetFeatureCenter())); + TEST_LESS(prevDist, dist + kDistanceEpsilon, (results[i-1], results[i])); + prevDist = dist; + } + + return firstDist; + } + + static std::vector GetClassifTypes(std::vector const & arr) + { + std::vector res; + res.reserve(arr.size()); + + Classificator const & c = classif(); + for (auto const & e : arr) + res.push_back(c.GetTypeByPath(e)); + return res; + } + + static void EqualClassifType(Range const & results, std::vector const & types) + { + for (auto const & r : results) + { + auto const it = std::find_if(types.begin(), types.end(), [type = r.GetFeatureType()](uint32_t inType) + { + uint32_t t = type; + ftype::TruncValue(t, ftype::GetLevel(inType)); + return t == inType; + }); + + TEST(it != types.end(), (r)); + } + } + + static void NameStartsWith(Range const & results, base::StringIL const & prefixes) + { + for (auto const & r : results) + { + auto const it = std::find_if(prefixes.begin(), prefixes.end(), [name = r.GetString()](char const * prefix) + { + return strings::StartsWith(name, prefix); + }); + + TEST(it != prefixes.end(), (r)); + } + } + + /// @param[in] rect { min_lon, min_lat, max_lon, max_lat } + static void CenterInRect(Range const & results, m2::RectD const & rect) + { + for (auto const & r : results) + { + auto const ll = mercator::ToLatLon(r.GetFeatureCenter()); + TEST(rect.IsPointInside({ll.m_lon, ll.m_lat}), (r)); + } + } +}; + +// https://github.com/organicmaps/organicmaps/issues/3026 +UNIT_CLASS_TEST(MwmTestsFixture, Berlin_Rewe) +{ + // Berlin + ms::LatLon const center(52.5170365, 13.3888599); + SetViewportAndLoadMaps(center); + + auto request = MakeRequest("rewe"); + auto const & results = request->Results(); + TEST_GREATER(results.size(), kTopPoiResultsCount, ()); + + TEST_EQUAL(results[0].GetFeatureType(), classif().GetTypeByPath({"amenity", "fast_food"}), ()); + + Range const range(results, 1); + EqualClassifType(range, GetClassifTypes({{"shop"}})); + double const dist = SortedByDistance(range, center); + TEST_LESS(dist, 1000, ()); +} + +// https://github.com/organicmaps/organicmaps/issues/1376 +UNIT_CLASS_TEST(MwmTestsFixture, Madrid_Carrefour) +{ + // Madrid + ms::LatLon const center(40.41048, -3.69773); + SetViewportAndLoadMaps(center); + + auto request = MakeRequest("carrefour"); + auto const & results = request->Results(); + TEST_GREATER(results.size(), 10, ()); + + /// @todo 'Carrefour' city in Haiti :) + TEST_EQUAL(results[0].GetFeatureType(), classif().GetTypeByPath({"place", "city", "capital", "3"}), ()); + + Range const range(results, 1, 10); + EqualClassifType(range, GetClassifTypes({{"shop"}})); + double const dist = SortedByDistance(range, center); + TEST_LESS(dist, 500, ()); +} + +// https://github.com/organicmaps/organicmaps/issues/2530 +UNIT_CLASS_TEST(MwmTestsFixture, Nicosia_Jumbo) +{ + // Nicosia + ms::LatLon const center(35.16915, 33.36141); + SetViewportAndLoadMaps(center); + + auto request = MakeRequest("jumb"); + auto const & results = request->Results(); + TEST_GREATER(results.size(), kTopPoiResultsCount, ()); + + Range const range(results); + EqualClassifType(range, GetClassifTypes({{"shop"}, {"amenity", "parking"}})); + double const dist = SortedByDistance(range, center); + TEST_LESS(dist, 5000, ()); +} + +// https://github.com/organicmaps/organicmaps/issues/2470 +UNIT_CLASS_TEST(MwmTestsFixture, Aarhus_Netto) +{ + // Aarhus + ms::LatLon const center(56.14958, 10.20394); + SetViewportAndLoadMaps(center); + + auto request = MakeRequest("netto"); + auto const & results = request->Results(); + TEST_GREATER(results.size(), kTopPoiResultsCount, ()); + + Range const range(results); + EqualClassifType(range, GetClassifTypes({{"shop"}})); + double const dist = SortedByDistance(range, center); + TEST_LESS(dist, 500, ()); +} + +// https://github.com/organicmaps/organicmaps/issues/2133 +UNIT_CLASS_TEST(MwmTestsFixture, NY_Subway) +{ + // New York + ms::LatLon const center(40.7355019, -73.9948155); + SetViewportAndLoadMaps(center); + + // Interesting case, because Manhattan has high density of: + // - "Subway" fast food + // - railway-subway category; + // - bus stops with name ".. subway .."; + // + Some noname cities LIKE("Subway", 1 error) in the World. + auto request = MakeRequest("subway"); + auto const & results = request->Results(); + TEST_GREATER(results.size(), kTopPoiResultsCount, ()); + + Range const range(results, 0, 3); + EqualClassifType(range, GetClassifTypes({{"amenity", "fast_food"}})); + double const dist = SortedByDistance(range, center); + TEST_LESS(dist, 1000, ()); +} + +// https://github.com/organicmaps/organicmaps/issues/1997 +UNIT_CLASS_TEST(MwmTestsFixture, London_Asda) +{ + // London + ms::LatLon const center(51.50295, 0.00325); + SetViewportAndLoadMaps(center); + + auto request = MakeRequest("asda"); + auto const & results = request->Results(); + TEST_GREATER(results.size(), kTopPoiResultsCount, ()); + + /// @todo 3 only because cafe is better than fuel, despite fuel is closer. + Range const range(results, 0, 3); + EqualClassifType(range, GetClassifTypes({{"shop"}, {"amenity"}})); + double const dist = SortedByDistance(range, center); + TEST_LESS(dist, 2000, ()); +} + +// https://github.com/organicmaps/organicmaps/issues/2470 +UNIT_CLASS_TEST(MwmTestsFixture, Hamburg_Park) +{ + // Hamburg + ms::LatLon const center(53.5503410, 10.0006540); + SetViewportAndLoadMaps(center); + + auto request = MakeRequest("Heide-Park"); + auto const & results = request->Results(); + TEST_GREATER(results.size(), kTopPoiResultsCount, ()); + + Range const range(results, 0, 3); + EqualClassifType(range, GetClassifTypes({{"tourism"}, {"amenity", "fast_food"}, {"highway", "bus_stop"}})); + NameStartsWith(range, {"Heide Park", "Heide-Park"}); + double const dist = SortedByDistance(range, center); + TEST_LESS(dist, 100000, ()); +} + +// https://github.com/organicmaps/organicmaps/issues/1560 +UNIT_CLASS_TEST(MwmTestsFixture, Barcelona_Carrers) +{ + // Barcelona + ms::LatLon const center(41.3828939, 2.177432); + SetViewportAndLoadMaps(center); + + { + auto request = MakeRequest("carrer de napols"); + auto const & results = request->Results(); + TEST_GREATER(results.size(), kTopPoiResultsCount, ()); + + Range const range(results, 0, 4); + EqualClassifType(range, GetClassifTypes({{"highway"}})); + CenterInRect(range, {2.1651583, 41.3899995, 2.1863021, 41.4060494}); + } + + { + auto request = MakeRequest("carrer de les planes sabadell"); + auto const & results = request->Results(); + TEST_GREATER(results.size(), kTopPoiResultsCount, ()); + + Range const range(results, 0, 1); + EqualClassifType(range, GetClassifTypes({{"highway"}})); + CenterInRect(range, {2.1078314, 41.5437515, 2.1106129, 41.5438819}); + } +} + +} // namespace real_mwm_tests diff --git a/search/search_tests_support/helpers.cpp b/search/search_tests_support/helpers.cpp index 8f5560b5b0..006b90e048 100644 --- a/search/search_tests_support/helpers.cpp +++ b/search/search_tests_support/helpers.cpp @@ -9,16 +9,22 @@ namespace search { +namespace tests_support +{ using namespace std; -using namespace tests_support; -SearchTest::SearchTest() - : m_scopedLog(LDEBUG) - , m_engine(m_dataSource, make_unique(), Engine::Params{}) +SearchTest::SearchTest(base::LogLevel logLevel /* = base::LDEBUG */) + : m_scopedLog(logLevel) + , m_engine(m_dataSource, make_unique(), {}) { SetViewport(mercator::Bounds::FullRect()); } +void SearchTest::SetViewport(ms::LatLon const & ll, double radiusM) +{ + SetViewport(mercator::MetersToXY(ll.m_lon, ll.m_lat, radiusM)); +} + void SearchTest::RegisterCountry(string const & name, m2::RectD const & rect) { auto & infoGetter = @@ -26,11 +32,6 @@ void SearchTest::RegisterCountry(string const & name, m2::RectD const & rect) infoGetter.AddCountry(storage::CountryDef(name, rect)); } -bool SearchTest::ResultsMatch(string const & query, Rules const & rules) -{ - return ResultsMatch(query, "en" /* locale */, rules); -} - bool SearchTest::CategoryMatch(std::string const & query, Rules const & rules, string const & locale) { TestSearchRequest request(m_engine, query, locale, Mode::Everywhere, m_viewport); @@ -40,16 +41,11 @@ bool SearchTest::CategoryMatch(std::string const & query, Rules const & rules, s return MatchResults(m_dataSource, rules, request.Results()); } -bool SearchTest::ResultsMatch(string const & query, string const & locale, Rules const & rules) +bool SearchTest::ResultsMatch(std::string const & query, Rules const & rules, + std::string const & locale /* = "en" */, + Mode mode /* = Mode::Everywhere */) { - TestSearchRequest request(m_engine, query, locale, Mode::Everywhere, m_viewport); - request.Run(); - return MatchResults(m_dataSource, rules, request.Results()); -} - -bool SearchTest::ResultsMatch(string const & query, Mode mode, Rules const & rules) -{ - TestSearchRequest request(m_engine, query, "en", mode, m_viewport); + TestSearchRequest request(m_engine, query, locale, mode, m_viewport); request.Run(); return MatchResults(m_dataSource, rules, request.Results()); } @@ -66,7 +62,7 @@ bool SearchTest::ResultsMatch(SearchParams const & params, Rules const & rules) return ResultsMatch(request.Results(), rules); } -bool SearchTest::ResultMatches(search::Result const & result, Rule const & rule) +bool SearchTest::IsResultMatches(search::Result const & result, Rule const & rule) { return tests_support::ResultMatches(m_dataSource, rule, result); } @@ -85,7 +81,7 @@ size_t SearchTest::GetResultsNumber(string const & query, string const & locale) return request.Results().size(); } -unique_ptr SearchTest::MakeRequest(SearchParams params) +unique_ptr SearchTest::MakeRequest(SearchParams const & params) { auto request = make_unique(m_engine, params); request->Run(); @@ -128,4 +124,6 @@ void SearchTest::OnMwmBuilt(MwmInfo const & info) case MwmInfo::COASTS: break; } } -} // namespace search + +} // namespace tests_supoort +} // namespace search diff --git a/search/search_tests_support/helpers.hpp b/search/search_tests_support/helpers.hpp index 1dccfccbe7..4b4ff960da 100644 --- a/search/search_tests_support/helpers.hpp +++ b/search/search_tests_support/helpers.hpp @@ -9,49 +9,47 @@ #include "geometry/rect2d.hpp" -#include #include #include #include namespace search { -class SearchTest : public tests_support::TestWithCustomMwms +namespace tests_support +{ + +class SearchTest : public TestWithCustomMwms { public: - using Rule = std::shared_ptr; + using Rule = std::shared_ptr; using Rules = std::vector; - SearchTest(); + explicit SearchTest(base::LogLevel logLevel = base::LDEBUG); ~SearchTest() override = default; - // Registers country in internal records. Note that physical country - // file may be absent. + // Registers country in internal records. Note that physical country file may be absent. void RegisterCountry(std::string const & name, m2::RectD const & rect); inline void SetViewport(m2::RectD const & viewport) { m_viewport = viewport; } + void SetViewport(ms::LatLon const & ll, double radiusM); - bool ResultsMatch(std::string const & query, Rules const & rules); - bool CategoryMatch(std::string const & query, Rules const & rules, std::string const & locale = "en"); - - bool ResultsMatch(std::string const & query, std::string const & locale, Rules const & rules); - - bool ResultsMatch(std::string const & query, Mode mode, Rules const & rules); - - bool ResultsMatch(std::vector const & results, Rules const & rules); + bool CategoryMatch(std::string const & query, Rules const & rules, + std::string const & locale = "en"); + bool ResultsMatch(std::string const & query, Rules const & rules, + std::string const & locale = "en", + Mode mode = Mode::Everywhere); + bool ResultsMatch(std::vector const & results, Rules const & rules); bool ResultsMatch(SearchParams const & params, Rules const & rules); - bool ResultMatches(search::Result const & result, Rule const & rule); + bool IsResultMatches(Result const & result, Rule const & rule); bool AlternativeMatch(std::string const & query, std::vector const & rulesList); size_t GetResultsNumber(std::string const & query, std::string const & locale); - std::unique_ptr MakeRequest(SearchParams params); - - std::unique_ptr MakeRequest(std::string const & query, - std::string const & locale = "en"); + std::unique_ptr MakeRequest(SearchParams const & params); + std::unique_ptr MakeRequest(std::string const & query, std::string const & locale = "en"); size_t CountFeatures(m2::RectD const & rect); @@ -60,7 +58,7 @@ protected: base::ScopedLogLevelChanger m_scopedLog; - tests_support::TestSearchEngine m_engine; + TestSearchEngine m_engine; m2::RectD m_viewport; }; @@ -88,4 +86,6 @@ public: explicit TestHotel(m2::PointD const & center) : TestHotel(center, "hotel", "en") {} }; -} // namespace search + +} // namespace tests_support +} // namespace search