Merge pull request #745 from deathbaba/metadata-fix

Metadata refactoring. Need it for Editor.
This commit is contained in:
Viktor Govako 2015-12-01 12:34:54 +03:00
commit 0e1ebedf93
9 changed files with 364 additions and 271 deletions

View file

@ -22,7 +22,7 @@ SOURCES += \
coasts_test.cpp \
feature_builder_test.cpp \
feature_merger_test.cpp \
metadata_test.cpp \
metadata_parser_test.cpp \
osm_id_test.cpp \
osm_o5m_source_test.cpp \
osm_type_test.cpp \

View file

@ -0,0 +1,204 @@
#include "testing/testing.hpp"
#include "generator/osm2meta.hpp"
#include "indexer/classificator_loader.hpp"
#include "coding/writer.hpp"
#include "coding/reader.hpp"
#include "base/logging.hpp"
#include "std/target_os.hpp"
using feature::Metadata;
UNIT_TEST(Metadata_ValidateAndFormat_stars)
{
FeatureParams params;
MetadataTagProcessor p(params);
Metadata & md = params.GetMetadata();
// Ignore incorrect values.
p("stars", "0");
TEST(md.Empty(), ());
p("stars", "-1");
TEST(md.Empty(), ());
p("stars", "aasdasdas");
TEST(md.Empty(), ());
p("stars", "8");
TEST(md.Empty(), ());
p("stars", "10");
TEST(md.Empty(), ());
p("stars", "910");
TEST(md.Empty(), ());
p("stars", "100");
TEST(md.Empty(), ());
// Check correct values.
p("stars", "1");
TEST_EQUAL(md.Get(Metadata::FMD_STARS), "1", ())
md.Drop(Metadata::FMD_STARS);
p("stars", "2");
TEST_EQUAL(md.Get(Metadata::FMD_STARS), "2", ())
md.Drop(Metadata::FMD_STARS);
p("stars", "3");
TEST_EQUAL(md.Get(Metadata::FMD_STARS), "3", ())
md.Drop(Metadata::FMD_STARS);
p("stars", "4");
TEST_EQUAL(md.Get(Metadata::FMD_STARS), "4", ())
md.Drop(Metadata::FMD_STARS);
p("stars", "5");
TEST_EQUAL(md.Get(Metadata::FMD_STARS), "5", ())
md.Drop(Metadata::FMD_STARS);
p("stars", "6");
TEST_EQUAL(md.Get(Metadata::FMD_STARS), "6", ())
md.Drop(Metadata::FMD_STARS);
p("stars", "7");
TEST_EQUAL(md.Get(Metadata::FMD_STARS), "7", ())
md.Drop(Metadata::FMD_STARS);
// Check almost correct values.
p("stars", "4+");
TEST_EQUAL(md.Get(Metadata::FMD_STARS), "4", ())
md.Drop(Metadata::FMD_STARS);
p("stars", "5s");
TEST_EQUAL(md.Get(Metadata::FMD_STARS), "5", ())
md.Drop(Metadata::FMD_STARS);
}
UNIT_TEST(Metadata_ValidateAndFormat_operator)
{
classificator::Load();
Classificator const & c = classif();
uint32_t const type_atm = c.GetTypeByPath({ "amenity", "atm" });
uint32_t const type_fuel = c.GetTypeByPath({ "amenity", "fuel" });
FeatureParams params;
MetadataTagProcessor p(params);
Metadata & md = params.GetMetadata();
// Ignore tag 'operator' if feature have inappropriate type.
p("operator", "Some");
TEST(md.Empty(), ());
params.SetType(type_atm);
p("operator", "Some");
TEST_EQUAL(md.Get(Metadata::FMD_OPERATOR), "Some", ());
md.Drop(Metadata::FMD_OPERATOR);
params.SetType(type_fuel);
p("operator", "Some");
TEST_EQUAL(md.Get(Metadata::FMD_OPERATOR), "Some", ());
md.Drop(Metadata::FMD_OPERATOR);
params.SetType(type_atm);
params.AddType(type_fuel);
p("operator", "Some");
TEST_EQUAL(md.Get(Metadata::FMD_OPERATOR), "Some", ());
md.Drop(Metadata::FMD_OPERATOR);
}
UNIT_TEST(Metadata_ValidateAndFormat_ele)
{
classificator::Load();
Classificator const & c = classif();
uint32_t const type_peak = c.GetTypeByPath({ "natural", "peak" });
FeatureParams params;
MetadataTagProcessor p(params);
Metadata & md = params.GetMetadata();
// Ignore tag 'operator' if feature have inappropriate type.
p("ele", "123");
TEST(md.Empty(), ());
params.SetType(type_peak);
p("ele", "0");
TEST(md.Empty(), ());
params.SetType(type_peak);
p("ele", "0,0000");
TEST(md.Empty(), ());
params.SetType(type_peak);
p("ele", "0.0");
TEST(md.Empty(), ());
params.SetType(type_peak);
p("ele", "123");
TEST_EQUAL(md.Get(Metadata::FMD_ELE), "123", ());
md.Drop(Metadata::FMD_ELE);
}
UNIT_TEST(Metadata_ValidateAndFormat_wikipedia)
{
char const * kWikiKey = "wikipedia";
FeatureParams params;
MetadataTagProcessor p(params);
Metadata & md = params.GetMetadata();
#ifdef OMIM_OS_MOBILE
#define WIKIHOST "m.wikipedia.org"
#else
#define WIKIHOST "wikipedia.org"
#endif
p(kWikiKey, "en:Bad %20Data");
TEST_EQUAL(md.Get(Metadata::FMD_WIKIPEDIA), "en:Bad %20Data", ());
TEST_EQUAL(md.GetWikiURL(), "https://en." WIKIHOST "/wiki/Bad_%2520Data", ());
md.Drop(Metadata::FMD_WIKIPEDIA);
p(kWikiKey, "ru:Тест_with % sign");
TEST_EQUAL(md.Get(Metadata::FMD_WIKIPEDIA), "ru:Тест with % sign", ());
TEST_EQUAL(md.GetWikiURL(), "https://ru." WIKIHOST "/wiki/Тест_with_%25_sign", ());
md.Drop(Metadata::FMD_WIKIPEDIA);
p(kWikiKey, "https://be-tarask.wikipedia.org/wiki/Вялікае_Княстваітоўскае");
TEST_EQUAL(md.Get(Metadata::FMD_WIKIPEDIA), "be-tarask:Вялікае Княства Літоўскае", ());
TEST_EQUAL(md.GetWikiURL(), "https://be-tarask." WIKIHOST "/wiki/Вялікае_Княстваітоўскае", ());
md.Drop(Metadata::FMD_WIKIPEDIA);
// Final link points to https and mobile version.
p(kWikiKey, "http://en.wikipedia.org/wiki/A");
TEST_EQUAL(md.Get(Metadata::FMD_WIKIPEDIA), "en:A", ());
TEST_EQUAL(md.GetWikiURL(), "https://en." WIKIHOST "/wiki/A", ());
md.Drop(Metadata::FMD_WIKIPEDIA);
p(kWikiKey, "invalid_input_without_language_and_colon");
TEST(md.Empty(), (md.Get(Metadata::FMD_WIKIPEDIA)));
p(kWikiKey, "https://en.wikipedia.org/wiki/");
TEST(md.Empty(), (md.Get(Metadata::FMD_WIKIPEDIA)));
p(kWikiKey, "http://wikipedia.org/wiki/Article");
TEST(md.Empty(), (md.Get(Metadata::FMD_WIKIPEDIA)));
p(kWikiKey, "http://somesite.org");
TEST(md.Empty(), (md.Get(Metadata::FMD_WIKIPEDIA)));
p(kWikiKey, "http://www.spamsitewithaslash.com/");
TEST(md.Empty(), (md.Get(Metadata::FMD_WIKIPEDIA)));
p(kWikiKey, "http://.wikipedia.org/wiki/Article");
TEST(md.Empty(), (md.Get(Metadata::FMD_WIKIPEDIA)));
// Ignore incorrect prefixes.
p(kWikiKey, "ht.tps://en.wikipedia.org/wiki/Whuh");
TEST_EQUAL(md.Get(Metadata::FMD_WIKIPEDIA), "en:Whuh", ());
md.Drop(Metadata::FMD_WIKIPEDIA);
p(kWikiKey, "http://ru.google.com/wiki/wutlol");
TEST(md.Empty(), ("Not a wikipedia site."));
#undef WIKIHOST
}

View file

@ -1,241 +0,0 @@
#include "testing/testing.hpp"
#include "base/logging.hpp"
#include "indexer/classificator_loader.hpp"
#include "generator/osm2meta.hpp"
#include "coding/writer.hpp"
#include "coding/reader.hpp"
UNIT_TEST(Metadata_ValidateAndFormat_stars)
{
FeatureParams params;
MetadataTagProcessor p(params);
// ignore incorrect values
p("stars", "0");
TEST(params.GetMetadata().Empty(), ());
p("stars", "-1");
TEST(params.GetMetadata().Empty(), ());
p("stars", "aasdasdas");
TEST(params.GetMetadata().Empty(), ());
p("stars", "8");
TEST(params.GetMetadata().Empty(), ());
p("stars", "10");
TEST(params.GetMetadata().Empty(), ());
p("stars", "910");
TEST(params.GetMetadata().Empty(), ());
p("stars", "100");
TEST(params.GetMetadata().Empty(), ());
// check correct values
p("stars", "1");
TEST_EQUAL(params.GetMetadata().Get(feature::Metadata::FMD_STARS), "1", ())
params.GetMetadata().Drop(feature::Metadata::FMD_STARS);
p("stars", "2");
TEST_EQUAL(params.GetMetadata().Get(feature::Metadata::FMD_STARS), "2", ())
params.GetMetadata().Drop(feature::Metadata::FMD_STARS);
p("stars", "3");
TEST_EQUAL(params.GetMetadata().Get(feature::Metadata::FMD_STARS), "3", ())
params.GetMetadata().Drop(feature::Metadata::FMD_STARS);
p("stars", "4");
TEST_EQUAL(params.GetMetadata().Get(feature::Metadata::FMD_STARS), "4", ())
params.GetMetadata().Drop(feature::Metadata::FMD_STARS);
p("stars", "5");
TEST_EQUAL(params.GetMetadata().Get(feature::Metadata::FMD_STARS), "5", ())
params.GetMetadata().Drop(feature::Metadata::FMD_STARS);
p("stars", "6");
TEST_EQUAL(params.GetMetadata().Get(feature::Metadata::FMD_STARS), "6", ())
params.GetMetadata().Drop(feature::Metadata::FMD_STARS);
p("stars", "7");
TEST_EQUAL(params.GetMetadata().Get(feature::Metadata::FMD_STARS), "7", ())
params.GetMetadata().Drop(feature::Metadata::FMD_STARS);
// check almost correct values
p("stars", "4+");
TEST_EQUAL(params.GetMetadata().Get(feature::Metadata::FMD_STARS), "4", ())
params.GetMetadata().Drop(feature::Metadata::FMD_STARS);
p("stars", "5s");
TEST_EQUAL(params.GetMetadata().Get(feature::Metadata::FMD_STARS), "5", ())
params.GetMetadata().Drop(feature::Metadata::FMD_STARS);
}
UNIT_TEST(Metadata_ValidateAndFormat_operator)
{
classificator::Load();
Classificator const & c = classif();
uint32_t const type_atm = c.GetTypeByPath({ "amenity", "atm" });
uint32_t const type_fuel = c.GetTypeByPath({ "amenity", "fuel" });
FeatureParams params;
MetadataTagProcessor p(params);
// ignore tag 'operator' if feature have inappropriate type
p("operator", "Some");
TEST(params.GetMetadata().Empty(), ());
params.SetType(type_atm);
p("operator", "Some");
TEST_EQUAL(params.GetMetadata().Get(feature::Metadata::FMD_OPERATOR), "Some", ());
params.GetMetadata().Drop(feature::Metadata::FMD_OPERATOR);
params.SetType(type_fuel);
p("operator", "Some");
TEST_EQUAL(params.GetMetadata().Get(feature::Metadata::FMD_OPERATOR), "Some", ());
params.GetMetadata().Drop(feature::Metadata::FMD_OPERATOR);
params.SetType(type_atm);
params.AddType(type_fuel);
p("operator", "Some");
TEST_EQUAL(params.GetMetadata().Get(feature::Metadata::FMD_OPERATOR), "Some", ());
params.GetMetadata().Drop(feature::Metadata::FMD_OPERATOR);
}
UNIT_TEST(Metadata_ValidateAndFormat_ele)
{
classificator::Load();
Classificator const & c = classif();
uint32_t const type_peak = c.GetTypeByPath({ "natural", "peak" });
FeatureParams params;
MetadataTagProcessor p(params);
// ignore tag 'operator' if feature have inappropriate type
p("ele", "123");
TEST(params.GetMetadata().Empty(), ());
params.SetType(type_peak);
p("ele", "0");
TEST(params.GetMetadata().Empty(), ());
params.SetType(type_peak);
p("ele", "0,0000");
TEST(params.GetMetadata().Empty(), ());
params.SetType(type_peak);
p("ele", "0.0");
TEST(params.GetMetadata().Empty(), ());
params.SetType(type_peak);
p("ele", "123");
TEST_EQUAL(params.GetMetadata().Get(feature::Metadata::FMD_ELE), "123", ());
params.GetMetadata().Drop(feature::Metadata::FMD_ELE);
}
UNIT_TEST(Metadata_ValidateAndFormat_wikipedia)
{
using feature::Metadata;
char const * kWikiKey = "wikipedia";
FeatureParams params;
MetadataTagProcessor p(params);
p(kWikiKey, "en:Bad %20Data");
TEST_EQUAL(params.GetMetadata().Get(Metadata::FMD_WIKIPEDIA), "en:Bad %20Data", ());
TEST_EQUAL(params.GetMetadata().GetWikiURL(), "https://en.m.wikipedia.org/wiki/Bad_%2520Data", ());
params.GetMetadata().Drop(Metadata::FMD_WIKIPEDIA);
p(kWikiKey, "ru:Тест_with % sign");
TEST_EQUAL(params.GetMetadata().Get(Metadata::FMD_WIKIPEDIA), "ru:Тест with % sign", ());
TEST_EQUAL(params.GetMetadata().GetWikiURL(), "https://ru.m.wikipedia.org/wiki/Тест_with_%25_sign", ());
params.GetMetadata().Drop(Metadata::FMD_WIKIPEDIA);
p(kWikiKey, "https://be-tarask.wikipedia.org/wiki/Вялікае_Княстваітоўскае");
TEST_EQUAL(params.GetMetadata().Get(Metadata::FMD_WIKIPEDIA), "be-tarask:Вялікае Княства Літоўскае", ());
TEST_EQUAL(params.GetMetadata().GetWikiURL(), "https://be-tarask.m.wikipedia.org/wiki/Вялікае_Княстваітоўскае", ());
params.GetMetadata().Drop(Metadata::FMD_WIKIPEDIA);
// Final link points to https and mobile version.
p(kWikiKey, "http://en.wikipedia.org/wiki/A");
TEST_EQUAL(params.GetMetadata().Get(Metadata::FMD_WIKIPEDIA), "en:A", ());
TEST_EQUAL(params.GetMetadata().GetWikiURL(), "https://en.m.wikipedia.org/wiki/A", ());
params.GetMetadata().Drop(Metadata::FMD_WIKIPEDIA);
p(kWikiKey, "invalid_input_without_language_and_colon");
TEST(params.GetMetadata().Empty(), (params.GetMetadata().Get(Metadata::FMD_WIKIPEDIA)));
p(kWikiKey, "https://en.wikipedia.org/wiki/");
TEST(params.GetMetadata().Empty(), (params.GetMetadata().Get(Metadata::FMD_WIKIPEDIA)));
p(kWikiKey, "http://wikipedia.org/wiki/Article");
TEST(params.GetMetadata().Empty(), (params.GetMetadata().Get(Metadata::FMD_WIKIPEDIA)));
p(kWikiKey, "http://somesite.org");
TEST(params.GetMetadata().Empty(), (params.GetMetadata().Get(Metadata::FMD_WIKIPEDIA)));
p(kWikiKey, "http://www.spamsitewithaslash.com/");
TEST(params.GetMetadata().Empty(), (params.GetMetadata().Get(Metadata::FMD_WIKIPEDIA)));
p(kWikiKey, "http://.wikipedia.org/wiki/Article");
TEST(params.GetMetadata().Empty(), (params.GetMetadata().Get(Metadata::FMD_WIKIPEDIA)));
// Ignore incorrect prefixes.
p(kWikiKey, "ht.tps://en.wikipedia.org/wiki/Whuh");
TEST_EQUAL(params.GetMetadata().Get(Metadata::FMD_WIKIPEDIA), "en:Whuh", ());
params.GetMetadata().Drop(Metadata::FMD_WIKIPEDIA);
p(kWikiKey, "http://ru.google.com/wiki/wutlol");
TEST(params.GetMetadata().Empty(), ("Not a wikipedia site."));
}
UNIT_TEST(Metadata_ReadWrite_Intermediate)
{
FeatureParams params;
FeatureParams params_test;
MetadataTagProcessor p(params);
vector<char> buffer;
MemWriter<vector<char> > writer(buffer);
p("stars", "3");
p("phone", "+123456789");
p("opening_hours", "24/7");
p("cuisine", "regional");
p("operator", "Unused");
params.GetMetadata().Serialize(writer);
MemReader reader(buffer.data(), buffer.size());
ReaderSource<MemReader> src(reader);
params_test.GetMetadata().Deserialize(src);
TEST_EQUAL(params_test.GetMetadata().Get(feature::Metadata::FMD_STARS), "3", ())
TEST_EQUAL(params_test.GetMetadata().Get(feature::Metadata::FMD_PHONE_NUMBER), "+123456789", ())
TEST_EQUAL(params_test.GetMetadata().Get(feature::Metadata::FMD_OPEN_HOURS), "24/7", ())
TEST_EQUAL(params_test.GetMetadata().Get(feature::Metadata::FMD_CUISINE), "regional", ())
TEST(params_test.GetMetadata().Get(feature::Metadata::FMD_OPERATOR).empty(), ())
}
UNIT_TEST(Metadata_ReadWrite_MWM)
{
FeatureParams params;
FeatureParams params_test;
MetadataTagProcessor p(params);
vector<char> buffer;
MemWriter<vector<char> > writer(buffer);
p("stars", "3");
p("phone", "+123456789");
p("opening_hours", "24/7");
p("cuisine", "regional");
p("operator", "Unused");
params.GetMetadata().SerializeToMWM(writer);
MemReader reader(buffer.data(), buffer.size());
ReaderSource<MemReader> src(reader);
params_test.GetMetadata().DeserializeFromMWM(src);
TEST_EQUAL(params_test.GetMetadata().Get(feature::Metadata::FMD_STARS), "3", ())
TEST_EQUAL(params_test.GetMetadata().Get(feature::Metadata::FMD_PHONE_NUMBER), "+123456789", ())
TEST_EQUAL(params_test.GetMetadata().Get(feature::Metadata::FMD_OPEN_HOURS), "24/7", ())
TEST_EQUAL(params_test.GetMetadata().Get(feature::Metadata::FMD_CUISINE), "regional", ())
TEST(params_test.GetMetadata().Get(feature::Metadata::FMD_OPERATOR).empty(), ())
}

View file

@ -31,97 +31,97 @@ public:
{
string const & value = ValidateAndFormat_cuisine(v);
if (!value.empty())
md.Add(Metadata::FMD_CUISINE, value);
md.Set(Metadata::FMD_CUISINE, value);
}
else if (k == "phone" || k == "contact:phone")
{
string const & value = ValidateAndFormat_phone(v);
if (!value.empty())
md.Add(Metadata::FMD_PHONE_NUMBER, value);
md.Set(Metadata::FMD_PHONE_NUMBER, value);
}
else if (k == "maxspeed")
{
string const & value = ValidateAndFormat_maxspeed(v);
if (!value.empty())
md.Add(Metadata::FMD_MAXSPEED, value);
md.Set(Metadata::FMD_MAXSPEED, value);
}
else if (k == "stars")
{
string const & value = ValidateAndFormat_stars(v);
if (!value.empty())
md.Add(Metadata::FMD_STARS, value);
md.Set(Metadata::FMD_STARS, value);
}
else if (k == "addr:postcode")
{
string const & value = ValidateAndFormat_postcode(v);
if (!value.empty())
md.Add(Metadata::FMD_POSTCODE, value);
md.Set(Metadata::FMD_POSTCODE, value);
}
else if (k == "url")
{
string const & value = ValidateAndFormat_url(v);
if (!value.empty())
md.Add(Metadata::FMD_URL, value);
md.Set(Metadata::FMD_URL, value);
}
else if (k == "website" || k == "contact:website")
{
string const & value = ValidateAndFormat_url(v);
if (!value.empty())
md.Add(Metadata::FMD_WEBSITE, value);
md.Set(Metadata::FMD_WEBSITE, value);
}
else if (k == "operator")
{
string const & value = ValidateAndFormat_operator(v);
if (!value.empty())
md.Add(Metadata::FMD_OPERATOR, value);
md.Set(Metadata::FMD_OPERATOR, value);
}
else if (k == "opening_hours")
{
string const & value = ValidateAndFormat_opening_hours(v);
if (!value.empty())
md.Add(Metadata::FMD_OPEN_HOURS, value);
md.Set(Metadata::FMD_OPEN_HOURS, value);
}
else if (k == "ele")
{
string const & value = ValidateAndFormat_ele(v);
if (!value.empty())
md.Add(Metadata::FMD_ELE, value);
md.Set(Metadata::FMD_ELE, value);
}
else if (k == "turn:lanes")
{
string const & value = ValidateAndFormat_turn_lanes(v);
if (!value.empty())
md.Add(Metadata::FMD_TURN_LANES, value);
md.Set(Metadata::FMD_TURN_LANES, value);
}
else if (k == "turn:lanes:forward")
{
string const & value = ValidateAndFormat_turn_lanes_forward(v);
if (!value.empty())
md.Add(Metadata::FMD_TURN_LANES_FORWARD, value);
md.Set(Metadata::FMD_TURN_LANES_FORWARD, value);
}
else if (k == "turn:lanes:backward")
{
string const & value = ValidateAndFormat_turn_lanes_backward(v);
if (!value.empty())
md.Add(Metadata::FMD_TURN_LANES_BACKWARD, value);
md.Set(Metadata::FMD_TURN_LANES_BACKWARD, value);
}
else if (k == "email" || k == "contact:email")
{
string const & value = ValidateAndFormat_email(v);
if (!value.empty())
md.Add(Metadata::FMD_EMAIL, value);
md.Set(Metadata::FMD_EMAIL, value);
}
else if (k == "wikipedia")
{
string const & value = ValidateAndFormat_wikipedia(v);
if (!value.empty())
md.Add(Metadata::FMD_WIKIPEDIA, value);
md.Set(Metadata::FMD_WIKIPEDIA, value);
}
else if (k == "addr:flats")
{
string const & value = ValidateAndFormat_flats(v);
if (!value.empty())
md.Add(Metadata::FMD_FLATS, value);
md.Set(Metadata::FMD_FLATS, value);
}
return false;
}

View file

@ -144,7 +144,7 @@ void FeatureType::ParseMetadata() const
m_pLoader->ParseMetadata();
if (HasInternet())
m_metadata.Add(Metadata::FMD_INTERNET, "wlan");
m_metadata.Set(Metadata::FMD_INTERNET, "wlan");
m_bMetadataParsed = true;
}

View file

@ -1,10 +1,21 @@
#include "indexer/feature_meta.hpp"
#include "std/algorithm.hpp"
#include "std/target_os.hpp"
namespace feature
{
namespace
{
char constexpr const * kBaseWikiUrl =
#ifdef OMIM_OS_MOBILE
".m.wikipedia.org/wiki/";
#else
".wikipedia.org/wiki/";
#endif
} // namespace
string Metadata::GetWikiURL() const
{
string v = this->Get(FMD_WIKIPEDIA);
@ -27,7 +38,7 @@ string Metadata::GetWikiURL() const
// Trying to avoid redirects by constructing the right link.
// TODO: Wikipedia article could be opened it a user's language, but need
// generator level support to check for available article languages first.
return "https://" + v.substr(0, colon) + ".m.wikipedia.org/wiki/" + v.substr(colon + 1);
return "https://" + v.substr(0, colon) + kBaseWikiUrl + v.substr(colon + 1);
}
} // namespace feature

View file

@ -42,14 +42,28 @@ namespace feature
static_assert(FMD_COUNT <= 255, "Meta types count is limited to one byte.");
bool Add(EType type, string const & s)
/// Empty value drops (clears) corresponding type.
void Set(EType type, string const & value)
{
string & val = m_metadata[type];
if (val.empty())
val = s;
auto found = m_metadata.find(type);
if (found == m_metadata.end())
{
if (!value.empty())
m_metadata[type] = value;
}
else
val = val + ", " + s;
return true;
{
if (value.empty())
m_metadata.erase(found);
else
found->second = value;
}
}
/// Synonym of Set(type, "").
void Drop(EType type)
{
Set(type, "");
}
string Get(EType type) const
@ -69,11 +83,6 @@ namespace feature
return types;
}
void Drop(EType type)
{
m_metadata.erase(type);
}
inline bool Empty() const { return m_metadata.empty(); }
inline size_t Size() const { return m_metadata.size(); }

View file

@ -0,0 +1,109 @@
#include "testing/testing.hpp"
#include "indexer/feature_meta.hpp"
#include "coding/reader.hpp"
#include "coding/writer.hpp"
#include "std/map.hpp"
#include "std/target_os.hpp"
using feature::Metadata;
namespace
{
map<Metadata::EType, string> const kKeyValues =
{
{Metadata::FMD_ELE, "12345"},
{Metadata::FMD_CUISINE, "greek;mediterranean"},
{Metadata::FMD_EMAIL, "cool@email.at"}
};
} // namespace
UNIT_TEST(Feature_Metadata_GetSet)
{
Metadata m;
Metadata::EType const type = Metadata::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, "5678");
TEST_EQUAL(m.Get(type), "5678", ());
// 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(), ());
auto const types = m.GetPresentTypes();
TEST_EQUAL(types.size(), m.Size(), ());
for (auto const & type : types)
TEST_EQUAL(m.Get(type), kKeyValues.find(type)->second, ());
}
UNIT_TEST(Feature_Serialization)
{
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.Serialize(writer);
MemReader reader(buffer.data(), buffer.size());
ReaderSource<MemReader> src(reader);
serialized.Deserialize(src);
for (auto const & value : kKeyValues)
TEST_EQUAL(serialized.Get(value.first), value.second, ());
TEST_EQUAL(serialized.Get(Metadata::FMD_OPERATOR), "", ());
TEST_EQUAL(serialized.Size(), kKeyValues.size(), ());
}
{
Metadata serialized;
vector<char> buffer;
MemWriter<decltype(buffer)> writer(buffer);
// Here is the difference.
original.SerializeToMWM(writer);
MemReader reader(buffer.data(), buffer.size());
ReaderSource<MemReader> src(reader);
// Here is another difference.
serialized.DeserializeFromMWM(src);
for (auto const & value : kKeyValues)
TEST_EQUAL(serialized.Get(value.first), value.second, ());
TEST_EQUAL(serialized.Get(Metadata::FMD_OPERATOR), "", ());
TEST_EQUAL(serialized.Size(), kKeyValues.size(), ());
}
}
UNIT_TEST(Feature_Metadata_GetWikipedia)
{
Metadata m;
Metadata::EType const wikiType = Metadata::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
}

View file

@ -22,6 +22,7 @@ SOURCES += \
cell_id_test.cpp \
checker_test.cpp \
drules_selector_parser_test.cpp \
feature_metadata_test.cpp \
features_offsets_table_test.cpp \
geometry_coding_test.cpp \
geometry_serialization_test.cpp \