Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
54
libs/indexer/indexer_tests/CMakeLists.txt
Normal file
54
libs/indexer/indexer_tests/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
project(indexer_tests)
|
||||
|
||||
set(SRC
|
||||
bounds.hpp
|
||||
brands_tests.cpp
|
||||
categories_test.cpp
|
||||
cell_coverer_test.cpp
|
||||
cell_id_test.cpp
|
||||
centers_table_test.cpp
|
||||
checker_test.cpp
|
||||
cities_boundaries_serdes_tests.cpp
|
||||
classificator_tests.cpp
|
||||
complex_serdes_tests.cpp
|
||||
complex_serdes_utils_tests.cpp
|
||||
custom_keyvalue_tests.cpp
|
||||
data_source_test.cpp
|
||||
drules_selector_parser_test.cpp
|
||||
editable_map_object_test.cpp
|
||||
feature_charge_sockets_test.cpp
|
||||
feature_metadata_test.cpp
|
||||
feature_names_test.cpp
|
||||
feature_to_osm_tests.cpp
|
||||
feature_types_test.cpp
|
||||
features_offsets_table_test.cpp
|
||||
features_vector_test.cpp
|
||||
index_builder_test.cpp
|
||||
interval_index_test.cpp
|
||||
metadata_serdes_tests.cpp
|
||||
mwm_set_test.cpp
|
||||
postcodes_matcher_tests.cpp
|
||||
rank_table_test.cpp
|
||||
read_features_tests.cpp
|
||||
road_shields_parser_tests.cpp
|
||||
scale_index_reading_tests.cpp
|
||||
search_string_utils_test.cpp
|
||||
sort_and_merge_intervals_test.cpp
|
||||
string_slice_tests.cpp
|
||||
succinct_trie_test.cpp
|
||||
test_mwm_set.hpp
|
||||
test_type.cpp
|
||||
tree_node_tests.cpp
|
||||
trie_test.cpp
|
||||
validate_and_format_contacts_test.cpp
|
||||
visibility_test.cpp
|
||||
wheelchair_tests.cpp
|
||||
)
|
||||
|
||||
omim_add_test(${PROJECT_NAME} ${SRC})
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
generator_tests_support
|
||||
platform_tests_support
|
||||
indexer
|
||||
)
|
||||
18
libs/indexer/indexer_tests/bounds.hpp
Normal file
18
libs/indexer/indexer_tests/bounds.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include "geometry/rect2d.hpp"
|
||||
|
||||
template <int MinX, int MinY, int MaxX, int MaxY>
|
||||
struct Bounds
|
||||
{
|
||||
static double constexpr kMinX = MinX;
|
||||
static double constexpr kMaxX = MaxX;
|
||||
static double constexpr kMinY = MinY;
|
||||
static double constexpr kMaxY = MaxY;
|
||||
static double constexpr kRangeX = kMaxX - kMinX;
|
||||
static double constexpr kRangeY = kMaxY - kMinY;
|
||||
|
||||
static m2::RectD FullRect() { return {MinX, MinY, MaxX, MaxY}; }
|
||||
};
|
||||
|
||||
using OrthoBounds = Bounds<-180, -90, 180, 90>;
|
||||
89
libs/indexer/indexer_tests/brands_tests.cpp
Normal file
89
libs/indexer/indexer_tests/brands_tests.cpp
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/brands_holder.hpp"
|
||||
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/string_utf8_multilang.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
using namespace indexer;
|
||||
|
||||
char const g_testBrandsTxt[] =
|
||||
"brand.mcdonalds\n"
|
||||
"en:McDonald's|Mc Donalds\n"
|
||||
"ru:МакДональд'с|Мак Доналдс\n"
|
||||
"uk:Макдональдз\n"
|
||||
"\n"
|
||||
"brand.subway\n"
|
||||
"en:Subway\n"
|
||||
"ru:Сабвэй|Сабвей";
|
||||
|
||||
UNIT_TEST(LoadDefaultBrands)
|
||||
{
|
||||
auto const & brands = GetDefaultBrands();
|
||||
|
||||
TEST(!brands.GetKeys().empty(), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(LoadBrands)
|
||||
{
|
||||
BrandsHolder const holder(make_unique<MemReader>(g_testBrandsTxt, sizeof(g_testBrandsTxt) - 1));
|
||||
|
||||
set<string> expectedKeys = {"mcdonalds", "subway"};
|
||||
auto const keys = holder.GetKeys();
|
||||
TEST_EQUAL(keys, expectedKeys, ());
|
||||
|
||||
using Names = set<BrandsHolder::Brand::Name>;
|
||||
|
||||
{
|
||||
Names expectedNames;
|
||||
expectedNames.emplace("McDonald's", StringUtf8Multilang::GetLangIndex("en"));
|
||||
expectedNames.emplace("Mc Donalds", StringUtf8Multilang::GetLangIndex("en"));
|
||||
expectedNames.emplace("МакДональд'с", StringUtf8Multilang::GetLangIndex("ru"));
|
||||
expectedNames.emplace("Мак Доналдс", StringUtf8Multilang::GetLangIndex("ru"));
|
||||
expectedNames.emplace("Макдональдз", StringUtf8Multilang::GetLangIndex("uk"));
|
||||
|
||||
Names names;
|
||||
holder.ForEachNameByKey("mcdonalds", [&names](BrandsHolder::Brand::Name const & name) { names.insert(name); });
|
||||
CHECK_EQUAL(names, expectedNames, ());
|
||||
}
|
||||
|
||||
{
|
||||
Names expectedNames;
|
||||
expectedNames.emplace("Subway", StringUtf8Multilang::GetLangIndex("en"));
|
||||
expectedNames.emplace("Сабвэй", StringUtf8Multilang::GetLangIndex("ru"));
|
||||
expectedNames.emplace("Сабвей", StringUtf8Multilang::GetLangIndex("ru"));
|
||||
|
||||
Names names;
|
||||
holder.ForEachNameByKey("subway", [&names](BrandsHolder::Brand::Name const & name) { names.insert(name); });
|
||||
CHECK_EQUAL(names, expectedNames, ());
|
||||
}
|
||||
|
||||
{
|
||||
set<string> expectedNames = {"McDonald's", "Mc Donalds"};
|
||||
|
||||
set<string> names;
|
||||
holder.ForEachNameByKeyAndLang("mcdonalds", "en", [&names](string const & name) { names.insert(name); });
|
||||
CHECK_EQUAL(names, expectedNames, ());
|
||||
}
|
||||
|
||||
{
|
||||
set<string> expectedNames = {"МакДональд'с", "Мак Доналдс"};
|
||||
|
||||
set<string> names;
|
||||
holder.ForEachNameByKeyAndLang("mcdonalds", "ru", [&names](string const & name) { names.insert(name); });
|
||||
CHECK_EQUAL(names, expectedNames, ());
|
||||
}
|
||||
|
||||
{
|
||||
set<string> expectedNames = {"Макдональдз"};
|
||||
|
||||
set<string> names;
|
||||
holder.ForEachNameByKeyAndLang("mcdonalds", "uk", [&names](string const & name) { names.insert(name); });
|
||||
CHECK_EQUAL(names, expectedNames, ());
|
||||
}
|
||||
}
|
||||
328
libs/indexer/indexer_tests/categories_test.cpp
Normal file
328
libs/indexer/indexer_tests/categories_test.cpp
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/categories_holder.hpp"
|
||||
#include "indexer/categories_index.hpp"
|
||||
#include "indexer/classificator.hpp"
|
||||
#include "indexer/classificator_loader.hpp"
|
||||
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/string_utf8_multilang.hpp"
|
||||
|
||||
#include "base/stl_helpers.hpp"
|
||||
#include "base/string_utils.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
using namespace indexer;
|
||||
using namespace std;
|
||||
|
||||
char const g_testCategoriesTxt[] =
|
||||
"amenity-bench\n"
|
||||
"en:1bench|sit down|to sit\n"
|
||||
"de:2bank|auf die strafbank schicken\n"
|
||||
"zh-Hans:长凳\n"
|
||||
"zh-Hant:長板凳\n"
|
||||
"da:bænk\n"
|
||||
"\n"
|
||||
"place-village|place-hamlet\n"
|
||||
"en:village\n"
|
||||
"de:2dorf|4weiler";
|
||||
|
||||
struct Checker
|
||||
{
|
||||
explicit Checker(size_t & count) : m_count(count) {}
|
||||
|
||||
void operator()(CategoriesHolder::Category const & cat)
|
||||
{
|
||||
switch (m_count)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
TEST_EQUAL(cat.m_synonyms.size(), 8, ());
|
||||
TEST_EQUAL(cat.m_synonyms[0].m_locale, CategoriesHolder::MapLocaleToInteger("en"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[0].m_name, "bench", ());
|
||||
TEST_EQUAL(cat.m_synonyms[0].m_prefixLengthToSuggest, 1, ());
|
||||
TEST_EQUAL(cat.m_synonyms[1].m_locale, CategoriesHolder::MapLocaleToInteger("en"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[1].m_name, "sit down", ());
|
||||
TEST_EQUAL(cat.m_synonyms[1].m_prefixLengthToSuggest, 10, ());
|
||||
TEST_EQUAL(cat.m_synonyms[2].m_locale, CategoriesHolder::MapLocaleToInteger("en"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[2].m_name, "to sit", ());
|
||||
TEST_EQUAL(cat.m_synonyms[3].m_locale, CategoriesHolder::MapLocaleToInteger("de"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[3].m_name, "bank", ());
|
||||
TEST_EQUAL(cat.m_synonyms[3].m_prefixLengthToSuggest, 2, ());
|
||||
TEST_EQUAL(cat.m_synonyms[4].m_locale, CategoriesHolder::MapLocaleToInteger("de"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[4].m_name, "auf die strafbank schicken", ());
|
||||
TEST_EQUAL(cat.m_synonyms[5].m_locale, CategoriesHolder::MapLocaleToInteger("zh_CN"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[5].m_locale, CategoriesHolder::MapLocaleToInteger("zh_rCN"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[5].m_locale, CategoriesHolder::MapLocaleToInteger("zh_HANS_CN"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[5].m_locale, CategoriesHolder::MapLocaleToInteger("zh-Hans"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[5].m_name, "长凳", ());
|
||||
TEST_EQUAL(cat.m_synonyms[6].m_locale, CategoriesHolder::MapLocaleToInteger("zh_TW"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[6].m_locale, CategoriesHolder::MapLocaleToInteger("zh-MO"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[6].m_locale, CategoriesHolder::MapLocaleToInteger("zh-rTW"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[6].m_locale, CategoriesHolder::MapLocaleToInteger("zh_HANT_HK"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[6].m_locale, CategoriesHolder::MapLocaleToInteger("zh_HK"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[6].m_locale, CategoriesHolder::MapLocaleToInteger("zh-Hant"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[6].m_name, "長板凳", ());
|
||||
TEST_EQUAL(cat.m_synonyms[7].m_locale, CategoriesHolder::MapLocaleToInteger("da"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[7].m_name, "bænk", ());
|
||||
++m_count;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
{
|
||||
TEST_EQUAL(cat.m_synonyms.size(), 3, ());
|
||||
TEST_EQUAL(cat.m_synonyms[0].m_locale, CategoriesHolder::MapLocaleToInteger("en"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[0].m_name, "village", ());
|
||||
TEST_EQUAL(cat.m_synonyms[1].m_locale, CategoriesHolder::MapLocaleToInteger("de"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[1].m_name, "dorf", ());
|
||||
TEST_EQUAL(cat.m_synonyms[1].m_prefixLengthToSuggest, 2, ());
|
||||
TEST_EQUAL(cat.m_synonyms[2].m_locale, CategoriesHolder::MapLocaleToInteger("de"), ());
|
||||
TEST_EQUAL(cat.m_synonyms[2].m_name, "weiler", ());
|
||||
TEST_EQUAL(cat.m_synonyms[2].m_prefixLengthToSuggest, 4, ());
|
||||
++m_count;
|
||||
}
|
||||
break;
|
||||
default: TEST(false, ("Too many categories"));
|
||||
}
|
||||
}
|
||||
|
||||
size_t & m_count;
|
||||
};
|
||||
|
||||
UNIT_TEST(LoadCategories)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
CategoriesHolder h(make_unique<MemReader>(g_testCategoriesTxt, sizeof(g_testCategoriesTxt) - 1));
|
||||
size_t count = 0;
|
||||
Checker f(count);
|
||||
h.ForEachCategory(f);
|
||||
TEST_EQUAL(count, 3, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(CategoriesHolder_Smoke)
|
||||
{
|
||||
auto const & mappings = CategoriesHolder::kLocaleMapping;
|
||||
for (size_t i = 0; i < mappings.size(); ++i)
|
||||
{
|
||||
auto const & mapping = mappings[i];
|
||||
TEST_EQUAL(static_cast<int8_t>(i + 1), mapping.m_code, ());
|
||||
TEST_EQUAL(static_cast<int8_t>(i + 1), CategoriesHolder::MapLocaleToInteger(mapping.m_name), (mapping.m_name));
|
||||
TEST_EQUAL(CategoriesHolder::MapIntegerToLocale(i + 1), mapping.m_name, ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(CategoriesHolder_LoadDefault)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
uint32_t counter = 0;
|
||||
auto const count = [&counter](CategoriesHolder::Category const &) { ++counter; };
|
||||
|
||||
auto const & categoriesHolder = GetDefaultCategories();
|
||||
categoriesHolder.ForEachCategory(count);
|
||||
TEST_GREATER(counter, 0, ());
|
||||
|
||||
counter = 0;
|
||||
auto const & cuisineCategoriesHolder = GetDefaultCuisineCategories();
|
||||
cuisineCategoriesHolder.ForEachCategory(count);
|
||||
TEST_GREATER(counter, 0, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(CategoriesHolder_ForEach)
|
||||
{
|
||||
char const kCategories[] =
|
||||
"amenity-bar\n"
|
||||
"en:abc|ddd-eee\n"
|
||||
"\n"
|
||||
"amenity-pub\n"
|
||||
"en:ddd\n"
|
||||
"\n"
|
||||
"amenity-cafe\n"
|
||||
"en:abc eee\n"
|
||||
"\n"
|
||||
"amenity-restaurant\n"
|
||||
"en:ddd|eee\n"
|
||||
"\n"
|
||||
"";
|
||||
|
||||
classificator::Load();
|
||||
CategoriesHolder holder(make_unique<MemReader>(kCategories, ARRAY_SIZE(kCategories) - 1));
|
||||
|
||||
{
|
||||
uint32_t counter = 0;
|
||||
holder.ForEachTypeByName(CategoriesHolder::kEnglishCode, strings::MakeUniString("abc"),
|
||||
[&](uint32_t /* type */) { ++counter; });
|
||||
TEST_EQUAL(counter, 2, ());
|
||||
}
|
||||
|
||||
{
|
||||
uint32_t counter = 0;
|
||||
holder.ForEachTypeByName(CategoriesHolder::kEnglishCode, strings::MakeUniString("ddd"),
|
||||
[&](uint32_t /* type */) { ++counter; });
|
||||
TEST_EQUAL(counter, 3, ());
|
||||
}
|
||||
|
||||
{
|
||||
uint32_t counter = 0;
|
||||
holder.ForEachTypeByName(CategoriesHolder::kEnglishCode, strings::MakeUniString("eee"),
|
||||
[&](uint32_t /* type */) { ++counter; });
|
||||
TEST_EQUAL(counter, 3, ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(CategoriesIndex_Smoke)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
CategoriesHolder holder(make_unique<MemReader>(g_testCategoriesTxt, sizeof(g_testCategoriesTxt) - 1));
|
||||
CategoriesIndex index(holder);
|
||||
|
||||
uint32_t type1 = classif().GetTypeByPath({"amenity", "bench"});
|
||||
uint32_t type2 = classif().GetTypeByPath({"place", "village"});
|
||||
if (type1 > type2)
|
||||
swap(type1, type2);
|
||||
int8_t lang1 = CategoriesHolder::MapLocaleToInteger("en");
|
||||
int8_t lang2 = CategoriesHolder::MapLocaleToInteger("de");
|
||||
|
||||
auto testTypes = [&](string const & query, vector<uint32_t> const & expected)
|
||||
{
|
||||
vector<uint32_t> result;
|
||||
index.GetAssociatedTypes(query, result);
|
||||
TEST_EQUAL(result, expected, (query));
|
||||
};
|
||||
|
||||
index.AddCategoryByTypeAndLang(type1, lang1);
|
||||
testTypes("bench", {type1});
|
||||
testTypes("BENCH", {type1});
|
||||
testTypes("down", {type1});
|
||||
testTypes("benck", {});
|
||||
testTypes("strafbank", {});
|
||||
index.AddCategoryByTypeAndLang(type1, lang2);
|
||||
testTypes("strafbank", {type1});
|
||||
testTypes("ie strafbank sc", {type1});
|
||||
testTypes("rafb", {type1});
|
||||
index.AddCategoryByTypeAndLang(type2, lang1);
|
||||
testTypes("i", {type1, type2});
|
||||
|
||||
CategoriesIndex fullIndex(holder);
|
||||
fullIndex.AddCategoryByTypeAllLangs(type1);
|
||||
fullIndex.AddCategoryByTypeAllLangs(type2);
|
||||
vector<CategoriesHolder::Category> cats;
|
||||
|
||||
// The letter 'a' matches "strafbank" and "village".
|
||||
// One language is not enough.
|
||||
fullIndex.GetCategories("a", cats);
|
||||
|
||||
TEST_EQUAL(cats.size(), 2, ());
|
||||
|
||||
TEST_EQUAL(cats[0].m_synonyms.size(), 8, ());
|
||||
TEST_EQUAL(cats[0].m_synonyms[4].m_locale, CategoriesHolder::MapLocaleToInteger("de"), ());
|
||||
TEST_EQUAL(cats[0].m_synonyms[4].m_name, "auf die strafbank schicken", ());
|
||||
|
||||
TEST_EQUAL(cats[1].m_synonyms.size(), 3, ());
|
||||
TEST_EQUAL(cats[1].m_synonyms[0].m_locale, CategoriesHolder::MapLocaleToInteger("en"), ());
|
||||
TEST_EQUAL(cats[1].m_synonyms[0].m_name, "village", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(CategoriesIndex_MultipleTokens)
|
||||
{
|
||||
char const kCategories[] =
|
||||
"shop-bakery\n"
|
||||
"en:shop of buns\n"
|
||||
"\n"
|
||||
"shop-butcher\n"
|
||||
"en:shop of meat";
|
||||
|
||||
classificator::Load();
|
||||
CategoriesHolder holder(make_unique<MemReader>(kCategories, sizeof(kCategories) - 1));
|
||||
CategoriesIndex index(holder);
|
||||
|
||||
index.AddAllCategoriesInAllLangs();
|
||||
auto testTypes = [&](string const & query, vector<uint32_t> const & expected)
|
||||
{
|
||||
vector<uint32_t> result;
|
||||
index.GetAssociatedTypes(query, result);
|
||||
TEST_EQUAL(result, expected, (query));
|
||||
};
|
||||
|
||||
uint32_t type1 = classif().GetTypeByPath({"shop", "bakery"});
|
||||
uint32_t type2 = classif().GetTypeByPath({"shop", "butcher"});
|
||||
if (type1 > type2)
|
||||
swap(type1, type2);
|
||||
|
||||
testTypes("shop", {type1, type2});
|
||||
testTypes("shop buns", {type1});
|
||||
testTypes("shop meat", {type2});
|
||||
}
|
||||
|
||||
UNIT_TEST(CategoriesIndex_Groups)
|
||||
{
|
||||
char const kCategories[] =
|
||||
"@shop\n"
|
||||
"en:shop\n"
|
||||
"ru:магазин\n"
|
||||
"\n"
|
||||
"@meat\n"
|
||||
"en:meat\n"
|
||||
"\n"
|
||||
"shop-bakery|@shop\n"
|
||||
"en:buns\n"
|
||||
"\n"
|
||||
"shop-butcher|@shop|@meat\n"
|
||||
"en:butcher\n"
|
||||
"";
|
||||
|
||||
classificator::Load();
|
||||
CategoriesHolder holder(make_unique<MemReader>(kCategories, sizeof(kCategories) - 1));
|
||||
CategoriesIndex index(holder);
|
||||
|
||||
index.AddAllCategoriesInAllLangs();
|
||||
auto testTypes = [&](string const & query, vector<uint32_t> const & expected)
|
||||
{
|
||||
vector<uint32_t> result;
|
||||
index.GetAssociatedTypes(query, result);
|
||||
TEST_EQUAL(result, expected, (query));
|
||||
};
|
||||
|
||||
uint32_t type1 = classif().GetTypeByPath({"shop", "bakery"});
|
||||
uint32_t type2 = classif().GetTypeByPath({"shop", "butcher"});
|
||||
if (type1 > type2)
|
||||
swap(type1, type2);
|
||||
|
||||
testTypes("buns", {type1});
|
||||
testTypes("butcher", {type2});
|
||||
testTypes("meat", {type2});
|
||||
testTypes("shop", {type1, type2});
|
||||
testTypes("магазин", {type1, type2});
|
||||
testTypes("http", {});
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// A check that this data structure is not too heavy.
|
||||
UNIT_TEST(CategoriesIndex_AllCategories)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
CategoriesIndex index;
|
||||
|
||||
index.AddAllCategoriesInAllLangs();
|
||||
// Consider deprecating this method if this bound rises as high as a million.
|
||||
LOG(LINFO, ("Number of nodes in the CategoriesIndex trie:", index.GetNumTrieNodes()));
|
||||
TEST_LESS(index.GetNumTrieNodes(), 900000, ());
|
||||
}
|
||||
|
||||
// A check that this data structure is not too heavy.
|
||||
UNIT_TEST(CategoriesIndex_AllCategoriesEnglishName)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
CategoriesIndex index;
|
||||
|
||||
index.AddAllCategoriesInLang(CategoriesHolder::MapLocaleToInteger("en"));
|
||||
TEST_LESS(index.GetNumTrieNodes(), 15000, ());
|
||||
}
|
||||
#endif
|
||||
66
libs/indexer/indexer_tests/cell_coverer_test.cpp
Normal file
66
libs/indexer/indexer_tests/cell_coverer_test.cpp
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "geometry/covering_utils.hpp"
|
||||
|
||||
#include "indexer/cell_coverer.hpp"
|
||||
#include "indexer/indexer_tests/bounds.hpp"
|
||||
|
||||
#include "coding/hex.hpp"
|
||||
|
||||
#include "base/logging.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Unit test uses m2::CellId<30> for historical reasons, the actual production code uses RectId.
|
||||
using CellId = m2::CellId<30>;
|
||||
|
||||
UNIT_TEST(CellIdToStringRecode)
|
||||
{
|
||||
char const kTest[] = "21032012203";
|
||||
TEST_EQUAL(CellId::FromString(kTest).ToString(), kTest, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(GoldenCoverRect)
|
||||
{
|
||||
vector<CellId> cells;
|
||||
CoverRect<OrthoBounds>({27.43, 53.83, 27.70, 53.96}, 4, RectId::DEPTH_LEVELS - 1, cells);
|
||||
|
||||
TEST_EQUAL(cells.size(), 4, ());
|
||||
|
||||
TEST_EQUAL(cells[0].ToString(), "32012211300", ());
|
||||
TEST_EQUAL(cells[1].ToString(), "32012211301", ());
|
||||
TEST_EQUAL(cells[2].ToString(), "32012211302", ());
|
||||
TEST_EQUAL(cells[3].ToString(), "32012211303", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(ArtificialCoverRect)
|
||||
{
|
||||
typedef Bounds<0, 0, 16, 16> TestBounds;
|
||||
|
||||
vector<CellId> cells;
|
||||
CoverRect<TestBounds>({5, 5, 11, 11}, 4, RectId::DEPTH_LEVELS - 1, cells);
|
||||
|
||||
TEST_EQUAL(cells.size(), 4, ());
|
||||
|
||||
TEST_EQUAL(cells[0].ToString(), "03", ());
|
||||
TEST_EQUAL(cells[1].ToString(), "12", ());
|
||||
TEST_EQUAL(cells[2].ToString(), "21", ());
|
||||
TEST_EQUAL(cells[3].ToString(), "30", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(MaxDepthCoverSpiral)
|
||||
{
|
||||
using TestBounds = Bounds<0, 0, 8, 8>;
|
||||
|
||||
for (auto levelMax = 0; levelMax <= 2; ++levelMax)
|
||||
{
|
||||
auto cells = vector<m2::CellId<3>>{};
|
||||
|
||||
CoverSpiral<TestBounds, m2::CellId<3>>({2.1, 4.1, 2.1, 4.1}, levelMax, cells);
|
||||
|
||||
TEST_EQUAL(cells.size(), 1, ());
|
||||
TEST_EQUAL(cells[0].Level(), levelMax, ());
|
||||
}
|
||||
}
|
||||
54
libs/indexer/indexer_tests/cell_id_test.cpp
Normal file
54
libs/indexer/indexer_tests/cell_id_test.cpp
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/cell_id.hpp"
|
||||
#include "indexer/indexer_tests/bounds.hpp"
|
||||
|
||||
#include "coding/hex.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
using namespace std;
|
||||
|
||||
typedef m2::CellId<30> CellIdT;
|
||||
|
||||
UNIT_TEST(ToCellId)
|
||||
{
|
||||
string s("2130000");
|
||||
s.append(CellIdT::DEPTH_LEVELS - 1 - s.size(), '0');
|
||||
TEST_EQUAL((CellIdConverter<Bounds<0, 0, 4, 4>, CellIdT>::ToCellId(1.5, 2.5).ToString()), s, ());
|
||||
TEST_EQUAL(CellIdT::FromString(s), (CellIdConverter<Bounds<0, 0, 4, 4>, CellIdT>::ToCellId(1.5, 2.5)), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(CommonCell)
|
||||
{
|
||||
TEST_EQUAL((CellIdConverter<Bounds<0, 0, 4, 4>, CellIdT>::Cover2PointsWithCell(3.5, 2.5, 2.5, 3.5)),
|
||||
CellIdT::FromString("3"), ());
|
||||
TEST_EQUAL((CellIdConverter<Bounds<0, 0, 4, 4>, CellIdT>::Cover2PointsWithCell(2.25, 1.75, 2.75, 1.25)),
|
||||
CellIdT::FromString("12"), ());
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T1, typename T2>
|
||||
bool PairsAlmostEqualULPs(pair<T1, T1> const & p1, pair<T2, T2> const & p2)
|
||||
{
|
||||
return fabs(p1.first - p2.first) + fabs(p1.second - p2.second) < 0.00001;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
UNIT_TEST(CellId_RandomRecode)
|
||||
{
|
||||
mt19937 rng(0);
|
||||
for (size_t i = 0; i < 1000; ++i)
|
||||
{
|
||||
uint32_t const x = rng() % 2000;
|
||||
uint32_t const y = rng() % 1000;
|
||||
m2::PointD const pt = CellIdConverter<Bounds<0, 0, 2000, 1000>, CellIdT>::FromCellId(
|
||||
CellIdConverter<Bounds<0, 0, 2000, 1000>, CellIdT>::ToCellId(x, y));
|
||||
TEST(fabs(pt.x - x) < 0.0002, (x, y, pt));
|
||||
TEST(fabs(pt.y - y) < 0.0001, (x, y, pt));
|
||||
}
|
||||
}
|
||||
156
libs/indexer/indexer_tests/centers_table_test.cpp
Normal file
156
libs/indexer/indexer_tests/centers_table_test.cpp
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/centers_table.hpp"
|
||||
#include "indexer/classificator_loader.hpp"
|
||||
#include "indexer/data_header.hpp"
|
||||
#include "indexer/feature_algo.hpp"
|
||||
#include "indexer/features_vector.hpp"
|
||||
|
||||
#include "platform/platform.hpp"
|
||||
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/writer.hpp"
|
||||
|
||||
#include "geometry/mercator.hpp"
|
||||
#include "geometry/point2d.hpp"
|
||||
|
||||
#include "base/file_name_utils.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace search;
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
using TBuffer = vector<uint8_t>;
|
||||
|
||||
struct CentersTableTest
|
||||
{
|
||||
CentersTableTest() { classificator::Load(); }
|
||||
};
|
||||
|
||||
UNIT_CLASS_TEST(CentersTableTest, Smoke)
|
||||
{
|
||||
string const kMap = base::JoinPath(GetPlatform().WritableDir(), "minsk-pass.mwm");
|
||||
|
||||
FeaturesVectorTest fv(kMap);
|
||||
|
||||
TBuffer buffer;
|
||||
|
||||
{
|
||||
CentersTableBuilder builder;
|
||||
feature::DataHeader header(kMap);
|
||||
|
||||
builder.SetGeometryParams(header.GetBounds());
|
||||
fv.GetVector().ForEach([&](FeatureType & ft, uint32_t id) { builder.Put(id, feature::GetCenter(ft)); });
|
||||
|
||||
MemWriter<TBuffer> writer(buffer);
|
||||
builder.Freeze(writer);
|
||||
}
|
||||
|
||||
{
|
||||
MemReader reader(buffer.data(), buffer.size());
|
||||
auto table = CentersTable::LoadV1(reader);
|
||||
TEST(table.get(), ());
|
||||
|
||||
fv.GetVector().ForEach([&](FeatureType & ft, uint32_t id)
|
||||
{
|
||||
m2::PointD actual;
|
||||
TEST(table->Get(id, actual), ());
|
||||
|
||||
m2::PointD expected = feature::GetCenter(ft);
|
||||
|
||||
TEST_LESS_OR_EQUAL(mercator::DistanceOnEarth(actual, expected), 1.0, (id));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_CLASS_TEST(CentersTableTest, SmokeV0)
|
||||
{
|
||||
string const kMap = base::JoinPath(GetPlatform().WritableDir(), "minsk-pass.mwm");
|
||||
|
||||
FeaturesVectorTest fv(kMap);
|
||||
|
||||
feature::DataHeader header(kMap);
|
||||
auto const codingParams = header.GetDefGeometryCodingParams();
|
||||
|
||||
TBuffer buffer;
|
||||
|
||||
{
|
||||
CentersTableBuilder builder;
|
||||
|
||||
builder.SetGeometryCodingParamsV0ForTests(codingParams);
|
||||
fv.GetVector().ForEach([&](FeatureType & ft, uint32_t id) { builder.PutV0ForTests(id, feature::GetCenter(ft)); });
|
||||
|
||||
MemWriter<TBuffer> writer(buffer);
|
||||
builder.FreezeV0ForTests(writer);
|
||||
}
|
||||
|
||||
{
|
||||
MemReader reader(buffer.data(), buffer.size());
|
||||
auto table = CentersTable::LoadV0(reader, codingParams);
|
||||
TEST(table.get(), ());
|
||||
|
||||
fv.GetVector().ForEach([&](FeatureType & ft, uint32_t id)
|
||||
{
|
||||
m2::PointD actual;
|
||||
TEST(table->Get(id, actual), ());
|
||||
|
||||
m2::PointD expected = feature::GetCenter(ft);
|
||||
|
||||
TEST_LESS_OR_EQUAL(mercator::DistanceOnEarth(actual, expected), 1.0, (id));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_CLASS_TEST(CentersTableTest, Subset)
|
||||
{
|
||||
vector<pair<uint32_t, m2::PointD>> const features = {
|
||||
{1, m2::PointD(0.0, 0.0)}, {5, m2::PointD(1.0, 1.0)}, {10, m2::PointD(2.0, 2.0)}};
|
||||
|
||||
TBuffer buffer;
|
||||
{
|
||||
CentersTableBuilder builder;
|
||||
|
||||
builder.SetGeometryParams({{0.0, 0.0}, {2.0, 2.0}});
|
||||
for (auto const & feature : features)
|
||||
builder.Put(feature.first, feature.second);
|
||||
|
||||
MemWriter<TBuffer> writer(buffer);
|
||||
builder.Freeze(writer);
|
||||
}
|
||||
|
||||
{
|
||||
MemReader reader(buffer.data(), buffer.size());
|
||||
auto table = CentersTable::LoadV1(reader);
|
||||
TEST(table.get(), ());
|
||||
|
||||
uint32_t i = 0;
|
||||
size_t j = 0;
|
||||
|
||||
while (i < 100)
|
||||
{
|
||||
ASSERT(j == features.size() || features[j].first >= i, ("Invariant violation"));
|
||||
|
||||
m2::PointD actual;
|
||||
if (j != features.size() && i == features[j].first)
|
||||
{
|
||||
TEST(table->Get(i, actual), ());
|
||||
TEST_LESS_OR_EQUAL(mercator::DistanceOnEarth(actual, features[j].second), 1.0, ());
|
||||
}
|
||||
else
|
||||
{
|
||||
TEST(!table->Get(i, actual), ());
|
||||
}
|
||||
|
||||
++i;
|
||||
while (j != features.size() && features[j].first < i)
|
||||
++j;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
148
libs/indexer/indexer_tests/checker_test.cpp
Normal file
148
libs/indexer/indexer_tests/checker_test.cpp
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "search/utils.hpp"
|
||||
|
||||
#include "indexer/classificator.hpp"
|
||||
#include "indexer/classificator_loader.hpp"
|
||||
#include "indexer/ftypes_matcher.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace checker_test
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
size_t const roadArrColumnCount = 3;
|
||||
|
||||
vector<uint32_t> GetTypes(char const * arr[][roadArrColumnCount], size_t const recCount)
|
||||
{
|
||||
Classificator const & c = classif();
|
||||
vector<uint32_t> types;
|
||||
|
||||
for (size_t i = 0; i < recCount; ++i)
|
||||
types.push_back(c.GetTypeByPath(vector<string>(arr[i], arr[i] + roadArrColumnCount)));
|
||||
return types;
|
||||
}
|
||||
|
||||
vector<uint32_t> GetStreetTypes()
|
||||
{
|
||||
char const * arr[][roadArrColumnCount] = {{"highway", "trunk", "bridge"}, {"highway", "tertiary", "tunnel"}};
|
||||
return GetTypes(arr, ARRAY_SIZE(arr));
|
||||
}
|
||||
|
||||
vector<uint32_t> GetStreetAndNotStreetTypes()
|
||||
{
|
||||
char const * arr[][roadArrColumnCount] = {{"highway", "trunk", "bridge"}, {"highway", "primary_link", "tunnel"}};
|
||||
return GetTypes(arr, ARRAY_SIZE(arr));
|
||||
}
|
||||
|
||||
vector<uint32_t> GetLinkTypes()
|
||||
{
|
||||
char const * arr[][roadArrColumnCount] = {{"highway", "secondary_link", "bridge"},
|
||||
{"highway", "motorway_link", "tunnel"}};
|
||||
return GetTypes(arr, ARRAY_SIZE(arr));
|
||||
}
|
||||
|
||||
uint32_t GetMotorwayJunctionType()
|
||||
{
|
||||
Classificator const & c = classif();
|
||||
return c.GetTypeByPath({"highway", "motorway_junction"});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
UNIT_TEST(IsBridgeOrTunnelChecker)
|
||||
{
|
||||
classificator::Load();
|
||||
auto const & c = classif();
|
||||
|
||||
base::StringIL arrYes[] = {
|
||||
{"highway", "trunk", "bridge"},
|
||||
{"highway", "motorway_link", "tunnel"},
|
||||
};
|
||||
for (auto const & e : arrYes)
|
||||
TEST(ftypes::IsBridgeOrTunnelChecker::Instance()(c.GetTypeByPath(e)), ());
|
||||
|
||||
base::StringIL arrNo[] = {
|
||||
{"highway", "motorway_junction"},
|
||||
{"highway", "service", "driveway"},
|
||||
};
|
||||
for (auto const & e : arrNo)
|
||||
TEST(!ftypes::IsBridgeOrTunnelChecker::Instance()(c.GetTypeByPath(e)), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(IsWayChecker)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
TEST(ftypes::IsWayChecker::Instance()(GetStreetTypes()), ());
|
||||
TEST(ftypes::IsWayChecker::Instance()(GetStreetAndNotStreetTypes()), ());
|
||||
// TODO (@y, @m, @vng): need to investigate - do we really need this
|
||||
// TEST for absence of links, because IsWayChecker() is used for
|
||||
// search only.
|
||||
//
|
||||
// TEST(!ftypes::IsWayChecker::Instance()(GetLinkTypes()), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(IsLinkChecker)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
TEST(ftypes::IsLinkChecker::Instance()(GetLinkTypes()), ());
|
||||
TEST(!ftypes::IsLinkChecker::Instance()(GetStreetTypes()), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(GetHighwayClassTest)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
Classificator const & c = classif();
|
||||
|
||||
feature::TypesHolder types1;
|
||||
types1.Add(c.GetTypeByPath({"route", "shuttle_train"}));
|
||||
TEST_EQUAL(ftypes::GetHighwayClass(types1), ftypes::HighwayClass::Transported, ());
|
||||
|
||||
feature::TypesHolder types2;
|
||||
types2.Add(c.GetTypeByPath({"highway", "motorway_link", "tunnel"}));
|
||||
TEST_EQUAL(ftypes::GetHighwayClass(types2), ftypes::HighwayClass::Motorway, ());
|
||||
|
||||
feature::TypesHolder types3;
|
||||
types3.Add(c.GetTypeByPath({"highway", "unclassified"}));
|
||||
TEST_EQUAL(ftypes::GetHighwayClass(types3), ftypes::HighwayClass::LivingStreet, ());
|
||||
|
||||
feature::TypesHolder types4;
|
||||
types4.Add(c.GetTypeByPath({"highway"}));
|
||||
TEST_EQUAL(ftypes::GetHighwayClass(types4), ftypes::HighwayClass::Undefined, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(IsAttractionsChecker)
|
||||
{
|
||||
classificator::Load();
|
||||
Classificator const & c = classif();
|
||||
auto const & checker = ftypes::AttractionsChecker::Instance();
|
||||
|
||||
base::StringIL arrExceptions[] = {
|
||||
{"tourism", "information"},
|
||||
{"amenity", "ranger_station"},
|
||||
};
|
||||
std::vector<uint32_t> exceptions;
|
||||
for (auto e : arrExceptions)
|
||||
exceptions.push_back(c.GetTypeByPath(e));
|
||||
|
||||
for (uint32_t const t : search::GetCategoryTypes("sights", "en", GetDefaultCategories()))
|
||||
if (!base::IsExist(exceptions, ftype::Trunc(t, 2)))
|
||||
TEST(checker(t), (c.GetFullObjectName(t)));
|
||||
}
|
||||
|
||||
UNIT_TEST(IsMotorwayJunctionChecker)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
TEST(ftypes::IsMotorwayJunctionChecker::Instance()(GetMotorwayJunctionType()), ());
|
||||
TEST(!ftypes::IsMotorwayJunctionChecker::Instance()(GetStreetTypes()), ());
|
||||
}
|
||||
|
||||
} // namespace checker_test
|
||||
195
libs/indexer/indexer_tests/cities_boundaries_serdes_tests.cpp
Normal file
195
libs/indexer/indexer_tests/cities_boundaries_serdes_tests.cpp
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/cities_boundaries_serdes.hpp"
|
||||
#include "indexer/city_boundary.hpp"
|
||||
|
||||
#include "platform/platform.hpp"
|
||||
|
||||
#include "coding/files_container.hpp"
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/writer.hpp"
|
||||
|
||||
#include "geometry/point2d.hpp"
|
||||
|
||||
#include "base/file_name_utils.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace cities_boundaries_serdes_tests
|
||||
{
|
||||
using namespace indexer;
|
||||
using namespace m2;
|
||||
using namespace std;
|
||||
|
||||
using Boundary = vector<CityBoundary>;
|
||||
using Boundaries = vector<Boundary>;
|
||||
|
||||
struct Result
|
||||
{
|
||||
Result(Boundaries const & boundaries, double eps) : m_boundaries(boundaries), m_eps(eps) {}
|
||||
|
||||
Boundaries m_boundaries;
|
||||
double m_eps = 0.0;
|
||||
};
|
||||
|
||||
void TestEqual(vector<PointD> const & lhs, vector<PointD> const & rhs, double eps)
|
||||
{
|
||||
TEST_EQUAL(lhs.size(), rhs.size(), (lhs, rhs));
|
||||
for (size_t i = 0; i < lhs.size(); ++i)
|
||||
TEST(AlmostEqualAbs(lhs[i], rhs[i], eps), (lhs, rhs));
|
||||
}
|
||||
|
||||
void TestEqual(BoundingBox const & lhs, BoundingBox const & rhs, double eps)
|
||||
{
|
||||
TEST(AlmostEqualAbs(lhs.Min(), rhs.Min(), eps), (lhs, rhs));
|
||||
TEST(AlmostEqualAbs(lhs.Max(), rhs.Max(), eps), (lhs, rhs));
|
||||
}
|
||||
|
||||
void TestEqual(CalipersBox const & lhs, CalipersBox const & rhs, double eps)
|
||||
{
|
||||
// SerDes for CaliperBox works without normalization.
|
||||
CalipersBox norm(rhs);
|
||||
norm.Normalize();
|
||||
|
||||
TestEqual(lhs.Points(), norm.Points(), eps);
|
||||
}
|
||||
|
||||
void TestEqual(DiamondBox const & lhs, DiamondBox const & rhs, double eps)
|
||||
{
|
||||
auto const lps = lhs.Points();
|
||||
auto const rps = rhs.Points();
|
||||
TEST_EQUAL(lps.size(), 4, (lhs));
|
||||
TEST_EQUAL(rps.size(), 4, (rhs));
|
||||
TestEqual(lps, rps, eps);
|
||||
}
|
||||
|
||||
void TestEqual(CityBoundary const & lhs, CityBoundary const & rhs, double eps)
|
||||
{
|
||||
TestEqual(lhs.m_bbox, rhs.m_bbox, eps);
|
||||
TestEqual(lhs.m_cbox, rhs.m_cbox, eps);
|
||||
TestEqual(lhs.m_dbox, rhs.m_dbox, eps);
|
||||
}
|
||||
|
||||
void TestEqual(Boundary const & lhs, Boundary const & rhs, double eps)
|
||||
{
|
||||
TEST_EQUAL(lhs.size(), rhs.size(), (lhs, rhs));
|
||||
for (size_t i = 0; i < lhs.size(); ++i)
|
||||
TestEqual(lhs[i], rhs[i], eps);
|
||||
}
|
||||
|
||||
// Eps equal function to compare initial (expected) value (lhs) with encoded-decoded (rhs).
|
||||
void TestEqual(Boundaries const & lhs, Boundaries const & rhs, double eps)
|
||||
{
|
||||
TEST_EQUAL(lhs.size(), rhs.size(), (lhs, rhs));
|
||||
for (size_t i = 0; i < lhs.size(); ++i)
|
||||
TestEqual(lhs[i], rhs[i], eps);
|
||||
}
|
||||
|
||||
Result EncodeDecode(Boundaries const & boundaries)
|
||||
{
|
||||
vector<uint8_t> buffer;
|
||||
{
|
||||
MemWriter<decltype(buffer)> sink(buffer);
|
||||
CitiesBoundariesSerDes::Serialize(sink, boundaries);
|
||||
}
|
||||
|
||||
{
|
||||
Boundaries boundaries;
|
||||
double precision;
|
||||
MemReader reader(buffer.data(), buffer.size());
|
||||
NonOwningReaderSource source(reader);
|
||||
CitiesBoundariesSerDes::Deserialize(source, boundaries, precision);
|
||||
return Result(boundaries, precision);
|
||||
}
|
||||
}
|
||||
|
||||
void TestEncodeDecode(Boundaries const & expected)
|
||||
{
|
||||
auto const r = EncodeDecode(expected);
|
||||
TestEqual(expected, r.m_boundaries, r.m_eps);
|
||||
}
|
||||
|
||||
UNIT_TEST(CitiesBoundariesSerDes_Smoke)
|
||||
{
|
||||
{
|
||||
Boundaries const expected;
|
||||
TestEncodeDecode(expected);
|
||||
}
|
||||
|
||||
{
|
||||
Boundary boundary0;
|
||||
boundary0.emplace_back(vector<PointD>{{PointD(0.1234, 5.6789)}});
|
||||
boundary0.emplace_back(vector<PointD>{{PointD(3.1415, 2.1828), PointD(2.1828, 3.1415)}});
|
||||
|
||||
Boundary boundary1;
|
||||
boundary1.emplace_back(vector<PointD>{{PointD(1.000, 1.000), PointD(1.002, 1.000), PointD(1.002, 1.003)}});
|
||||
|
||||
Boundaries const expected = {{boundary0, boundary1}};
|
||||
TestEncodeDecode(expected);
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(CitiesBoundaries_Moscow)
|
||||
{
|
||||
vector<PointD> const points = {
|
||||
{37.04001, 67.55964}, {37.55650, 66.96428}, {38.02513, 67.37082}, {37.50865, 67.96618}};
|
||||
|
||||
PointD const target(37.44765, 67.65243);
|
||||
|
||||
vector<uint8_t> buffer;
|
||||
{
|
||||
CityBoundary boundary(points);
|
||||
TEST(boundary.HasPoint(target), ());
|
||||
|
||||
MemWriter<decltype(buffer)> sink(buffer);
|
||||
CitiesBoundariesSerDes::Serialize(sink, {{boundary}});
|
||||
}
|
||||
|
||||
{
|
||||
Boundaries boundaries;
|
||||
double precision;
|
||||
|
||||
MemReader reader(buffer.data(), buffer.size());
|
||||
NonOwningReaderSource source(reader);
|
||||
CitiesBoundariesSerDes::Deserialize(source, boundaries, precision);
|
||||
|
||||
TEST_EQUAL(boundaries.size(), 1, ());
|
||||
TEST_EQUAL(boundaries[0].size(), 1, ());
|
||||
TEST(boundaries[0][0].HasPoint(target, precision), ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(CitiesBoundaries_Compression)
|
||||
{
|
||||
FilesContainerR cont(base::JoinPath(GetPlatform().WritableDir(), WORLD_FILE_NAME) + DATA_FILE_EXTENSION);
|
||||
|
||||
vector<vector<CityBoundary>> all1;
|
||||
double precision;
|
||||
|
||||
ReaderSource source1(cont.GetReader(CITIES_BOUNDARIES_FILE_TAG));
|
||||
LOG(LINFO, ("Size before:", source1.Size()));
|
||||
|
||||
CitiesBoundariesSerDes::Deserialize(source1, all1, precision);
|
||||
|
||||
vector<uint8_t> buffer;
|
||||
MemWriter writer(buffer);
|
||||
CitiesBoundariesSerDes::Serialize(writer, all1);
|
||||
LOG(LINFO, ("Size after:", buffer.size()));
|
||||
|
||||
// Equal test.
|
||||
vector<vector<CityBoundary>> all2;
|
||||
MemReader reader(buffer.data(), buffer.size());
|
||||
ReaderSource source2(reader);
|
||||
CitiesBoundariesSerDes::Deserialize(source2, all2, precision);
|
||||
|
||||
TEST_EQUAL(all1.size(), all2.size(), ());
|
||||
for (size_t i = 0; i < all1.size(); ++i)
|
||||
{
|
||||
TEST_EQUAL(all1[i].size(), all2[i].size(), ());
|
||||
for (size_t j = 0; j < all1[i].size(); ++j)
|
||||
if (!(all1[i][j] == all2[i][j]))
|
||||
LOG(LINFO, (i, all1[i][j], all2[i][j]));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cities_boundaries_serdes_tests
|
||||
104
libs/indexer/indexer_tests/classificator_tests.cpp
Normal file
104
libs/indexer/indexer_tests/classificator_tests.cpp
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/classificator.hpp"
|
||||
|
||||
#include "generator/generator_tests_support/test_with_classificator.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace generator::tests_support;
|
||||
using namespace std;
|
||||
|
||||
UNIT_CLASS_TEST(TestWithClassificator, Classificator_GetType)
|
||||
{
|
||||
Classificator const & c = classif();
|
||||
|
||||
uint32_t const type1 = c.GetTypeByPath({"natural", "coastline"});
|
||||
TEST_NOT_EQUAL(0, type1, ());
|
||||
TEST(c.IsTypeValid(type1), ());
|
||||
TEST_EQUAL(type1, c.GetTypeByReadableObjectName("natural-coastline"), ());
|
||||
|
||||
uint32_t const type2 = c.GetTypeByPath({"amenity", "parking", "private"});
|
||||
TEST_NOT_EQUAL(0, type2, ());
|
||||
TEST(c.IsTypeValid(type2), ());
|
||||
TEST_EQUAL(type2, c.GetTypeByReadableObjectName("amenity-parking-private"), ());
|
||||
|
||||
TEST_EQUAL(0, c.GetTypeByPathSafe({"nonexisting", "type"}), ());
|
||||
TEST_EQUAL(0, c.GetTypeByReadableObjectName("nonexisting-type"), ());
|
||||
TEST(!c.IsTypeValid(0), ());
|
||||
}
|
||||
|
||||
UNIT_CLASS_TEST(TestWithClassificator, Classificator_CoastlineType)
|
||||
{
|
||||
Classificator const & c = classif();
|
||||
|
||||
uint32_t const type = c.GetTypeByPath({"natural", "coastline"});
|
||||
TEST(c.IsTypeValid(type), ());
|
||||
TEST_EQUAL(type, c.GetCoastType(), ());
|
||||
}
|
||||
|
||||
UNIT_CLASS_TEST(TestWithClassificator, Classificator_GetIndex)
|
||||
{
|
||||
Classificator const & c = classif();
|
||||
|
||||
uint32_t const type = c.GetTypeByPath({"railway", "station", "subway"});
|
||||
uint32_t const index = c.GetIndexForType(type);
|
||||
TEST(c.IsTypeValid(type), ());
|
||||
TEST_EQUAL(type, c.GetTypeForIndex(index), ());
|
||||
}
|
||||
|
||||
UNIT_CLASS_TEST(TestWithClassificator, Classificator_Subtree)
|
||||
{
|
||||
Classificator const & c = classif();
|
||||
|
||||
uint32_t const cityType = c.GetTypeByPath({"place", "city"});
|
||||
|
||||
vector<vector<string>> const expectedPaths = {
|
||||
{"place", "city"},
|
||||
{"place", "city", "capital"},
|
||||
{"place", "city", "capital", "2"},
|
||||
{"place", "city", "capital", "3"},
|
||||
{"place", "city", "capital", "4"},
|
||||
{"place", "city", "capital", "5"},
|
||||
{"place", "city", "capital", "6"},
|
||||
{"place", "city", "capital", "7"},
|
||||
{"place", "city", "capital", "8"},
|
||||
{"place", "city", "capital", "9"},
|
||||
{"place", "city", "capital", "10"},
|
||||
{"place", "city", "capital", "11"},
|
||||
};
|
||||
|
||||
vector<uint32_t> expectedTypes;
|
||||
for (auto const & path : expectedPaths)
|
||||
expectedTypes.push_back(classif().GetTypeByPath(path));
|
||||
sort(expectedTypes.begin(), expectedTypes.end());
|
||||
|
||||
vector<uint32_t> subtreeTypes;
|
||||
c.ForEachInSubtree([&subtreeTypes](uint32_t type) { subtreeTypes.push_back(type); }, cityType);
|
||||
sort(subtreeTypes.begin(), subtreeTypes.end());
|
||||
|
||||
TEST_EQUAL(expectedTypes, subtreeTypes, ());
|
||||
}
|
||||
|
||||
UNIT_CLASS_TEST(TestWithClassificator, Classificator_StableIndex)
|
||||
{
|
||||
// mapcss-mapping.csv:
|
||||
//
|
||||
// amenity|parking|underground|fee;[amenity=parking][location=underground][fee?],[amenity=parking][parking=underground][fee?];x;name;int_name;356;amenity|parking|underground
|
||||
// amenity|parking|underground;[amenity=parking][location=underground],[amenity=parking][parking=underground];;name;int_name;357;
|
||||
//
|
||||
// The main definition of amenity|parking|underground goes second but we must use it for index. Test both indexes.
|
||||
// belong to amenity|parking|underground type and GetIndexForType returns second one.
|
||||
|
||||
Classificator const & c = classif();
|
||||
|
||||
uint32_t const type = c.GetTypeByPath({"amenity", "parking", "underground"});
|
||||
TEST(c.IsTypeValid(type), ());
|
||||
uint32_t const index = c.GetIndexForType(type);
|
||||
TEST_EQUAL(index, 357 - 1, ());
|
||||
TEST_NOT_EQUAL(type, c.GetTypeForIndex(356 - 1), ()); // Restored underground-fee
|
||||
TEST_EQUAL(type, c.GetTypeForIndex(357 - 1), ());
|
||||
}
|
||||
71
libs/indexer/indexer_tests/complex_serdes_tests.cpp
Normal file
71
libs/indexer/indexer_tests/complex_serdes_tests.cpp
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/complex/serdes.hpp"
|
||||
#include "indexer/complex/tree_node.hpp"
|
||||
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/writer.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace complex_serdes_tests
|
||||
{
|
||||
using ByteVector = std::vector<uint8_t>;
|
||||
using ::complex::ComplexSerdes;
|
||||
|
||||
decltype(auto) GetForest()
|
||||
{
|
||||
auto tree1 = tree_node::MakeTreeNode<ComplexSerdes::Ids>({1, 2, 3});
|
||||
auto node11 = tree_node::MakeTreeNode<ComplexSerdes::Ids>({11, 12, 13});
|
||||
tree_node::Link(tree_node::MakeTreeNode<ComplexSerdes::Ids>({111}), node11);
|
||||
tree_node::Link(tree_node::MakeTreeNode<ComplexSerdes::Ids>({112, 113}), node11);
|
||||
tree_node::Link(tree_node::MakeTreeNode<ComplexSerdes::Ids>({114}), node11);
|
||||
tree_node::Link(node11, tree1);
|
||||
tree_node::Link(tree_node::MakeTreeNode<ComplexSerdes::Ids>({6, 7}), tree1);
|
||||
|
||||
auto tree2 = tree_node::MakeTreeNode<ComplexSerdes::Ids>({9});
|
||||
tree_node::Link(tree_node::MakeTreeNode<ComplexSerdes::Ids>({21, 22, 23}), tree2);
|
||||
tree_node::Link(tree_node::MakeTreeNode<ComplexSerdes::Ids>({24, 25}), tree2);
|
||||
|
||||
tree_node::Forest<ComplexSerdes::Ids> forest;
|
||||
forest.Append(tree1);
|
||||
forest.Append(tree2);
|
||||
return forest;
|
||||
}
|
||||
|
||||
UNIT_TEST(Complex_SerdesV0)
|
||||
{
|
||||
auto const expectedForest = GetForest();
|
||||
ByteVector buffer;
|
||||
{
|
||||
MemWriter<decltype(buffer)> writer(buffer);
|
||||
WriterSink<decltype(writer)> sink(writer);
|
||||
ComplexSerdes::Serialize(sink, ComplexSerdes::Version::V0, expectedForest);
|
||||
}
|
||||
{
|
||||
MemReader reader(buffer.data(), buffer.size());
|
||||
ReaderSource<decltype(reader)> src(reader);
|
||||
tree_node::Forest<ComplexSerdes::Ids> forest;
|
||||
ComplexSerdes::Deserialize(src, ComplexSerdes::Version::V0, forest);
|
||||
TEST_EQUAL(forest, expectedForest, ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(Complex_Serdes)
|
||||
{
|
||||
auto const expectedForest = GetForest();
|
||||
ByteVector buffer;
|
||||
{
|
||||
MemWriter<decltype(buffer)> writer(buffer);
|
||||
WriterSink<decltype(writer)> sink(writer);
|
||||
ComplexSerdes::Serialize(sink, expectedForest);
|
||||
}
|
||||
{
|
||||
MemReader reader(buffer.data(), buffer.size());
|
||||
tree_node::Forest<ComplexSerdes::Ids> forest;
|
||||
ComplexSerdes::Deserialize(reader, forest);
|
||||
TEST_EQUAL(forest, expectedForest, ());
|
||||
}
|
||||
}
|
||||
} // namespace complex_serdes_tests
|
||||
60
libs/indexer/indexer_tests/complex_serdes_utils_tests.cpp
Normal file
60
libs/indexer/indexer_tests/complex_serdes_utils_tests.cpp
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/complex/serdes_utils.hpp"
|
||||
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/writer.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
using ByteVector = std::vector<uint8_t>;
|
||||
|
||||
template <typename Cont>
|
||||
void CollectionPrimitiveTest(Cont const & cont)
|
||||
{
|
||||
ByteVector buffer;
|
||||
MemWriter<decltype(buffer)> writer(buffer);
|
||||
WriterSink<decltype(writer)> sink(writer);
|
||||
coding_utils::WriteCollectionPrimitive(sink, cont);
|
||||
|
||||
MemReader reader(buffer.data(), buffer.size());
|
||||
ReaderSource<decltype(reader)> src(reader);
|
||||
Cont res;
|
||||
coding_utils::ReadCollectionPrimitive(src, std::inserter(res, std::end(res)));
|
||||
TEST_EQUAL(cont, res, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Utils_CollectionPrimitive)
|
||||
{
|
||||
{
|
||||
std::list<uint8_t> const cont{1, 2, 3, 4};
|
||||
CollectionPrimitiveTest(cont);
|
||||
}
|
||||
{
|
||||
std::list<int8_t> const cont{-1, -2, -3, -4};
|
||||
CollectionPrimitiveTest(cont);
|
||||
}
|
||||
{
|
||||
std::vector<uint32_t> const cont{1, 2, 3, 4};
|
||||
CollectionPrimitiveTest(cont);
|
||||
}
|
||||
{
|
||||
std::vector<int32_t> const cont{-1, -2, -3, -4};
|
||||
CollectionPrimitiveTest(cont);
|
||||
}
|
||||
{
|
||||
std::set<uint64_t> const cont{1, 2, 3, 4};
|
||||
CollectionPrimitiveTest(cont);
|
||||
}
|
||||
{
|
||||
std::set<int64_t> const cont{-1, -2, -3, -4};
|
||||
CollectionPrimitiveTest(cont);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
21
libs/indexer/indexer_tests/custom_keyvalue_tests.cpp
Normal file
21
libs/indexer/indexer_tests/custom_keyvalue_tests.cpp
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/custom_keyvalue.hpp"
|
||||
|
||||
UNIT_TEST(CustomKeyValue_Smoke)
|
||||
{
|
||||
indexer::CustomKeyValue empty("");
|
||||
TEST(!empty.Get(0), ());
|
||||
TEST_EQUAL(empty.ToString(), "", ());
|
||||
|
||||
indexer::CustomKeyValue kv;
|
||||
kv.Add(1, 777);
|
||||
kv.Add(255, 0xFFFFFFFF);
|
||||
kv.Add(0, 0);
|
||||
|
||||
indexer::CustomKeyValue actual(kv.ToString());
|
||||
TEST(!actual.Get(5), ());
|
||||
TEST_EQUAL(actual.GetSure(1), 777, ());
|
||||
TEST_EQUAL(actual.GetSure(255), 0xFFFFFFFF, ());
|
||||
TEST_EQUAL(actual.GetSure(0), 0, ());
|
||||
}
|
||||
157
libs/indexer/indexer_tests/data_source_test.cpp
Normal file
157
libs/indexer/indexer_tests/data_source_test.cpp
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/data_header.hpp"
|
||||
#include "indexer/data_source.hpp"
|
||||
#include "indexer/feature_source.hpp"
|
||||
#include "indexer/mwm_set.hpp"
|
||||
|
||||
#include "coding/internal/file_data.hpp"
|
||||
|
||||
#include "platform/country_file.hpp"
|
||||
#include "platform/local_country_file.hpp"
|
||||
#include "platform/platform.hpp"
|
||||
|
||||
#include "base/file_name_utils.hpp"
|
||||
#include "base/logging.hpp"
|
||||
#include "base/macros.hpp"
|
||||
#include "base/scope_guard.hpp"
|
||||
#include "base/stl_helpers.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
namespace data_source_test
|
||||
{
|
||||
using platform::CountryFile;
|
||||
using platform::LocalCountryFile;
|
||||
|
||||
class DataSourceTest : public MwmSet::Observer
|
||||
{
|
||||
public:
|
||||
DataSourceTest() { TEST(m_dataSource.AddObserver(*this), ()); }
|
||||
|
||||
~DataSourceTest() override { TEST(m_dataSource.RemoveObserver(*this), ()); }
|
||||
|
||||
void ExpectRegistered(platform::LocalCountryFile const & localFile)
|
||||
{
|
||||
AddEvent(m_expected, MwmSet::Event::TYPE_REGISTERED, localFile);
|
||||
}
|
||||
|
||||
void ExpectDeregistered(platform::LocalCountryFile const & localFile)
|
||||
{
|
||||
AddEvent(m_expected, MwmSet::Event::TYPE_DEREGISTERED, localFile);
|
||||
}
|
||||
|
||||
// Checks expectations and clears them.
|
||||
bool CheckExpectations()
|
||||
{
|
||||
bool ok = true;
|
||||
if (m_actual != m_expected)
|
||||
{
|
||||
LOG(LINFO, ("Check failed. Expected:", m_expected, "actual:", m_actual));
|
||||
ok = false;
|
||||
}
|
||||
m_actual.clear();
|
||||
m_expected.clear();
|
||||
return ok;
|
||||
}
|
||||
|
||||
// MwmSet::Observer overrides:
|
||||
void OnMapRegistered(platform::LocalCountryFile const & localFile) override
|
||||
{
|
||||
AddEvent(m_actual, MwmSet::Event::TYPE_REGISTERED, localFile);
|
||||
}
|
||||
|
||||
void OnMapDeregistered(platform::LocalCountryFile const & localFile) override
|
||||
{
|
||||
AddEvent(m_actual, MwmSet::Event::TYPE_DEREGISTERED, localFile);
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename... TArgs>
|
||||
void AddEvent(std::vector<MwmSet::Event> & events, TArgs... args)
|
||||
{
|
||||
events.emplace_back(std::forward<TArgs>(args)...);
|
||||
}
|
||||
|
||||
FrozenDataSource m_dataSource;
|
||||
std::vector<MwmSet::Event> m_expected;
|
||||
std::vector<MwmSet::Event> m_actual;
|
||||
};
|
||||
|
||||
UNIT_CLASS_TEST(DataSourceTest, Parse)
|
||||
{
|
||||
UNUSED_VALUE(m_dataSource.RegisterMap(platform::LocalCountryFile::MakeForTesting("minsk-pass")));
|
||||
|
||||
// Make sure that index is actually parsed.
|
||||
m_dataSource.ForEachInScale([](FeatureType &) { return; }, 15);
|
||||
}
|
||||
|
||||
UNIT_CLASS_TEST(DataSourceTest, StatusNotifications)
|
||||
{
|
||||
std::string const mapsDir = GetPlatform().WritableDir();
|
||||
CountryFile const country("minsk-pass");
|
||||
|
||||
// These two classes point to the same file, but will be considered
|
||||
// by DataSource as distinct files because versions are artificially set
|
||||
// to different numbers.
|
||||
LocalCountryFile const file1(mapsDir, country, 1 /* version */);
|
||||
LocalCountryFile const file2(mapsDir, country, 2 /* version */);
|
||||
|
||||
MwmSet::MwmId id1;
|
||||
|
||||
// Checks that observers are triggered after map registration.
|
||||
{
|
||||
auto result = m_dataSource.RegisterMap(file1);
|
||||
TEST_EQUAL(MwmSet::RegResult::Success, result.second, ());
|
||||
|
||||
id1 = result.first;
|
||||
TEST(id1.IsAlive(), ());
|
||||
|
||||
ExpectRegistered(file1);
|
||||
TEST(CheckExpectations(), ());
|
||||
}
|
||||
|
||||
// Checks that map can't registered twice.
|
||||
{
|
||||
auto result = m_dataSource.RegisterMap(file1);
|
||||
TEST_EQUAL(MwmSet::RegResult::VersionAlreadyExists, result.second, ());
|
||||
|
||||
TEST(result.first.IsAlive(), ());
|
||||
TEST_EQUAL(id1, result.first, ());
|
||||
|
||||
TEST(CheckExpectations(), ());
|
||||
}
|
||||
|
||||
// Checks that observers are notified when map is updated.
|
||||
MwmSet::MwmId id2;
|
||||
{
|
||||
auto result = m_dataSource.RegisterMap(file2);
|
||||
TEST_EQUAL(MwmSet::RegResult::Success, result.second, ());
|
||||
|
||||
id2 = result.first;
|
||||
TEST(id2.IsAlive(), ());
|
||||
TEST_NOT_EQUAL(id1, id2, ());
|
||||
|
||||
ExpectDeregistered(file1);
|
||||
ExpectRegistered(file2);
|
||||
TEST(CheckExpectations(), ());
|
||||
}
|
||||
|
||||
// Tries to deregister a map in presence of an active handle. Map
|
||||
// should be marked "to be removed" but can't be deregistered. After
|
||||
// leaving the inner block the map should be deregistered.
|
||||
{
|
||||
{
|
||||
MwmSet::MwmHandle const handle = m_dataSource.GetMwmHandleByCountryFile(country);
|
||||
TEST(handle.IsAlive(), ());
|
||||
|
||||
TEST(!m_dataSource.DeregisterMap(country), ());
|
||||
TEST(CheckExpectations(), ());
|
||||
}
|
||||
|
||||
ExpectDeregistered(file2);
|
||||
TEST(CheckExpectations(), ());
|
||||
}
|
||||
}
|
||||
} // namespace data_source_test
|
||||
168
libs/indexer/indexer_tests/drules_selector_parser_test.cpp
Normal file
168
libs/indexer/indexer_tests/drules_selector_parser_test.cpp
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/drules_selector.hpp"
|
||||
#include "indexer/drules_selector_parser.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace drules_selector_parser_test
|
||||
{
|
||||
using namespace drule;
|
||||
using namespace std;
|
||||
|
||||
UNIT_TEST(TestDruleSelectorIsSet)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("name", e), ());
|
||||
|
||||
TEST_EQUAL("name", e.m_tag, ());
|
||||
TEST_EQUAL("", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorIsSet, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorIsSet2)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("bbox_area", e), ());
|
||||
|
||||
TEST_EQUAL("bbox_area", e.m_tag, ());
|
||||
TEST_EQUAL("", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorIsSet, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorIsNotSet)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("!name", e), ());
|
||||
|
||||
TEST_EQUAL("name", e.m_tag, ());
|
||||
TEST_EQUAL("", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorIsNotSet, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorIsNotSet2)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("!bbox_area", e), ());
|
||||
|
||||
TEST_EQUAL("bbox_area", e.m_tag, ());
|
||||
TEST_EQUAL("", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorIsNotSet, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorEqual)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("population=1000", e), ());
|
||||
|
||||
TEST_EQUAL("population", e.m_tag, ());
|
||||
TEST_EQUAL("1000", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorEqual, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorNotEqual)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("population!=1000", e), ());
|
||||
|
||||
TEST_EQUAL("population", e.m_tag, ());
|
||||
TEST_EQUAL("1000", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorNotEqual, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorLess)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("population<1000", e), ());
|
||||
|
||||
TEST_EQUAL("population", e.m_tag, ());
|
||||
TEST_EQUAL("1000", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorLess, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorLess2)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("bbox_area<1000", e), ());
|
||||
|
||||
TEST_EQUAL("bbox_area", e.m_tag, ());
|
||||
TEST_EQUAL("1000", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorLess, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorGreater)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("population>1000", e), ());
|
||||
|
||||
TEST_EQUAL("population", e.m_tag, ());
|
||||
TEST_EQUAL("1000", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorGreater, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorGreater2)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("bbox_area>1000", e), ());
|
||||
|
||||
TEST_EQUAL("bbox_area", e.m_tag, ());
|
||||
TEST_EQUAL("1000", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorGreater, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorLessOrEqual)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("population<=1000", e), ());
|
||||
|
||||
TEST_EQUAL("population", e.m_tag, ());
|
||||
TEST_EQUAL("1000", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorLessOrEqual, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorGreaterOrEqual)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("population>=1000", e), ());
|
||||
|
||||
TEST_EQUAL("population", e.m_tag, ());
|
||||
TEST_EQUAL("1000", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorGreaterOrEqual, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorInvalid)
|
||||
{
|
||||
char const * const badFormats[] = {
|
||||
"", "=badformat", "!=badformat", ">badformat", "<badformat", ">=badformat", "<=badformat",
|
||||
"bad$name", "!bad$name", "bad$name=1000",
|
||||
};
|
||||
|
||||
for (auto e : badFormats)
|
||||
{
|
||||
SelectorExpression expr;
|
||||
TEST_EQUAL(false, ParseSelector(e, expr), ("string is", e));
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(PopulationSelector_Smoke)
|
||||
{
|
||||
TEST(ParseSelector("population<1000"), ());
|
||||
TEST(ParseSelector(vector<string>({"population>1000"})), ());
|
||||
TEST(ParseSelector(vector<string>({"population>=1000", "population<=1000000"})), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(NameSelector_Smoke)
|
||||
{
|
||||
TEST(ParseSelector("name"), ());
|
||||
TEST(ParseSelector("!name"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(InvalidSelector_Smoke)
|
||||
{
|
||||
TEST(!ParseSelector(""), ());
|
||||
TEST(!ParseSelector(vector<string>({""})), ());
|
||||
TEST(!ParseSelector(vector<string>({"population>=1000", "population<=1000000", ""})), ());
|
||||
}
|
||||
|
||||
} // namespace drules_selector_parser_test
|
||||
554
libs/indexer/indexer_tests/editable_map_object_test.cpp
Normal file
554
libs/indexer/indexer_tests/editable_map_object_test.cpp
Normal file
|
|
@ -0,0 +1,554 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/classificator.hpp"
|
||||
#include "indexer/classificator_loader.hpp"
|
||||
#include "indexer/editable_map_object.hpp"
|
||||
#include "indexer/feature.hpp"
|
||||
#include "indexer/feature_utils.hpp"
|
||||
#include "indexer/validate_and_format_contacts.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace editable_map_object_test
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
using osm::EditableMapObject;
|
||||
|
||||
int8_t GetLangCode(char const * ch)
|
||||
{
|
||||
return StringUtf8Multilang::GetLangIndex(ch);
|
||||
}
|
||||
|
||||
struct ExpectedName
|
||||
{
|
||||
string m_lang;
|
||||
string m_value;
|
||||
};
|
||||
|
||||
string DebugPrint(ExpectedName const & expectedName)
|
||||
{
|
||||
return expectedName.m_lang + ", " + expectedName.m_value;
|
||||
}
|
||||
|
||||
void CheckExpectations(StringUtf8Multilang const & s, vector<ExpectedName> const & expectations)
|
||||
{
|
||||
size_t counter = 0;
|
||||
s.ForEach([&expectations, &counter](int8_t const code, string_view name)
|
||||
{
|
||||
auto const it = find_if(expectations.begin(), expectations.end(),
|
||||
[&code](ExpectedName const & item) { return GetLangCode(item.m_lang.c_str()) == code; });
|
||||
|
||||
if (it == expectations.end())
|
||||
TEST(false, ("Unexpected language code: ", code, ". Expectations: ", expectations));
|
||||
|
||||
TEST_EQUAL(name, it->m_value, ());
|
||||
++counter;
|
||||
});
|
||||
|
||||
TEST_EQUAL(counter, expectations.size(),
|
||||
("Unexpected count of names, expected ", expectations.size(), ", but turned out ", counter,
|
||||
". Expectations: ", expectations));
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_SetWebsite)
|
||||
{
|
||||
pair<char const *, char const *> arr[] = {
|
||||
{"https://some.thing.org", "https://some.thing.org"},
|
||||
{"http://some.thing.org", "http://some.thing.org"},
|
||||
{"some.thing.org", "http://some.thing.org"},
|
||||
{"", ""},
|
||||
};
|
||||
|
||||
EditableMapObject emo;
|
||||
for (auto const & e : arr)
|
||||
{
|
||||
emo.SetMetadata(feature::Metadata::FMD_WEBSITE, e.first);
|
||||
TEST_EQUAL(emo.GetMetadata(feature::Metadata::FMD_WEBSITE), e.second, ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateBuildingLevels)
|
||||
{
|
||||
TEST(EditableMapObject::ValidateBuildingLevels(""), ());
|
||||
TEST(EditableMapObject::ValidateBuildingLevels("7"), ());
|
||||
TEST(EditableMapObject::ValidateBuildingLevels("17"), ());
|
||||
TEST(EditableMapObject::ValidateBuildingLevels("25"), ());
|
||||
TEST(!EditableMapObject::ValidateBuildingLevels("0"), ());
|
||||
TEST(!EditableMapObject::ValidateBuildingLevels("005"), ());
|
||||
TEST(!EditableMapObject::ValidateBuildingLevels(std::to_string(EditableMapObject::kMaximumLevelsEditableByUsers + 1)),
|
||||
());
|
||||
TEST(!EditableMapObject::ValidateBuildingLevels("22a"), ());
|
||||
TEST(!EditableMapObject::ValidateBuildingLevels("a22"), ());
|
||||
TEST(!EditableMapObject::ValidateBuildingLevels("2a22"), ());
|
||||
TEST(!EditableMapObject::ValidateBuildingLevels("ab"), ());
|
||||
TEST(!EditableMapObject::ValidateBuildingLevels("2345534564564453645534545345534564564453645"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateHouseNumber)
|
||||
{
|
||||
TEST(EditableMapObject::ValidateHouseNumber(""), ());
|
||||
TEST(EditableMapObject::ValidateHouseNumber("qwer7ty"), ());
|
||||
TEST(EditableMapObject::ValidateHouseNumber("12345678"), ());
|
||||
|
||||
// House number must contain at least one number.
|
||||
TEST(!EditableMapObject::ValidateHouseNumber("qwerty"), ());
|
||||
// House number is too long.
|
||||
TEST(!EditableMapObject::ValidateHouseNumber("1234567890123456"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateFlats)
|
||||
{
|
||||
TEST(EditableMapObject::ValidateFlats(""), ());
|
||||
TEST(EditableMapObject::ValidateFlats("123"), ());
|
||||
TEST(EditableMapObject::ValidateFlats("123a"), ());
|
||||
TEST(EditableMapObject::ValidateFlats("a"), ());
|
||||
TEST(EditableMapObject::ValidateFlats("123-456;a-e"), ());
|
||||
TEST(EditableMapObject::ValidateFlats("123-456"), ());
|
||||
TEST(EditableMapObject::ValidateFlats("123-456; 43-45"), ());
|
||||
TEST(!EditableMapObject::ValidateFlats("123-456, 43-45"), ());
|
||||
TEST(!EditableMapObject::ValidateFlats("234-234 124"), ());
|
||||
TEST(!EditableMapObject::ValidateFlats("123-345-567"), ());
|
||||
TEST(!EditableMapObject::ValidateFlats("234-234;234("), ());
|
||||
TEST(!EditableMapObject::ValidateFlats("-;"), ());
|
||||
}
|
||||
|
||||
// See search_tests/postcodes_matcher_test.cpp
|
||||
// UNIT_TEST(EditableMapObject_ValidatePostCode)
|
||||
// {
|
||||
// }
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidatePhoneList)
|
||||
{
|
||||
TEST(EditableMapObject::ValidatePhoneList(""), ());
|
||||
TEST(EditableMapObject::ValidatePhoneList("+7 000 000 00 00"), ());
|
||||
TEST(EditableMapObject::ValidatePhoneList("+7 (000) 000 00 00"), ());
|
||||
TEST(EditableMapObject::ValidatePhoneList("+7 0000000000"), ());
|
||||
TEST(EditableMapObject::ValidatePhoneList("+7 0000 000 000"), ());
|
||||
TEST(EditableMapObject::ValidatePhoneList("8 0000-000-000"), ());
|
||||
|
||||
TEST(EditableMapObject::ValidatePhoneList("000 00 00"), ());
|
||||
TEST(EditableMapObject::ValidatePhoneList("000 000 00"), ());
|
||||
TEST(EditableMapObject::ValidatePhoneList("+00 0000 000 000"), ());
|
||||
|
||||
TEST(EditableMapObject::ValidatePhoneList("+7 000 000 00 00; +7 000 000 00 00"), ());
|
||||
TEST(EditableMapObject::ValidatePhoneList("+7 (000) 000 00 00, +7 (000) 000 00 00"), ());
|
||||
TEST(EditableMapObject::ValidatePhoneList("+7 0000000000;+7 0000000000"), ());
|
||||
TEST(EditableMapObject::ValidatePhoneList("+7 0000 000 000,+7 0000 000 000"), ());
|
||||
TEST(EditableMapObject::ValidatePhoneList("8 0000-000-000; 8 0000-000-000"), ());
|
||||
|
||||
TEST(EditableMapObject::ValidatePhoneList("+7 00 00;7 (0)00 0, 800-00-0; 000000000000000,12345"), ());
|
||||
|
||||
TEST(!EditableMapObject::ValidatePhoneList("+00 0000 000 0000 000"), ());
|
||||
TEST(!EditableMapObject::ValidatePhoneList("00 00"), ());
|
||||
TEST(!EditableMapObject::ValidatePhoneList("acb"), ());
|
||||
TEST(!EditableMapObject::ValidatePhoneList("000 000 00b"), ());
|
||||
TEST(!EditableMapObject::ValidatePhoneList(";"), ());
|
||||
TEST(!EditableMapObject::ValidatePhoneList(","), ());
|
||||
TEST(!EditableMapObject::ValidatePhoneList(";;;;;;"), ());
|
||||
|
||||
// Now it is possible to specify the following incorrect phone numbers.
|
||||
// TODO: replace current implementation of ValidatePhoneList by a correct one.
|
||||
TEST(EditableMapObject::ValidatePhoneList("7+ 10 10"), ());
|
||||
TEST(EditableMapObject::ValidatePhoneList("+7 )10( 10"), ());
|
||||
TEST(EditableMapObject::ValidatePhoneList("+7 )10 10"), ());
|
||||
TEST(EditableMapObject::ValidatePhoneList("+7 10 (---) 10"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateWebsite)
|
||||
{
|
||||
TEST(osm::ValidateWebsite(""), ());
|
||||
TEST(osm::ValidateWebsite("qwe.rty"), ());
|
||||
TEST(osm::ValidateWebsite("http://websit.e"), ());
|
||||
TEST(osm::ValidateWebsite("https://websit.e"), ());
|
||||
|
||||
TEST(!osm::ValidateWebsite("qwerty"), ());
|
||||
TEST(!osm::ValidateWebsite(".qwerty"), ());
|
||||
TEST(!osm::ValidateWebsite("qwerty."), ());
|
||||
TEST(!osm::ValidateWebsite(".qwerty."), ());
|
||||
TEST(!osm::ValidateWebsite("w..com"), ());
|
||||
TEST(!osm::ValidateWebsite("http://.websit.e"), ());
|
||||
TEST(!osm::ValidateWebsite("https://.websit.e"), ());
|
||||
TEST(!osm::ValidateWebsite("http://"), ());
|
||||
TEST(!osm::ValidateWebsite("https://"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateEmail)
|
||||
{
|
||||
TEST(EditableMapObject::ValidateEmail(""), ());
|
||||
TEST(EditableMapObject::ValidateEmail("e@ma.il"), ());
|
||||
TEST(EditableMapObject::ValidateEmail("e@ma.i.l"), ());
|
||||
TEST(EditableMapObject::ValidateEmail("e-m.ail@dot.com.gov"), ());
|
||||
TEST(EditableMapObject::ValidateEmail("#$%&'*+-/=?^`_{}|~.@dot.qw.com.gov"), ());
|
||||
|
||||
TEST(!EditableMapObject::ValidateEmail("e.ma.il"), ());
|
||||
TEST(!EditableMapObject::ValidateEmail("e@ma@il"), ());
|
||||
TEST(!EditableMapObject::ValidateEmail("e@ma@i.l"), ());
|
||||
TEST(!EditableMapObject::ValidateEmail("e@mail"), ());
|
||||
TEST(!EditableMapObject::ValidateEmail("@email.a"), ());
|
||||
TEST(!EditableMapObject::ValidateEmail("emai.l@"), ());
|
||||
TEST(!EditableMapObject::ValidateEmail("emai@l."), ());
|
||||
TEST(!EditableMapObject::ValidateEmail("e mai@l.com"), ());
|
||||
TEST(!EditableMapObject::ValidateEmail("emai@.l"), ());
|
||||
TEST(!EditableMapObject::ValidateEmail("emai@_l.ab"), ());
|
||||
TEST(!EditableMapObject::ValidateEmail("emai@l_.ab"), ());
|
||||
TEST(!EditableMapObject::ValidateEmail("email@e#$%&'*+-/=?^`_{}|~.com"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateName)
|
||||
{
|
||||
vector<string> correctNames = {"abc", "абв", "ᆺᆯㅕ", "꫞ꪺꫀꪸ", "a b?c", "a!b.c", "a(b)c",
|
||||
"a,b.c", "a$bc", "a%bc", "a#bc", "a№bc", "c&a", "a[bc"};
|
||||
vector<string> incorrectNames = {"a^bc",
|
||||
"a~bc",
|
||||
"a§bc",
|
||||
"a>bc",
|
||||
"a<bc",
|
||||
"a{bc",
|
||||
"*",
|
||||
"a*bc",
|
||||
"a=bc",
|
||||
"a_bc",
|
||||
"a±bc",
|
||||
"a\nbc",
|
||||
"a\tbc",
|
||||
"a\rbc",
|
||||
"a\vbc",
|
||||
"a\fbc",
|
||||
"a|bc",
|
||||
"N√",
|
||||
"Hello World!\U0001F600",
|
||||
"Exit →",
|
||||
"∫0dx = C",
|
||||
"\U0001210A",
|
||||
"⚠︎",
|
||||
"⚠️"};
|
||||
|
||||
for (auto const & name : correctNames)
|
||||
TEST(EditableMapObject::ValidateName(name), ());
|
||||
|
||||
for (auto const & name : incorrectNames)
|
||||
TEST(!EditableMapObject::ValidateName(name), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_CanUseAsDefaultName)
|
||||
{
|
||||
EditableMapObject emo;
|
||||
vector<int8_t> const nativeMwmLanguages{GetLangCode("de"), GetLangCode("fr")};
|
||||
|
||||
TEST(EditableMapObject::CanUseAsDefaultName(GetLangCode("de"), nativeMwmLanguages),
|
||||
("Check possibility to use Mwm language code"));
|
||||
TEST(EditableMapObject::CanUseAsDefaultName(GetLangCode("fr"), nativeMwmLanguages),
|
||||
("Check possibility to use Mwm language code"));
|
||||
TEST(!EditableMapObject::CanUseAsDefaultName(GetLangCode("int_name"), nativeMwmLanguages),
|
||||
("Check possibility to use international language code"));
|
||||
TEST(!EditableMapObject::CanUseAsDefaultName(100, nativeMwmLanguages), ("Incorrect language code is not supported"));
|
||||
TEST(!EditableMapObject::CanUseAsDefaultName(GetLangCode("en"), {GetLangCode("abcd")}),
|
||||
("Incorrect Mwm language name is not supported"));
|
||||
TEST(!EditableMapObject::CanUseAsDefaultName(GetLangCode("en"), nativeMwmLanguages),
|
||||
("Can not to use language which not Mwm language or international"));
|
||||
TEST(!EditableMapObject::CanUseAsDefaultName(GetLangCode("ru"), nativeMwmLanguages),
|
||||
("Check possibility to use user`s language code"));
|
||||
|
||||
// Trying to use language codes in reverse priority.
|
||||
StringUtf8Multilang names;
|
||||
names.AddString(GetLangCode("fr"), "second mwm language");
|
||||
emo.SetName(names);
|
||||
|
||||
TEST(EditableMapObject::CanUseAsDefaultName(GetLangCode("fr"), nativeMwmLanguages), ("It is possible to fix typo"));
|
||||
|
||||
names.AddString(GetLangCode("de"), "first mwm language");
|
||||
emo.SetName(names);
|
||||
|
||||
TEST(EditableMapObject::CanUseAsDefaultName(GetLangCode("de"), nativeMwmLanguages), ("It is possible to fix typo"));
|
||||
TEST(EditableMapObject::CanUseAsDefaultName(GetLangCode("fr"), nativeMwmLanguages), ("It is possible to fix typo"));
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_GetNamesDataSource)
|
||||
{
|
||||
EditableMapObject emo;
|
||||
StringUtf8Multilang names;
|
||||
|
||||
names.AddString(GetLangCode("default"), "Default name");
|
||||
names.AddString(GetLangCode("en"), "Eng name");
|
||||
names.AddString(GetLangCode("int_name"), "Int name");
|
||||
names.AddString(GetLangCode("de"), "De name");
|
||||
names.AddString(GetLangCode("ru"), "Ru name");
|
||||
names.AddString(GetLangCode("sv"), "Sv name");
|
||||
names.AddString(GetLangCode("be"), "By name");
|
||||
names.AddString(GetLangCode("ko"), "Ko name");
|
||||
names.AddString(GetLangCode("it"), "It name");
|
||||
emo.SetName(names);
|
||||
|
||||
vector<int8_t> nativeMwmLanguages = {GetLangCode("de"), GetLangCode("fr")};
|
||||
|
||||
auto const namesDataSource =
|
||||
EditableMapObject::GetNamesDataSource(emo.GetNameMultilang(), nativeMwmLanguages, GetLangCode("ko"));
|
||||
|
||||
TEST_EQUAL(namesDataSource.names.size(), 9, ("All names including the default should be pushed into data source"));
|
||||
TEST_EQUAL(namesDataSource.mandatoryNamesCount, 1, ("Mandatory names count should always be 1"));
|
||||
TEST_EQUAL(namesDataSource.names[0].m_code, GetLangCode("default"), ("Default is always first in the list"));
|
||||
|
||||
{
|
||||
vector<int8_t> nativeMwmLanguages = {GetLangCode("de"), GetLangCode("fr")};
|
||||
|
||||
auto const namesDataSource =
|
||||
EditableMapObject::GetNamesDataSource(emo.GetNameMultilang(), nativeMwmLanguages, GetLangCode("fr"));
|
||||
TEST_EQUAL(namesDataSource.names.size(), 9, ("All names including the default should be pushed into data source"));
|
||||
TEST_EQUAL(namesDataSource.mandatoryNamesCount, 1, ("Mandatory names count should always be 1"));
|
||||
}
|
||||
{
|
||||
vector<int8_t> nativeMwmLanguages = {GetLangCode("fr"), GetLangCode("en")};
|
||||
|
||||
auto const namesDataSource =
|
||||
EditableMapObject::GetNamesDataSource(emo.GetNameMultilang(), nativeMwmLanguages, GetLangCode("fr"));
|
||||
TEST_EQUAL(namesDataSource.names.size(), 9, ("All names including the default should be pushed into data source"));
|
||||
TEST_EQUAL(namesDataSource.mandatoryNamesCount, 1, ("Mandatory names count should always be 1"));
|
||||
}
|
||||
{
|
||||
vector<int8_t> nativeMwmLanguages = {GetLangCode("en"), GetLangCode("en")};
|
||||
|
||||
auto const namesDataSource =
|
||||
EditableMapObject::GetNamesDataSource(emo.GetNameMultilang(), nativeMwmLanguages, GetLangCode("en"));
|
||||
TEST_EQUAL(namesDataSource.names.size(), 9, ("All names including the default should be pushed into data source"));
|
||||
TEST_EQUAL(namesDataSource.mandatoryNamesCount, 1, ("Mandatory names count should always be 1"));
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
void SetTypes(EditableMapObject & emo, std::initializer_list<base::StringIL> types)
|
||||
{
|
||||
auto const & cl = classif();
|
||||
feature::TypesHolder holder;
|
||||
for (auto const & t : types)
|
||||
holder.Add(cl.GetTypeByPath(t));
|
||||
emo.SetTypes(holder);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
UNIT_TEST(EditableMapObject_SetInternet)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
EditableMapObject emo;
|
||||
auto const wifiType = classif().GetTypeByPath({"internet_access", "wlan"});
|
||||
emo.SetType(wifiType);
|
||||
|
||||
auto types = emo.GetTypes();
|
||||
TEST(types.Has(wifiType), ());
|
||||
|
||||
auto const setInternetAndCheck = [wifiType](EditableMapObject & emo, feature::Internet internet, bool hasWifi)
|
||||
{
|
||||
emo.SetInternet(internet);
|
||||
|
||||
TEST_EQUAL(emo.GetInternet(), internet, ());
|
||||
auto const & types = emo.GetTypes();
|
||||
TEST_EQUAL(types.Has(wifiType), hasWifi, ());
|
||||
};
|
||||
|
||||
setInternetAndCheck(emo, feature::Internet::No, false);
|
||||
setInternetAndCheck(emo, feature::Internet::Yes, false);
|
||||
setInternetAndCheck(emo, feature::Internet::Wired, false);
|
||||
setInternetAndCheck(emo, feature::Internet::Wlan, true);
|
||||
setInternetAndCheck(emo, feature::Internet::Unknown, false);
|
||||
setInternetAndCheck(emo, feature::Internet::Terminal, false);
|
||||
|
||||
EditableMapObject bunkerEmo;
|
||||
SetTypes(bunkerEmo, {{"military", "bunker"}});
|
||||
types = bunkerEmo.GetTypes();
|
||||
TEST(!types.Has(wifiType), ());
|
||||
|
||||
setInternetAndCheck(bunkerEmo, feature::Internet::Wlan, true);
|
||||
setInternetAndCheck(bunkerEmo, feature::Internet::No, false);
|
||||
setInternetAndCheck(bunkerEmo, feature::Internet::Wlan, true);
|
||||
setInternetAndCheck(bunkerEmo, feature::Internet::Yes, false);
|
||||
setInternetAndCheck(bunkerEmo, feature::Internet::Wlan, true);
|
||||
setInternetAndCheck(bunkerEmo, feature::Internet::Wired, false);
|
||||
setInternetAndCheck(bunkerEmo, feature::Internet::Wlan, true);
|
||||
setInternetAndCheck(bunkerEmo, feature::Internet::Unknown, false);
|
||||
setInternetAndCheck(bunkerEmo, feature::Internet::Wlan, true);
|
||||
setInternetAndCheck(bunkerEmo, feature::Internet::Terminal, false);
|
||||
setInternetAndCheck(bunkerEmo, feature::Internet::Wlan, true);
|
||||
setInternetAndCheck(bunkerEmo, feature::Internet::Wlan, true);
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_RemoveBlankNames)
|
||||
{
|
||||
auto const getCountOfNames = [](StringUtf8Multilang const & names)
|
||||
{
|
||||
size_t counter = 0;
|
||||
names.ForEach([&counter](int8_t, string_view) { ++counter; });
|
||||
return counter;
|
||||
};
|
||||
|
||||
StringUtf8Multilang name;
|
||||
|
||||
name.AddString(GetLangCode("default"), "Default name");
|
||||
name.AddString(GetLangCode("ru"), "Ru name");
|
||||
name.AddString(GetLangCode("en"), "En name");
|
||||
name.AddString(GetLangCode("de"), "De name");
|
||||
|
||||
EditableMapObject emo;
|
||||
emo.SetName(name);
|
||||
emo.RemoveBlankNames();
|
||||
|
||||
TEST_EQUAL(getCountOfNames(emo.GetNameMultilang()), 4, ());
|
||||
|
||||
name.Clear();
|
||||
|
||||
name.AddString(GetLangCode("default"), "");
|
||||
name.AddString(GetLangCode("ru"), "Ru name");
|
||||
name.AddString(GetLangCode("en"), "En name");
|
||||
name.AddString(GetLangCode("de"), "");
|
||||
|
||||
emo.SetName(name);
|
||||
emo.RemoveBlankNames();
|
||||
|
||||
TEST_EQUAL(getCountOfNames(emo.GetNameMultilang()), 2, ());
|
||||
|
||||
name.Clear();
|
||||
|
||||
name.AddString(GetLangCode("default"), "Default name");
|
||||
name.AddString(GetLangCode("ru"), "");
|
||||
name.AddString(GetLangCode("en"), "");
|
||||
name.AddString(GetLangCode("de"), "");
|
||||
|
||||
emo.SetName(name);
|
||||
emo.RemoveBlankNames();
|
||||
|
||||
TEST_EQUAL(getCountOfNames(emo.GetNameMultilang()), 1, ());
|
||||
|
||||
name.Clear();
|
||||
|
||||
name.AddString(GetLangCode("default"), "");
|
||||
name.AddString(GetLangCode("ru"), "");
|
||||
name.AddString(GetLangCode("en"), "");
|
||||
name.AddString(GetLangCode("de"), "De name");
|
||||
|
||||
emo.SetName(name);
|
||||
emo.RemoveBlankNames();
|
||||
|
||||
TEST_EQUAL(getCountOfNames(emo.GetNameMultilang()), 1, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_FromFeatureType)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
EditableMapObject emo;
|
||||
SetTypes(emo, {{"amenity", "cafe"}});
|
||||
|
||||
emo.SetHouseNumber("1");
|
||||
|
||||
StringUtf8Multilang names;
|
||||
names.AddString(GetLangCode("default"), "Default name");
|
||||
names.AddString(GetLangCode("ru"), "Ru name");
|
||||
emo.SetName(names);
|
||||
|
||||
emo.SetMetadata(feature::Metadata::FMD_WEBSITE, "https://some.thing.org");
|
||||
emo.SetInternet(feature::Internet::Wlan);
|
||||
|
||||
emo.SetPointType();
|
||||
emo.SetMercator(m2::PointD(1.0, 1.0));
|
||||
|
||||
auto ft = FeatureType::CreateFromMapObject(emo);
|
||||
EditableMapObject emo2;
|
||||
emo2.SetFromFeatureType(*ft);
|
||||
|
||||
TEST(emo.GetTypes().Equals(emo2.GetTypes()), ());
|
||||
|
||||
TEST_EQUAL(emo.GetNameMultilang(), emo2.GetNameMultilang(), ());
|
||||
TEST_EQUAL(emo.GetHouseNumber(), emo2.GetHouseNumber(), ());
|
||||
TEST_EQUAL(emo.GetMercator(), emo2.GetMercator(), ());
|
||||
TEST_EQUAL(emo.GetMetadata(feature::Metadata::FMD_WEBSITE), emo2.GetMetadata(feature::Metadata::FMD_WEBSITE), ());
|
||||
TEST_EQUAL(emo.GetInternet(), emo2.GetInternet(), ());
|
||||
|
||||
TEST(emo.IsPointType(), ());
|
||||
TEST(emo2.IsPointType(), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_GetLocalizedAllTypes)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
{
|
||||
EditableMapObject emo;
|
||||
SetTypes(emo, {{"amenity", "fuel"}, {"shop"}, {"building"}, {"toilets", "yes"}});
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(true), "amenity-fuel • shop", ());
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(false), "shop", ());
|
||||
}
|
||||
|
||||
{
|
||||
EditableMapObject emo;
|
||||
SetTypes(emo, {{"amenity", "shelter"}, {"amenity", "bench"}, {"highway", "bus_stop"}});
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(true), "highway-bus_stop • amenity-shelter • amenity-bench", ());
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(false), "amenity-shelter • amenity-bench", ());
|
||||
}
|
||||
|
||||
{
|
||||
EditableMapObject emo;
|
||||
SetTypes(emo, {{"leisure", "pitch"}, {"sport", "soccer"}});
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(true), "sport-soccer • leisure-pitch", ());
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(false), "leisure-pitch", ());
|
||||
}
|
||||
|
||||
{
|
||||
EditableMapObject emo;
|
||||
SetTypes(emo, {{"craft", "key_cutter"}});
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(true), "craft-key_cutter", ());
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(false), "", ());
|
||||
}
|
||||
|
||||
{
|
||||
EditableMapObject emo;
|
||||
SetTypes(emo, {{"amenity", "parking_entrance"}, {"barrier", "gate"}});
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(true), "barrier-gate • amenity-parking_entrance", ());
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(false), "amenity-parking_entrance", ());
|
||||
}
|
||||
|
||||
{
|
||||
EditableMapObject emo;
|
||||
SetTypes(emo, {{"barrier", "gate"}});
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(true), "barrier-gate", ());
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(false), "", ());
|
||||
}
|
||||
|
||||
{
|
||||
EditableMapObject emo;
|
||||
SetTypes(emo, {{"entrance", "main"}});
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(true), "entrance-main", ());
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(false), "", ());
|
||||
}
|
||||
|
||||
{
|
||||
EditableMapObject emo;
|
||||
SetTypes(emo, {{"entrance", "main"}, {"barrier", "gate"}});
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(true), "barrier-gate", ());
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(false), "", ());
|
||||
}
|
||||
|
||||
{
|
||||
EditableMapObject emo;
|
||||
SetTypes(emo, {{"amenity"}});
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(true), "amenity", ());
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(false), "", ());
|
||||
}
|
||||
|
||||
{
|
||||
EditableMapObject emo;
|
||||
SetTypes(emo, {{"shop"}});
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(true), "shop", ());
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(false), "", ());
|
||||
}
|
||||
|
||||
{
|
||||
EditableMapObject emo;
|
||||
SetTypes(emo, {{"tourism", "artwork"}, {"amenity"}});
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(true), "tourism-artwork", ());
|
||||
TEST_EQUAL(emo.GetLocalizedAllTypes(false), "", ());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace editable_map_object_test
|
||||
254
libs/indexer/indexer_tests/feature_charge_sockets_test.cpp
Normal file
254
libs/indexer/indexer_tests/feature_charge_sockets_test.cpp
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
#include "indexer/feature_charge_sockets.hpp"
|
||||
|
||||
#include "testing/testing.hpp"
|
||||
|
||||
namespace feature_charge_sockets_test
|
||||
{
|
||||
|
||||
ChargeSocketsHelper FromKVs(OSMKeyValues const & kvs)
|
||||
{
|
||||
ChargeSocketsHelper helper;
|
||||
for (auto const & kv : kvs)
|
||||
helper.AggregateChargeSocketKey(kv.first, kv.second);
|
||||
return helper;
|
||||
}
|
||||
|
||||
UNIT_TEST(ChargeSockets_Processing)
|
||||
{
|
||||
///////////////////////////////////////////////////////////
|
||||
// Internal model consistency
|
||||
|
||||
// valid socket lists
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2||").GetSockets().size(), 1, ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2|1|50;type2|2|43").GetSockets().size(), 2, ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2|1|50;type2|2|43;type1||").GetSockets().size(), 3, ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2||;type2_cable||;type2_combo||;type1||;nacs||;chademo||").GetSockets().size(), 6,
|
||||
());
|
||||
TEST_EQUAL(ChargeSocketsHelper("unknown|2|150").GetSockets().size(), 1, ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("||").GetSockets().size(), 1, ());
|
||||
|
||||
// invalid/partially valid socket lists
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2|").GetSockets().size(), 0, ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2|;|;|||;|45||").GetSockets().size(), 0, ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2|;type2_cable|1|50").GetSockets().size(), 1, ());
|
||||
|
||||
TEST(ChargeSocketsHelper("type2||").ToString() != "", ("ChargeSocketsHelper::ToString returned an empty string!"));
|
||||
|
||||
TEST_EQUAL(ChargeSocketsHelper("||").ToString(), "unknown||", ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("this_type_does_not_exist||").ToString(), "unknown||", ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2||").ToString(), "type2||", ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2|0|0").ToString(), "type2||", ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2||50").ToString(), "type2||50", ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2||7.4").ToString(), "type2||7.4", ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2|0|50").ToString(), "type2||50", ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2|1|50").ToString(), "type2|1|50", ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("unknown||").ToString(), "unknown||", ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("unknown||150").ToString(), "unknown||150", ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2|;type2_cable|1|50").ToString(), "type2_cable|1|50", ());
|
||||
|
||||
// sorting
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2||;type2_cable|1|50").ToString(), "type2_cable|1|50;type2||", ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2||;type2_cable||;||;type2_combo||").ToString(),
|
||||
"type2_combo||;type2_cable||;type2||;unknown||", ());
|
||||
|
||||
// multiple sockets of same type, but different power
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2|1|50;type2|2|43").ToString(), "type2|1|50;type2|2|43", ());
|
||||
|
||||
// TEST_EQUAL(ChargeSocketsHelper("type2|1|43;type2|2|50").ToString(), "type2|1|50;type2|2|43", ());
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// OSM key parsing
|
||||
|
||||
OSMKeyValues kvs;
|
||||
|
||||
kvs = {{"socket:type2", "2"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2|2|", ());
|
||||
|
||||
kvs = {{"socket:type2", "yes"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2||", ());
|
||||
|
||||
kvs = {{"socket:type2", "malformed"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "", ());
|
||||
|
||||
kvs = {{"socket:type2:output", "22"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2||22", ());
|
||||
|
||||
kvs = {{"socket:type2:malformed", "22"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "", ());
|
||||
|
||||
kvs = {{"socket:type2", "malformed"}, {"socket:type2:output", "22 kW"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2||22", ());
|
||||
|
||||
kvs = {{"socket:type2", "2"}, {"socket:type2:output", "22 kW"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2|2|22", ());
|
||||
|
||||
kvs = {{"socket:type2", "2"}, {"socket:type2:output", "22kW"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2|2|22", ());
|
||||
|
||||
kvs = {{"socket:type2", "2"}, {"socket:type2:output", "22KW"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2|2|22", ());
|
||||
|
||||
kvs = {{"socket:type2", "2"}, {"socket:type2:output", "22"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2|2|22", ());
|
||||
|
||||
kvs = {{"socket:chademo", "2"}, {"socket:chademo:output", "50"},
|
||||
{"socket:type2_combo", "10"}, {"socket:type2_combo:output", "200"},
|
||||
{"socket:type2_cable", "2"}, {"socket:type2_cable:output", "50"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2_combo|10|200;chademo|2|50;type2_cable|2|50", ());
|
||||
|
||||
// unit conversion
|
||||
kvs = {{"socket:type2:output", "7400W"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2||7.4", ());
|
||||
|
||||
kvs = {{"socket:type2_combo:output", "150 kw"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2_combo||150", ());
|
||||
|
||||
kvs = {{"socket:type2_combo:output", "150 KW"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2_combo||150", ());
|
||||
|
||||
kvs = {{"socket:type2_combo:output", " 150kw"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2_combo||150", ());
|
||||
|
||||
kvs = {{"socket:type2_combo:output", "150kva"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2_combo||150", ());
|
||||
|
||||
kvs = {{"socket:type2_combo:output", "0.150MW"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2_combo||150", ());
|
||||
|
||||
kvs = {{"socket:type2_combo:output", ".150MW"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2_combo||150", ());
|
||||
|
||||
// invalid
|
||||
kvs = {{"socket:type2", "-1"}};
|
||||
TEST_EQUAL(FromKVs(kvs).GetSockets().size(), 0, ());
|
||||
|
||||
kvs = {{"socket:type2", "-2"}};
|
||||
TEST_EQUAL(FromKVs(kvs).GetSockets().size(), 0, ());
|
||||
|
||||
kvs = {{"socket:type2", "-2"}, {"socket:type2:output", "-50"}};
|
||||
TEST_EQUAL(FromKVs(kvs).GetSockets().size(), 0, ());
|
||||
|
||||
// count ignored (because invalid), but power valid
|
||||
kvs = {{"socket:type2", "-2"}, {"socket:type2:output", "50"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2||50", ());
|
||||
|
||||
// normalization
|
||||
kvs = {{"socket:tesla_supercharger", "2"}, {"socket:tesla_supercharger:output", "150"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "nacs|2|150", ());
|
||||
|
||||
kvs = {{"socket:ccs", "2"}, {"socket:ccs:output", "150"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2_combo|2|150", ());
|
||||
|
||||
// multiple socket of same type
|
||||
kvs = {{"socket:type2", "2;3"}, {"socket:type2:output", "50;43"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2|2|50;type2|3|43", ());
|
||||
|
||||
kvs = {{"socket:type2:output", "50;43"}, {"socket:type2", "2;3"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2|2|50;type2|3|43", ());
|
||||
|
||||
kvs = {{"socket:type2", "2;3"}, {"socket:type2:output", "43;50"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2|3|50;type2|2|43", ());
|
||||
|
||||
kvs = {{"socket:type2", "2;3;5"}, {"socket:type2:output", "43;50;7.4"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2|3|50;type2|2|43;type2|5|7.4", ());
|
||||
|
||||
kvs = {{"socket:type2", "2;3"}, {"socket:type2:output", "50 kW; 43 kw"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2|2|50;type2|3|43", ());
|
||||
|
||||
// unbalanced multiple sockets
|
||||
kvs = {{"socket:type2", "2"}, {"socket:type2:output", "50 kW; 43 kw"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2|2|50;type2||43", ());
|
||||
|
||||
kvs = {{"socket:type2", "2;"}, {"socket:type2:output", "50 kW; 43 kw"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2|2|50;type2||43", ());
|
||||
|
||||
kvs = {{"socket:type2", "2;3"}, {"socket:type2:output", "50 kW"}};
|
||||
TEST_EQUAL(FromKVs(kvs).ToString(), "type2|2|50;type2|3|", ());
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// OSM key generation
|
||||
|
||||
kvs = {{"socket:type2", "2"}};
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2|2|").GetOSMKeyValues(), kvs, ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2|2|0").GetOSMKeyValues(), kvs, ());
|
||||
|
||||
kvs = {{"socket:type2", "yes"}};
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2||").GetOSMKeyValues(), kvs, ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2|0|").GetOSMKeyValues(), kvs, ());
|
||||
|
||||
kvs = {{"socket:type2", "yes"}, {"socket:type2:output", "150"}};
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2||150").GetOSMKeyValues(), kvs, ());
|
||||
|
||||
// the order should always be the same, as the sockets are sorted
|
||||
kvs = {{"socket:type2_combo", "10"}, {"socket:type2_combo:output", "200"}, {"socket:chademo", "2"},
|
||||
{"socket:chademo:output", "50"}, {"socket:type2_cable", "2"}, {"socket:type2_cable:output", "50"}};
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2_combo|10|200;chademo|2|50;type2_cable|2|50").GetOSMKeyValues(), kvs, ());
|
||||
TEST_EQUAL(ChargeSocketsHelper("chademo|2|50;type2_cable|2|50;type2_combo|10|200").GetOSMKeyValues(), kvs, ());
|
||||
|
||||
// multiple socket of same type
|
||||
// (should always be ordered from higher power to lower)
|
||||
kvs = {{"socket:type2", "2;3"}, {"socket:type2:output", "50;43"}};
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2|2|50;type2|3|43").GetOSMKeyValues(), kvs, ());
|
||||
|
||||
kvs = {{"socket:type2", "3;2"}, {"socket:type2:output", "50;43"}};
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2|2|43;type2|3|50").GetOSMKeyValues(), kvs, ());
|
||||
|
||||
kvs = {{"socket:type2", "2;3;5"}, {"socket:type2:output", "50;43;7.4"}};
|
||||
TEST_EQUAL(ChargeSocketsHelper("type2|3|43;type2|5|7.4;type2|2|50").GetOSMKeyValues(), kvs, ());
|
||||
|
||||
kvs = {{"socket:type2_combo", "10;2"},
|
||||
{"socket:type2_combo:output", "250;100"},
|
||||
{"socket:type2", "2;3;5"},
|
||||
{"socket:type2:output", "50;43;7.4"}};
|
||||
TEST_EQUAL(
|
||||
ChargeSocketsHelper("type2|3|43;type2|5|7.4;type2_combo|10|250;type2|2|50;type2_combo|2|100").GetOSMKeyValues(),
|
||||
kvs, ());
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// OSM attribute diff
|
||||
OSMKeyValues kvs_old, kvs_new;
|
||||
KeyValueDiffSet diff;
|
||||
|
||||
kvs_old = {{"socket:type2", "2"}};
|
||||
kvs_new = {{"socket:type2", "2"}};
|
||||
diff = {};
|
||||
TEST_EQUAL(FromKVs(kvs_new).Diff(FromKVs(kvs_old).GetSockets()), diff, ());
|
||||
|
||||
kvs_old = {{"socket:type2", "3"}};
|
||||
kvs_new = {{"socket:type2", "2"}};
|
||||
diff = {{"socket:type2", "3", "2"}};
|
||||
TEST_EQUAL(FromKVs(kvs_new).Diff(FromKVs(kvs_old).GetSockets()), diff, ());
|
||||
|
||||
kvs_old = {{"socket:type2", "2"}};
|
||||
kvs_new = {{"socket:type2", "3"}};
|
||||
diff = {{"socket:type2", "2", "3"}};
|
||||
TEST_EQUAL(FromKVs(kvs_new).Diff(FromKVs(kvs_old).GetSockets()), diff, ());
|
||||
|
||||
kvs_old = {};
|
||||
kvs_new = {{"socket:type2", "2"}};
|
||||
diff = {{"socket:type2", "", "2"}};
|
||||
TEST_EQUAL(FromKVs(kvs_new).Diff(FromKVs(kvs_old).GetSockets()), diff, ());
|
||||
|
||||
kvs_old = {{"socket:type2", "2"}};
|
||||
kvs_new = {};
|
||||
diff = {{"socket:type2", "2", ""}};
|
||||
TEST_EQUAL(FromKVs(kvs_new).Diff(FromKVs(kvs_old).GetSockets()), diff, ());
|
||||
|
||||
kvs_old = {{"socket:type2_combo", "10;2"},
|
||||
{"socket:type2_combo:output", "250;100"},
|
||||
{"socket:type1", "5"},
|
||||
{"socket:type2", "2;3;5"},
|
||||
{"socket:type2:output", "50;43;7.4"}};
|
||||
kvs_new = {{"socket:type2_combo", "10;2"},
|
||||
{"socket:type2_combo:output", "250;100"},
|
||||
{"socket:chademo", "2"},
|
||||
{"socket:type2", "2;3"},
|
||||
{"socket:type2:output", "50;43"}};
|
||||
diff = {{"socket:type1", "5", ""},
|
||||
{"socket:type2", "2;3;5", "2;3"},
|
||||
{"socket:type2:output", "50;43;7.4", "50;43"},
|
||||
{"socket:chademo", "", "2"}};
|
||||
TEST_EQUAL(FromKVs(kvs_new).Diff(FromKVs(kvs_old).GetSockets()), diff, ());
|
||||
}
|
||||
|
||||
} // namespace feature_charge_sockets_test
|
||||
131
libs/indexer/indexer_tests/feature_metadata_test.cpp
Normal file
131
libs/indexer/indexer_tests/feature_metadata_test.cpp
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/feature_meta.hpp"
|
||||
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/writer.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace feature_metadata_test
|
||||
{
|
||||
using namespace std;
|
||||
using feature::Metadata;
|
||||
using EType = Metadata::EType;
|
||||
|
||||
map<EType, string> const kKeyValues = {{EType::FMD_ELE, "12345"},
|
||||
{EType::FMD_EMAIL, "cool@email.at"},
|
||||
// This string is longer than 255 bytes.
|
||||
{EType::FMD_WEBSITE,
|
||||
"http://rskxmkjwnikfnjqhyvkpjgaghhyhukjyenduiuanxgbmndtlpfphdgaizfcpzuiuspcp"
|
||||
"umeojwvekvjprlutwjmxudyzrlwwsepewevsuqelobqcfdzsoqozkesghojribepbaitivmaqep"
|
||||
"hheckitonddqhbapdybhetvnwvlchjafepdjaeoaapysdvculxuwjbgdddryodiihvnpvmkgqvs"
|
||||
"mawbdsrbmnndcozmrgeoahbkhcevxkmtdqnxpxlsju.org"}};
|
||||
|
||||
UNIT_TEST(Feature_Metadata_GetSet)
|
||||
{
|
||||
Metadata m;
|
||||
EType const type = EType::FMD_ELE;
|
||||
|
||||
// Absent types should return empty values.
|
||||
TEST_EQUAL(m.Get(type), "", ());
|
||||
m.Set(type, "12345");
|
||||
TEST_EQUAL(m.Get(type), "12345", ());
|
||||
TEST_EQUAL(m.Size(), 1, ());
|
||||
|
||||
// Same types should replace old metadata values.
|
||||
m.Set(type, "9876543210");
|
||||
TEST_EQUAL(m.Get(type), "9876543210", ());
|
||||
|
||||
// Empty values should drop fields.
|
||||
m.Set(type, "");
|
||||
TEST_EQUAL(m.Get(type), "", ());
|
||||
TEST_EQUAL(m.Size(), 0, ());
|
||||
TEST(m.Empty(), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Feature_Metadata_PresentTypes)
|
||||
{
|
||||
Metadata m;
|
||||
for (auto const & value : kKeyValues)
|
||||
m.Set(value.first, value.second);
|
||||
TEST_EQUAL(m.Size(), kKeyValues.size(), ());
|
||||
|
||||
m.ForEach([&](Metadata::EType type, std::string const &)
|
||||
{ TEST_EQUAL(m.Get(type), kKeyValues.find(type)->second, ()); });
|
||||
}
|
||||
|
||||
UNIT_TEST(Feature_Metadata_MwmTmpSerialization)
|
||||
{
|
||||
Metadata original;
|
||||
for (auto const & value : kKeyValues)
|
||||
original.Set(value.first, value.second);
|
||||
TEST_EQUAL(original.Size(), kKeyValues.size(), ());
|
||||
|
||||
{
|
||||
Metadata serialized;
|
||||
vector<char> buffer;
|
||||
MemWriter<decltype(buffer)> writer(buffer);
|
||||
original.SerializeForMwmTmp(writer);
|
||||
|
||||
MemReader reader(buffer.data(), buffer.size());
|
||||
ReaderSource<MemReader> src(reader);
|
||||
serialized.DeserializeFromMwmTmp(src);
|
||||
|
||||
for (auto const & value : kKeyValues)
|
||||
TEST_EQUAL(serialized.Get(value.first), value.second, ());
|
||||
TEST_EQUAL(serialized.Get(EType::FMD_OPERATOR), "", ());
|
||||
TEST_EQUAL(serialized.Size(), kKeyValues.size(), ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(Feature_Metadata_GetWikipedia)
|
||||
{
|
||||
Metadata m;
|
||||
EType const wikiType = EType::FMD_WIKIPEDIA;
|
||||
m.Set(wikiType, "en:Article");
|
||||
TEST_EQUAL(m.Get(wikiType), "en:Article", ());
|
||||
#ifdef OMIM_OS_MOBILE
|
||||
TEST_EQUAL(m.GetWikiURL(), "https://en.m.wikipedia.org/wiki/Article", ());
|
||||
#else
|
||||
TEST_EQUAL(m.GetWikiURL(), "https://en.wikipedia.org/wiki/Article", ());
|
||||
#endif
|
||||
}
|
||||
|
||||
UNIT_TEST(Feature_Metadata_RegionData_Languages)
|
||||
{
|
||||
{
|
||||
feature::RegionData rd;
|
||||
vector<string> const langs = {"ru", "en", "et"};
|
||||
rd.SetLanguages(langs);
|
||||
TEST(rd.HasLanguage(StringUtf8Multilang::GetLangIndex("ru")), ());
|
||||
TEST(rd.HasLanguage(StringUtf8Multilang::GetLangIndex("en")), ());
|
||||
TEST(rd.HasLanguage(StringUtf8Multilang::GetLangIndex("et")), ());
|
||||
TEST(!rd.HasLanguage(StringUtf8Multilang::GetLangIndex("es")), ());
|
||||
TEST(!rd.IsSingleLanguage(StringUtf8Multilang::GetLangIndex("ru")), ());
|
||||
}
|
||||
{
|
||||
feature::RegionData rd;
|
||||
vector<string> const langs = {"et"};
|
||||
rd.SetLanguages(langs);
|
||||
TEST(rd.HasLanguage(StringUtf8Multilang::GetLangIndex("et")), ());
|
||||
TEST(rd.IsSingleLanguage(StringUtf8Multilang::GetLangIndex("et")), ());
|
||||
TEST(!rd.HasLanguage(StringUtf8Multilang::GetLangIndex("en")), ());
|
||||
TEST(!rd.IsSingleLanguage(StringUtf8Multilang::GetLangIndex("en")), ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(Feature_Metadata_Print)
|
||||
{
|
||||
StringUtf8Multilang s;
|
||||
s.AddString("en", "English");
|
||||
s.AddString("be", "Беларуская");
|
||||
|
||||
Metadata m;
|
||||
m.Set(EType::FMD_DESCRIPTION, s.GetBuffer());
|
||||
|
||||
TEST_EQUAL(DebugPrint(m), "Metadata [description=" + DebugPrint(s) + "]", ());
|
||||
}
|
||||
} // namespace feature_metadata_test
|
||||
563
libs/indexer/indexer_tests/feature_names_test.cpp
Normal file
563
libs/indexer/indexer_tests/feature_names_test.cpp
Normal file
|
|
@ -0,0 +1,563 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/feature_meta.hpp"
|
||||
#include "indexer/feature_utils.hpp"
|
||||
|
||||
#include "coding/string_utf8_multilang.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace feature_names_test
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
using StrUtf8 = StringUtf8Multilang;
|
||||
|
||||
void GetPreferredNames(feature::RegionData const & regionData, StrUtf8 const & src, int8_t deviceLang,
|
||||
bool allowTranslit, std::string & primary, std::string & secondary)
|
||||
{
|
||||
feature::NameParamsIn in{src, regionData, deviceLang, allowTranslit};
|
||||
feature::NameParamsOut out;
|
||||
feature::GetPreferredNames(in, out);
|
||||
primary = out.GetPrimary();
|
||||
secondary = out.secondary;
|
||||
}
|
||||
|
||||
UNIT_TEST(GetPrefferedNames)
|
||||
{
|
||||
feature::RegionData regionData;
|
||||
regionData.SetLanguages({"de", "ko"});
|
||||
|
||||
int8_t deviceLang = StrUtf8::GetLangIndex("ru");
|
||||
string primary, secondary;
|
||||
bool const allowTranslit = false;
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("fr", "fr name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "", ());
|
||||
TEST_EQUAL(secondary, "", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("default", "default name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "default name", ());
|
||||
TEST_EQUAL(secondary, "", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("default", "default name");
|
||||
src.AddString("en", "en name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "en name", ());
|
||||
TEST_EQUAL(secondary, "default name", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("default", "default name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("ru", "ru name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "ru name", ());
|
||||
TEST_EQUAL(secondary, "default name", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("default", "same name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("ru", "same name");
|
||||
src.AddString("int_name", "int name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "same name", ());
|
||||
TEST_EQUAL(secondary, "", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("default", "default name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("ru", "ru name");
|
||||
src.AddString("int_name", "int name");
|
||||
src.AddString("de", "de name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "ru name", ());
|
||||
TEST_EQUAL(secondary, "default name", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("default", "default name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("ru", "ru name");
|
||||
src.AddString("int_name", "int name");
|
||||
src.AddString("de", "de name");
|
||||
src.AddString("ko", "ko name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "ru name", ());
|
||||
TEST_EQUAL(secondary, "default name", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("default", "default name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("int_name", "int name");
|
||||
src.AddString("de", "de name");
|
||||
src.AddString("ko", "ko name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "int name", ());
|
||||
TEST_EQUAL(secondary, "default name", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("int_name", "int name");
|
||||
src.AddString("de", "de name");
|
||||
src.AddString("ko", "ko name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "int name", ());
|
||||
TEST_EQUAL(secondary, "", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("de", "de name");
|
||||
src.AddString("ko", "ko name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "en name", ());
|
||||
TEST_EQUAL(secondary, "de name", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("ko", "ko name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "en name", ());
|
||||
TEST_EQUAL(secondary, "ko name", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("en", "en name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "en name", ());
|
||||
TEST_EQUAL(secondary, "", ());
|
||||
}
|
||||
{
|
||||
int8_t deviceLang = StrUtf8::GetLangIndex("be");
|
||||
StrUtf8 src;
|
||||
src.AddString("int_name", "int name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("ru", "ru name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "ru name", ());
|
||||
TEST_EQUAL(secondary, "int name", ());
|
||||
}
|
||||
{
|
||||
feature::RegionData regionData;
|
||||
regionData.SetLanguages({"ru"});
|
||||
int8_t deviceLang = StrUtf8::GetLangIndex("be");
|
||||
StrUtf8 src;
|
||||
src.AddString("int_name", "int name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("ru", "ru name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "ru name", ());
|
||||
TEST_EQUAL(secondary, "", ());
|
||||
}
|
||||
{
|
||||
feature::RegionData regionData;
|
||||
regionData.SetLanguages({"ru"});
|
||||
int8_t deviceLang = StrUtf8::GetLangIndex("be");
|
||||
StrUtf8 src;
|
||||
src.AddString("default", "default name");
|
||||
src.AddString("int_name", "int name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("ru", "ru name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "default name", ());
|
||||
TEST_EQUAL(secondary, "", ());
|
||||
}
|
||||
{
|
||||
feature::RegionData regionData;
|
||||
regionData.SetLanguages({"ru"});
|
||||
int8_t deviceLang = StrUtf8::GetLangIndex("ru");
|
||||
StrUtf8 src;
|
||||
src.AddString("default", "default name");
|
||||
src.AddString("int_name", "int name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("be", "be name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "default name", ());
|
||||
TEST_EQUAL(secondary, "", ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(GetPrefferedNamesLocal)
|
||||
{
|
||||
string primary, secondary;
|
||||
bool const allowTranslit = true;
|
||||
{
|
||||
feature::RegionData regionData;
|
||||
regionData.SetLanguages({"kk", "ru"});
|
||||
|
||||
int8_t deviceLang = StrUtf8::GetLangIndex("ru");
|
||||
|
||||
StrUtf8 src;
|
||||
src.AddString("default", "default name");
|
||||
src.AddString("en", "en name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "default name", ());
|
||||
TEST_EQUAL(secondary, "", ());
|
||||
}
|
||||
{
|
||||
feature::RegionData regionData;
|
||||
regionData.SetLanguages({"kk", "be"});
|
||||
|
||||
int8_t deviceLang = StrUtf8::GetLangIndex("be");
|
||||
|
||||
StrUtf8 src;
|
||||
src.AddString("int_name", "int name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("ru", "ru name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "ru name", ());
|
||||
TEST_EQUAL(secondary, "", ());
|
||||
}
|
||||
{
|
||||
feature::RegionData regionData;
|
||||
regionData.SetLanguages({"kk", "ru"});
|
||||
|
||||
int8_t deviceLang = StrUtf8::GetLangIndex("ru");
|
||||
|
||||
StrUtf8 src;
|
||||
src.AddString("int_name", "int name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("be", "be name");
|
||||
|
||||
GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary);
|
||||
|
||||
TEST_EQUAL(primary, "int name", ());
|
||||
TEST_EQUAL(secondary, "", ());
|
||||
}
|
||||
}
|
||||
|
||||
void GetReadableName(feature::RegionData const & regionData, StrUtf8 const & src, int8_t deviceLang, bool allowTranslit,
|
||||
std::string & name)
|
||||
{
|
||||
feature::NameParamsIn in{src, regionData, deviceLang, allowTranslit};
|
||||
feature::NameParamsOut out;
|
||||
feature::GetPreferredNames(in, out);
|
||||
name = out.GetPrimary();
|
||||
}
|
||||
|
||||
UNIT_TEST(GetReadableName)
|
||||
{
|
||||
feature::RegionData regionData;
|
||||
regionData.SetLanguages({"de", "ko"});
|
||||
|
||||
int8_t deviceLang = StrUtf8::GetLangIndex("ru");
|
||||
bool const allowTranslit = false;
|
||||
string name;
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("fr", "fr name");
|
||||
|
||||
GetReadableName(regionData, src, deviceLang, allowTranslit, name);
|
||||
|
||||
TEST_EQUAL(name, "", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("ko", "ko name");
|
||||
|
||||
GetReadableName(regionData, src, deviceLang, allowTranslit, name);
|
||||
|
||||
TEST_EQUAL(name, "ko name", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("ko", "ko name");
|
||||
src.AddString("de", "de name");
|
||||
|
||||
GetReadableName(regionData, src, deviceLang, allowTranslit, name);
|
||||
|
||||
TEST_EQUAL(name, "de name", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("ko", "ko name");
|
||||
src.AddString("de", "de name");
|
||||
src.AddString("default", "default name");
|
||||
|
||||
GetReadableName(regionData, src, deviceLang, allowTranslit, name);
|
||||
|
||||
TEST_EQUAL(name, "default name", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("ko", "ko name");
|
||||
src.AddString("de", "de name");
|
||||
src.AddString("default", "default name");
|
||||
src.AddString("en", "en name");
|
||||
|
||||
GetReadableName(regionData, src, deviceLang, allowTranslit, name);
|
||||
|
||||
TEST_EQUAL(name, "en name", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("ko", "ko name");
|
||||
src.AddString("de", "de name");
|
||||
src.AddString("default", "default name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("int_name", "int name");
|
||||
|
||||
GetReadableName(regionData, src, deviceLang, allowTranslit, name);
|
||||
|
||||
TEST_EQUAL(name, "int name", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("ko", "ko name");
|
||||
src.AddString("de", "de name");
|
||||
src.AddString("default", "default name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("int_name", "int name");
|
||||
src.AddString("ru", "ru name");
|
||||
|
||||
GetReadableName(regionData, src, deviceLang, allowTranslit, name);
|
||||
|
||||
TEST_EQUAL(name, "ru name", ());
|
||||
}
|
||||
|
||||
deviceLang = StrUtf8::GetLangIndex("de");
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("ko", "ko name");
|
||||
src.AddString("de", "de name");
|
||||
src.AddString("default", "default name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("int_name", "int name");
|
||||
|
||||
GetReadableName(regionData, src, deviceLang, allowTranslit, name);
|
||||
|
||||
TEST_EQUAL(name, "de name", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("ko", "ko name");
|
||||
src.AddString("default", "default name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("int_name", "int name");
|
||||
|
||||
GetReadableName(regionData, src, deviceLang, allowTranslit, name);
|
||||
|
||||
TEST_EQUAL(name, "default name", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("ko", "ko name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("int_name", "int name");
|
||||
|
||||
GetReadableName(regionData, src, deviceLang, allowTranslit, name);
|
||||
|
||||
TEST_EQUAL(name, "int name", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("ko", "ko name");
|
||||
src.AddString("en", "en name");
|
||||
|
||||
GetReadableName(regionData, src, deviceLang, allowTranslit, name);
|
||||
|
||||
TEST_EQUAL(name, "en name", ());
|
||||
}
|
||||
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("ko", "ko name");
|
||||
|
||||
GetReadableName(regionData, src, deviceLang, allowTranslit, name);
|
||||
|
||||
TEST_EQUAL(name, "ko name", ());
|
||||
}
|
||||
{
|
||||
int8_t deviceLang = StrUtf8::GetLangIndex("be");
|
||||
StrUtf8 src;
|
||||
src.AddString("int_name", "int name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("ru", "ru name");
|
||||
|
||||
GetReadableName(regionData, src, deviceLang, allowTranslit, name);
|
||||
|
||||
TEST_EQUAL(name, "ru name", ());
|
||||
}
|
||||
{
|
||||
feature::RegionData regionData;
|
||||
regionData.SetLanguages({"ru"});
|
||||
int8_t deviceLang = StrUtf8::GetLangIndex("be");
|
||||
StrUtf8 src;
|
||||
src.AddString("default", "default name");
|
||||
src.AddString("int_name", "int name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("ru", "ru name");
|
||||
|
||||
GetReadableName(regionData, src, deviceLang, allowTranslit, name);
|
||||
|
||||
TEST_EQUAL(name, "default name", ());
|
||||
}
|
||||
{
|
||||
feature::RegionData regionData;
|
||||
regionData.SetLanguages({"ru"});
|
||||
int8_t deviceLang = StrUtf8::GetLangIndex("ru");
|
||||
StrUtf8 src;
|
||||
src.AddString("default", "default name");
|
||||
src.AddString("int_name", "int name");
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("be", "be name");
|
||||
|
||||
GetReadableName(regionData, src, deviceLang, allowTranslit, name);
|
||||
|
||||
TEST_EQUAL(name, "default name", ());
|
||||
}
|
||||
{
|
||||
feature::RegionData regionData;
|
||||
regionData.SetLanguages({"ru"});
|
||||
int8_t deviceLang = StrUtf8::GetLangIndex("ru");
|
||||
StrUtf8 src;
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("be", "be name");
|
||||
|
||||
GetReadableName(regionData, src, deviceLang, allowTranslit, name);
|
||||
|
||||
TEST_EQUAL(name, "en name", ());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
UNIT_TEST(GetNameForSearchOnBooking)
|
||||
{
|
||||
{
|
||||
StrUtf8 src;
|
||||
feature::RegionData regionData;
|
||||
string result;
|
||||
auto lang = feature::GetNameForSearchOnBooking(regionData, src, result);
|
||||
TEST_EQUAL(lang, StrUtf8::kUnsupportedLanguageCode, ());
|
||||
TEST(result.empty(), ());
|
||||
}
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("default", "default name");
|
||||
feature::RegionData regionData;
|
||||
string result;
|
||||
auto lang = feature::GetNameForSearchOnBooking(regionData, src, result);
|
||||
TEST_EQUAL(lang, StrUtf8::kDefaultCode, ());
|
||||
TEST_EQUAL(result, "default name", ());
|
||||
}
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("default", "default name");
|
||||
src.AddString("ko", "ko name");
|
||||
src.AddString("en", "en name");
|
||||
feature::RegionData regionData;
|
||||
regionData.SetLanguages({"ko", "en"});
|
||||
string result;
|
||||
auto lang = feature::GetNameForSearchOnBooking(regionData, src, result);
|
||||
TEST_EQUAL(lang, StrUtf8::kDefaultCode, ());
|
||||
TEST_EQUAL(result, "default name", ());
|
||||
}
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("ko", "ko name");
|
||||
feature::RegionData regionData;
|
||||
regionData.SetLanguages({"ko"});
|
||||
string result;
|
||||
auto lang = feature::GetNameForSearchOnBooking(regionData, src, result);
|
||||
TEST_EQUAL(lang, StrUtf8::GetLangIndex("ko"), ());
|
||||
TEST_EQUAL(result, "ko name", ());
|
||||
}
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("ko", "ko name");
|
||||
src.AddString("de", "de name");
|
||||
feature::RegionData regionData;
|
||||
regionData.SetLanguages({"de", "ko"});
|
||||
string result;
|
||||
auto lang = feature::GetNameForSearchOnBooking(regionData, src, result);
|
||||
TEST_EQUAL(lang, StrUtf8::GetLangIndex("de"), ());
|
||||
TEST_EQUAL(result, "de name", ());
|
||||
}
|
||||
{
|
||||
StrUtf8 src;
|
||||
src.AddString("en", "en name");
|
||||
src.AddString("ko", "ko name");
|
||||
feature::RegionData regionData;
|
||||
regionData.SetLanguages({"de", "fr"});
|
||||
string result;
|
||||
auto lang = feature::GetNameForSearchOnBooking(regionData, src, result);
|
||||
TEST_EQUAL(lang, StrUtf8::GetLangIndex("en"), ());
|
||||
TEST_EQUAL(result, "en name", ());
|
||||
}
|
||||
}
|
||||
*/
|
||||
} // namespace feature_names_test
|
||||
110
libs/indexer/indexer_tests/feature_to_osm_tests.cpp
Normal file
110
libs/indexer/indexer_tests/feature_to_osm_tests.cpp
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "generator/generator_tests_support/test_with_custom_mwms.hpp"
|
||||
|
||||
#include "indexer/feature_decl.hpp"
|
||||
#include "indexer/feature_to_osm.hpp"
|
||||
|
||||
#include "coding/file_writer.hpp"
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/writer.hpp"
|
||||
|
||||
#include "base/geo_object_id.hpp"
|
||||
#include "base/macros.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "defines.hpp"
|
||||
|
||||
namespace feature_to_osm_tests
|
||||
{
|
||||
using namespace indexer;
|
||||
using namespace generator::tests_support;
|
||||
|
||||
using Entries = std::vector<std::pair<uint32_t, base::GeoObjectId>>;
|
||||
|
||||
template <typename Cont>
|
||||
Entries GetEntries(Cont const & cont)
|
||||
{
|
||||
Entries res;
|
||||
cont.ForEachEntry([&res](uint32_t const fid, base::GeoObjectId const & gid)
|
||||
{ res.emplace_back(std::make_pair(fid, gid)); });
|
||||
std::sort(res.begin(), res.end());
|
||||
return res;
|
||||
}
|
||||
|
||||
class FeatureIdToGeoObjectIdTest : public TestWithCustomMwms
|
||||
{
|
||||
public:
|
||||
DataSource const & GetDataSource() const { return m_dataSource; }
|
||||
};
|
||||
|
||||
UNIT_CLASS_TEST(FeatureIdToGeoObjectIdTest, Smoke)
|
||||
{
|
||||
Entries const kEntries = {
|
||||
{0, base::MakeOsmNode(123)},
|
||||
{1, base::MakeOsmWay(456)},
|
||||
{2, base::MakeOsmRelation(789)},
|
||||
};
|
||||
|
||||
FeatureIdToGeoObjectIdBimapMem origM;
|
||||
for (auto const & e : kEntries)
|
||||
origM.Add(e.first, e.second);
|
||||
|
||||
// TestMwmBuilder will create the section but we will rewrite it right away.
|
||||
auto testWorldId = BuildWorld([&](TestMwmBuilder & builder) {});
|
||||
auto const testWorldPath = testWorldId.GetInfo()->GetLocalFile().GetPath(MapFileType::Map);
|
||||
|
||||
std::vector<uint8_t> buf;
|
||||
{
|
||||
MemWriter<decltype(buf)> writer(buf);
|
||||
FeatureIdToGeoObjectIdSerDes::Serialize(writer, origM);
|
||||
}
|
||||
|
||||
{
|
||||
FilesContainerW writer(testWorldPath, FileWriter::OP_WRITE_EXISTING);
|
||||
writer.Write(buf, FEATURE_TO_OSM_FILE_TAG);
|
||||
}
|
||||
|
||||
FeatureIdToGeoObjectIdBimapMem deserMem;
|
||||
{
|
||||
MemReader reader(buf.data(), buf.size());
|
||||
FeatureIdToGeoObjectIdSerDes::Deserialize(reader, deserMem);
|
||||
}
|
||||
|
||||
indexer::FeatureIdToGeoObjectIdOneWay deserOneWay(GetDataSource());
|
||||
TEST(deserOneWay.Load(), ());
|
||||
|
||||
indexer::FeatureIdToGeoObjectIdTwoWay deserTwoWay(GetDataSource());
|
||||
TEST(deserTwoWay.Load(), ());
|
||||
|
||||
Entries actualEntriesMem = GetEntries(deserMem);
|
||||
Entries actualEntriesOneWay = GetEntries(deserOneWay);
|
||||
Entries actualEntriesTwoWay = GetEntries(deserTwoWay);
|
||||
TEST_EQUAL(kEntries, actualEntriesMem, ());
|
||||
TEST_EQUAL(kEntries, actualEntriesOneWay, ());
|
||||
TEST_EQUAL(kEntries, actualEntriesTwoWay, ());
|
||||
|
||||
for (auto const & entry : kEntries)
|
||||
{
|
||||
base::GeoObjectId gid;
|
||||
TEST(deserOneWay.GetGeoObjectId(FeatureID(testWorldId, entry.first), gid), ());
|
||||
TEST_EQUAL(entry.second, gid, ());
|
||||
|
||||
TEST(deserTwoWay.GetGeoObjectId(FeatureID(testWorldId, entry.first), gid), ());
|
||||
TEST_EQUAL(entry.second, gid, ());
|
||||
}
|
||||
|
||||
for (auto const & entry : kEntries)
|
||||
{
|
||||
FeatureID fid;
|
||||
TEST(deserTwoWay.GetFeatureID(entry.second, fid), ());
|
||||
TEST_EQUAL(entry.first, fid.m_index, ());
|
||||
}
|
||||
}
|
||||
} // namespace feature_to_osm_tests
|
||||
140
libs/indexer/indexer_tests/feature_types_test.cpp
Normal file
140
libs/indexer/indexer_tests/feature_types_test.cpp
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/classificator.hpp"
|
||||
#include "indexer/classificator_loader.hpp"
|
||||
#include "indexer/feature_data.hpp"
|
||||
|
||||
namespace feature_types_test
|
||||
{
|
||||
|
||||
feature::TypesHolder MakeTypesHolder(std::initializer_list<base::StringIL> const & arr, bool sortBySpec = true,
|
||||
feature::GeomType geomType = feature::GeomType::Point)
|
||||
{
|
||||
auto const & cl = classif();
|
||||
feature::TypesHolder types(geomType);
|
||||
for (auto const & t : arr)
|
||||
types.Add(cl.GetTypeByPath(t));
|
||||
|
||||
if (sortBySpec)
|
||||
types.SortBySpec();
|
||||
else
|
||||
types.SortByUseless();
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
UNIT_TEST(Feature_UselessTypes)
|
||||
{
|
||||
/// @todo Take out TestWithClassificator into some common test support lib.
|
||||
classificator::Load();
|
||||
auto const & cl = classif();
|
||||
|
||||
{
|
||||
feature::TypesHolder types = MakeTypesHolder(
|
||||
{
|
||||
{"wheelchair", "yes"},
|
||||
{"building", "train_station"},
|
||||
},
|
||||
false /* sortBySpec */);
|
||||
|
||||
TEST_EQUAL(types.front(), cl.GetTypeByPath({"building", "train_station"}), ());
|
||||
}
|
||||
|
||||
{
|
||||
feature::TypesHolder types = MakeTypesHolder(
|
||||
{
|
||||
{"hwtag", "lit"},
|
||||
{"hwtag", "oneway"},
|
||||
},
|
||||
false /* sortBySpec */);
|
||||
|
||||
TEST_EQUAL(types.front(), cl.GetTypeByPath({"hwtag", "oneway"}), ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(Feature_TypesPriority)
|
||||
{
|
||||
/// @todo Take out TestWithClassificator into some common test support lib.
|
||||
classificator::Load();
|
||||
auto const & cl = classif();
|
||||
|
||||
{
|
||||
feature::TypesHolder types = MakeTypesHolder({
|
||||
{"wheelchair", "yes"},
|
||||
{"building", "train_station"},
|
||||
});
|
||||
|
||||
TEST_EQUAL(types.front(), cl.GetTypeByPath({"building", "train_station"}), ());
|
||||
}
|
||||
|
||||
/// @todo post_office should be bigger than copyshop.
|
||||
// {
|
||||
// feature::TypesHolder types = MakeTypesHolder({
|
||||
// {"shop", "copyshop"},
|
||||
// {"amenity", "post_office"},
|
||||
// });
|
||||
|
||||
// TEST_EQUAL(types.front(), cl.GetTypeByPath({"amenity", "post_office"}), ());
|
||||
// }
|
||||
|
||||
{
|
||||
feature::TypesHolder types = MakeTypesHolder({
|
||||
{"internet_access", "wlan"},
|
||||
{"amenity", "compressed_air"},
|
||||
{"amenity", "fuel"},
|
||||
});
|
||||
|
||||
TEST_EQUAL(types.front(), cl.GetTypeByPath({"amenity", "fuel"}), ());
|
||||
}
|
||||
|
||||
{
|
||||
feature::TypesHolder types = MakeTypesHolder({
|
||||
{"leisure", "pitch"},
|
||||
{"sport", "soccer"},
|
||||
});
|
||||
|
||||
TEST_EQUAL(types.front(), cl.GetTypeByPath({"sport", "soccer"}), ());
|
||||
}
|
||||
|
||||
{
|
||||
feature::TypesHolder types = MakeTypesHolder({
|
||||
{"amenity", "shelter"},
|
||||
{"highway", "bus_stop"},
|
||||
});
|
||||
|
||||
TEST_EQUAL(types.front(), cl.GetTypeByPath({"highway", "bus_stop"}), ());
|
||||
}
|
||||
|
||||
{
|
||||
feature::TypesHolder types = MakeTypesHolder({
|
||||
{"amenity", "toilets"},
|
||||
{"amenity", "community_centre"},
|
||||
});
|
||||
|
||||
TEST_EQUAL(types.front(), cl.GetTypeByPath({"amenity", "community_centre"}), ());
|
||||
}
|
||||
|
||||
{
|
||||
feature::TypesHolder types = MakeTypesHolder({
|
||||
{"highway", "elevator"},
|
||||
{"emergency", "defibrillator"},
|
||||
{"railway", "subway_entrance"},
|
||||
});
|
||||
|
||||
TEST_EQUAL(types.front(), cl.GetTypeByPath({"railway", "subway_entrance"}), ());
|
||||
}
|
||||
|
||||
{
|
||||
feature::TypesHolder types = MakeTypesHolder(
|
||||
{
|
||||
{"hwtag", "lit"},
|
||||
{"hwtag", "oneway"},
|
||||
{"highway", "cycleway"},
|
||||
},
|
||||
true /* sortBySpec */, feature::GeomType::Line);
|
||||
|
||||
TEST_EQUAL(types.front(), cl.GetTypeByPath({"highway", "cycleway"}), ());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace feature_types_test
|
||||
94
libs/indexer/indexer_tests/features_offsets_table_test.cpp
Normal file
94
libs/indexer/indexer_tests/features_offsets_table_test.cpp
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/data_header.hpp"
|
||||
#include "indexer/features_offsets_table.hpp"
|
||||
#include "indexer/features_vector.hpp"
|
||||
|
||||
#include "platform/local_country_file_utils.hpp"
|
||||
#include "platform/platform.hpp"
|
||||
|
||||
#include "coding/files_container.hpp"
|
||||
|
||||
#include "base/scope_guard.hpp"
|
||||
|
||||
#include "defines.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
using namespace platform;
|
||||
using namespace std;
|
||||
|
||||
namespace feature
|
||||
{
|
||||
UNIT_TEST(FeaturesOffsetsTable_Empty)
|
||||
{
|
||||
FeaturesOffsetsTable::Builder builder;
|
||||
unique_ptr<FeaturesOffsetsTable> table(FeaturesOffsetsTable::Build(builder));
|
||||
TEST(table.get(), ());
|
||||
TEST_EQUAL(static_cast<uint64_t>(0), table->size(), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(FeaturesOffsetsTable_Basic)
|
||||
{
|
||||
FeaturesOffsetsTable::Builder builder;
|
||||
builder.PushOffset(1);
|
||||
builder.PushOffset(4);
|
||||
builder.PushOffset(17);
|
||||
builder.PushOffset(128);
|
||||
builder.PushOffset(129);
|
||||
builder.PushOffset(510);
|
||||
builder.PushOffset(513);
|
||||
builder.PushOffset(1024);
|
||||
|
||||
unique_ptr<FeaturesOffsetsTable> table(FeaturesOffsetsTable::Build(builder));
|
||||
TEST(table.get(), ());
|
||||
TEST_EQUAL(static_cast<uint64_t>(8), table->size(), ());
|
||||
|
||||
TEST_EQUAL(static_cast<uint64_t>(1), table->GetFeatureOffset(0), ());
|
||||
TEST_EQUAL(static_cast<uint64_t>(4), table->GetFeatureOffset(1), ());
|
||||
TEST_EQUAL(static_cast<uint64_t>(17), table->GetFeatureOffset(2), ());
|
||||
TEST_EQUAL(static_cast<uint64_t>(128), table->GetFeatureOffset(3), ());
|
||||
TEST_EQUAL(static_cast<uint64_t>(129), table->GetFeatureOffset(4), ());
|
||||
TEST_EQUAL(static_cast<uint64_t>(510), table->GetFeatureOffset(5), ());
|
||||
TEST_EQUAL(static_cast<uint64_t>(513), table->GetFeatureOffset(6), ());
|
||||
TEST_EQUAL(static_cast<uint64_t>(1024), table->GetFeatureOffset(7), ());
|
||||
|
||||
TEST_EQUAL(static_cast<size_t>(0), table->GetFeatureIndexbyOffset(1), ());
|
||||
TEST_EQUAL(static_cast<size_t>(1), table->GetFeatureIndexbyOffset(4), ());
|
||||
TEST_EQUAL(static_cast<size_t>(2), table->GetFeatureIndexbyOffset(17), ());
|
||||
TEST_EQUAL(static_cast<size_t>(3), table->GetFeatureIndexbyOffset(128), ());
|
||||
TEST_EQUAL(static_cast<size_t>(4), table->GetFeatureIndexbyOffset(129), ());
|
||||
TEST_EQUAL(static_cast<size_t>(5), table->GetFeatureIndexbyOffset(510), ());
|
||||
TEST_EQUAL(static_cast<size_t>(6), table->GetFeatureIndexbyOffset(513), ());
|
||||
TEST_EQUAL(static_cast<size_t>(7), table->GetFeatureIndexbyOffset(1024), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(FeaturesOffsetsTable_ReadWrite)
|
||||
{
|
||||
string const testFileName = "test_file";
|
||||
Platform & pl = GetPlatform();
|
||||
|
||||
FilesContainerR baseContainer(pl.GetReader("minsk-pass" DATA_FILE_EXTENSION));
|
||||
size_t constexpr minFeaturesCount = 5000;
|
||||
|
||||
LocalCountryFile localFile = LocalCountryFile::MakeForTesting(testFileName);
|
||||
CountryIndexes::PreparePlaceOnDisk(localFile);
|
||||
|
||||
string const indexFile = CountryIndexes::GetPath(localFile, CountryIndexes::Index::Offsets);
|
||||
SCOPE_GUARD(deleteTestFileIndexGuard, bind(&FileWriter::DeleteFileX, cref(indexFile)));
|
||||
|
||||
FeaturesOffsetsTable::Build(baseContainer, indexFile);
|
||||
|
||||
unique_ptr<FeaturesOffsetsTable> table(FeaturesOffsetsTable::Load(baseContainer, FEATURE_OFFSETS_FILE_TAG));
|
||||
TEST(table.get() && table->size() > minFeaturesCount, ());
|
||||
|
||||
unique_ptr<FeaturesOffsetsTable> loadedTable(FeaturesOffsetsTable::Load(indexFile));
|
||||
TEST(loadedTable.get() && loadedTable->size() > minFeaturesCount, ());
|
||||
|
||||
TEST_EQUAL(table->size(), loadedTable->size(), ());
|
||||
for (uint64_t i = 0; i < table->size(); ++i)
|
||||
TEST_EQUAL(table->GetFeatureOffset(i), loadedTable->GetFeatureOffset(i), ());
|
||||
}
|
||||
} // namespace feature
|
||||
63
libs/indexer/indexer_tests/features_vector_test.cpp
Normal file
63
libs/indexer/indexer_tests/features_vector_test.cpp
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/data_source.hpp"
|
||||
#include "indexer/features_vector.hpp"
|
||||
#include "indexer/mwm_set.hpp"
|
||||
|
||||
#include "platform/local_country_file.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace features_vector_test
|
||||
{
|
||||
using namespace platform;
|
||||
using namespace std;
|
||||
|
||||
// Postcodes with frequences.
|
||||
// One can easily get this list of frequences with postcodes:
|
||||
//
|
||||
// cat data/minsk-pass.osm.bz2 | bunzip2 | grep 'addr:postcode' |
|
||||
// sed "s/.*v='\(.*\)'.*/\1/g" |
|
||||
// sort | uniq -c | awk '{ printf("{%s, %s},\n", $2, $1) }'
|
||||
//
|
||||
// Note, (220006, 145) (220007, 271) are broken and not included in minsk-pass.mwm,
|
||||
// corresponding postcode frequencies are decremented.
|
||||
vector<pair<int, int>> kCodeFreq = {{220000, 2}, {220001, 3}, {220004, 10}, {220006, 144}, {220007, 270},
|
||||
{220010, 4}, {220011, 1}, {220014, 3}, {220030, 247}, {220033, 7},
|
||||
{220036, 204}, {220039, 15}, {220048, 1}, {220050, 4}, {220069, 5},
|
||||
{220073, 1}, {220089, 1}, {220121, 1}, {721816, 1}};
|
||||
|
||||
UNIT_TEST(FeaturesVectorTest_ParseMetadata)
|
||||
{
|
||||
string const kCountryName = "minsk-pass";
|
||||
|
||||
map<string, int> expected;
|
||||
for (auto const & p : kCodeFreq)
|
||||
expected[strings::to_string(p.first)] = p.second;
|
||||
|
||||
LocalCountryFile localFile = LocalCountryFile::MakeForTesting(kCountryName);
|
||||
|
||||
FrozenDataSource dataSource;
|
||||
auto result = dataSource.RegisterMap(localFile);
|
||||
TEST_EQUAL(result.second, MwmSet::RegResult::Success, ());
|
||||
|
||||
auto const & id = result.first;
|
||||
MwmSet::MwmHandle handle = dataSource.GetMwmHandleById(id);
|
||||
TEST(handle.IsAlive(), ());
|
||||
|
||||
auto const * value = handle.GetValue();
|
||||
FeaturesVector fv(value->m_cont, value->GetHeader(), value->m_ftTable.get(), value->m_relTable.get(),
|
||||
value->m_metaDeserializer.get());
|
||||
|
||||
map<string, int> actual;
|
||||
fv.ForEach([&](FeatureType & ft, uint32_t index)
|
||||
{
|
||||
string const postcode(ft.GetMetadata(feature::Metadata::FMD_POSTCODE));
|
||||
if (!postcode.empty())
|
||||
++actual[postcode];
|
||||
});
|
||||
TEST_EQUAL(expected, actual, ());
|
||||
}
|
||||
} // namespace features_vector_test
|
||||
66
libs/indexer/indexer_tests/index_builder_test.cpp
Normal file
66
libs/indexer/indexer_tests/index_builder_test.cpp
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/classificator_loader.hpp"
|
||||
#include "indexer/data_source.hpp"
|
||||
#include "indexer/features_vector.hpp"
|
||||
#include "indexer/index_builder.hpp"
|
||||
#include "indexer/scales.hpp"
|
||||
|
||||
#include "defines.hpp"
|
||||
|
||||
#include "platform/platform.hpp"
|
||||
|
||||
#include "coding/files_container.hpp"
|
||||
|
||||
#include "base/macros.hpp"
|
||||
#include "base/stl_helpers.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
UNIT_TEST(BuildIndexTest)
|
||||
{
|
||||
Platform & p = GetPlatform();
|
||||
classificator::Load();
|
||||
|
||||
FilesContainerR originalContainer(p.GetReader("minsk-pass" DATA_FILE_EXTENSION));
|
||||
|
||||
// Build index.
|
||||
vector<char> serialIndex;
|
||||
{
|
||||
FeaturesVectorTest features(originalContainer);
|
||||
|
||||
MemWriter<vector<char>> serialWriter(serialIndex);
|
||||
indexer::BuildIndex(features.GetHeader(), features.GetVector(), serialWriter, "build_index_test");
|
||||
}
|
||||
|
||||
// Create a new mwm file.
|
||||
string const fileName = "build_index_test" DATA_FILE_EXTENSION;
|
||||
string const filePath = p.WritablePathForFile(fileName);
|
||||
FileWriter::DeleteFileX(filePath);
|
||||
|
||||
// Copy original mwm file and replace index in it.
|
||||
{
|
||||
FilesContainerW containerWriter(filePath);
|
||||
vector<string> tags;
|
||||
originalContainer.ForEachTag(base::MakeBackInsertFunctor(tags));
|
||||
for (size_t i = 0; i < tags.size(); ++i)
|
||||
if (tags[i] != INDEX_FILE_TAG)
|
||||
containerWriter.Write(originalContainer.GetReader(tags[i]), tags[i]);
|
||||
containerWriter.Write(serialIndex, INDEX_FILE_TAG);
|
||||
}
|
||||
|
||||
{
|
||||
// Check that index actually works.
|
||||
FrozenDataSource dataSource;
|
||||
UNUSED_VALUE(dataSource.Register(platform::LocalCountryFile::MakeForTesting("build_index_test")));
|
||||
|
||||
// Make sure that index is actually parsed.
|
||||
dataSource.ForEachInScale([](FeatureType &) { return; }, 15);
|
||||
}
|
||||
|
||||
// Clean after the test.
|
||||
FileWriter::DeleteFileX(filePath);
|
||||
}
|
||||
298
libs/indexer/indexer_tests/interval_index_test.cpp
Normal file
298
libs/indexer/indexer_tests/interval_index_test.cpp
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/interval_index.hpp"
|
||||
#include "indexer/interval_index_builder.hpp"
|
||||
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/writer.hpp"
|
||||
|
||||
#include "base/macros.hpp"
|
||||
#include "base/stl_helpers.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct CellIdFeaturePairForTest
|
||||
{
|
||||
using ValueType = uint32_t;
|
||||
|
||||
CellIdFeaturePairForTest(uint64_t cell, uint32_t value) : m_cell(cell), m_value(value) {}
|
||||
|
||||
uint64_t GetCell() const { return m_cell; }
|
||||
uint32_t GetValue() const { return m_value; }
|
||||
|
||||
uint64_t m_cell;
|
||||
uint32_t m_value;
|
||||
};
|
||||
|
||||
auto IndexValueInserter(vector<uint32_t> & values)
|
||||
{
|
||||
return [inserter = base::MakeBackInsertFunctor(values)](uint64_t, auto value) { inserter(value); };
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
UNIT_TEST(IntervalIndex_LevelCount)
|
||||
{
|
||||
TEST_EQUAL(IntervalIndexBuilder(10, 1, 3).GetLevelCount(), 1, ());
|
||||
TEST_EQUAL(IntervalIndexBuilder(11, 1, 3).GetLevelCount(), 1, ());
|
||||
TEST_EQUAL(IntervalIndexBuilder(12, 1, 3).GetLevelCount(), 2, ());
|
||||
TEST_EQUAL(IntervalIndexBuilder(19, 2, 3).GetLevelCount(), 1, ());
|
||||
TEST_EQUAL(IntervalIndexBuilder(19, 1, 3).GetLevelCount(), 4, ());
|
||||
TEST_EQUAL(IntervalIndexBuilder(20, 1, 3).GetLevelCount(), 4, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(IntervalIndex_SerializedNodeBitmap)
|
||||
{
|
||||
uint32_t const offset = 350; // == 0x15E
|
||||
uint32_t childSizes[8] = {0, 0, 0, 10, 0, 0, 1000, 0};
|
||||
char const expSerial[] =
|
||||
"\xBD\x05" // (350 << 1) + 1 == 701 == 0x2BD - offset encoded as varuint.
|
||||
"\x48" // (1 << 3) | (1 << 6) == 72 == 0x48 - bitmap.
|
||||
"\x0A" // 10 - childSizes[3] encoded as varuint.
|
||||
"\xE8\x07" // 1000 = 0x3E8 - childSizes[6] encoded as varuint.
|
||||
"";
|
||||
vector<uint8_t> serializedNode;
|
||||
MemWriter<vector<uint8_t>> writer(serializedNode);
|
||||
IntervalIndexBuilder(11, 1, 3).WriteNode(writer, offset, childSizes);
|
||||
TEST_EQUAL(serializedNode, vector<uint8_t>(expSerial, expSerial + ARRAY_SIZE(expSerial) - 1), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(IntervalIndex_SerializedNodeList)
|
||||
{
|
||||
uint32_t const offset = 350; // == 0x15E
|
||||
uint32_t childSizes[16] = {0, 0, 0, 0, 0, 0, 1000, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
char const expSerial[] =
|
||||
"\xBC\x05" // (350 << 1) + 0 == 700 == 0x2BC - offset encoded as varuint.
|
||||
"\x06"
|
||||
"\xE8\x07" // 6, 1000
|
||||
"";
|
||||
vector<uint8_t> serializedNode;
|
||||
MemWriter<vector<uint8_t>> writer(serializedNode);
|
||||
IntervalIndexBuilder(11, 1, 4).WriteNode(writer, offset, childSizes);
|
||||
TEST_EQUAL(serializedNode, vector<uint8_t>(expSerial, expSerial + ARRAY_SIZE(expSerial) - 1), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(IntervalIndex_SerializedLeaves)
|
||||
{
|
||||
vector<CellIdFeaturePairForTest> data;
|
||||
data.push_back(CellIdFeaturePairForTest(0x1537U, 0));
|
||||
data.push_back(CellIdFeaturePairForTest(0x1538U, 1));
|
||||
data.push_back(CellIdFeaturePairForTest(0x1637U, 2));
|
||||
vector<uint8_t> serialLeaves;
|
||||
MemWriter<vector<uint8_t>> writer(serialLeaves);
|
||||
vector<uint32_t> sizes;
|
||||
IntervalIndexBuilder(16, 1, 4).BuildLeaves(writer, data.begin(), data.end(), sizes);
|
||||
char const expSerial[] =
|
||||
"\x37\x00"
|
||||
"\x38\x02"
|
||||
"\x37\x04"; // 0x1537 0x1538 0x1637
|
||||
uint32_t const expSizes[] = {4, 2};
|
||||
TEST_EQUAL(serialLeaves, vector<uint8_t>(expSerial, expSerial + ARRAY_SIZE(expSerial) - 1), ());
|
||||
TEST_EQUAL(sizes, vector<uint32_t>(expSizes, expSizes + ARRAY_SIZE(expSizes)), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(IntervalIndex_SerializedNodes)
|
||||
{
|
||||
vector<CellIdFeaturePairForTest> data;
|
||||
data.push_back(CellIdFeaturePairForTest(0x1537U, 0));
|
||||
data.push_back(CellIdFeaturePairForTest(0x1538U, 1));
|
||||
data.push_back(CellIdFeaturePairForTest(0x1637U, 2));
|
||||
uint32_t const leavesSizes[] = {4, 2};
|
||||
vector<uint8_t> serialNodes;
|
||||
MemWriter<vector<uint8_t>> writer(serialNodes);
|
||||
vector<uint32_t> sizes;
|
||||
IntervalIndexBuilder(16, 1, 4).BuildLevel(writer, data.begin(), data.end(), 1, leavesSizes,
|
||||
leavesSizes + ARRAY_SIZE(leavesSizes), sizes);
|
||||
char const expSerial[] = "\x01\x60\x00\x04\x02";
|
||||
uint32_t const expSizes[] = {ARRAY_SIZE(expSerial) - 1};
|
||||
TEST_EQUAL(serialNodes, vector<uint8_t>(expSerial, expSerial + ARRAY_SIZE(expSerial) - 1), ());
|
||||
TEST_EQUAL(sizes, vector<uint32_t>(expSizes, expSizes + ARRAY_SIZE(expSizes)), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(IntervalIndex_Serialized)
|
||||
{
|
||||
vector<CellIdFeaturePairForTest> data;
|
||||
data.push_back(CellIdFeaturePairForTest(0x1537U, 0));
|
||||
data.push_back(CellIdFeaturePairForTest(0x1538U, 1));
|
||||
data.push_back(CellIdFeaturePairForTest(0x1637U, 2));
|
||||
vector<uint8_t> serialIndex;
|
||||
MemWriter<vector<uint8_t>> writer(serialIndex);
|
||||
IntervalIndexBuilder(16, 1, 4).BuildIndex(writer, data.begin(), data.end());
|
||||
|
||||
char const expSerial[] =
|
||||
"\x01\x02\x04\x01" // Header
|
||||
"\x14\x00\x00\x00" // Leaves level offset
|
||||
"\x1A\x00\x00\x00" // Level 1 offset
|
||||
"\x1F\x00\x00\x00" // Root level offset
|
||||
"\x22\x00\x00\x00" // Root level offset
|
||||
"\x37\x00"
|
||||
"\x38\x02"
|
||||
"\x37\x04" // 0x1537 0x1538 0x1637
|
||||
"\x01\x60\x00\x04\x02" // 0x15, 0x16 node
|
||||
"\x00\x01\x05" // Root
|
||||
"";
|
||||
|
||||
TEST_EQUAL(serialIndex, vector<uint8_t>(expSerial, expSerial + ARRAY_SIZE(expSerial) - 1), ());
|
||||
|
||||
MemReader reader(&serialIndex[0], serialIndex.size());
|
||||
IntervalIndex<MemReader, uint32_t> index(reader);
|
||||
uint32_t expected[] = {0, 1, 2};
|
||||
vector<uint32_t> values;
|
||||
TEST_EQUAL(index.KeyEnd(), 0x10000, ());
|
||||
index.ForEach(IndexValueInserter(values), 0, 0x10000);
|
||||
TEST_EQUAL(values, vector<uint32_t>(expected, expected + ARRAY_SIZE(expected)), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(IntervalIndex_Simple)
|
||||
{
|
||||
vector<CellIdFeaturePairForTest> data;
|
||||
data.push_back(CellIdFeaturePairForTest(0xA0B1C2D100ULL, 0));
|
||||
data.push_back(CellIdFeaturePairForTest(0xA0B1C2D200ULL, 1));
|
||||
data.push_back(CellIdFeaturePairForTest(0xA0B2C2D100ULL, 2));
|
||||
vector<char> serialIndex;
|
||||
MemWriter<vector<char>> writer(serialIndex);
|
||||
BuildIntervalIndex(data.begin(), data.end(), writer, 40);
|
||||
MemReader reader(&serialIndex[0], serialIndex.size());
|
||||
IntervalIndex<MemReader, uint32_t> index(reader);
|
||||
TEST_EQUAL(index.KeyEnd(), 0x10000000000ULL, ());
|
||||
{
|
||||
uint32_t expected[] = {0, 1, 2};
|
||||
vector<uint32_t> values;
|
||||
index.ForEach(IndexValueInserter(values), 0ULL, index.KeyEnd());
|
||||
TEST_EQUAL(values, vector<uint32_t>(expected, expected + ARRAY_SIZE(expected)), ());
|
||||
}
|
||||
{
|
||||
uint32_t expected[] = {0, 1};
|
||||
vector<uint32_t> values;
|
||||
index.ForEach(IndexValueInserter(values), 0xA0B1C2D100ULL, 0xA0B1C2D201ULL);
|
||||
TEST_EQUAL(values, vector<uint32_t>(expected, expected + ARRAY_SIZE(expected)), ());
|
||||
}
|
||||
{
|
||||
uint32_t expected[] = {0, 1};
|
||||
vector<uint32_t> values;
|
||||
index.ForEach(IndexValueInserter(values), 0x0ULL, 0xA0B1C30000ULL);
|
||||
TEST_EQUAL(values, vector<uint32_t>(expected, expected + ARRAY_SIZE(expected)), ());
|
||||
}
|
||||
{
|
||||
uint32_t expected[] = {0};
|
||||
vector<uint32_t> values;
|
||||
index.ForEach(IndexValueInserter(values), 0xA0B1C2D100ULL, 0xA0B1C2D101ULL);
|
||||
TEST_EQUAL(values, vector<uint32_t>(expected, expected + ARRAY_SIZE(expected)), ());
|
||||
}
|
||||
{
|
||||
uint32_t expected[] = {0};
|
||||
vector<uint32_t> values;
|
||||
index.ForEach(IndexValueInserter(values), 0xA0B1C2D100ULL, 0xA0B1C2D200ULL);
|
||||
TEST_EQUAL(values, vector<uint32_t>(expected, expected + ARRAY_SIZE(expected)), ());
|
||||
}
|
||||
{
|
||||
vector<uint32_t> values;
|
||||
index.ForEach(IndexValueInserter(values), 0xA0B1C2D100ULL, 0xA0B1C2D100ULL);
|
||||
TEST_EQUAL(values, vector<uint32_t>(), ());
|
||||
}
|
||||
{
|
||||
vector<uint32_t> values;
|
||||
index.ForEach(IndexValueInserter(values), 0xA0B1000000ULL, 0xA0B1B20000ULL);
|
||||
TEST_EQUAL(values, vector<uint32_t>(), ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(IntervalIndex_Empty)
|
||||
{
|
||||
vector<CellIdFeaturePairForTest> data;
|
||||
vector<char> serialIndex;
|
||||
MemWriter<vector<char>> writer(serialIndex);
|
||||
BuildIntervalIndex(data.begin(), data.end(), writer, 40);
|
||||
MemReader reader(&serialIndex[0], serialIndex.size());
|
||||
IntervalIndex<MemReader, uint32_t> index(reader);
|
||||
{
|
||||
vector<uint32_t> values;
|
||||
index.ForEach(IndexValueInserter(values), 0ULL, 0xFFFFFFFFFFULL);
|
||||
TEST_EQUAL(values, vector<uint32_t>(), ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(IntervalIndex_Simple2)
|
||||
{
|
||||
vector<CellIdFeaturePairForTest> data;
|
||||
data.push_back(CellIdFeaturePairForTest(0xA0B1C2D200ULL, 0));
|
||||
data.push_back(CellIdFeaturePairForTest(0xA0B1C2D200ULL, 1));
|
||||
data.push_back(CellIdFeaturePairForTest(0xA0B1C2D200ULL, 3));
|
||||
data.push_back(CellIdFeaturePairForTest(0xA0B2C2D200ULL, 2));
|
||||
vector<char> serialIndex;
|
||||
MemWriter<vector<char>> writer(serialIndex);
|
||||
BuildIntervalIndex(data.begin(), data.end(), writer, 40);
|
||||
MemReader reader(&serialIndex[0], serialIndex.size());
|
||||
IntervalIndex<MemReader, uint32_t> index(reader);
|
||||
{
|
||||
uint32_t expected[] = {0, 1, 2, 3};
|
||||
vector<uint32_t> values;
|
||||
index.ForEach(IndexValueInserter(values), 0, 0xFFFFFFFFFFULL);
|
||||
sort(values.begin(), values.end());
|
||||
TEST_EQUAL(values, vector<uint32_t>(expected, expected + ARRAY_SIZE(expected)), ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(IntervalIndex_Simple3)
|
||||
{
|
||||
vector<CellIdFeaturePairForTest> data;
|
||||
data.push_back(CellIdFeaturePairForTest(0x0100ULL, 0));
|
||||
data.push_back(CellIdFeaturePairForTest(0x0200ULL, 1));
|
||||
vector<char> serialIndex;
|
||||
MemWriter<vector<char>> writer(serialIndex);
|
||||
BuildIntervalIndex(data.begin(), data.end(), writer, 40);
|
||||
MemReader reader(&serialIndex[0], serialIndex.size());
|
||||
IntervalIndex<MemReader, uint32_t> index(reader);
|
||||
{
|
||||
uint32_t expected[] = {0, 1};
|
||||
vector<uint32_t> values;
|
||||
index.ForEach(IndexValueInserter(values), 0, 0xFFFFULL);
|
||||
sort(values.begin(), values.end());
|
||||
TEST_EQUAL(values, vector<uint32_t>(expected, expected + ARRAY_SIZE(expected)), ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(IntervalIndex_Simple4)
|
||||
{
|
||||
vector<CellIdFeaturePairForTest> data;
|
||||
data.push_back(CellIdFeaturePairForTest(0x01030400ULL, 0));
|
||||
data.push_back(CellIdFeaturePairForTest(0x02030400ULL, 1));
|
||||
vector<char> serialIndex;
|
||||
MemWriter<vector<char>> writer(serialIndex);
|
||||
BuildIntervalIndex(data.begin(), data.end(), writer, 40);
|
||||
MemReader reader(&serialIndex[0], serialIndex.size());
|
||||
IntervalIndex<MemReader, uint32_t> index(reader);
|
||||
{
|
||||
uint32_t expected[] = {0, 1};
|
||||
vector<uint32_t> values;
|
||||
index.ForEach(IndexValueInserter(values), 0, 0xFFFFFFFFULL);
|
||||
sort(values.begin(), values.end());
|
||||
TEST_EQUAL(values, vector<uint32_t>(expected, expected + ARRAY_SIZE(expected)), ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(IntervalIndex_Simple5)
|
||||
{
|
||||
vector<CellIdFeaturePairForTest> data;
|
||||
data.push_back(CellIdFeaturePairForTest(0xA0B1C2D200ULL, 0));
|
||||
data.push_back(CellIdFeaturePairForTest(0xA0B1C2D200ULL, 1));
|
||||
data.push_back(CellIdFeaturePairForTest(0xA0B1C2D200ULL, 3));
|
||||
data.push_back(CellIdFeaturePairForTest(0xA0B2C2D200ULL, 2));
|
||||
vector<char> serialIndex;
|
||||
MemWriter<vector<char>> writer(serialIndex);
|
||||
BuildIntervalIndex(data.begin(), data.end(), writer, 40);
|
||||
MemReader reader(&serialIndex[0], serialIndex.size());
|
||||
IntervalIndex<MemReader, uint32_t> index(reader);
|
||||
{
|
||||
uint32_t expected[] = {0, 1, 2, 3};
|
||||
vector<uint32_t> values;
|
||||
index.ForEach(IndexValueInserter(values), 0, 0xFFFFFFFFFFULL);
|
||||
sort(values.begin(), values.end());
|
||||
TEST_EQUAL(values, vector<uint32_t>(expected, expected + ARRAY_SIZE(expected)), ());
|
||||
}
|
||||
}
|
||||
81
libs/indexer/indexer_tests/metadata_serdes_tests.cpp
Normal file
81
libs/indexer/indexer_tests/metadata_serdes_tests.cpp
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/feature_meta.hpp"
|
||||
#include "indexer/metadata_serdes.hpp"
|
||||
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/writer.hpp"
|
||||
|
||||
#include "base/string_utils.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace feature;
|
||||
using namespace indexer;
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
using Buffer = vector<uint8_t>;
|
||||
|
||||
UNIT_TEST(MetadataSerDesTest_Smoke)
|
||||
{
|
||||
Buffer buffer;
|
||||
|
||||
auto const genMeta = [](uint32_t i)
|
||||
{
|
||||
feature::Metadata meta;
|
||||
meta.Set(Metadata::FMD_TEST_ID, strings::to_string(i));
|
||||
return meta;
|
||||
};
|
||||
|
||||
uint32_t constexpr kMetaNumber = 1000;
|
||||
map<uint32_t, Metadata> values;
|
||||
for (uint32_t i = 0; i < kMetaNumber; ++i)
|
||||
values.emplace(i, genMeta(i));
|
||||
|
||||
{
|
||||
MetadataBuilder builder;
|
||||
|
||||
for (auto const & kv : values)
|
||||
builder.Put(kv.first, kv.second);
|
||||
|
||||
MemWriter<Buffer> writer(buffer);
|
||||
builder.Freeze(writer);
|
||||
}
|
||||
|
||||
{
|
||||
MemReader reader(buffer.data(), buffer.size());
|
||||
auto deserializer = MetadataDeserializer::Load(reader);
|
||||
TEST(deserializer.get(), ());
|
||||
|
||||
for (uint32_t i = 0; i < kMetaNumber; ++i)
|
||||
{
|
||||
Metadata meta;
|
||||
TEST(deserializer->Get(i, meta), ());
|
||||
TEST(meta.Equals(values[i]), (meta, i));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
MemReader reader(buffer.data(), buffer.size());
|
||||
auto deserializer = MetadataDeserializer::Load(reader);
|
||||
TEST(deserializer.get(), ());
|
||||
|
||||
for (uint32_t i = 0; i < kMetaNumber; ++i)
|
||||
{
|
||||
MetadataDeserializer::MetaIds ids;
|
||||
TEST(deserializer->GetIds(i, ids), ());
|
||||
auto const & meta = values[i];
|
||||
TEST_EQUAL(meta.Size(), 1, (meta));
|
||||
TEST_EQUAL(ids.size(), 1, (ids));
|
||||
TEST(meta.Has(Metadata::FMD_TEST_ID), (meta));
|
||||
TEST_EQUAL(ids[0].first, Metadata::FMD_TEST_ID, (ids));
|
||||
TEST_EQUAL(meta.Get(Metadata::FMD_TEST_ID), deserializer->GetMetaById(ids[0].second), (i, meta, ids));
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
171
libs/indexer/indexer_tests/mwm_set_test.cpp
Normal file
171
libs/indexer/indexer_tests/mwm_set_test.cpp
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "platform/platform_tests_support/scoped_mwm.hpp"
|
||||
|
||||
#include "indexer/indexer_tests/test_mwm_set.hpp"
|
||||
#include "indexer/mwm_set.hpp"
|
||||
|
||||
#include "base/macros.hpp"
|
||||
|
||||
#include <initializer_list>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace mwm_set_test
|
||||
{
|
||||
using namespace platform::tests_support;
|
||||
using namespace std;
|
||||
using platform::CountryFile;
|
||||
using platform::LocalCountryFile;
|
||||
using tests::TestMwmSet;
|
||||
|
||||
using MwmsInfo = unordered_map<string, shared_ptr<MwmInfo>>;
|
||||
|
||||
void GetMwmsInfo(MwmSet const & mwmSet, MwmsInfo & mwmsInfo)
|
||||
{
|
||||
vector<shared_ptr<MwmInfo>> mwmsInfoList;
|
||||
mwmSet.GetMwmsInfo(mwmsInfoList);
|
||||
|
||||
mwmsInfo.clear();
|
||||
for (shared_ptr<MwmInfo> const & info : mwmsInfoList)
|
||||
mwmsInfo[info->GetCountryName()] = info;
|
||||
}
|
||||
|
||||
void TestFilesPresence(MwmsInfo const & mwmsInfo, initializer_list<string> const & expectedNames)
|
||||
{
|
||||
TEST_EQUAL(expectedNames.size(), mwmsInfo.size(), ());
|
||||
for (string const & countryFileName : expectedNames)
|
||||
TEST_EQUAL(1, mwmsInfo.count(countryFileName), (countryFileName));
|
||||
}
|
||||
|
||||
UNIT_TEST(MwmSetSmokeTest)
|
||||
{
|
||||
TestMwmSet mwmSet;
|
||||
MwmsInfo mwmsInfo;
|
||||
|
||||
ScopedMwm mwm0("0.mwm");
|
||||
ScopedMwm mwm1("1.mwm");
|
||||
ScopedMwm mwm2("2.mwm");
|
||||
ScopedMwm mwm3("3.mwm");
|
||||
ScopedMwm mwm4("4.mwm");
|
||||
ScopedMwm mwm5("5.mwm");
|
||||
|
||||
UNUSED_VALUE(mwmSet.Register(LocalCountryFile::MakeForTesting("0")));
|
||||
UNUSED_VALUE(mwmSet.Register(LocalCountryFile::MakeForTesting("1")));
|
||||
UNUSED_VALUE(mwmSet.Register(LocalCountryFile::MakeForTesting("2")));
|
||||
mwmSet.Deregister(CountryFile("1"));
|
||||
|
||||
GetMwmsInfo(mwmSet, mwmsInfo);
|
||||
TestFilesPresence(mwmsInfo, {"0", "2"});
|
||||
|
||||
TEST(mwmsInfo["0"]->IsUpToDate(), ());
|
||||
TEST_EQUAL(mwmsInfo["0"]->m_maxScale, 0, ());
|
||||
TEST(mwmsInfo["2"]->IsUpToDate(), ());
|
||||
{
|
||||
MwmSet::MwmHandle const handle0 = mwmSet.GetMwmHandleByCountryFile(CountryFile("0"));
|
||||
MwmSet::MwmHandle const handle1 = mwmSet.GetMwmHandleByCountryFile(CountryFile("1"));
|
||||
TEST(handle0.IsAlive(), ());
|
||||
TEST(!handle1.IsAlive(), ());
|
||||
}
|
||||
|
||||
UNUSED_VALUE(mwmSet.Register(LocalCountryFile::MakeForTesting("3")));
|
||||
|
||||
GetMwmsInfo(mwmSet, mwmsInfo);
|
||||
TestFilesPresence(mwmsInfo, {"0", "2", "3"});
|
||||
|
||||
TEST(mwmsInfo["0"]->IsUpToDate(), ());
|
||||
TEST_EQUAL(mwmsInfo["0"]->m_maxScale, 0, ());
|
||||
TEST(mwmsInfo["2"]->IsUpToDate(), ());
|
||||
TEST_EQUAL(mwmsInfo["2"]->m_maxScale, 2, ());
|
||||
TEST(mwmsInfo["3"]->IsUpToDate(), ());
|
||||
TEST_EQUAL(mwmsInfo["3"]->m_maxScale, 3, ());
|
||||
|
||||
{
|
||||
MwmSet::MwmHandle const handle1 = mwmSet.GetMwmHandleByCountryFile(CountryFile("1"));
|
||||
TEST(!handle1.IsAlive(), ());
|
||||
mwmSet.Deregister(CountryFile("3"));
|
||||
UNUSED_VALUE(mwmSet.Register(LocalCountryFile::MakeForTesting("4")));
|
||||
}
|
||||
|
||||
GetMwmsInfo(mwmSet, mwmsInfo);
|
||||
TestFilesPresence(mwmsInfo, {"0", "2", "4"});
|
||||
|
||||
TEST(mwmsInfo["0"]->IsUpToDate(), ());
|
||||
TEST_EQUAL(mwmsInfo["0"]->m_maxScale, 0, ());
|
||||
TEST(mwmsInfo["2"]->IsUpToDate(), ());
|
||||
TEST_EQUAL(mwmsInfo["2"]->m_maxScale, 2, ());
|
||||
TEST(mwmsInfo["4"]->IsUpToDate(), ());
|
||||
TEST_EQUAL(mwmsInfo["4"]->m_maxScale, 4, ());
|
||||
|
||||
UNUSED_VALUE(mwmSet.Register(LocalCountryFile::MakeForTesting("5")));
|
||||
|
||||
GetMwmsInfo(mwmSet, mwmsInfo);
|
||||
TestFilesPresence(mwmsInfo, {"0", "2", "4", "5"});
|
||||
|
||||
TEST_EQUAL(mwmsInfo.size(), 4, ());
|
||||
TEST(mwmsInfo["0"]->IsUpToDate(), ());
|
||||
TEST_EQUAL(mwmsInfo["0"]->m_maxScale, 0, ());
|
||||
TEST(mwmsInfo["2"]->IsUpToDate(), ());
|
||||
TEST_EQUAL(mwmsInfo["2"]->m_maxScale, 2, ());
|
||||
TEST(mwmsInfo["4"]->IsUpToDate(), ());
|
||||
TEST_EQUAL(mwmsInfo["4"]->m_maxScale, 4, ());
|
||||
TEST(mwmsInfo["5"]->IsUpToDate(), ());
|
||||
TEST_EQUAL(mwmsInfo["5"]->m_maxScale, 5, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(MwmSetIdTest)
|
||||
{
|
||||
ScopedMwm mwm3("3.mwm");
|
||||
|
||||
TestMwmSet mwmSet;
|
||||
TEST_EQUAL(MwmSet::RegResult::Success, mwmSet.Register(LocalCountryFile::MakeForTesting("3")).second, ());
|
||||
|
||||
MwmSet::MwmId const id0 = mwmSet.GetMwmHandleByCountryFile(CountryFile("3")).GetId();
|
||||
MwmSet::MwmId const id1 = mwmSet.GetMwmHandleByCountryFile(CountryFile("3")).GetId();
|
||||
|
||||
TEST(id0.IsAlive(), ());
|
||||
TEST(id1.IsAlive(), ());
|
||||
TEST_EQUAL(id0.GetInfo().get(), id1.GetInfo().get(), ());
|
||||
TEST_EQUAL(MwmInfo::STATUS_REGISTERED, id0.GetInfo()->GetStatus(), ());
|
||||
|
||||
TEST(mwmSet.Deregister(CountryFile("3")), ());
|
||||
|
||||
// Test that both id's are sour now.
|
||||
TEST(!id0.IsAlive(), ());
|
||||
TEST(!id1.IsAlive(), ());
|
||||
TEST_EQUAL(id0.GetInfo().get(), id1.GetInfo().get(), ());
|
||||
TEST_EQUAL(MwmInfo::STATUS_DEREGISTERED, id0.GetInfo()->GetStatus(), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(MwmSetLockAndIdTest)
|
||||
{
|
||||
ScopedMwm mwm4("4.mwm");
|
||||
TestMwmSet mwmSet;
|
||||
MwmSet::MwmId id;
|
||||
|
||||
{
|
||||
auto p = mwmSet.Register(LocalCountryFile::MakeForTesting("4"));
|
||||
MwmSet::MwmHandle handle = mwmSet.GetMwmHandleById(p.first);
|
||||
TEST(handle.IsAlive(), ());
|
||||
TEST_EQUAL(MwmSet::RegResult::Success, p.second, ("Can't register test mwm 4"));
|
||||
TEST_EQUAL(MwmInfo::STATUS_REGISTERED, handle.GetInfo()->GetStatus(), ());
|
||||
|
||||
TEST(!mwmSet.Deregister(CountryFile("4")), ()); // It's not possible to remove mwm 4 right now.
|
||||
TEST(handle.IsAlive(), ());
|
||||
TEST_EQUAL(MwmInfo::STATUS_MARKED_TO_DEREGISTER, handle.GetInfo()->GetStatus(), ());
|
||||
id = handle.GetId();
|
||||
TEST(id.IsAlive(), ());
|
||||
}
|
||||
|
||||
TEST(!id.IsAlive(), ()); // Mwm is not alive, so id is sour now.
|
||||
TEST(id.GetInfo().get(), ()); // But it's still possible to get an MwmInfo.
|
||||
TEST_EQUAL(MwmInfo::STATUS_DEREGISTERED, id.GetInfo()->GetStatus(), ());
|
||||
TEST_EQUAL(4, id.GetInfo()->m_maxScale, ());
|
||||
|
||||
// It is not possible to lock mwm 4 because it is already deleted,
|
||||
// and it is not possible to get to it's info from mwmSet.
|
||||
MwmSet::MwmHandle handle = mwmSet.GetMwmHandleByCountryFile(CountryFile("4"));
|
||||
TEST(!handle.IsAlive(), ());
|
||||
TEST(!handle.GetId().IsAlive(), ());
|
||||
TEST(!handle.GetId().GetInfo().get(), ());
|
||||
}
|
||||
} // namespace mwm_set_test
|
||||
41
libs/indexer/indexer_tests/postcodes_matcher_tests.cpp
Normal file
41
libs/indexer/indexer_tests/postcodes_matcher_tests.cpp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/postcodes_matcher.hpp"
|
||||
|
||||
namespace postcodes_matcher_test
|
||||
{
|
||||
using namespace search;
|
||||
|
||||
UNIT_TEST(PostcodesMatcher_Smoke)
|
||||
{
|
||||
/// @todo We are not _complete_ here, because G4 is also a postcode prefix (Glasgow, Scotland)
|
||||
/// like BN1 or BN3 (Brighton).
|
||||
TEST(!LooksLikePostcode("G4", false /* handleAsPrefix */), ());
|
||||
TEST(LooksLikePostcode("G4", true /* handleAsPrefix */), ());
|
||||
TEST(LooksLikePostcode("BN1", false /* handleAsPrefix */), ());
|
||||
TEST(LooksLikePostcode("BN3 ", false /* handleAsPrefix */), ());
|
||||
TEST(LooksLikePostcode("BN1", true /* handleAsPrefix */), ());
|
||||
TEST(LooksLikePostcode("BN3 ", true /* handleAsPrefix */), ());
|
||||
|
||||
TEST(LooksLikePostcode("141701", false /* handleAsPrefix */), ());
|
||||
TEST(LooksLikePostcode("141", true /* handleAsPrefix */), ());
|
||||
TEST(LooksLikePostcode("BA6 8JP", true /* handleAsPrefix */), ());
|
||||
TEST(LooksLikePostcode("BA6-8JP", true /* handleAsPrefix */), ());
|
||||
TEST(LooksLikePostcode("BA22 9HR", true /* handleAsPrefix */), ());
|
||||
TEST(LooksLikePostcode("BA22", true /* handleAsPrefix */), ());
|
||||
TEST(LooksLikePostcode("DE56 4FW", true /* handleAsPrefix */), ());
|
||||
TEST(LooksLikePostcode("NY 1000", true /* handleAsPrefix */), ());
|
||||
TEST(LooksLikePostcode("AZ 85203", true /* handleAsPrefix */), ());
|
||||
TEST(LooksLikePostcode("AZ", true /* handleAsPrefix */), ());
|
||||
|
||||
TEST(LooksLikePostcode("803 0271", true /* handleAsPrefix */), ());
|
||||
TEST(LooksLikePostcode("803-0271", true /* handleAsPrefix */), ());
|
||||
TEST(LooksLikePostcode("〒803-0271", true /* handleAsPrefix */), ());
|
||||
|
||||
TEST(!LooksLikePostcode("1 мая", true /* handleAsPrefix */), ());
|
||||
TEST(!LooksLikePostcode("1 мая улица", true /* handleAsPrefix */), ());
|
||||
TEST(!LooksLikePostcode("москва", true /* handleAsPrefix */), ());
|
||||
TEST(!LooksLikePostcode("39 с 79", true /* handleAsPrefix */), ());
|
||||
}
|
||||
|
||||
} // namespace postcodes_matcher_test
|
||||
107
libs/indexer/indexer_tests/rank_table_test.cpp
Normal file
107
libs/indexer/indexer_tests/rank_table_test.cpp
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/classificator_loader.hpp"
|
||||
#include "indexer/data_source.hpp"
|
||||
#include "indexer/mwm_set.hpp"
|
||||
#include "indexer/rank_table.hpp"
|
||||
|
||||
#include "platform/country_defines.hpp"
|
||||
#include "platform/local_country_file.hpp"
|
||||
#include "platform/platform.hpp"
|
||||
|
||||
#include "coding/file_writer.hpp"
|
||||
#include "coding/files_container.hpp"
|
||||
#include "coding/internal/file_data.hpp"
|
||||
#include "coding/writer.hpp"
|
||||
|
||||
#include "base/file_name_utils.hpp"
|
||||
#include "base/scope_guard.hpp"
|
||||
|
||||
#include "defines.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
void TestTable(vector<uint8_t> const & ranks, search::RankTable const & table)
|
||||
{
|
||||
TEST_EQUAL(ranks.size(), table.Size(), ());
|
||||
TEST_EQUAL(table.GetVersion(), search::RankTable::V0, ());
|
||||
for (size_t i = 0; i < ranks.size(); ++i)
|
||||
TEST_EQUAL(ranks[i], table.Get(i), ());
|
||||
}
|
||||
|
||||
void TestTable(vector<uint8_t> const & ranks, string const & path)
|
||||
{
|
||||
// Tries to load table via file read.
|
||||
{
|
||||
FilesContainerR rcont(path);
|
||||
auto table = search::RankTable::Load(rcont, SEARCH_RANKS_FILE_TAG);
|
||||
TEST(table, ());
|
||||
TestTable(ranks, *table);
|
||||
}
|
||||
|
||||
// Tries to load table via file mapping.
|
||||
{
|
||||
FilesMappingContainer mcont(path);
|
||||
auto table = search::RankTable::Load(mcont, SEARCH_RANKS_FILE_TAG);
|
||||
TEST(table, ());
|
||||
TestTable(ranks, *table);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
UNIT_TEST(RankTableBuilder_Smoke)
|
||||
{
|
||||
char const kTestCont[] = "test.tmp";
|
||||
size_t const kNumRanks = 256;
|
||||
|
||||
FileWriter::DeleteFileX(kTestCont);
|
||||
SCOPE_GUARD(cleanup, bind(&FileWriter::DeleteFileX, kTestCont));
|
||||
|
||||
vector<uint8_t> ranks;
|
||||
for (size_t i = 0; i < kNumRanks; ++i)
|
||||
ranks.push_back(i);
|
||||
|
||||
{
|
||||
FilesContainerW wcont(kTestCont);
|
||||
search::RankTableBuilder::Create(ranks, wcont, SEARCH_RANKS_FILE_TAG);
|
||||
}
|
||||
|
||||
TestTable(ranks, kTestCont);
|
||||
}
|
||||
|
||||
UNIT_TEST(RankTableBuilder_EndToEnd)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
string const originalMapPath = base::JoinPath(GetPlatform().WritableDir(), "minsk-pass.mwm");
|
||||
string const mapPath = base::JoinPath(GetPlatform().WritableDir(), "minsk-pass-copy.mwm");
|
||||
base::CopyFileX(originalMapPath, mapPath);
|
||||
SCOPE_GUARD(cleanup, bind(&FileWriter::DeleteFileX, mapPath));
|
||||
|
||||
auto const localFile = platform::LocalCountryFile::MakeForTesting("minsk-pass-copy");
|
||||
TEST(localFile.OnDisk(MapFileType::Map), ());
|
||||
|
||||
vector<uint8_t> ranks;
|
||||
{
|
||||
FilesContainerR rcont(mapPath);
|
||||
search::SearchRankTableBuilder::CalcSearchRanks(rcont, ranks);
|
||||
}
|
||||
|
||||
{
|
||||
FilesContainerW wcont(mapPath, FileWriter::OP_WRITE_EXISTING);
|
||||
search::RankTableBuilder::Create(ranks, wcont, SEARCH_RANKS_FILE_TAG);
|
||||
}
|
||||
|
||||
FrozenDataSource dataSource;
|
||||
auto regResult = dataSource.RegisterMap(localFile);
|
||||
TEST_EQUAL(regResult.second, MwmSet::RegResult::Success, ());
|
||||
|
||||
TestTable(ranks, mapPath);
|
||||
}
|
||||
37
libs/indexer/indexer_tests/read_features_tests.cpp
Normal file
37
libs/indexer/indexer_tests/read_features_tests.cpp
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/classificator_loader.hpp"
|
||||
#include "indexer/data_source.hpp"
|
||||
|
||||
#include "platform/local_country_file.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
UNIT_TEST(ReadFeatures_Smoke)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
FrozenDataSource dataSource;
|
||||
dataSource.RegisterMap(platform::LocalCountryFile::MakeForTesting("minsk-pass"));
|
||||
|
||||
vector<shared_ptr<MwmInfo>> infos;
|
||||
dataSource.GetMwmsInfo(infos);
|
||||
CHECK_EQUAL(infos.size(), 1, ());
|
||||
|
||||
auto handle = dataSource.GetMwmHandleById(MwmSet::MwmId(infos[0]));
|
||||
|
||||
FeaturesLoaderGuard const guard(dataSource, handle.GetId());
|
||||
LOG(LINFO, (guard.GetNumFeatures()));
|
||||
for (uint32_t i = 0; i + 1 < guard.GetNumFeatures(); ++i)
|
||||
{
|
||||
auto ft1 = guard.GetFeatureByIndex(i);
|
||||
auto ft2 = guard.GetFeatureByIndex(i + 1);
|
||||
|
||||
ft2->ForEachType([](auto const /* t */) {});
|
||||
ft1->ForEachType([](auto const /* t */) {});
|
||||
}
|
||||
}
|
||||
58
libs/indexer/indexer_tests/road_shields_parser_tests.cpp
Normal file
58
libs/indexer/indexer_tests/road_shields_parser_tests.cpp
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/road_shields_parser.hpp"
|
||||
|
||||
UNIT_TEST(RoadShields_Smoke)
|
||||
{
|
||||
using namespace ftypes;
|
||||
|
||||
auto shields = GetRoadShields("France", "D 116A");
|
||||
TEST_EQUAL(shields.size(), 1, ());
|
||||
TEST_EQUAL(shields[0].m_type, RoadShieldType::Generic_Orange, ());
|
||||
|
||||
shields = GetRoadShields("Belarus", "M1"); // latin letter M
|
||||
TEST_EQUAL(shields.size(), 1, ());
|
||||
TEST_EQUAL(shields[0].m_type, RoadShieldType::Generic_Red, ());
|
||||
|
||||
shields = GetRoadShields("Belarus", "Е2"); // cyrillic letter Е
|
||||
TEST_EQUAL(shields.size(), 1, ());
|
||||
TEST_EQUAL(shields[0].m_type, RoadShieldType::Generic_Green, ());
|
||||
|
||||
shields = GetRoadShields("Ukraine", "Р50"); // cyrillic letter Р
|
||||
TEST_EQUAL(shields.size(), 1, ());
|
||||
TEST_EQUAL(shields[0].m_type, RoadShieldType::Generic_Blue, ());
|
||||
|
||||
shields = GetRoadShields("Malaysia", "AH7");
|
||||
TEST_EQUAL(shields.size(), 1, ());
|
||||
TEST_EQUAL(shields[0].m_type, RoadShieldType::Generic_Blue, ());
|
||||
|
||||
shields = GetRoadShields("Germany", "A 3;A 7");
|
||||
TEST_EQUAL(shields.size(), 2, ());
|
||||
TEST_EQUAL(shields[0].m_type, RoadShieldType::Generic_Blue, ());
|
||||
TEST_EQUAL(shields[1].m_type, RoadShieldType::Generic_Blue, ());
|
||||
|
||||
shields = GetRoadShields("Germany", "blue/A 31;national/B 2R");
|
||||
TEST_EQUAL(shields.size(), 2, ());
|
||||
TEST_EQUAL(shields[0].m_type, RoadShieldType::Generic_Blue, ());
|
||||
TEST_EQUAL(shields[1].m_type, RoadShieldType::Generic_Orange, ());
|
||||
|
||||
shields = GetRoadShields("Germany", "TMC 33388 (St 2047)");
|
||||
TEST_EQUAL(shields.size(), 0, ());
|
||||
|
||||
shields = GetRoadShields("US", "US:IN");
|
||||
TEST_EQUAL(shields.size(), 1, ());
|
||||
TEST_EQUAL(shields[0].m_type, RoadShieldType::Default, ());
|
||||
|
||||
shields = GetRoadShields("US", "SR 38;US:IN");
|
||||
TEST_EQUAL(shields.size(), 2, ());
|
||||
TEST_EQUAL(shields[0].m_type, RoadShieldType::Generic_White, ());
|
||||
TEST_EQUAL(shields[1].m_type, RoadShieldType::Default, ());
|
||||
|
||||
shields = GetRoadShields("Switzerland", "e-road/E 67");
|
||||
TEST_EQUAL(shields.size(), 1, ());
|
||||
TEST_EQUAL(shields[0].m_type, RoadShieldType::Generic_Green, ());
|
||||
|
||||
shields = GetRoadShields("Estonia", "ee:national/27;ee:local/7841171");
|
||||
TEST_EQUAL(shields.size(), 1, ());
|
||||
TEST_EQUAL(shields[0].m_type, RoadShieldType::Generic_Orange, ());
|
||||
}
|
||||
120
libs/indexer/indexer_tests/scale_index_reading_tests.cpp
Normal file
120
libs/indexer/indexer_tests/scale_index_reading_tests.cpp
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "generator/generator_tests_support/test_feature.hpp"
|
||||
#include "generator/generator_tests_support/test_mwm_builder.hpp"
|
||||
#include "generator/generator_tests_support/test_with_custom_mwms.hpp"
|
||||
|
||||
#include "indexer/cell_id.hpp"
|
||||
#include "indexer/data_header.hpp"
|
||||
#include "indexer/data_source.hpp"
|
||||
#include "indexer/feature.hpp"
|
||||
#include "indexer/feature_covering.hpp"
|
||||
#include "indexer/feature_visibility.hpp"
|
||||
#include "indexer/mwm_set.hpp"
|
||||
#include "indexer/scale_index.hpp"
|
||||
|
||||
#include "platform/country_defines.hpp"
|
||||
#include "platform/local_country_file.hpp"
|
||||
|
||||
#include "coding/files_container.hpp"
|
||||
#include "coding/mmap_reader.hpp"
|
||||
#include "coding/reader.hpp"
|
||||
|
||||
#include "geometry/rect2d.hpp"
|
||||
|
||||
#include "defines.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace scale_index_reading_tests
|
||||
{
|
||||
using namespace generator::tests_support;
|
||||
using namespace indexer;
|
||||
using namespace std;
|
||||
|
||||
using Names = vector<string>;
|
||||
|
||||
class ScaleIndexReadingTest : public TestWithCustomMwms
|
||||
{
|
||||
public:
|
||||
template <typename ScaleIndex>
|
||||
Names CollectNames(MwmSet::MwmId const & id, ScaleIndex const & index, int scaleForIntervals, int scaleForZoomLevels,
|
||||
m2::RectD const & rect)
|
||||
{
|
||||
covering::CoveringGetter covering(rect, covering::ViewportWithLowLevels);
|
||||
|
||||
vector<uint32_t> indices;
|
||||
for (auto const & interval : covering.Get<RectId::DEPTH_LEVELS>(scaleForIntervals))
|
||||
{
|
||||
index.ForEachInIntervalAndScale(interval.first, interval.second, scaleForZoomLevels,
|
||||
[&](uint64_t /* key */, uint32_t value) { indices.push_back(value); });
|
||||
}
|
||||
|
||||
FeaturesLoaderGuard loader(m_dataSource, id);
|
||||
|
||||
Names names;
|
||||
for (auto const & index : indices)
|
||||
{
|
||||
auto ft = loader.GetFeatureByIndex(index);
|
||||
TEST(ft, (index));
|
||||
|
||||
string_view const name = ft->GetName(StringUtf8Multilang::kEnglishCode);
|
||||
TEST(!name.empty(), (index));
|
||||
names.push_back(std::string(name));
|
||||
}
|
||||
|
||||
sort(names.begin(), names.end());
|
||||
return names;
|
||||
}
|
||||
};
|
||||
|
||||
UNIT_CLASS_TEST(ScaleIndexReadingTest, Mmap)
|
||||
{
|
||||
TestPOI a(m2::PointD{0, 0}, "A", "en");
|
||||
TestPOI b(m2::PointD{1, 0}, "B", "en");
|
||||
TestPOI c(m2::PointD{1, 1}, "C", "en");
|
||||
TestPOI d(m2::PointD{0, 1}, "D", "en");
|
||||
|
||||
auto id = BuildCountry("Wonderland", [&](TestMwmBuilder & builder)
|
||||
{
|
||||
builder.Add(a);
|
||||
builder.Add(b);
|
||||
builder.Add(c);
|
||||
builder.Add(d);
|
||||
});
|
||||
|
||||
TEST(id.IsAlive(), ());
|
||||
|
||||
auto const path = id.GetInfo()->GetLocalFile().GetPath(MapFileType::Map);
|
||||
|
||||
FilesContainerR cont(path);
|
||||
feature::DataHeader header(cont);
|
||||
|
||||
auto const offsetSize = cont.GetAbsoluteOffsetAndSize(INDEX_FILE_TAG);
|
||||
|
||||
MmapReader reader(path);
|
||||
ReaderPtr<Reader> subReader(reader.CreateSubReader(offsetSize.first, offsetSize.second));
|
||||
|
||||
ScaleIndex<ReaderPtr<Reader>> index(subReader);
|
||||
|
||||
auto collectNames = [&](m2::RectD const & rect)
|
||||
{ return CollectNames(id, index, header.GetLastScale(), header.GetLastScale(), rect); };
|
||||
|
||||
TEST_EQUAL(collectNames(m2::RectD{-0.5, -0.5, 0.5, 0.5}), Names({"A"}), ());
|
||||
TEST_EQUAL(collectNames(m2::RectD{0.5, -0.5, 1.5, 1.5}), Names({"B", "C"}), ());
|
||||
TEST_EQUAL(collectNames(m2::RectD{-0.5, -0.5, 1.5, 1.5}), Names({"A", "B", "C", "D"}), ());
|
||||
|
||||
auto collectNamesForExactScale = [&](m2::RectD const & rect, int scale)
|
||||
{ return CollectNames(id, index, header.GetLastScale(), scale, rect); };
|
||||
|
||||
auto const drawableScale = feature::GetMinDrawableScaleClassifOnly(a.GetTypes());
|
||||
CHECK_LESS(drawableScale, header.GetLastScale(), ("Change the test to ensure scales less than last scale work."));
|
||||
|
||||
TEST_EQUAL(collectNamesForExactScale(m2::RectD{-0.5, -0.5, 0.5, 0.5}, drawableScale), Names({"A"}), ());
|
||||
TEST_EQUAL(collectNamesForExactScale(m2::RectD{0.5, -0.5, 1.5, 1.5}, drawableScale), Names({"B", "C"}), ());
|
||||
TEST_EQUAL(collectNamesForExactScale(m2::RectD{-0.5, -0.5, 1.5, 1.5}, drawableScale), Names({"A", "B", "C", "D"}),
|
||||
());
|
||||
}
|
||||
} // namespace scale_index_reading_tests
|
||||
351
libs/indexer/indexer_tests/search_string_utils_test.cpp
Normal file
351
libs/indexer/indexer_tests/search_string_utils_test.cpp
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/search_string_utils.hpp"
|
||||
|
||||
#include "base/string_utils.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace search_string_utils_test
|
||||
{
|
||||
using namespace search;
|
||||
using namespace std;
|
||||
using namespace strings;
|
||||
|
||||
class Utf8StreetTokensFilter
|
||||
{
|
||||
public:
|
||||
explicit Utf8StreetTokensFilter(vector<pair<string, size_t>> & cont, bool withMisprints = false)
|
||||
: m_cont(cont)
|
||||
, m_filter([&](UniString const & token, size_t tag) { m_cont.emplace_back(ToUtf8(token), tag); }, withMisprints)
|
||||
{}
|
||||
|
||||
void Put(string const & token, bool isPrefix, size_t tag) { m_filter.Put(MakeUniString(token), isPrefix, tag); }
|
||||
|
||||
private:
|
||||
vector<pair<string, size_t>> & m_cont;
|
||||
StreetTokensFilter m_filter;
|
||||
};
|
||||
|
||||
bool TestStreetSynonym(char const * s)
|
||||
{
|
||||
return IsStreetSynonym(MakeUniString(s));
|
||||
}
|
||||
|
||||
bool TestStreetPrefixMatch(char const * s)
|
||||
{
|
||||
return IsStreetSynonymPrefix(MakeUniString(s));
|
||||
}
|
||||
|
||||
bool TestStreetSynonymWithMisprints(char const * s)
|
||||
{
|
||||
return IsStreetSynonymWithMisprints(MakeUniString(s));
|
||||
}
|
||||
|
||||
bool TestStreetPrefixMatchWithMisprints(char const * s)
|
||||
{
|
||||
return IsStreetSynonymPrefixWithMisprints(MakeUniString(s));
|
||||
}
|
||||
|
||||
string NormalizeAndSimplifyStringUtf8(string const & s)
|
||||
{
|
||||
return strings::ToUtf8(NormalizeAndSimplifyString(s));
|
||||
}
|
||||
|
||||
UNIT_TEST(FeatureTypeToString)
|
||||
{
|
||||
TEST_EQUAL("!type:123", ToUtf8(FeatureTypeToString(123)), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(NormalizeAndSimplifyString_WithOurTambourines)
|
||||
{
|
||||
// This test is dependent from strings::NormalizeAndSimplifyString implementation.
|
||||
// TODO: Fix it when logic with и-й will change.
|
||||
|
||||
/*
|
||||
string const arr[] = {"ÜbërÅłłęšß", "uberallesss", // Basic test case.
|
||||
"Iiİı", "iiii", // Famous turkish "I" letter bug.
|
||||
"ЙЁйёШКИЙй", "йейешкийй", // Better handling of Russian й letter.
|
||||
"ØøÆæŒœ", "ooaeaeoeoe",
|
||||
"バス", "ハス",
|
||||
"âàáạăốợồôểềệếỉđưựứửýĂÂĐÊÔƠƯ",
|
||||
"aaaaaooooeeeeiduuuuyaadeoou", // Vietnamese
|
||||
"ăâț", "aat" // Romanian
|
||||
};
|
||||
*/
|
||||
string const arr[] = {
|
||||
"ÜbërÅłłęšß",
|
||||
"uberallesss", // Basic test case.
|
||||
"Iiİı",
|
||||
"iiii", // Famous turkish "I" letter bug.
|
||||
"ЙЁйёШКИЙй",
|
||||
"иеиешкиии", // Better handling of Russian й letter.
|
||||
"ØøÆæŒœ",
|
||||
"ooaeaeoeoe", // Dansk
|
||||
"バス",
|
||||
"ハス",
|
||||
"âàáạăốợồôểềệếỉđưựứửýĂÂĐÊÔƠƯ",
|
||||
"aaaaaooooeeeeiduuuuyaadeoou", // Vietnamese
|
||||
"ăâț",
|
||||
"aat", // Romanian
|
||||
"Триу́мф-Пала́с",
|
||||
"триумф-палас", // Russian accent
|
||||
" a b c d ",
|
||||
" a b c d ", // Multiple spaces
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(arr); i += 2)
|
||||
TEST_EQUAL(arr[i + 1], NormalizeAndSimplifyStringUtf8(arr[i]), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(NormalizeAndSimplifyString_Contains)
|
||||
{
|
||||
constexpr char const * kTestStr = "ØøÆæŒœ Ўвага!";
|
||||
TEST(ContainsNormalized(kTestStr, ""), ());
|
||||
TEST(!ContainsNormalized("", "z"), ());
|
||||
TEST(ContainsNormalized(kTestStr, "ooae"), ());
|
||||
TEST(ContainsNormalized(kTestStr, " у"), ());
|
||||
TEST(ContainsNormalized(kTestStr, "Ў"), ());
|
||||
TEST(ContainsNormalized(kTestStr, "ўв"), ());
|
||||
TEST(!ContainsNormalized(kTestStr, "ага! "), ());
|
||||
TEST(!ContainsNormalized(kTestStr, "z"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Street_Synonym)
|
||||
{
|
||||
TEST(TestStreetSynonym("street"), ());
|
||||
TEST(TestStreetSynonym("улица"), ());
|
||||
|
||||
TEST(TestStreetSynonym("strasse"), ());
|
||||
TEST(TestStreetSynonymWithMisprints("strasse"), ());
|
||||
TEST(!TestStreetSynonym("strase"), ());
|
||||
TEST(TestStreetSynonymWithMisprints("strase"), ());
|
||||
|
||||
// TEST(TestStreetSynonym("boulevard"), ());
|
||||
// TEST(TestStreetSynonymWithMisprints("boulevard"), ());
|
||||
// TEST(!TestStreetSynonym("boulevrd"), ());
|
||||
// TEST(TestStreetSynonymWithMisprints("boulevrd"), ());
|
||||
|
||||
TEST(TestStreetSynonym("avenue"), ());
|
||||
TEST(TestStreetSynonymWithMisprints("avenue"), ());
|
||||
TEST(!TestStreetSynonym("aveneu"), ());
|
||||
TEST(TestStreetSynonymWithMisprints("aveneu"), ());
|
||||
|
||||
TEST(!TestStreetSynonymWithMisprints("abcdefg"), ());
|
||||
|
||||
TEST(TestStreetSynonym("g."), ());
|
||||
TEST(TestStreetSynonymWithMisprints("g."), ());
|
||||
|
||||
TEST(!TestStreetSynonymWithMisprints("ву"), ());
|
||||
TEST(TestStreetSynonymWithMisprints("вул"), ());
|
||||
|
||||
TEST(!TestStreetSynonymWithMisprints("gat"), ());
|
||||
TEST(!TestStreetSynonymWithMisprints("sok"), ());
|
||||
TEST(!TestStreetSynonymWithMisprints("ca"), ());
|
||||
|
||||
// soka -> sokak
|
||||
TEST(TestStreetSynonymWithMisprints("soka"), ());
|
||||
TEST(!TestStreetSynonym("soka"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Street_PrefixMatch)
|
||||
{
|
||||
TEST(TestStreetPrefixMatch("у"), ());
|
||||
TEST(TestStreetPrefixMatch("ул"), ());
|
||||
TEST(TestStreetPrefixMatch("ули"), ());
|
||||
|
||||
TEST(TestStreetPrefixMatch("gat"), ());
|
||||
TEST(TestStreetPrefixMatch("sok"), ());
|
||||
TEST(TestStreetPrefixMatch("ca"), ());
|
||||
TEST(TestStreetPrefixMatch("ву"), ());
|
||||
|
||||
// TEST(TestStreetPrefixMatch("п"), ());
|
||||
// TEST(TestStreetPrefixMatch("пр"), ());
|
||||
// TEST(TestStreetPrefixMatch("про"), ());
|
||||
// TEST(TestStreetPrefixMatch("прое"), ());
|
||||
// TEST(TestStreetPrefixMatch("проез"), ());
|
||||
// TEST(TestStreetPrefixMatch("проезд"), ());
|
||||
// TEST(!TestStreetPrefixMatch("проездд"), ());
|
||||
|
||||
TEST(TestStreetPrefixMatchWithMisprints("ул"), ());
|
||||
TEST(!TestStreetPrefixMatch("уле"), ());
|
||||
TEST(!TestStreetPrefixMatchWithMisprints("уле"), ());
|
||||
TEST(!TestStreetPrefixMatch("улец"), ());
|
||||
TEST(TestStreetPrefixMatchWithMisprints("улец"), ());
|
||||
TEST(!TestStreetPrefixMatch("улеца"), ());
|
||||
TEST(TestStreetPrefixMatchWithMisprints("улеца"), ());
|
||||
|
||||
TEST(TestStreetPrefixMatchWithMisprints("roadx"), ());
|
||||
TEST(!TestStreetPrefixMatchWithMisprints("roadxx"), ());
|
||||
|
||||
TEST(!TestStreetPrefixMatchWithMisprints("groad"), ()); // road, but no
|
||||
TEST(TestStreetPrefixMatchWithMisprints("karre"), ()); // carrer
|
||||
TEST(!TestStreetPrefixMatchWithMisprints("karrerx"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Street_TokensFilter)
|
||||
{
|
||||
using List = vector<pair<string, size_t>>;
|
||||
|
||||
{
|
||||
List expected = {};
|
||||
List actual;
|
||||
|
||||
Utf8StreetTokensFilter filter(actual);
|
||||
filter.Put("ули", true /* isPrefix */, 0 /* tag */);
|
||||
|
||||
TEST_EQUAL(expected, actual, ());
|
||||
}
|
||||
|
||||
{
|
||||
List expected = {};
|
||||
List actual;
|
||||
|
||||
Utf8StreetTokensFilter filter(actual);
|
||||
filter.Put("улица", false /* isPrefix */, 0 /* tag */);
|
||||
|
||||
TEST_EQUAL(expected, actual, ());
|
||||
}
|
||||
|
||||
{
|
||||
List expected = {{"генерала", 1}, {"антонова", 2}};
|
||||
List actual;
|
||||
|
||||
Utf8StreetTokensFilter filter(actual);
|
||||
filter.Put("ул", false /* isPrefix */, 0 /* tag */);
|
||||
filter.Put("генерала", false /* isPrefix */, 1 /* tag */);
|
||||
filter.Put("антонова", false /* isPrefix */, 2 /* tag */);
|
||||
|
||||
TEST_EQUAL(expected, actual, ());
|
||||
}
|
||||
|
||||
{
|
||||
List expected = {{"набережная", 50}};
|
||||
List actual;
|
||||
|
||||
Utf8StreetTokensFilter filter(actual);
|
||||
filter.Put("улица", false /* isPrefix */, 100 /* tag */);
|
||||
filter.Put("набережная", true /* isPrefix */, 50 /* tag */);
|
||||
|
||||
TEST_EQUAL(expected, actual, ());
|
||||
}
|
||||
|
||||
{
|
||||
List expected = {{"набережная", 1}};
|
||||
List actual;
|
||||
|
||||
Utf8StreetTokensFilter filter(actual);
|
||||
filter.Put("улица", false /* isPrefix */, 0 /* tag */);
|
||||
filter.Put("набережная", true /* isPrefix */, 1 /* tag */);
|
||||
filter.Put("проспект", false /* isPrefix */, 2 /* tag */);
|
||||
|
||||
TEST_EQUAL(expected, actual, ());
|
||||
}
|
||||
|
||||
{
|
||||
List expectedWithMP = {{"ленинский", 0}};
|
||||
List expectedWithoutMP = {{"ленинский", 0}, {"пропект", 1}};
|
||||
List actualWithMisprints;
|
||||
List actualWithoutMisprints;
|
||||
|
||||
Utf8StreetTokensFilter filterWithMisprints(actualWithMisprints, true /* withMisprints */);
|
||||
Utf8StreetTokensFilter filterWithoutMisprints(actualWithoutMisprints, false /* withMisprints */);
|
||||
filterWithMisprints.Put("ленинский", false /* isPrefix */, 0 /* tag */);
|
||||
filterWithoutMisprints.Put("ленинский", false /* isPrefix */, 0 /* tag */);
|
||||
filterWithMisprints.Put("пропект", false /* isPrefix */, 1 /* tag */);
|
||||
filterWithoutMisprints.Put("пропект", false /* isPrefix */, 1 /* tag */);
|
||||
|
||||
TEST_EQUAL(expectedWithMP, actualWithMisprints, ());
|
||||
TEST_EQUAL(expectedWithoutMP, actualWithoutMisprints, ());
|
||||
}
|
||||
|
||||
{
|
||||
List expected = {{"набрежная", 1}};
|
||||
List actualWithMisprints;
|
||||
List actualWithoutMisprints;
|
||||
|
||||
Utf8StreetTokensFilter filterWithMisprints(actualWithMisprints, true /* withMisprints */);
|
||||
Utf8StreetTokensFilter filterWithoutMisprints(actualWithoutMisprints, false /* withMisprints */);
|
||||
filterWithMisprints.Put("улица", false /* isPrefix */, 0 /* tag */);
|
||||
filterWithoutMisprints.Put("улица", false /* isPrefix */, 0 /* tag */);
|
||||
filterWithMisprints.Put("набрежная", false /* isPrefix */, 1 /* tag */);
|
||||
filterWithoutMisprints.Put("набрежная", false /* isPrefix */, 1 /* tag */);
|
||||
|
||||
TEST_EQUAL(expected, actualWithMisprints, ());
|
||||
TEST_EQUAL(expected, actualWithoutMisprints, ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(NormalizeAndSimplifyString_Numero)
|
||||
{
|
||||
TEST_EQUAL(NormalizeAndSimplifyStringUtf8("Зона №51"), "зона #51", ());
|
||||
TEST_EQUAL(NormalizeAndSimplifyStringUtf8("Area № 51"), "area # 51", ());
|
||||
TEST_EQUAL(NormalizeAndSimplifyStringUtf8("Area #One"), "area #one", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(NormalizeAndSimplifyString_Apostrophe)
|
||||
{
|
||||
TEST_EQUAL(NormalizeAndSimplifyStringUtf8("Pop’s"), "pop's", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Steet_GetStreetNameAsKey)
|
||||
{
|
||||
auto const Check = [](std::string_view src, std::string_view expected)
|
||||
{ TEST_EQUAL(GetStreetNameAsKey(src, true /* ignoreStreetSynonyms */), strings::MakeUniString(expected), ()); };
|
||||
|
||||
{
|
||||
std::string_view const ethalon = "680northwest";
|
||||
Check("N 680 W", ethalon);
|
||||
Check("North 680 West", ethalon);
|
||||
Check("680 NW", ethalon);
|
||||
}
|
||||
|
||||
Check("North 20th Rd", "20thnorth");
|
||||
Check("Lane st", "lane st"); /// @todo Probably, doesn't matter here?
|
||||
Check("West North", "westnorth"); /// @todo Should order?
|
||||
Check("NW", "northwest");
|
||||
}
|
||||
|
||||
UNIT_TEST(Steet_GetNormalizedStreetName)
|
||||
{
|
||||
auto const Check = [](std::string_view s1, std::string_view s2)
|
||||
{ TEST_EQUAL(GetNormalizedStreetName(s1), GetNormalizedStreetName(s2), ()); };
|
||||
|
||||
Check("Lane G", "G Ln");
|
||||
Check("South Grapetree Road", "S Grape Tree Rd");
|
||||
Check("Peter's Farm Road", "Peters Farm Rd");
|
||||
Check("Farrelly - Soto Avenue", "Farrelly-Soto Ave");
|
||||
Check("2nd Loop South", "2nd Lp S");
|
||||
Check("Circle Street", "Circle St");
|
||||
Check("Rue de St. Anne", "Rue de St Anne");
|
||||
Check("St. Lucia Drive", "St Lucia Dr");
|
||||
Check("County Road 87", "Co Rd 87");
|
||||
Check("Mountain Vista", "Mtn Vis");
|
||||
Check("Scott's Trace", "Scotts Trce");
|
||||
Check("Inverness Cliffs Drive", "Inverness Clfs Dr");
|
||||
Check("Pine Crest Loop", "Pine Crst Lp");
|
||||
Check("8th Street North East", "N Eighth E St");
|
||||
Check("Black Creek Crossing", "Black Creek Xing");
|
||||
Check("Magruders Bluff", "Magruders Blf");
|
||||
Check("5th Avenue", "Fifth ave");
|
||||
Check("Northeast 26th Avenue", "NE 26th Ave");
|
||||
|
||||
/// @todo Fancy examples:
|
||||
// https://www.openstreetmap.org/way/1188750428
|
||||
// Check("East Ridge Road", "E Rdg");
|
||||
// Check("7th Street", "Sevens St");
|
||||
// https://www.openstreetmap.org/way/8605899
|
||||
// Check("Beaver Crest Drive", "Beaver Crst");
|
||||
// https://www.openstreetmap.org/way/8607254
|
||||
// Check("St Annes Drive", "Saint Annes Dr");
|
||||
// https://www.openstreetmap.org/way/7703018
|
||||
// Check("AL 60", "Al Highway 60");
|
||||
// https://www.openstreetmap.org/way/7705380
|
||||
// Seems like it means "Centerville Street" or "County Road 25"
|
||||
// Check("Centreville Street", "Centerville St Co Rd 25");
|
||||
// https://www.openstreetmap.org/way/23629713
|
||||
// Check("Northeast Martin Luther King Junior Boulevard", "NE M L King Blvd");
|
||||
}
|
||||
|
||||
} // namespace search_string_utils_test
|
||||
63
libs/indexer/indexer_tests/sort_and_merge_intervals_test.cpp
Normal file
63
libs/indexer/indexer_tests/sort_and_merge_intervals_test.cpp
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#include "indexer/feature_covering.hpp"
|
||||
#include "testing/testing.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
UNIT_TEST(SortAndMergeIntervals_1Interval)
|
||||
{
|
||||
vector<pair<int64_t, int64_t>> v;
|
||||
v.push_back(make_pair(1ULL, 2ULL));
|
||||
TEST_EQUAL(covering::SortAndMergeIntervals(v), v, ());
|
||||
}
|
||||
UNIT_TEST(SortAndMergeIntervals_2NotSortedNotOverlappin)
|
||||
{
|
||||
vector<pair<int64_t, int64_t>> v;
|
||||
v.push_back(make_pair(3ULL, 4ULL));
|
||||
v.push_back(make_pair(1ULL, 2ULL));
|
||||
vector<pair<int64_t, int64_t>> e;
|
||||
e.push_back(make_pair(1ULL, 2ULL));
|
||||
e.push_back(make_pair(3ULL, 4ULL));
|
||||
TEST_EQUAL(covering::SortAndMergeIntervals(v), e, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(SortAndMergeIntervals_BorderMerge)
|
||||
{
|
||||
vector<pair<int64_t, int64_t>> v;
|
||||
v.push_back(make_pair(1ULL, 2ULL));
|
||||
v.push_back(make_pair(2ULL, 3ULL));
|
||||
vector<pair<int64_t, int64_t>> e;
|
||||
e.push_back(make_pair(1ULL, 3ULL));
|
||||
TEST_EQUAL(covering::SortAndMergeIntervals(v), e, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(SortAndMergeIntervals_Overlap)
|
||||
{
|
||||
vector<pair<int64_t, int64_t>> v;
|
||||
v.push_back(make_pair(1ULL, 3ULL));
|
||||
v.push_back(make_pair(2ULL, 4ULL));
|
||||
vector<pair<int64_t, int64_t>> e;
|
||||
e.push_back(make_pair(1ULL, 4ULL));
|
||||
TEST_EQUAL(covering::SortAndMergeIntervals(v), e, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(SortAndMergeIntervals_Contain)
|
||||
{
|
||||
vector<pair<int64_t, int64_t>> v;
|
||||
v.push_back(make_pair(2ULL, 3ULL));
|
||||
v.push_back(make_pair(1ULL, 4ULL));
|
||||
vector<pair<int64_t, int64_t>> e;
|
||||
e.push_back(make_pair(1ULL, 4ULL));
|
||||
TEST_EQUAL(covering::SortAndMergeIntervals(v), e, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(SortAndMergeIntervals_ContainAndTouchBorder)
|
||||
{
|
||||
vector<pair<int64_t, int64_t>> v;
|
||||
v.push_back(make_pair(1ULL, 3ULL));
|
||||
v.push_back(make_pair(1ULL, 4ULL));
|
||||
vector<pair<int64_t, int64_t>> e;
|
||||
e.push_back(make_pair(1ULL, 4ULL));
|
||||
TEST_EQUAL(covering::SortAndMergeIntervals(v), e, ());
|
||||
}
|
||||
78
libs/indexer/indexer_tests/string_slice_tests.cpp
Normal file
78
libs/indexer/indexer_tests/string_slice_tests.cpp
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#include "../../testing/testing.hpp"
|
||||
|
||||
#include "indexer/string_slice.hpp"
|
||||
|
||||
#include "base/string_utils.hpp"
|
||||
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
using namespace search;
|
||||
using namespace std;
|
||||
using namespace strings;
|
||||
|
||||
namespace
|
||||
{
|
||||
UniString ToString(vector<UniString> const & v)
|
||||
{
|
||||
StringSlice slice(v);
|
||||
UniString r;
|
||||
copy(JoinIterator::Begin(slice), JoinIterator::End(slice), back_inserter(r));
|
||||
return r;
|
||||
}
|
||||
|
||||
UNIT_TEST(JoinIterator_Smoke)
|
||||
{
|
||||
{
|
||||
vector<UniString> v;
|
||||
|
||||
StringSlice slice1(v);
|
||||
auto begin1 = JoinIterator::Begin(slice1);
|
||||
auto end1 = JoinIterator::End(slice1);
|
||||
|
||||
StringSlice slice2(v);
|
||||
auto begin2 = JoinIterator::Begin(slice2);
|
||||
auto end2 = JoinIterator::End(slice2);
|
||||
|
||||
TEST(begin1 == end1, ());
|
||||
|
||||
TEST(begin2 == end2, ());
|
||||
|
||||
TEST(begin1 != begin2, ());
|
||||
TEST(end1 != end2, ());
|
||||
|
||||
TEST(begin1 != end2, ());
|
||||
TEST(begin2 != end1, ());
|
||||
}
|
||||
|
||||
{
|
||||
vector<UniString> const v;
|
||||
TEST_EQUAL(MakeUniString(""), ToString(v), ());
|
||||
}
|
||||
|
||||
{
|
||||
vector<UniString> const v = {MakeUniString("")};
|
||||
TEST_EQUAL(MakeUniString(""), ToString(v), ());
|
||||
}
|
||||
|
||||
{
|
||||
vector<UniString> const v = {MakeUniString(""), MakeUniString("")};
|
||||
TEST_EQUAL(MakeUniString(" "), ToString(v), ());
|
||||
}
|
||||
|
||||
{
|
||||
vector<UniString> const v = {MakeUniString(""), MakeUniString("b"), MakeUniString("")};
|
||||
TEST_EQUAL(MakeUniString(" b "), ToString(v), ());
|
||||
}
|
||||
|
||||
{
|
||||
vector<UniString> const v = {MakeUniString("Hello")};
|
||||
TEST_EQUAL(MakeUniString("Hello"), ToString(v), ());
|
||||
}
|
||||
|
||||
{
|
||||
vector<UniString> const v = {MakeUniString("Hello"), MakeUniString("World!")};
|
||||
TEST_EQUAL(MakeUniString("Hello World!"), ToString(v), ());
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
270
libs/indexer/indexer_tests/succinct_trie_test.cpp
Normal file
270
libs/indexer/indexer_tests/succinct_trie_test.cpp
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/writer.hpp"
|
||||
|
||||
#include "indexer/succinct_trie_builder.hpp"
|
||||
#include "indexer/succinct_trie_reader.hpp"
|
||||
#include "indexer/trie.hpp"
|
||||
#include "indexer/trie_builder.hpp"
|
||||
#include "indexer/trie_reader.hpp"
|
||||
|
||||
#include "base/string_utils.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct StringsFileEntryMock
|
||||
{
|
||||
StringsFileEntryMock() = default;
|
||||
StringsFileEntryMock(string const & key, uint8_t value) : m_key(key.begin(), key.end()), m_value(value) {}
|
||||
|
||||
trie::TrieChar const * GetKeyData() { return m_key.data(); }
|
||||
|
||||
size_t GetKeySize() const { return m_key.size(); }
|
||||
|
||||
uint8_t GetValue() const { return m_value; }
|
||||
void * value_data() const { return nullptr; }
|
||||
size_t value_size() const { return 0; }
|
||||
|
||||
void Swap(StringsFileEntryMock & o)
|
||||
{
|
||||
swap(m_key, o.m_key);
|
||||
swap(m_value, o.m_value);
|
||||
}
|
||||
|
||||
bool operator==(StringsFileEntryMock const & o) const { return m_key == o.m_key && m_value == o.m_value; }
|
||||
|
||||
bool operator<(StringsFileEntryMock const & o) const
|
||||
{
|
||||
if (m_key != o.m_key)
|
||||
return m_key < o.m_key;
|
||||
return m_value < o.m_value;
|
||||
}
|
||||
|
||||
vector<trie::TrieChar> m_key;
|
||||
uint8_t m_value;
|
||||
};
|
||||
|
||||
template <typename TWriter>
|
||||
struct EmptyValueList
|
||||
{
|
||||
size_t size() const { return 0; }
|
||||
void Dump(TWriter &) const {}
|
||||
void Append(int) {}
|
||||
};
|
||||
|
||||
struct EmptyValueReader
|
||||
{
|
||||
using ValueType = unsigned char;
|
||||
|
||||
EmptyValueReader() = default;
|
||||
|
||||
template <typename SourceT>
|
||||
void operator()(SourceT &, ValueType & value) const
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct SimpleValueReader
|
||||
{
|
||||
public:
|
||||
SimpleValueReader() = default;
|
||||
|
||||
using ValueType = uint8_t;
|
||||
|
||||
template <typename TReader>
|
||||
void operator()(TReader & reader, ValueType & v) const
|
||||
{
|
||||
v = ReadPrimitiveFromSource<uint8_t>(reader);
|
||||
}
|
||||
|
||||
template <class TWriter>
|
||||
void Save(TWriter & writer, ValueType const & v) const
|
||||
{
|
||||
WriteToSink(writer, v);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TWriter>
|
||||
struct SimpleValueList
|
||||
{
|
||||
size_t size() const { return m_valueList.size(); }
|
||||
|
||||
void Dump(TWriter & writer) const
|
||||
{
|
||||
for (uint8_t x : m_valueList)
|
||||
WriteToSink(writer, x);
|
||||
}
|
||||
|
||||
void Append(uint8_t x) { m_valueList.push_back(x); }
|
||||
|
||||
vector<uint8_t> m_valueList;
|
||||
};
|
||||
|
||||
using TSimpleIterator = trie::SuccinctTrieIterator<MemReader, SimpleValueReader>;
|
||||
|
||||
void ReadAllValues(TSimpleIterator & root, vector<uint8_t> & values)
|
||||
{
|
||||
for (size_t i = 0; i < root.NumValues(); ++i)
|
||||
values.push_back(root.GetValue(i));
|
||||
}
|
||||
|
||||
void CollectInSubtree(TSimpleIterator & root, vector<uint8_t> & collectedValues)
|
||||
{
|
||||
ReadAllValues(root, collectedValues);
|
||||
|
||||
if (auto l = root.GoToEdge(0))
|
||||
CollectInSubtree(*l, collectedValues);
|
||||
if (auto r = root.GoToEdge(1))
|
||||
CollectInSubtree(*r, collectedValues);
|
||||
}
|
||||
|
||||
template <typename TWriter>
|
||||
void BuildFromSimpleValueList(TWriter & writer, vector<StringsFileEntryMock> & data)
|
||||
{
|
||||
trie::BuildSuccinctTrie<TWriter, vector<StringsFileEntryMock>::iterator, SimpleValueList<TWriter>>(
|
||||
writer, data.begin(), data.end());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace trie
|
||||
{
|
||||
// todo(@pimenov): It may be worth it to write a test
|
||||
// for the trie's topology but the test may be flaky because
|
||||
// it has to depend on the particular Huffman encoding of the key strings.
|
||||
// This is remedied by separation of the string-encoding and trie-building
|
||||
// parts, but they are not separated now, hence there is no such test.
|
||||
|
||||
UNIT_TEST(SuccinctTrie_Serialization_Smoke1)
|
||||
{
|
||||
vector<uint8_t> buf;
|
||||
|
||||
using TWriter = MemWriter<vector<uint8_t>>;
|
||||
TWriter memWriter(buf);
|
||||
|
||||
vector<StringsFileEntryMock> data = {StringsFileEntryMock("abacaba", 1)};
|
||||
|
||||
trie::BuildSuccinctTrie<TWriter, vector<StringsFileEntryMock>::iterator, EmptyValueList<TWriter>>(
|
||||
memWriter, data.begin(), data.end());
|
||||
|
||||
MemReader memReader(buf.data(), buf.size());
|
||||
|
||||
auto trieRoot = trie::ReadSuccinctTrie(memReader, EmptyValueReader());
|
||||
TEST(trieRoot, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(SuccinctTrie_Serialization_Smoke2)
|
||||
{
|
||||
vector<uint8_t> buf;
|
||||
|
||||
using TWriter = MemWriter<vector<uint8_t>>;
|
||||
TWriter memWriter(buf);
|
||||
|
||||
vector<StringsFileEntryMock> data = {StringsFileEntryMock("abacaba", 1)};
|
||||
|
||||
BuildFromSimpleValueList(memWriter, data);
|
||||
|
||||
MemReader memReader(buf.data(), buf.size());
|
||||
|
||||
auto trieRoot = trie::ReadSuccinctTrie(memReader, SimpleValueReader());
|
||||
TEST(trieRoot, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(SuccinctTrie_Iterator)
|
||||
{
|
||||
vector<uint8_t> buf;
|
||||
|
||||
using TWriter = MemWriter<vector<uint8_t>>;
|
||||
TWriter memWriter(buf);
|
||||
|
||||
vector<StringsFileEntryMock> data = {StringsFileEntryMock("a", 1), StringsFileEntryMock("b", 2),
|
||||
StringsFileEntryMock("ab", 3), StringsFileEntryMock("ba", 4),
|
||||
StringsFileEntryMock("abc", 5)};
|
||||
sort(data.begin(), data.end());
|
||||
|
||||
BuildFromSimpleValueList(memWriter, data);
|
||||
|
||||
MemReader memReader(buf.data(), buf.size());
|
||||
|
||||
auto trieRoot = trie::ReadSuccinctTrie(memReader, SimpleValueReader());
|
||||
TEST(trieRoot, ());
|
||||
|
||||
vector<uint8_t> collectedValues;
|
||||
CollectInSubtree(*trieRoot, collectedValues);
|
||||
sort(collectedValues.begin(), collectedValues.end());
|
||||
TEST_EQUAL(collectedValues.size(), 5, ());
|
||||
for (size_t i = 0; i < collectedValues.size(); ++i)
|
||||
TEST_EQUAL(collectedValues[i], i + 1, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(SuccinctTrie_MoveToString)
|
||||
{
|
||||
vector<uint8_t> buf;
|
||||
|
||||
using TWriter = MemWriter<vector<uint8_t>>;
|
||||
TWriter memWriter(buf);
|
||||
|
||||
vector<StringsFileEntryMock> data = {StringsFileEntryMock("abcde", 1), StringsFileEntryMock("aaaaa", 2),
|
||||
StringsFileEntryMock("aaa", 3), StringsFileEntryMock("aaa", 4)};
|
||||
sort(data.begin(), data.end());
|
||||
|
||||
BuildFromSimpleValueList(memWriter, data);
|
||||
MemReader memReader(buf.data(), buf.size());
|
||||
|
||||
auto trieRoot = trie::ReadSuccinctTrie(memReader, SimpleValueReader());
|
||||
|
||||
{
|
||||
auto it = trieRoot->GoToString(strings::MakeUniString("a"));
|
||||
TEST(it != nullptr, ());
|
||||
vector<uint8_t> expectedValues;
|
||||
vector<uint8_t> receivedValues;
|
||||
ReadAllValues(*it.get(), receivedValues);
|
||||
TEST_EQUAL(expectedValues, receivedValues, ());
|
||||
}
|
||||
|
||||
{
|
||||
auto it = trieRoot->GoToString(strings::MakeUniString("abcde"));
|
||||
TEST(it != nullptr, ());
|
||||
vector<uint8_t> expectedValues{1};
|
||||
vector<uint8_t> receivedValues;
|
||||
ReadAllValues(*it.get(), receivedValues);
|
||||
TEST_EQUAL(expectedValues, receivedValues, ());
|
||||
}
|
||||
|
||||
{
|
||||
auto it = trieRoot->GoToString(strings::MakeUniString("aaaaa"));
|
||||
TEST(it != nullptr, ());
|
||||
vector<uint8_t> expectedValues{2};
|
||||
vector<uint8_t> receivedValues;
|
||||
ReadAllValues(*it.get(), receivedValues);
|
||||
TEST_EQUAL(expectedValues, receivedValues, ());
|
||||
}
|
||||
|
||||
{
|
||||
auto it = trieRoot->GoToString(strings::MakeUniString("aaa"));
|
||||
TEST(it != nullptr, ());
|
||||
vector<uint8_t> expectedValues{3, 4};
|
||||
vector<uint8_t> receivedValues;
|
||||
ReadAllValues(*it.get(), receivedValues);
|
||||
TEST_EQUAL(expectedValues, receivedValues, ());
|
||||
}
|
||||
|
||||
{
|
||||
auto it = trieRoot->GoToString(strings::MakeUniString("b"));
|
||||
TEST(it == nullptr, ());
|
||||
}
|
||||
|
||||
{
|
||||
auto it = trieRoot->GoToString(strings::MakeUniString("bbbbb"));
|
||||
TEST(it == nullptr, ());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace trie
|
||||
41
libs/indexer/indexer_tests/test_mwm_set.hpp
Normal file
41
libs/indexer/indexer_tests/test_mwm_set.hpp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#include "indexer/mwm_set.hpp"
|
||||
|
||||
#include "platform/country_file.hpp"
|
||||
#include "platform/local_country_file.hpp"
|
||||
#include "platform/mwm_version.hpp"
|
||||
|
||||
#include "geometry/rect2d.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
using platform::CountryFile;
|
||||
using platform::LocalCountryFile;
|
||||
|
||||
namespace tests
|
||||
{
|
||||
|
||||
class TestMwmSet : public MwmSet
|
||||
{
|
||||
protected:
|
||||
/// @name MwmSet overrides
|
||||
//@{
|
||||
std::unique_ptr<MwmInfo> CreateInfo(platform::LocalCountryFile const & localFile) const override
|
||||
{
|
||||
int const n = localFile.GetCountryName()[0] - '0';
|
||||
auto info = std::make_unique<MwmInfo>();
|
||||
info->m_maxScale = n;
|
||||
info->m_bordersRect = m2::RectD(0, 0, 1, 1);
|
||||
info->m_version.SetFormat(version::Format::lastFormat);
|
||||
return info;
|
||||
}
|
||||
|
||||
std::unique_ptr<MwmValue> CreateValue(MwmInfo & info) const override
|
||||
{
|
||||
return std::make_unique<MwmValue>(info.GetLocalFile());
|
||||
}
|
||||
//@}
|
||||
};
|
||||
|
||||
} // namespace tests
|
||||
46
libs/indexer/indexer_tests/test_type.cpp
Normal file
46
libs/indexer/indexer_tests/test_type.cpp
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/classificator.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
void check_values_array(uint8_t values[], uint8_t count)
|
||||
{
|
||||
uint32_t type = ftype::GetEmptyValue();
|
||||
|
||||
for (uint8_t i = 0; i < count; ++i)
|
||||
ftype::PushValue(type, values[i]);
|
||||
|
||||
for (uint8_t i = 0; i < count; ++i)
|
||||
TEST_EQUAL(ftype::GetValue(type, i), values[i], ());
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
TEST_EQUAL(ftype::GetLevel(type), count, ());
|
||||
ftype::PopValue(type);
|
||||
--count;
|
||||
}
|
||||
|
||||
TEST_EQUAL(ftype::GetLevel(type), 0, ());
|
||||
TEST_EQUAL(type, ftype::GetEmptyValue(), (type));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
UNIT_TEST(SetGetTypes)
|
||||
{
|
||||
uint8_t v1[] = {6, 30, 0, 1};
|
||||
check_values_array(v1, 4);
|
||||
check_values_array(v1, 3);
|
||||
|
||||
uint8_t v2[] = {0, 0, 0, 0};
|
||||
check_values_array(v2, 4);
|
||||
check_values_array(v2, 3);
|
||||
|
||||
uint8_t v3[] = {1, 1, 1, 1};
|
||||
check_values_array(v3, 4);
|
||||
check_values_array(v3, 3);
|
||||
|
||||
uint8_t v4[] = {63, 63, 63, 63};
|
||||
check_values_array(v4, 4);
|
||||
check_values_array(v4, 3);
|
||||
}
|
||||
196
libs/indexer/indexer_tests/tree_node_tests.cpp
Normal file
196
libs/indexer/indexer_tests/tree_node_tests.cpp
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/complex/tree_node.hpp"
|
||||
|
||||
#include "base/control_flow.hpp"
|
||||
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
decltype(auto) MakeTree()
|
||||
{
|
||||
auto tree1 = tree_node::MakeTreeNode(1);
|
||||
|
||||
auto node11 = tree_node::MakeTreeNode(21);
|
||||
tree_node::Link(tree_node::MakeTreeNode(31), node11);
|
||||
tree_node::Link(tree_node::MakeTreeNode(32), node11);
|
||||
tree_node::Link(tree_node::MakeTreeNode(33), node11);
|
||||
tree_node::Link(node11, tree1);
|
||||
tree_node::Link(tree_node::MakeTreeNode(34), tree1);
|
||||
|
||||
auto tree2 = tree_node::MakeTreeNode(22);
|
||||
tree_node::Link(tree_node::MakeTreeNode(35), tree2);
|
||||
tree_node::Link(tree_node::MakeTreeNode(36), tree2);
|
||||
tree_node::Link(tree2, tree1);
|
||||
return tree1;
|
||||
}
|
||||
|
||||
UNIT_TEST(TreeNode_PreOrderVisit)
|
||||
{
|
||||
auto const tree = MakeTree();
|
||||
std::vector<int> res;
|
||||
tree_node::PreOrderVisit(tree, [&](auto const & node) { res.emplace_back(node->GetData()); });
|
||||
std::vector<int> const expected = {1, 21, 31, 32, 33, 34, 22, 35, 36};
|
||||
TEST_EQUAL(res, expected, ());
|
||||
|
||||
auto countVisitedNode = 0;
|
||||
tree_node::PreOrderVisit(tree, [&](auto const & node)
|
||||
{
|
||||
++countVisitedNode;
|
||||
return node->GetData() == 32 ? base::ControlFlow::Break : base::ControlFlow::Continue;
|
||||
});
|
||||
TEST_EQUAL(countVisitedNode, 4, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TreeNode_Size)
|
||||
{
|
||||
auto const tree = MakeTree();
|
||||
auto const size = tree_node::Size(tree);
|
||||
TEST_EQUAL(size, 9, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TreeNode_FindIf)
|
||||
{
|
||||
auto const tree = MakeTree();
|
||||
auto node = tree_node::FindIf(tree, [](auto const & d) { return d == 1; });
|
||||
TEST(node, ());
|
||||
|
||||
node = tree_node::FindIf(tree, [](auto const & d) { return d == 22; });
|
||||
TEST(node, ());
|
||||
|
||||
node = tree_node::FindIf(tree, [](auto const & d) { return d == 36; });
|
||||
TEST(node, ());
|
||||
|
||||
node = tree_node::FindIf(tree, [](auto const & d) { return d == 100; });
|
||||
TEST(!node, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TreeNode_GetDepth)
|
||||
{
|
||||
auto const tree = MakeTree();
|
||||
auto depth = tree_node::GetDepth(tree_node::FindIf(tree, [](auto const & d) { return d == 1; }));
|
||||
TEST_EQUAL(depth, 1, ());
|
||||
|
||||
depth = tree_node::GetDepth(tree_node::FindIf(tree, [](auto const & d) { return d == 22; }));
|
||||
TEST_EQUAL(depth, 2, ());
|
||||
|
||||
depth = tree_node::GetDepth(tree_node::FindIf(tree, [](auto const & d) { return d == 36; }));
|
||||
TEST_EQUAL(depth, 3, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TreeNode_GetRoot)
|
||||
{
|
||||
auto const tree = MakeTree();
|
||||
auto const node22 = tree_node::FindIf(tree, [](auto const & d) { return d == 22; });
|
||||
auto const root = tree_node::GetRoot(node22);
|
||||
TEST(tree, ());
|
||||
TEST_EQUAL(tree->GetData(), root->GetData(), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TreeNode_GetPath)
|
||||
{
|
||||
auto const tree = MakeTree();
|
||||
auto const node33 = tree_node::FindIf(tree, [](auto const & d) { return d == 33; });
|
||||
auto const path = tree_node::GetPathToRoot(node33);
|
||||
tree_node::types::Ptrs<int> expected = {tree_node::FindIf(tree, [](auto const & d) { return d == 33; }),
|
||||
tree_node::FindIf(tree, [](auto const & d) { return d == 21; }),
|
||||
tree_node::FindIf(tree, [](auto const & d) { return d == 1; })};
|
||||
TEST_EQUAL(path, expected, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TreeNode_IsEqual)
|
||||
{
|
||||
auto tree1 = tree_node::MakeTreeNode(1);
|
||||
auto node11 = tree_node::MakeTreeNode(21);
|
||||
tree_node::Link(tree_node::MakeTreeNode(31), node11);
|
||||
tree_node::Link(tree_node::MakeTreeNode(32), node11);
|
||||
tree_node::Link(tree_node::MakeTreeNode(33), node11);
|
||||
tree_node::Link(node11, tree1);
|
||||
|
||||
TEST(tree_node::IsEqual(tree1, tree1), ());
|
||||
TEST(!tree_node::IsEqual(tree1, node11), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TreeNode_TransformToTree)
|
||||
{
|
||||
auto const tree = MakeTree();
|
||||
auto const newTree = tree_node::TransformToTree(tree, [](auto const & data) { return std::to_string(data); });
|
||||
|
||||
auto expected = tree_node::MakeTreeNode<std::string>("1");
|
||||
auto node11 = tree_node::MakeTreeNode<std::string>("21");
|
||||
tree_node::Link(tree_node::MakeTreeNode<std::string>("31"), node11);
|
||||
tree_node::Link(tree_node::MakeTreeNode<std::string>("32"), node11);
|
||||
tree_node::Link(tree_node::MakeTreeNode<std::string>("33"), node11);
|
||||
tree_node::Link(node11, expected);
|
||||
tree_node::Link(tree_node::MakeTreeNode<std::string>("34"), expected);
|
||||
|
||||
auto tree2 = tree_node::MakeTreeNode<std::string>("22");
|
||||
tree_node::Link(tree_node::MakeTreeNode<std::string>("35"), tree2);
|
||||
tree_node::Link(tree_node::MakeTreeNode<std::string>("36"), tree2);
|
||||
tree_node::Link(tree2, expected);
|
||||
|
||||
TEST(tree_node::IsEqual(newTree, expected), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TreeNode_CountIf)
|
||||
{
|
||||
auto const tree = MakeTree();
|
||||
auto const count = tree_node::CountIf(tree, [](auto const & data) { return data >= 30; });
|
||||
TEST_EQUAL(count, 6, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TreeNode_DebugPrint)
|
||||
{
|
||||
auto const tree = MakeTree();
|
||||
LOG(LINFO, (tree_node::DebugPrint(tree)));
|
||||
}
|
||||
|
||||
UNIT_TEST(TreeNode_Forest)
|
||||
{
|
||||
tree_node::Forest<int> forest;
|
||||
std::set<tree_node::types::Ptr<int>> s = {MakeTree(), tree_node::MakeTreeNode(10)};
|
||||
for (auto const & tree : s)
|
||||
forest.Append(tree);
|
||||
|
||||
TEST_EQUAL(forest.Size(), 2, ());
|
||||
forest.ForEachTree([&](auto const & tree)
|
||||
{
|
||||
auto const count = s.erase(tree);
|
||||
TEST_EQUAL(count, 1, ());
|
||||
});
|
||||
TEST(s.empty(), ());
|
||||
|
||||
auto const copy = forest;
|
||||
TEST_EQUAL(copy, forest, ());
|
||||
|
||||
tree_node::Forest<int> empty;
|
||||
TEST_NOT_EQUAL(empty, forest, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TreeNode_ForestFindIf)
|
||||
{
|
||||
tree_node::Forest<int> forest;
|
||||
forest.Append(MakeTree());
|
||||
forest.Append(tree_node::MakeTreeNode(100));
|
||||
auto const node33 = tree_node::FindIf(forest, [](auto const & d) { return d == 33; });
|
||||
TEST(node33, ());
|
||||
TEST_EQUAL(node33->GetData(), 33, ());
|
||||
|
||||
auto const node100 = tree_node::FindIf(forest, [](auto const & d) { return d == 100; });
|
||||
TEST(node100, ());
|
||||
TEST_EQUAL(node100->GetData(), 100, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TreeNode_ForestDebugPrint)
|
||||
{
|
||||
tree_node::Forest<int> forest;
|
||||
forest.Append(MakeTree());
|
||||
forest.Append(tree_node::MakeTreeNode(100));
|
||||
forest.Append(tree_node::MakeTreeNode(200));
|
||||
LOG(LINFO, (tree_node::DebugPrint(forest)));
|
||||
}
|
||||
} // namespace
|
||||
285
libs/indexer/indexer_tests/trie_test.cpp
Normal file
285
libs/indexer/indexer_tests/trie_test.cpp
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/trie.hpp"
|
||||
#include "indexer/trie_builder.hpp"
|
||||
#include "indexer/trie_reader.hpp"
|
||||
|
||||
#include "coding/byte_stream.hpp"
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/write_to_sink.hpp"
|
||||
|
||||
#include "base/logging.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/utility/binary.hpp>
|
||||
|
||||
namespace trie_test
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
struct ChildNodeInfo
|
||||
{
|
||||
ChildNodeInfo(bool isLeaf, uint32_t size, char const * edge) : m_isLeaf(isLeaf), m_size(size)
|
||||
{
|
||||
while (*edge)
|
||||
m_edge.push_back(*edge++);
|
||||
}
|
||||
|
||||
uint32_t Size() const { return m_size; }
|
||||
bool IsLeaf() const { return m_isLeaf; }
|
||||
trie::TrieChar const * GetEdge() const { return &m_edge[0]; }
|
||||
size_t GetEdgeSize() const { return m_edge.size(); }
|
||||
|
||||
bool m_isLeaf;
|
||||
uint32_t m_size;
|
||||
vector<trie::TrieChar> m_edge;
|
||||
};
|
||||
|
||||
// The SingleValueSerializer and ValueList classes are similar to
|
||||
// those in indexer/search_index_values.hpp.
|
||||
template <typename Primitive>
|
||||
class SingleValueSerializer
|
||||
{
|
||||
public:
|
||||
#if !defined(OMIM_OS_LINUX)
|
||||
static_assert(std::is_trivially_copyable<Primitive>::value, "");
|
||||
#endif
|
||||
|
||||
template <typename Sink>
|
||||
void Serialize(Sink & sink, Primitive const & v) const
|
||||
{
|
||||
WriteToSink(sink, v);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Primitive>
|
||||
class ValueList
|
||||
{
|
||||
public:
|
||||
using Value = Primitive;
|
||||
using Serializer = SingleValueSerializer<Value>;
|
||||
|
||||
#if !defined(OMIM_OS_LINUX)
|
||||
static_assert(std::is_trivially_copyable<Primitive>::value, "");
|
||||
#endif
|
||||
|
||||
void Init(vector<Value> const & values) { m_values = values; }
|
||||
|
||||
size_t Size() const { return m_values.size(); }
|
||||
|
||||
bool IsEmpty() const { return m_values.empty(); }
|
||||
|
||||
template <typename Sink>
|
||||
void Serialize(Sink & sink, Serializer const & /* serializer */) const
|
||||
{
|
||||
for (auto const & value : m_values)
|
||||
WriteToSink(sink, value);
|
||||
}
|
||||
|
||||
template <typename Source>
|
||||
void Deserialize(Source & src, uint32_t valueCount, Serializer const & /* serializer */)
|
||||
{
|
||||
m_values.resize(valueCount);
|
||||
for (size_t i = 0; i < valueCount; ++i)
|
||||
m_values[i] = ReadPrimitiveFromSource<Value>(src);
|
||||
}
|
||||
|
||||
template <typename Source>
|
||||
void Deserialize(Source & source, Serializer const & /* serializer */)
|
||||
{
|
||||
m_values.clear();
|
||||
while (source.Size() > 0)
|
||||
m_values.emplace_back(ReadPrimitiveFromSource<Value>(source));
|
||||
}
|
||||
|
||||
template <typename ToDo>
|
||||
void ForEach(ToDo && toDo) const
|
||||
{
|
||||
for (auto const & value : m_values)
|
||||
toDo(value);
|
||||
}
|
||||
|
||||
private:
|
||||
vector<Value> m_values;
|
||||
};
|
||||
|
||||
#define ZENC bits::ZigZagEncode
|
||||
#define MKSC(x) static_cast<signed char>(x)
|
||||
#define MKUC(x) static_cast<uint8_t>(x)
|
||||
|
||||
UNIT_TEST(TrieBuilder_WriteNode_Smoke)
|
||||
{
|
||||
vector<uint8_t> buf;
|
||||
PushBackByteSink<vector<uint8_t>> sink(buf);
|
||||
ChildNodeInfo children[] = {
|
||||
ChildNodeInfo(true, 1, "1A"), ChildNodeInfo(false, 2, "B"), ChildNodeInfo(false, 3, "zz"),
|
||||
ChildNodeInfo(true, 4, "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij"),
|
||||
ChildNodeInfo(true, 5, "a")};
|
||||
|
||||
ValueList<char> valueList;
|
||||
valueList.Init({'1', '2', '3'});
|
||||
trie::WriteNode(sink, SingleValueSerializer<char>(), 0, valueList, &children[0], &children[0] + ARRAY_SIZE(children));
|
||||
uint8_t const expected[] = {
|
||||
BOOST_BINARY(11000101), // Header: [0b11] [0b000101]
|
||||
3, // Number of values
|
||||
'1',
|
||||
'2',
|
||||
'3', // Values
|
||||
BOOST_BINARY(10000001), // Child 1: header: [+leaf] [-supershort] [2 symbols]
|
||||
MKUC(ZENC(MKSC('1'))),
|
||||
MKUC(ZENC(MKSC('A') - MKSC('1'))), // Child 1: edge
|
||||
1, // Child 1: size
|
||||
MKUC(64 | ZENC(MKSC('B') - MKSC('1'))), // Child 2: header: [-leaf] [+supershort]
|
||||
2, // Child 2: size
|
||||
BOOST_BINARY(00000001), // Child 3: header: [-leaf] [-supershort] [2 symbols]
|
||||
MKUC(ZENC(MKSC('z') - MKSC('B'))),
|
||||
0, // Child 3: edge
|
||||
3, // Child 3: size
|
||||
BOOST_BINARY(10111111), // Child 4: header: [+leaf] [-supershort] [>= 63 symbols]
|
||||
69, // Child 4: edgeSize - 1
|
||||
MKUC(ZENC(MKSC('a') - MKSC('z'))),
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2, // Child 4: edge
|
||||
MKUC(ZENC(MKSC('a') - MKSC('j'))),
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2, // Child 4: edge
|
||||
MKUC(ZENC(MKSC('a') - MKSC('j'))),
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2, // Child 4: edge
|
||||
MKUC(ZENC(MKSC('a') - MKSC('j'))),
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2, // Child 4: edge
|
||||
MKUC(ZENC(MKSC('a') - MKSC('j'))),
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2, // Child 4: edge
|
||||
MKUC(ZENC(MKSC('a') - MKSC('j'))),
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2, // Child 4: edge
|
||||
MKUC(ZENC(MKSC('a') - MKSC('j'))),
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2, // Child 4: edge
|
||||
4, // Child 4: size
|
||||
MKUC(BOOST_BINARY(11000000) | ZENC(0)), // Child 5: header: [+leaf] [+supershort]
|
||||
};
|
||||
|
||||
TEST_EQUAL(buf, vector<uint8_t>(&expected[0], &expected[0] + ARRAY_SIZE(expected)), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TrieBuilder_Build)
|
||||
{
|
||||
uint32_t const kBase = 3;
|
||||
int const kMaxLen = 3;
|
||||
|
||||
vector<string> possibleStrings(1, string{});
|
||||
for (int len = 1; len <= kMaxLen; ++len)
|
||||
{
|
||||
for (uint32_t i = 0, p = math::PowUint(kBase, len); i < p; ++i)
|
||||
{
|
||||
string s(len, 'A');
|
||||
uint32_t t = i;
|
||||
for (int l = len - 1; l >= 0; --l, t /= kBase)
|
||||
s[l] += (t % kBase);
|
||||
possibleStrings.push_back(s);
|
||||
}
|
||||
}
|
||||
sort(possibleStrings.begin(), possibleStrings.end());
|
||||
// LOG(LINFO, (possibleStrings));
|
||||
|
||||
int const count = static_cast<int>(possibleStrings.size());
|
||||
for (int i0 = -1; i0 < count; ++i0)
|
||||
{
|
||||
for (int i1 = i0; i1 < count; ++i1)
|
||||
{
|
||||
for (int i2 = i1; i2 < count; ++i2)
|
||||
{
|
||||
using Key = buffer_vector<trie::TrieChar, 8>;
|
||||
using Value = uint32_t;
|
||||
using KeyValuePair = pair<Key, Value>;
|
||||
|
||||
vector<KeyValuePair> v;
|
||||
auto makeKey = [](string const & s) { return Key(s.begin(), s.end()); };
|
||||
if (i0 >= 0)
|
||||
v.emplace_back(makeKey(possibleStrings[i0]), i0);
|
||||
if (i1 >= 0)
|
||||
v.emplace_back(makeKey(possibleStrings[i1]), i1 + 10);
|
||||
if (i2 >= 0)
|
||||
v.emplace_back(makeKey(possibleStrings[i2]), i2 + 100);
|
||||
vector<string> vs;
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
vs.push_back(string(v[i].first.begin(), v[i].first.end()));
|
||||
|
||||
vector<uint8_t> buf;
|
||||
PushBackByteSink<vector<uint8_t>> sink(buf);
|
||||
SingleValueSerializer<uint32_t> serializer;
|
||||
trie::Build<PushBackByteSink<vector<uint8_t>>, Key, ValueList<uint32_t>, SingleValueSerializer<uint32_t>>(
|
||||
sink, serializer, v);
|
||||
reverse(buf.begin(), buf.end());
|
||||
|
||||
MemReader memReader = MemReader(&buf[0], buf.size());
|
||||
auto const root = trie::ReadTrie<MemReader, ValueList<uint32_t>>(memReader, serializer);
|
||||
vector<KeyValuePair> res;
|
||||
auto addKeyValuePair = [&res](Key const & k, Value const & v) { res.emplace_back(k, v); };
|
||||
trie::ForEachRef(*root, addKeyValuePair, Key{});
|
||||
sort(res.begin(), res.end());
|
||||
TEST_EQUAL(v, res, ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace trie_test
|
||||
367
libs/indexer/indexer_tests/validate_and_format_contacts_test.cpp
Normal file
367
libs/indexer/indexer_tests/validate_and_format_contacts_test.cpp
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/validate_and_format_contacts.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateAndFormat_facebook)
|
||||
{
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook(""), "", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("facebook.com/OpenStreetMap"), "OpenStreetMap", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("www.facebook.com/OpenStreetMap"), "OpenStreetMap", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("www.facebook.fr/OpenStreetMap"), "OpenStreetMap", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("http://facebook.com/OpenStreetMap"), "OpenStreetMap", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("https://facebook.com/OpenStreetMap"), "OpenStreetMap", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("http://www.facebook.com/OpenStreetMap"), "OpenStreetMap", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("https://www.facebook.com/OpenStreetMap"), "OpenStreetMap", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("https://de-de.facebook.de/Open_Street_Map"), "Open_Street_Map", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("https://en-us.facebook.com/OpenStreetMap"), "OpenStreetMap", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("https://de-de.facebook.com/profile.php?id=100085707580841"),
|
||||
"100085707580841", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("http://facebook.com/profile.php?share=app&id=100086487430889#m"),
|
||||
"100086487430889", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("some.good.page"), "some.good.page", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("@tree-house-interiors"), "tree-house-interiors", ());
|
||||
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("instagram.com/openstreetmapus"), "", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("https://instagram.com/openstreetmapus"), "", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("osm"), "", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("@spaces are not welcome here"), "", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_facebook("spaces are not welcome here"), "", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateAndFormat_instagram)
|
||||
{
|
||||
TEST_EQUAL(osm::ValidateAndFormat_instagram(""), "", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_instagram("instagram.com/openstreetmapus"), "openstreetmapus", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_instagram("www.instagram.com/openstreetmapus"), "openstreetmapus", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_instagram("http://instagram.com/openstreetmapus"), "openstreetmapus", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_instagram("https://instagram.com/openstreetmapus"), "openstreetmapus", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_instagram("http://www.instagram.com/openstreetmapus"), "openstreetmapus", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_instagram("https://www.instagram.com/openstreetmapus"), "openstreetmapus", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_instagram("https://en-us.instagram.com/openstreetmapus"), "openstreetmapus", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_instagram("@open_street_map_us"), "open_street_map_us", ());
|
||||
TEST_EQUAL(
|
||||
osm::ValidateAndFormat_instagram("https://www.instagram.com/explore/locations/358536820/trivium-sport-en-dance/"),
|
||||
"explore/locations/358536820/trivium-sport-en-dance", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_instagram("https://www.instagram.com/p/BvkgKZNDbqN/?ghid=UwPchX7B"),
|
||||
"p/BvkgKZNDbqN", ());
|
||||
|
||||
TEST_EQUAL(osm::ValidateAndFormat_instagram("facebook.com/osm_us"), "", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_instagram(".dots_not_allowed."), "", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_instagram("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), "", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateAndFormat_twitter)
|
||||
{
|
||||
TEST_EQUAL(osm::ValidateAndFormat_twitter("twitter.com/osm_tech"), "osm_tech", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_twitter("www.twitter.com/osm_tech"), "osm_tech", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_twitter("http://twitter.com/osm_tech"), "osm_tech", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_twitter("https://twitter.com/osm_tech"), "osm_tech", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_twitter("http://www.twitter.com/osm_tech"), "osm_tech", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_twitter("https://www.twitter.com/osm_tech"), "osm_tech", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_twitter("@_osm_tech_"), "_osm_tech_", ());
|
||||
|
||||
TEST_EQUAL(osm::ValidateAndFormat_twitter("instagram.com/osm_tech"), "", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_twitter("dots.not.allowed"), "", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_twitter("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), "", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateAndFormat_vk)
|
||||
{
|
||||
TEST_EQUAL(osm::ValidateAndFormat_vk("vk.com/id404"), "id404", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_vk("vkontakte.ru/id4321"), "id4321", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_vk("www.vkontakte.ru/id43210"), "id43210", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_vk("www.vk.com/id404"), "id404", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_vk("http://vk.com/ozon"), "ozon", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_vk("https://vk.com/sklad169"), "sklad169", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_vk("https://vkontakte.ru/id4321"), "id4321", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_vk("https://www.vkontakte.ru/id4321"), "id4321", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_vk("http://www.vk.com/ugona.net.expert"), "ugona.net.expert", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_vk("https://www.vk.com/7cvetov18"), "7cvetov18", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_vk("https://www.vk.com/7cvetov18/"), "7cvetov18", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_vk("@22ab.cdef"), "22ab.cdef", ());
|
||||
|
||||
TEST_EQUAL(osm::ValidateAndFormat_vk("instagram.com/hello_world"), "", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateAndFormat_contactLine)
|
||||
{
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("http://line.me/ti/p/mzog4fnz24"), "mzog4fnz24", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("https://line.me/ti/p/xnv0g02rws"), "xnv0g02rws", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("https://line.me/ti/p/@dgxs9r6wad"), "dgxs9r6wad", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("https://line.me/ti/p/%40vne5uwke17"), "vne5uwke17", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("http://line.me/R/ti/p/bfsg1a8x9u"), "bfsg1a8x9u", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("line.me/R/ti/p/bfsg1a8x9u"), "bfsg1a8x9u", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("https://line.me/R/ti/p/gdltt7s380"), "gdltt7s380", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("https://line.me/R/ti/p/@sdb2pb3lsg"), "sdb2pb3lsg", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("https://line.me/R/ti/p/%40b30h5mdj11"), "b30h5mdj11", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("http://line.me/R/home/public/main?id=hmczqsbav5"), "hmczqsbav5", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("https://line.me/R/home/public/main?id=wa1gvx91jb"), "wa1gvx91jb", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("http://line.me/R/home/public/profile?id=5qll5dyqqu"), "5qll5dyqqu",
|
||||
());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("https://line.me/R/home/public/profile?id=r90ck7n1rq"), "r90ck7n1rq",
|
||||
());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("https://line.me/R/home/public/profile?id=r90ck7n1rq"), "r90ck7n1rq",
|
||||
());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("https://page.line.me/fom5198h"), "fom5198h", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("https://page.line.me/qn58n8g?web=mobile"), "qn58n8g", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("https://page.line.me/?accountId=673watcr"), "673watcr", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("page.line.me/?accountId=673watcr"), "673watcr", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("https://liff.line.me/1645278921-kWRPP32q/?accountId=673watcr"),
|
||||
"liff.line.me/1645278921-kWRPP32q/?accountId=673watcr", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("https://abc.line.me/en/some/page?id=xaladqv"),
|
||||
"abc.line.me/en/some/page?id=xaladqv", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("@abcd"), "abcd", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("@-hyphen-test-"), "-hyphen-test-", ());
|
||||
|
||||
TEST_EQUAL(osm::ValidateAndFormat_contactLine("https://line.com/ti/p/invalid-domain"), "", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateAndFormat_fediverse)
|
||||
{
|
||||
TEST_EQUAL(osm::ValidateAndFormat_fediverse("https://floss.social/@comaps"), "comaps@floss.social", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_fediverse("https://floss.social/users/comaps"), "comaps@floss.social", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_fediverse("http://floss.social/users/comaps"), "comaps@floss.social", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_fediverse("floss.social/users/comaps"), "comaps@floss.social", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_fediverse("comaps@floss.social"), "comaps@floss.social", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_fediverse("@comaps@floss.social"), "comaps@floss.social", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_fediverse("@comaps@floss.social.uk"), "comaps@floss.social.uk", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_fediverse("pub.mastodon.org.uk/@comaps"), "comaps@pub.mastodon.org.uk", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_fediverse("pub.mastodon.org.uk/users/@comaps"), "comaps@pub.mastodon.org.uk", ());
|
||||
|
||||
TEST_EQUAL(osm::ValidateAndFormat_fediverse("comaps@fosstodon@mastodon.org"), "", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_fediverse("co$maps@mastodon.social"), "", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_fediverse("pub.mastodon.org.uk/comaps"), "", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_fediverse("pub.mastodon.org.uk/users/"), "", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateAndFormat_bluesky)
|
||||
{
|
||||
TEST_EQUAL(osm::ValidateAndFormat_bluesky("comaps.bsky.social"), "comaps.bsky.social", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_bluesky("@comaps.bsky.social"), "comaps.bsky.social", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_bluesky("https://bsky.app/profile/comaps.bsky.social"), "comaps.bsky.social", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_bluesky("https://bsky.app/profile/@comaps.bsky.social"), "comaps.bsky.social", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_bluesky("http://bsky.app/profile/comaps.bsky.social"), "comaps.bsky.social", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_bluesky("bsky.app/profile/comaps.bsky.social"), "comaps.bsky.social", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_bluesky("https://bsky.app/profile/comaps.bsky.social"), "comaps.bsky.social", ());
|
||||
|
||||
TEST_EQUAL(osm::ValidateAndFormat_bluesky("https://bsky.app/profile/comap$.bsky.social"), "", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_bluesky("https://bsky.app/profile/comaps.bsky.social$"), "", ());
|
||||
TEST_EQUAL(osm::ValidateAndFormat_bluesky("https://bsky.app/pineapple/comaps.bsky.social"), "", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateFacebookPage)
|
||||
{
|
||||
TEST(osm::ValidateFacebookPage(""), ());
|
||||
TEST(osm::ValidateFacebookPage("facebook.com/OpenStreetMap"), ());
|
||||
TEST(osm::ValidateFacebookPage("www.facebook.com/OpenStreetMap"), ());
|
||||
TEST(osm::ValidateFacebookPage("www.facebook.fr/OpenStreetMap"), ());
|
||||
TEST(osm::ValidateFacebookPage("http://facebook.com/OpenStreetMap"), ());
|
||||
TEST(osm::ValidateFacebookPage("https://facebook.com/OpenStreetMap"), ());
|
||||
TEST(osm::ValidateFacebookPage("http://www.facebook.com/OpenStreetMap"), ());
|
||||
TEST(osm::ValidateFacebookPage("https://www.facebook.com/OpenStreetMap"), ());
|
||||
TEST(osm::ValidateFacebookPage("https://de-de.facebook.de/OpenStreetMap"), ());
|
||||
TEST(osm::ValidateFacebookPage("https://en-us.facebook.com/OpenStreetMap"), ());
|
||||
TEST(osm::ValidateFacebookPage("https://www.facebook.com/profile.php?id=100085707580841"), ());
|
||||
TEST(osm::ValidateFacebookPage("OpenStreetMap"), ());
|
||||
TEST(osm::ValidateFacebookPage("some.good.page"), ());
|
||||
TEST(osm::ValidateFacebookPage("Quaama-Volunteer-Bushfire-Brigade-526790054021506"), ());
|
||||
TEST(osm::ValidateFacebookPage("Páter-Bonifác-Restaurant-Budapest-111001693867133"), ());
|
||||
TEST(osm::ValidateFacebookPage("MÊGÅ--CÄFË-3141592653589793"), ());
|
||||
TEST(osm::ValidateFacebookPage("ресторан"), ()); // Cyrillic
|
||||
TEST(osm::ValidateFacebookPage("საქართველო"), ()); // Georgian
|
||||
TEST(osm::ValidateFacebookPage("日本語"), ()); // Japanese
|
||||
TEST(osm::ValidateFacebookPage("@tree-house-interiors"), ());
|
||||
TEST(osm::ValidateFacebookPage("allow_underscore-1234567890"), ());
|
||||
TEST(osm::ValidateFacebookPage("alexander.net"), ());
|
||||
|
||||
TEST(!osm::ValidateFacebookPage("instagram.com/openstreetmapus"), ());
|
||||
TEST(!osm::ValidateFacebookPage("https://instagram.com/openstreetmapus"), ());
|
||||
TEST(!osm::ValidateFacebookPage("osm"), ());
|
||||
TEST(!osm::ValidateFacebookPage("@spaces are not welcome here"), ());
|
||||
TEST(!osm::ValidateFacebookPage("spaces are not welcome here"), ());
|
||||
|
||||
constexpr char kForbiddenFBSymbols[] = " !@^*()~[]{}#$%&;,:+\"'/\\";
|
||||
for (size_t i = 0; i < std::size(kForbiddenFBSymbols) - 1; i++)
|
||||
{
|
||||
auto test_str = std::string("special-symbol-") + kForbiddenFBSymbols[i] + "-forbidden";
|
||||
TEST(!osm::ValidateFacebookPage(test_str), (test_str));
|
||||
}
|
||||
|
||||
// Symbols "£€¥" are not allowed, but to check such cases it requires unicode magic. Not supported currently.
|
||||
// TODO: find all restricted *Unicode* symbols from https://www.facebook.com/pages/create page
|
||||
// and them to the test
|
||||
// TEST(!osm::ValidateFacebookPage(u8"you-shall-not-pass-£€¥"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateInstagramPage)
|
||||
{
|
||||
TEST(osm::ValidateInstagramPage(""), ());
|
||||
TEST(osm::ValidateInstagramPage("instagram.com/openstreetmapus"), ());
|
||||
TEST(osm::ValidateInstagramPage("www.instagram.com/openstreetmapus"), ());
|
||||
TEST(osm::ValidateInstagramPage("http://instagram.com/openstreetmapus"), ());
|
||||
TEST(osm::ValidateInstagramPage("https://instagram.com/openstreetmapus"), ());
|
||||
TEST(osm::ValidateInstagramPage("http://www.instagram.com/openstreetmapus"), ());
|
||||
TEST(osm::ValidateInstagramPage("https://www.instagram.com/openstreetmapus"), ());
|
||||
TEST(osm::ValidateInstagramPage("https://en-us.instagram.com/openstreetmapus"), ());
|
||||
TEST(osm::ValidateInstagramPage("openstreetmapus"), ());
|
||||
TEST(osm::ValidateInstagramPage("open.street.map.us"), ());
|
||||
TEST(osm::ValidateInstagramPage("open_street_map_us"), ());
|
||||
TEST(osm::ValidateInstagramPage("@open_street_map_us"), ());
|
||||
TEST(osm::ValidateInstagramPage("_osm_"), ());
|
||||
|
||||
TEST(!osm::ValidateInstagramPage("facebook.com/osm_us"), ());
|
||||
TEST(!osm::ValidateInstagramPage("https://facebook.com/osm_us"), ());
|
||||
TEST(!osm::ValidateInstagramPage(".osm"), ());
|
||||
TEST(!osm::ValidateInstagramPage("osm."), ());
|
||||
TEST(!osm::ValidateInstagramPage(".dots_not_allowed."), ());
|
||||
TEST(!osm::ValidateInstagramPage("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateTwitterPage)
|
||||
{
|
||||
TEST(osm::ValidateTwitterPage(""), ());
|
||||
TEST(osm::ValidateTwitterPage("twitter.com/osm_tech"), ());
|
||||
TEST(osm::ValidateTwitterPage("www.twitter.com/osm_tech"), ());
|
||||
TEST(osm::ValidateTwitterPage("http://twitter.com/osm_tech"), ());
|
||||
TEST(osm::ValidateTwitterPage("https://twitter.com/osm_tech"), ());
|
||||
TEST(osm::ValidateTwitterPage("http://www.twitter.com/osm_tech"), ());
|
||||
TEST(osm::ValidateTwitterPage("https://www.twitter.com/osm_tech"), ());
|
||||
TEST(osm::ValidateTwitterPage("osm_tech"), ());
|
||||
TEST(osm::ValidateTwitterPage("_osm_tech_"), ());
|
||||
TEST(osm::ValidateTwitterPage("@_osm_tech_"), ());
|
||||
TEST(osm::ValidateTwitterPage("1"), ());
|
||||
|
||||
TEST(!osm::ValidateTwitterPage("instagram.com/osm_tech"), ());
|
||||
TEST(!osm::ValidateTwitterPage("https://instagram.com/osm_tech"), ());
|
||||
TEST(!osm::ValidateTwitterPage("dots.not.allowed"), ());
|
||||
TEST(!osm::ValidateTwitterPage("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateVkPage)
|
||||
{
|
||||
TEST(osm::ValidateVkPage(""), ());
|
||||
TEST(osm::ValidateVkPage("vk.com/id404"), ());
|
||||
TEST(osm::ValidateVkPage("vkontakte.ru/id404"), ());
|
||||
TEST(osm::ValidateVkPage("www.vk.com/id404"), ());
|
||||
TEST(osm::ValidateVkPage("http://vk.com/id404"), ());
|
||||
TEST(osm::ValidateVkPage("https://vk.com/id404"), ());
|
||||
TEST(osm::ValidateVkPage("https://vkontakte.ru/id404"), ());
|
||||
TEST(osm::ValidateVkPage("http://www.vk.com/id404"), ());
|
||||
TEST(osm::ValidateVkPage("https://www.vk.com/id404"), ());
|
||||
TEST(osm::ValidateVkPage("id432160160"), ());
|
||||
TEST(osm::ValidateVkPage("hello_world"), ());
|
||||
TEST(osm::ValidateVkPage("osm63rus"), ());
|
||||
TEST(osm::ValidateVkPage("22ab.cdef"), ());
|
||||
TEST(osm::ValidateVkPage("@hello_world"), ());
|
||||
TEST(osm::ValidateVkPage("@osm63rus"), ());
|
||||
TEST(osm::ValidateVkPage("@22ab.cdef"), ());
|
||||
|
||||
TEST(!osm::ValidateVkPage("333too_many_numbers"), ());
|
||||
TEST(!osm::ValidateVkPage("vk"), ());
|
||||
TEST(!osm::ValidateVkPage("@five"), ());
|
||||
TEST(!osm::ValidateVkPage("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), ());
|
||||
TEST(!osm::ValidateVkPage("_invalid_underscores_"), ());
|
||||
TEST(!osm::ValidateVkPage("invalid-dashes"), ());
|
||||
// TEST(!osm::ValidateVkPage("to.ma.ny.do.ts"), ()); //TODO: it's hard to test such cases. Skip for now
|
||||
// TEST(!osm::ValidateVkPage("dots.__.dots"), ()); //TODO: it's hard to test such cases. Skip for now
|
||||
TEST(!osm::ValidateVkPage("instagram.com/hello_world"), ());
|
||||
TEST(!osm::ValidateVkPage("https://instagram.com/hello_world"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateLinePage)
|
||||
{
|
||||
TEST(osm::ValidateLinePage(""), ());
|
||||
TEST(osm::ValidateLinePage("http://line.me/ti/p/mzog4fnz24"), ());
|
||||
TEST(osm::ValidateLinePage("https://line.me/ti/p/xnv0g02rws"), ());
|
||||
TEST(osm::ValidateLinePage("https://line.me/ti/p/@dgxs9r6wad"), ());
|
||||
TEST(osm::ValidateLinePage("https://line.me/ti/p/%40vne5uwke17"), ());
|
||||
TEST(osm::ValidateLinePage("http://line.me/R/ti/p/bfsg1a8x9u"), ());
|
||||
TEST(osm::ValidateLinePage("https://line.me/R/ti/p/gdltt7s380"), ());
|
||||
TEST(osm::ValidateLinePage("https://line.me/R/ti/p/@sdb2pb3lsg"), ());
|
||||
TEST(osm::ValidateLinePage("https://line.me/R/ti/p/%40b30h5mdj11"), ());
|
||||
TEST(osm::ValidateLinePage("http://line.me/R/home/public/main?id=hmczqsbav5"), ());
|
||||
TEST(osm::ValidateLinePage("https://line.me/R/home/public/main?id=wa1gvx91jb"), ());
|
||||
TEST(osm::ValidateLinePage("http://line.me/R/home/public/profile?id=5qll5dyqqu"), ());
|
||||
TEST(osm::ValidateLinePage("https://line.me/R/home/public/profile?id=r90ck7n1rq"), ());
|
||||
TEST(osm::ValidateLinePage("https://line.me/R/home/public/profile?id=r90ck7n1rq"), ());
|
||||
TEST(osm::ValidateLinePage("https://page.line.me/fom5198h"), ());
|
||||
TEST(osm::ValidateLinePage("https://page.line.me/qn58n8g?web=mobile"), ());
|
||||
TEST(osm::ValidateLinePage("https://abc.line.me/en/some/page?id=xaladqv"), ());
|
||||
TEST(osm::ValidateLinePage("@abcd"), ());
|
||||
TEST(osm::ValidateLinePage("0000"), ());
|
||||
TEST(osm::ValidateLinePage(".dots.are.allowed."), ());
|
||||
TEST(osm::ValidateLinePage("@.dots.are.allowed."), ());
|
||||
TEST(osm::ValidateLinePage("-hyphen-test-"), ());
|
||||
TEST(osm::ValidateLinePage("@-hyphen-test-"), ());
|
||||
TEST(osm::ValidateLinePage("under_score"), ());
|
||||
TEST(osm::ValidateLinePage("@under_score"), ());
|
||||
|
||||
TEST(!osm::ValidateLinePage("no"), ());
|
||||
TEST(!osm::ValidateLinePage("yes"), ());
|
||||
TEST(!osm::ValidateLinePage("No-upper-case"), ());
|
||||
TEST(!osm::ValidateLinePage("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), ());
|
||||
TEST(!osm::ValidateLinePage("https://line.com/ti/p/invalid-domain"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateFediversePage)
|
||||
{
|
||||
TEST(osm::ValidateFediversePage("https://floss.social/@comaps"), ());
|
||||
TEST(osm::ValidateFediversePage("https://floss.social/users/comaps"), ());
|
||||
TEST(osm::ValidateFediversePage("http://floss.social/users/comaps"), ());
|
||||
TEST(osm::ValidateFediversePage("floss.social/users/comaps"), ());
|
||||
TEST(osm::ValidateFediversePage("comaps@floss.social"), ());
|
||||
TEST(osm::ValidateFediversePage("@comaps@floss.social"), ());
|
||||
TEST(osm::ValidateFediversePage("@comaps@floss.social.uk"), ());
|
||||
TEST(osm::ValidateFediversePage("pub.mastodon.org.uk/@comaps"), ());
|
||||
TEST(osm::ValidateFediversePage("pub.mastodon.org.uk/users/@comaps"), ());
|
||||
|
||||
TEST(!osm::ValidateFediversePage("comaps@floss@mastodon.org"), ());
|
||||
TEST(!osm::ValidateFediversePage("orga$nicmaps@mastodon.social"), ());
|
||||
TEST(!osm::ValidateFediversePage("pub.mastodon.org.uk/comaps"), ());
|
||||
TEST(!osm::ValidateFediversePage("pub.mastodon.org.uk/users/"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_ValidateBlueskyPage)
|
||||
{
|
||||
TEST(osm::ValidateBlueskyPage("comaps.bsky.social"), ());
|
||||
TEST(osm::ValidateBlueskyPage("@comaps.bsky.social"), ());
|
||||
TEST(osm::ValidateBlueskyPage("https://bsky.app/profile/comaps.bsky.social"), ());
|
||||
TEST(osm::ValidateBlueskyPage("https://bsky.app/profile/@comaps.bsky.social"), ());
|
||||
TEST(osm::ValidateBlueskyPage("http://bsky.app/profile/comaps.bsky.social"), ());
|
||||
TEST(osm::ValidateBlueskyPage("bsky.app/profile/comaps.bsky.social"), ());
|
||||
TEST(osm::ValidateBlueskyPage("https://bsky.app/profile/comaps.bsky.social"), ());
|
||||
|
||||
TEST(!osm::ValidateBlueskyPage("https://bsky.app/profile/comap$.bsky.social"), ());
|
||||
TEST(!osm::ValidateBlueskyPage("https://bsky.app/profile/comaps.bsky.social$"), ());
|
||||
TEST(!osm::ValidateBlueskyPage("https://bsky.app/pineapple/comaps.bsky.social"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(EditableMapObject_socialContactToURL)
|
||||
{
|
||||
TEST_EQUAL(osm::socialContactToURL(osm::MapObject::MetadataID::FMD_CONTACT_INSTAGRAM, "some_page_name"),
|
||||
"https://instagram.com/some_page_name", ());
|
||||
TEST_EQUAL(osm::socialContactToURL(osm::MapObject::MetadataID::FMD_CONTACT_INSTAGRAM, "p/BvkgKZNDbqN"),
|
||||
"https://instagram.com/p/BvkgKZNDbqN", ());
|
||||
TEST_EQUAL(osm::socialContactToURL(osm::MapObject::MetadataID::FMD_CONTACT_FACEBOOK, "100086487430889"),
|
||||
"https://facebook.com/100086487430889", ());
|
||||
TEST_EQUAL(osm::socialContactToURL(osm::MapObject::MetadataID::FMD_CONTACT_FACEBOOK, "nova.poshta.official"),
|
||||
"https://facebook.com/nova.poshta.official", ());
|
||||
TEST_EQUAL(osm::socialContactToURL(osm::MapObject::MetadataID::FMD_CONTACT_FACEBOOK, "pg/ESQ-336537783591903/about"),
|
||||
"https://facebook.com/pg/ESQ-336537783591903/about", ());
|
||||
TEST_EQUAL(osm::socialContactToURL(osm::MapObject::MetadataID::FMD_CONTACT_TWITTER, "carmelopizza"),
|
||||
"https://twitter.com/carmelopizza", ());
|
||||
TEST_EQUAL(osm::socialContactToURL(osm::MapObject::MetadataID::FMD_CONTACT_TWITTER,
|
||||
"demhamburguesa/status/688001869269078016"),
|
||||
"https://twitter.com/demhamburguesa/status/688001869269078016", ());
|
||||
TEST_EQUAL(osm::socialContactToURL(osm::MapObject::MetadataID::FMD_CONTACT_VK, "beerhousebar"),
|
||||
"https://vk.com/beerhousebar", ());
|
||||
TEST_EQUAL(osm::socialContactToURL(osm::MapObject::MetadataID::FMD_CONTACT_VK, "wall-41524_29351"),
|
||||
"https://vk.com/wall-41524_29351", ());
|
||||
TEST_EQUAL(osm::socialContactToURL(osm::MapObject::MetadataID::FMD_CONTACT_LINE, "a26235875"),
|
||||
"https://line.me/R/ti/p/@a26235875", ());
|
||||
TEST_EQUAL(osm::socialContactToURL(osm::MapObject::MetadataID::FMD_CONTACT_LINE,
|
||||
"liff.line.me/1645278921-kWRPP32q/?accountId=673watcr"),
|
||||
"https://liff.line.me/1645278921-kWRPP32q/?accountId=673watcr", ());
|
||||
}
|
||||
91
libs/indexer/indexer_tests/visibility_test.cpp
Normal file
91
libs/indexer/indexer_tests/visibility_test.cpp
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/classificator.hpp"
|
||||
#include "indexer/classificator_loader.hpp"
|
||||
#include "indexer/feature_data.hpp"
|
||||
#include "indexer/feature_visibility.hpp"
|
||||
#include "indexer/scales.hpp"
|
||||
|
||||
#include "base/logging.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
class DoGetMaxLowMinHighZoom
|
||||
{
|
||||
Classificator const & m_classif;
|
||||
pair<int, int> m_res;
|
||||
string m_low;
|
||||
|
||||
set<uint32_t> m_skip;
|
||||
bool IsSkip(uint32_t t) const
|
||||
{
|
||||
ftype::TruncValue(t, 2);
|
||||
return m_skip.count(t) > 0;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit DoGetMaxLowMinHighZoom(Classificator const & c) : m_classif(classif()), m_res(-1, 1000)
|
||||
{
|
||||
char const * arr[][2] = {
|
||||
{"highway", "bus_stop"},
|
||||
{"highway", "speed_camera"},
|
||||
{"highway", "world_level"},
|
||||
{"highway", "world_towns_level"},
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(arr); ++i)
|
||||
m_skip.insert(c.GetTypeByPath(vector<string>(arr[i], arr[i] + 2)));
|
||||
}
|
||||
|
||||
void operator()(ClassifObject const * p, uint32_t type)
|
||||
{
|
||||
if (IsSkip(type))
|
||||
return;
|
||||
|
||||
pair<int, int> const r = feature::GetDrawableScaleRange(type);
|
||||
if (r.first == -1 || r.second == -1)
|
||||
{
|
||||
LOG(LINFO, (r, m_classif.GetFullObjectName(type)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_res.first < r.first)
|
||||
{
|
||||
m_res.first = r.first;
|
||||
m_low = p->GetName();
|
||||
}
|
||||
if (m_res.second > r.second)
|
||||
m_res.second = r.second;
|
||||
}
|
||||
|
||||
void Print()
|
||||
{
|
||||
TEST_EQUAL(m_res.second, scales::GetUpperStyleScale(), (m_res));
|
||||
LOG(LINFO, ("Max low highway zoom:", m_res, "for type:", m_low));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
UNIT_TEST(VisibleScales_Highway)
|
||||
{
|
||||
Classificator const & c = classif();
|
||||
|
||||
char const * arr[] = {"highway"};
|
||||
uint32_t const type = c.GetTypeByPath(vector<string>(arr, arr + 1));
|
||||
|
||||
ClassifObject const * pObj = c.GetObject(type);
|
||||
|
||||
DoGetMaxLowMinHighZoom doGet(c);
|
||||
pObj->ForEachObjectInTree(doGet, type);
|
||||
|
||||
doGet.Print();
|
||||
}
|
||||
37
libs/indexer/indexer_tests/wheelchair_tests.cpp
Normal file
37
libs/indexer/indexer_tests/wheelchair_tests.cpp
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/classificator.hpp"
|
||||
#include "indexer/classificator_loader.hpp"
|
||||
#include "indexer/ftraits.hpp"
|
||||
|
||||
UNIT_TEST(Wheelchair_GetType)
|
||||
{
|
||||
classificator::Load();
|
||||
Classificator const & c = classif();
|
||||
|
||||
using ftraits::Wheelchair;
|
||||
using ftraits::WheelchairAvailability;
|
||||
|
||||
feature::TypesHolder holder;
|
||||
{
|
||||
holder.Assign(c.GetTypeByPath({"wheelchair", "no"}));
|
||||
TEST_EQUAL(*Wheelchair::GetValue(holder), WheelchairAvailability::No, ());
|
||||
}
|
||||
{
|
||||
holder.Assign(c.GetTypeByPath({"wheelchair", "yes"}));
|
||||
TEST_EQUAL(*Wheelchair::GetValue(holder), WheelchairAvailability::Yes, ());
|
||||
}
|
||||
{
|
||||
holder.Assign(c.GetTypeByPath({"wheelchair", "limited"}));
|
||||
TEST_EQUAL(*Wheelchair::GetValue(holder), WheelchairAvailability::Limited, ());
|
||||
}
|
||||
{
|
||||
holder.Assign(c.GetTypeByPath({"amenity", "dentist"}));
|
||||
TEST(!Wheelchair::GetValue(holder), ());
|
||||
}
|
||||
{
|
||||
holder.Assign(c.GetTypeByPath({"amenity", "dentist"}));
|
||||
holder.Add(c.GetTypeByPath({"wheelchair", "yes"}));
|
||||
TEST_EQUAL(*Wheelchair::GetValue(holder), WheelchairAvailability::Yes, ());
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue