From 8d63d1a50778e42502606e9844c2fa50633e0bd6 Mon Sep 17 00:00:00 2001 From: tatiana-yan Date: Fri, 8 Jun 2018 19:40:07 +0300 Subject: [PATCH] [search] Fix index build for categories which are deeper than 3 levels --- generator/search_index_builder.cpp | 21 ++- .../test_with_custom_mwms.hpp | 14 ++ .../search_integration_tests/smoke_test.cpp | 140 ++++++++++++++++++ 3 files changed, 170 insertions(+), 5 deletions(-) diff --git a/generator/search_index_builder.cpp b/generator/search_index_builder.cpp index cd8177fe89..6df7481c7a 100644 --- a/generator/search_index_builder.cpp +++ b/generator/search_index_builder.cpp @@ -106,13 +106,24 @@ void GetCategoryTypes(CategoriesHolder const & categories, pair const for (uint32_t t : types) { - // Leave only 2 levels of types - for example, do not distinguish: - // highway-primary-bridge and highway-primary-tunnel - // or amenity-parking-fee and amenity-parking-underground-fee. - ftype::TruncValue(t, 2); + // Truncate |t| up to 2 levels and choose the best category match to find explicit category if + // any and not distinguish types like highway-primary-bridge and highway-primary-tunnel or + // amenity-parking-fee and amenity-parking-underground-fee if we do not have such explicit + // categories. + + bool found = false; + for (uint8_t level = ftype::GetLevel(t); level >= 2; --level) + { + ftype::TruncValue(t, level); + if (categories.IsTypeExist(t)) + { + found = true; + break; + } + } // Only categorized types will be added to index. - if (!categories.IsTypeExist(t)) + if (!found) continue; // There are some special non-drawable types we plan to search on. diff --git a/indexer/indexer_tests_support/test_with_custom_mwms.hpp b/indexer/indexer_tests_support/test_with_custom_mwms.hpp index 9fbc81614b..75d6ed2aef 100644 --- a/indexer/indexer_tests_support/test_with_custom_mwms.hpp +++ b/indexer/indexer_tests_support/test_with_custom_mwms.hpp @@ -57,6 +57,20 @@ public: return id; } + void DeregisterMap(std::string const & name) + { + auto const file = platform::CountryFile(name); + auto it = find_if( + m_files.begin(), m_files.end(), + [&file](platform::LocalCountryFile const & f) { return f.GetCountryFile() == file; }); + if (it == m_files.end()) + return; + + m_index.DeregisterMap(file); + Cleanup(*it); + m_files.erase(it); + } + template MwmSet::MwmId BuildWorld(BuildFn && fn) { diff --git a/search/search_integration_tests/smoke_test.cpp b/search/search_integration_tests/smoke_test.cpp index e16791c060..3df27d240c 100644 --- a/search/search_integration_tests/smoke_test.cpp +++ b/search/search_integration_tests/smoke_test.cpp @@ -64,6 +64,30 @@ public: ~AlcoShop() override = default; }; +class SubwayStation : public TestPOI +{ +public: + SubwayStation(m2::PointD const & center, string const & name, string const & lang) + : TestPOI(center, name, lang) + { + SetTypes({{"railway", "station", "subway"}}); + } + + ~SubwayStation() override = default; +}; + +class SubwayStationMoscow : public TestPOI +{ +public: + SubwayStationMoscow(m2::PointD const & center, string const & name, string const & lang) + : TestPOI(center, name, lang) + { + SetTypes({{"railway", "station", "subway", "moscow"}}); + } + + ~SubwayStationMoscow() override = default; +}; + UNIT_CLASS_TEST(SmokeTest, Smoke) { char const kCountryName[] = "BuzzTown"; @@ -96,6 +120,122 @@ UNIT_CLASS_TEST(SmokeTest, Smoke) } } +UNIT_CLASS_TEST(SmokeTest, DeepCategoryTest) +{ + char const kCountryName[] = "Wonderland"; + + SubwayStation redStation(m2::PointD(0, 0), "red", "en"); + SubwayStationMoscow blueStation(m2::PointD(1, 1), "blue", "en"); + + auto id = BuildMwm(kCountryName, feature::DataHeader::country, [&](TestMwmBuilder & builder) { + builder.Add(redStation); + builder.Add(blueStation); + }); + + SetViewport(m2::RectD(m2::PointD(0, 0), m2::PointD(1, 1))); + { + TRules rules = {ExactMatch(id, redStation), ExactMatch(id, blueStation)}; + TEST(ResultsMatch("Subway ", rules), ()); + } +} + +UNIT_CLASS_TEST(SmokeTest, CategoriesTest) +{ + // todo(@t.yan): fix some or delete category. + vector> const invisibleTags = {{"amenity", "driving_school"}, + {"military", "bunker"}, + {"waterway", "canal"}, + {"waterway", "river"}, + {"waterway", "riverbank"}, + {"waterway", "stream"}, + {"landuse", "basin"}, + {"place", "county"}, + {"place", "islet"}, + {"power", "pole"}, + {"highway", "footway"}, + {"highway", "living_street"}, + {"highway", "motorway"}, + {"highway", "motorway_link"}, + {"highway", "path"}, + {"highway", "pedestrian"}, + {"highway", "primary"}, + {"highway", "primary_link"}, + {"highway", "raceway"}, + {"highway", "residential"}, + {"highway", "road"}, + {"highway", "secondary"}, + {"highway", "secondary_link"}, + {"highway", "service"}, + {"highway", "steps"}, + {"area:highway", "steps"}, + {"highway", "tertiary"}, + {"highway", "tertiary_link"}, + {"highway", "track"}, + {"highway", "traffic_signals"}, + {"highway", "trunk"}, + {"highway", "trunk_link"}, + {"highway", "unclassified"}, + {"man_made", "surveillance"}, + {"man_made", "tower"}, + {"man_made", "water_tower"}, + {"man_made", "water_well"}, + {"natural", "pond"}, + {"natural", "tree"}, + {"natural", "wood"}}; + set invisibleTypes; + for (auto const & tags : invisibleTags) + invisibleTypes.insert(classif().GetTypeByPath(tags)); + + // todo(@t.yan): fix some or delete category. + vector> const badTags = {{"building"}, + {"building", "address"}, + {"entrance"}, + {"internet_access"}, + {"internet_access", "wlan"}, + {"office"}, + {"shop"}, + {"shop", "butcher"}, + {"shop", "florist"}, + {"shop", "greengrocer"}, + {"shop", "optician"}, + {"place", "continent"}, + {"place", "region"}, + {"event", "fc2018_city"}, + {"sponsored", "holiday"}, + {"railway", "level_crossing"}, + {"highway", "rest_area"}}; + set badTypes; + for (auto const & tags : badTags) + badTypes.insert(classif().GetTypeByPath(tags)); + + auto const & holder = GetDefaultCategories(); + auto testCategory = [&](uint32_t type, CategoriesHolder::Category const &) { + if (invisibleTypes.find(type) != invisibleTypes.end()) + return; + + if (badTypes.find(type) != badTypes.end()) + return; + + string const countryName = "Wonderland"; + + TestPOI poi(m2::PointD(1.0, 1.0), "poi", "en"); + poi.SetTypes({strings::Tokenize(classif().GetFullObjectName(type), "|")}); + + auto id = BuildMwm(countryName, feature::DataHeader::country, + [&](TestMwmBuilder & builder) { builder.Add(poi); }); + + SetViewport(m2::RectD(m2::PointD(0.0, 0.0), m2::PointD(2.0, 2.0))); + { + TRules rules = {ExactMatch(id, poi)}; + auto const query = holder.GetReadableFeatureType(type, CategoriesHolder::kEnglishCode) + " "; + TEST(ResultsMatch(query, rules), ()); + } + DeregisterMap(countryName); + }; + + holder.ForEachTypeAndCategory(testCategory); +} + UNIT_CLASS_TEST(SmokeTest, NotPrefixFreeNames) { char const kCountryName[] = "ATown";