Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
15
libs/kml/kml_tests/CMakeLists.txt
Normal file
15
libs/kml/kml_tests/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
project(kml_tests)
|
||||
|
||||
set(SRC
|
||||
color_parser_tests.cpp
|
||||
gpx_tests.cpp
|
||||
minzoom_quadtree_tests.cpp
|
||||
serdes_tests.cpp
|
||||
tests_data.hpp
|
||||
)
|
||||
|
||||
omim_add_test(${PROJECT_NAME} ${SRC})
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
kml
|
||||
)
|
||||
19
libs/kml/kml_tests/color_parser_tests.cpp
Normal file
19
libs/kml/kml_tests/color_parser_tests.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "kml/color_parser.hpp"
|
||||
|
||||
UNIT_TEST(ColorParser_Smoke)
|
||||
{
|
||||
auto const magenta = kml::ParseGarminColor("Magenta");
|
||||
TEST(magenta, ());
|
||||
TEST_EQUAL(magenta, kml::ParseOSMColor("magenta"), ());
|
||||
TEST_EQUAL(magenta, kml::ParseHexColor("ff00ff"), ());
|
||||
TEST_EQUAL(magenta, kml::ParseHexColor("#ff00ff"), ());
|
||||
TEST_EQUAL(magenta, kml::ParseOSMColor("#f0f"), ());
|
||||
|
||||
TEST(!kml::ParseGarminColor("xxyyzz"), ());
|
||||
TEST(!kml::ParseOSMColor("#xxyyzz"), ());
|
||||
|
||||
// Current implementation gives assert with default 0 channel value. I didn't change this.
|
||||
// TEST(!kml::ParseHexColor("#xxyyzz"), ());
|
||||
}
|
||||
431
libs/kml/kml_tests/gpx_tests.cpp
Normal file
431
libs/kml/kml_tests/gpx_tests.cpp
Normal file
|
|
@ -0,0 +1,431 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "kml/color_parser.hpp"
|
||||
#include "kml/serdes_common.hpp"
|
||||
#include "kml/serdes_gpx.hpp"
|
||||
|
||||
#include "geometry/mercator.hpp"
|
||||
|
||||
#include "coding/file_reader.hpp"
|
||||
|
||||
#include "platform/platform.hpp"
|
||||
|
||||
namespace gpx_tests
|
||||
{
|
||||
static kml::FileData LoadGpxFromString(std::string_view content)
|
||||
{
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
kml::FileData dataFromText;
|
||||
kml::DeserializerGpx(dataFromText).Deserialize(MemReader(content));
|
||||
return dataFromText;
|
||||
},
|
||||
());
|
||||
}
|
||||
|
||||
static kml::FileData LoadGpxFromFile(std::string const & file)
|
||||
{
|
||||
auto const fileName = GetPlatform().TestsDataPathForFile(file);
|
||||
std::string text;
|
||||
FileReader(fileName).ReadAsString(text);
|
||||
return LoadGpxFromString(text);
|
||||
}
|
||||
|
||||
static std::string ReadFile(char const * testFile)
|
||||
{
|
||||
auto const fileName = GetPlatform().TestsDataPathForFile(testFile);
|
||||
std::string sourceFileText;
|
||||
FileReader(fileName).ReadAsString(sourceFileText);
|
||||
return sourceFileText;
|
||||
}
|
||||
|
||||
static std::string Serialize(kml::FileData const & dataFromFile)
|
||||
{
|
||||
std::string resultBuffer;
|
||||
MemWriter<decltype(resultBuffer)> sink(resultBuffer);
|
||||
kml::gpx::SerializerGpx ser(dataFromFile);
|
||||
ser.Serialize(sink);
|
||||
return resultBuffer;
|
||||
}
|
||||
|
||||
static std::string ReadFileAndSerialize(char const * testFile)
|
||||
{
|
||||
kml::FileData const dataFromFile = LoadGpxFromFile(testFile);
|
||||
return Serialize(dataFromFile);
|
||||
}
|
||||
|
||||
void ImportExportCompare(char const * testFile)
|
||||
{
|
||||
std::string const sourceFileText = ReadFile(testFile);
|
||||
std::string const resultBuffer = ReadFileAndSerialize(testFile);
|
||||
TEST_EQUAL(resultBuffer, sourceFileText, ());
|
||||
}
|
||||
|
||||
void ImportExportCompare(char const * sourceFile, char const * destinationFile)
|
||||
{
|
||||
std::string const resultBuffer = ReadFileAndSerialize(sourceFile);
|
||||
std::string const destinationFileText = ReadFile(destinationFile);
|
||||
TEST_EQUAL(resultBuffer, destinationFileText, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Gpx_ImportExport_Test)
|
||||
{
|
||||
ImportExportCompare("test_data/gpx/export_test.gpx");
|
||||
}
|
||||
|
||||
UNIT_TEST(Gpx_ImportExportEmpty_Test)
|
||||
{
|
||||
ImportExportCompare("test_data/gpx/export_test_empty.gpx");
|
||||
}
|
||||
|
||||
UNIT_TEST(Gpx_ColorMapExport_Test)
|
||||
{
|
||||
ImportExportCompare("test_data/gpx/color_map_src.gpx", "test_data/gpx/color_map_dst.gpx");
|
||||
}
|
||||
|
||||
UNIT_TEST(Gpx_Test_Point_With_Valid_Timestamp)
|
||||
{
|
||||
std::string_view constexpr input = R"(<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx version="1.0">
|
||||
<wpt lat="42.81025" lon="-1.65727">
|
||||
<time>2022-09-05T08:39:39.3700Z</time>
|
||||
<name>Waypoint 1</name>
|
||||
</wpt>
|
||||
)";
|
||||
|
||||
kml::FileData data;
|
||||
kml::BookmarkData bookmarkData;
|
||||
bookmarkData.m_name[kml::kDefaultLang] = "Waypoint 1";
|
||||
bookmarkData.m_point = mercator::FromLatLon(42.81025, -1.65727);
|
||||
bookmarkData.m_customName[kml::kDefaultLang] = "Waypoint 1";
|
||||
bookmarkData.m_color = {kml::PredefinedColor::Red, 0};
|
||||
data.m_bookmarksData.emplace_back(std::move(bookmarkData));
|
||||
|
||||
kml::FileData const dataFromText = LoadGpxFromString(input);
|
||||
|
||||
TEST_EQUAL(dataFromText, data, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Gpx_Test_Point_With_Invalid_Timestamp)
|
||||
{
|
||||
std::string_view constexpr input = R"(<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx version="1.0">
|
||||
<wpt lat="42.81025" lon="-1.65727">
|
||||
<time>2022-09-05T08:39:39.3700X</time>
|
||||
<name>Waypoint 1</name>
|
||||
</wpt>
|
||||
)";
|
||||
|
||||
kml::FileData const dataFromText = LoadGpxFromString(input);
|
||||
TEST_EQUAL(dataFromText.m_bookmarksData.size(), 1, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Gpx_Test_Track_Without_Timestamps)
|
||||
{
|
||||
auto const fileName = "test_data/gpx/track_without_timestamps.gpx";
|
||||
kml::FileData const dataFromText = LoadGpxFromFile(fileName);
|
||||
auto const & lines = dataFromText.m_tracksData[0].m_geometry.m_lines;
|
||||
TEST_EQUAL(lines.size(), 2, ());
|
||||
{
|
||||
auto const & line = lines[0];
|
||||
TEST_EQUAL(line.size(), 3, ());
|
||||
TEST_EQUAL(line.back(), geometry::PointWithAltitude(mercator::FromLatLon(54.05293900056246, 25.72998046875), 0),
|
||||
());
|
||||
}
|
||||
{
|
||||
auto const & line = lines[1];
|
||||
TEST_EQUAL(line.size(), 2, ());
|
||||
TEST_EQUAL(line.back(), geometry::PointWithAltitude(mercator::FromLatLon(54.32933804825253, 25.136718750000004), 0),
|
||||
());
|
||||
}
|
||||
// Also test default colors for tracks.
|
||||
{
|
||||
TEST_EQUAL(dataFromText.m_tracksData.size(), 1, ());
|
||||
TEST_EQUAL(dataFromText.m_tracksData[0].m_layers.size(), 1, ());
|
||||
auto const & layer = dataFromText.m_tracksData[0].m_layers[0];
|
||||
TEST_EQUAL(layer.m_color.m_rgba, kml::kDefaultTrackColor, ());
|
||||
TEST_EQUAL(layer.m_color.m_predefinedColor, kml::PredefinedColor::None, ());
|
||||
TEST_EQUAL(layer.m_lineWidth, kml::kDefaultTrackWidth, ());
|
||||
auto const & geometry = dataFromText.m_tracksData[0].m_geometry;
|
||||
TEST_EQUAL(geometry.m_timestamps.size(), 2, ());
|
||||
TEST(geometry.m_timestamps[0].empty(), ());
|
||||
TEST(geometry.m_timestamps[1].empty(), ());
|
||||
TEST(!geometry.HasTimestamps(), ());
|
||||
TEST(!geometry.HasTimestampsFor(0), ());
|
||||
TEST(!geometry.HasTimestampsFor(1), ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(Gpx_Test_Track_With_Timestamps)
|
||||
{
|
||||
auto const fileName = "test_data/gpx/track_with_timestamps.gpx";
|
||||
kml::FileData const dataFromText = LoadGpxFromFile(fileName);
|
||||
auto const & geometry = dataFromText.m_tracksData[0].m_geometry;
|
||||
TEST_EQUAL(geometry.m_lines.size(), 2, ());
|
||||
TEST_EQUAL(geometry.m_timestamps.size(), 2, ());
|
||||
TEST(geometry.IsValid(), ());
|
||||
TEST(geometry.HasTimestamps(), ());
|
||||
TEST(geometry.HasTimestampsFor(0), ());
|
||||
TEST(geometry.HasTimestampsFor(1), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Gpx_Test_Track_With_Timestamps_Mismatch)
|
||||
{
|
||||
auto const fileName = GetPlatform().TestsDataPathForFile("test_data/gpx/track_with_timestamps_broken.gpx");
|
||||
std::string text;
|
||||
FileReader(fileName).ReadAsString(text);
|
||||
|
||||
kml::FileData data;
|
||||
kml::DeserializerGpx(data).Deserialize(MemReader(text));
|
||||
|
||||
TEST_EQUAL(data.m_tracksData.size(), 1, ());
|
||||
TEST_EQUAL(data.m_tracksData[0].m_geometry.m_timestamps.size(), 2, ());
|
||||
TEST(data.m_tracksData[0].m_geometry.HasTimestampsFor(0), ());
|
||||
TEST(data.m_tracksData[0].m_geometry.HasTimestampsFor(1), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Gpx_Altitude_Issues)
|
||||
{
|
||||
std::string_view constexpr input = R"(<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx version="1.0">
|
||||
<trk>
|
||||
<name>new</name>
|
||||
<type>Cycling</type>
|
||||
<trkseg>
|
||||
<trkpt lat="1" lon="1"></trkpt>
|
||||
<trkpt lat="2" lon="2"><ele>1.0</ele></trkpt>
|
||||
<trkpt lat="3" lon="3"></trkpt>
|
||||
<trkpt lat="4" lon="4"><ele>2.0</ele></trkpt>
|
||||
<trkpt lat="5" lon="5"><ele>Wrong</ele></trkpt>
|
||||
<trkpt lat="6" lon="6"><ele>3</ele></trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
||||
)";
|
||||
|
||||
kml::FileData const dataFromText = LoadGpxFromString(input);
|
||||
auto const & line = dataFromText.m_tracksData[0].m_geometry.m_lines[0];
|
||||
TEST_EQUAL(line.size(), 6, ());
|
||||
TEST_EQUAL(line[0], geometry::PointWithAltitude(mercator::FromLatLon(1, 1), geometry::kInvalidAltitude), ());
|
||||
TEST_EQUAL(line[1], geometry::PointWithAltitude(mercator::FromLatLon(2, 2), 1), ());
|
||||
TEST_EQUAL(line[2], geometry::PointWithAltitude(mercator::FromLatLon(3, 3), geometry::kInvalidAltitude), ());
|
||||
TEST_EQUAL(line[3], geometry::PointWithAltitude(mercator::FromLatLon(4, 4), 2), ());
|
||||
TEST_EQUAL(line[4], geometry::PointWithAltitude(mercator::FromLatLon(5, 5), geometry::kInvalidAltitude), ());
|
||||
TEST_EQUAL(line[5], geometry::PointWithAltitude(mercator::FromLatLon(6, 6), 3), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Gpx_Timestamp_Issues)
|
||||
{
|
||||
std::string_view constexpr input = R"(<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx version="1.0">
|
||||
<trk>
|
||||
<name>new</name>
|
||||
<type>Cycling</type>
|
||||
<trkseg>
|
||||
<trkpt lat="0" lon="0"></trkpt>
|
||||
<trkpt lat="1" lon="1"><time>2024-05-04T19:00:00Z</time></trkpt>
|
||||
<trkpt lat="2" lon="2"><time>2024-05-04T19:00:01Z</time></trkpt>
|
||||
<trkpt lat="3" lon="3"></trkpt>
|
||||
<trkpt lat="4" lon="4"><time>Abra-hadabra</time></trkpt>
|
||||
<trkpt lat="5" lon="5"><time>2024-05-04T19:00:04Z</time></trkpt>
|
||||
<trkpt lat="6" lon="6"><time>2024-05-04T19:00:05Z</time></trkpt>
|
||||
<trkpt lat="7" lon="7"></trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
||||
)";
|
||||
|
||||
kml::FileData const dataFromText = LoadGpxFromString(input);
|
||||
auto const & times = dataFromText.m_tracksData[0].m_geometry.m_timestamps[0];
|
||||
TEST_EQUAL(times.size(), 8, ());
|
||||
TEST_EQUAL(times[0], base::StringToTimestamp("2024-05-04T19:00:00Z"), ());
|
||||
TEST_EQUAL(times[1], base::StringToTimestamp("2024-05-04T19:00:00Z"), ());
|
||||
TEST_EQUAL(times[2], base::StringToTimestamp("2024-05-04T19:00:01Z"), ());
|
||||
TEST_EQUAL(times[3], base::StringToTimestamp("2024-05-04T19:00:02Z"), ());
|
||||
TEST_EQUAL(times[4], base::StringToTimestamp("2024-05-04T19:00:03Z"), ());
|
||||
TEST_EQUAL(times[5], base::StringToTimestamp("2024-05-04T19:00:04Z"), ());
|
||||
TEST_EQUAL(times[6], base::StringToTimestamp("2024-05-04T19:00:05Z"), ());
|
||||
TEST_EQUAL(times[7], base::StringToTimestamp("2024-05-04T19:00:05Z"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(GoMap)
|
||||
{
|
||||
kml::FileData const dataFromFile = LoadGpxFromFile("test_data/gpx/go_map.gpx");
|
||||
auto const & line = dataFromFile.m_tracksData[0].m_geometry.m_lines[0];
|
||||
TEST_EQUAL(line.size(), 101, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(GpxStudio)
|
||||
{
|
||||
kml::FileData const dataFromFile = LoadGpxFromFile("test_data/gpx/gpx_studio.gpx");
|
||||
auto const & line = dataFromFile.m_tracksData[0].m_geometry.m_lines[0];
|
||||
TEST_EQUAL(line.size(), 328, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(OsmTrack)
|
||||
{
|
||||
kml::FileData const dataFromFile = LoadGpxFromFile("test_data/gpx/osm_track.gpx");
|
||||
auto const & line = dataFromFile.m_tracksData[0].m_geometry.m_lines[0];
|
||||
auto const & timestamps = dataFromFile.m_tracksData[0].m_geometry.m_timestamps[0];
|
||||
TEST_EQUAL(line.size(), 182, ());
|
||||
TEST_EQUAL(timestamps.size(), 182, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TowerCollector)
|
||||
{
|
||||
kml::FileData const dataFromFile = LoadGpxFromFile("test_data/gpx/tower_collector.gpx");
|
||||
auto line = dataFromFile.m_tracksData[0].m_geometry.m_lines[0];
|
||||
TEST_EQUAL(line.size(), 35, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(PointsOnly)
|
||||
{
|
||||
kml::FileData const dataFromFile = LoadGpxFromFile("test_data/gpx/points.gpx");
|
||||
auto bookmarks = dataFromFile.m_bookmarksData;
|
||||
TEST_EQUAL(bookmarks.size(), 3, ());
|
||||
TEST_EQUAL("Point 1", bookmarks[0].m_name[kml::kDefaultLang], ());
|
||||
TEST_EQUAL(bookmarks[0].m_point, mercator::FromLatLon(48.20984622935899, 16.376023292541507), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Route)
|
||||
{
|
||||
kml::FileData dataFromFile = LoadGpxFromFile("test_data/gpx/route.gpx");
|
||||
auto line = dataFromFile.m_tracksData[0].m_geometry.m_lines[0];
|
||||
TEST_EQUAL(line.size(), 2, ());
|
||||
TEST_EQUAL(dataFromFile.m_categoryData.m_name[kml::kDefaultLang], "Some random route", ());
|
||||
TEST_EQUAL(line[0], geometry::PointWithAltitude(mercator::FromLatLon(48.20984622935899, 16.376023292541507), 184),
|
||||
());
|
||||
TEST_EQUAL(line[1], geometry::PointWithAltitude(mercator::FromLatLon(48.209503040543545, 16.381065845489506), 187),
|
||||
());
|
||||
}
|
||||
|
||||
UNIT_TEST(Color)
|
||||
{
|
||||
kml::FileData const dataFromFile = LoadGpxFromFile("test_data/gpx/color.gpx");
|
||||
uint32_t const red = 0xFF0000FF;
|
||||
uint32_t const blue = 0x0000FFFF;
|
||||
uint32_t const black = 0x000000FF;
|
||||
TEST_EQUAL(red, dataFromFile.m_tracksData[0].m_layers[0].m_color.m_rgba, ());
|
||||
TEST_EQUAL(blue, dataFromFile.m_tracksData[1].m_layers[0].m_color.m_rgba, ());
|
||||
TEST_EQUAL(black, dataFromFile.m_tracksData[2].m_layers[0].m_color.m_rgba, ());
|
||||
TEST_EQUAL(dataFromFile.m_tracksData.size(), 3, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(ParseExportedGpxColor)
|
||||
{
|
||||
kml::FileData const dataFromFile = LoadGpxFromFile("test_data/gpx/point_with_predefined_color_2.gpx");
|
||||
TEST_EQUAL(0x0066CCFF, dataFromFile.m_bookmarksData[0].m_color.m_rgba, ());
|
||||
TEST_EQUAL(kml::PredefinedColor::Blue, dataFromFile.m_bookmarksData[0].m_color.m_predefinedColor, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(MultiTrackNames)
|
||||
{
|
||||
kml::FileData dataFromFile = LoadGpxFromFile("test_data/gpx/color.gpx");
|
||||
TEST_EQUAL("new", dataFromFile.m_categoryData.m_name[kml::kDefaultLang], ());
|
||||
TEST_EQUAL("Short description", dataFromFile.m_categoryData.m_description[kml::kDefaultLang], ());
|
||||
TEST_EQUAL("new red", dataFromFile.m_tracksData[0].m_name[kml::kDefaultLang], ());
|
||||
TEST_EQUAL("description 1", dataFromFile.m_tracksData[0].m_description[kml::kDefaultLang], ());
|
||||
TEST_EQUAL("new blue", dataFromFile.m_tracksData[1].m_name[kml::kDefaultLang], ());
|
||||
TEST_EQUAL("description 2", dataFromFile.m_tracksData[1].m_description[kml::kDefaultLang], ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Empty)
|
||||
{
|
||||
kml::FileData dataFromFile = LoadGpxFromFile("test_data/gpx/empty.gpx");
|
||||
TEST_EQUAL("new", dataFromFile.m_categoryData.m_name[kml::kDefaultLang], ());
|
||||
TEST_EQUAL(0, dataFromFile.m_tracksData.size(), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(ImportExportWptColor)
|
||||
{
|
||||
ImportExportCompare("test_data/gpx/point_with_predefined_color_2.gpx");
|
||||
}
|
||||
|
||||
UNIT_TEST(PointWithPredefinedColor)
|
||||
{
|
||||
kml::FileData dataFromFile = LoadGpxFromFile("test_data/gpx/point_with_predefined_color_1.gpx");
|
||||
dataFromFile.m_bookmarksData[0].m_color.m_predefinedColor = kml::PredefinedColor::Blue;
|
||||
auto const actual = Serialize(dataFromFile);
|
||||
auto const expected = ReadFile("test_data/gpx/point_with_predefined_color_2.gpx");
|
||||
TEST_EQUAL(expected, actual, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(OsmandColor1)
|
||||
{
|
||||
kml::FileData const dataFromFile = LoadGpxFromFile("test_data/gpx/osmand1.gpx");
|
||||
uint32_t constexpr expected = 0xFF7800FF;
|
||||
TEST_EQUAL(dataFromFile.m_tracksData.size(), 4, ());
|
||||
TEST_EQUAL(expected, dataFromFile.m_tracksData[0].m_layers[0].m_color.m_rgba, ());
|
||||
TEST_EQUAL(expected, dataFromFile.m_tracksData[1].m_layers[0].m_color.m_rgba, ());
|
||||
TEST_EQUAL(expected, dataFromFile.m_tracksData[2].m_layers[0].m_color.m_rgba, ());
|
||||
TEST_EQUAL(expected, dataFromFile.m_tracksData[3].m_layers[0].m_color.m_rgba, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(OsmandColor2)
|
||||
{
|
||||
kml::FileData const dataFromFile = LoadGpxFromFile("test_data/gpx/osmand2.gpx");
|
||||
uint32_t const expected1 = 0x00FF00FF;
|
||||
uint32_t const expected2 = 0x1010A0FF;
|
||||
TEST_EQUAL(expected1, dataFromFile.m_bookmarksData[0].m_color.m_rgba, ());
|
||||
TEST_EQUAL(expected2, dataFromFile.m_bookmarksData[1].m_color.m_rgba, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Gpx_Test_Cmt)
|
||||
{
|
||||
std::string const input = R"(<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx version="1.0">
|
||||
<wpt lat="1" lon="2"><name>1</name><desc>d1</desc></wpt>
|
||||
<wpt lat="1" lon="2"><name>2</name><desc>d2</desc><cmt>c2</cmt></wpt>
|
||||
<wpt lat="1" lon="2"><name>3</name><cmt>c3</cmt></wpt>
|
||||
<wpt lat="1" lon="2"><name>4</name>
|
||||
<desc>
|
||||
d4
|
||||
d5
|
||||
|
||||
|
||||
</desc>
|
||||
<cmt>c4</cmt>
|
||||
</wpt>
|
||||
<wpt lat="1" lon="2"><name>5</name><cmt>qqq</cmt><desc>qqq</desc></wpt>
|
||||
)";
|
||||
kml::FileData const dataFromText = LoadGpxFromString(input);
|
||||
TEST_EQUAL("d1", dataFromText.m_bookmarksData[0].m_description.at(kml::kDefaultLang), ());
|
||||
TEST_EQUAL("d2\n\nc2", dataFromText.m_bookmarksData[1].m_description.at(kml::kDefaultLang), ());
|
||||
TEST_EQUAL("c3", dataFromText.m_bookmarksData[2].m_description.at(kml::kDefaultLang), ());
|
||||
TEST_EQUAL("d4\nd5\n\nc4", dataFromText.m_bookmarksData[3].m_description.at(kml::kDefaultLang), ());
|
||||
TEST_EQUAL("qqq", dataFromText.m_bookmarksData[4].m_description.at(kml::kDefaultLang), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(OpentracksColor)
|
||||
{
|
||||
kml::FileData dataFromFile = LoadGpxFromFile("test_data/gpx/opentracks_color.gpx");
|
||||
uint32_t const expected = 0xC0C0C0FF;
|
||||
TEST_EQUAL(expected, dataFromFile.m_tracksData[0].m_layers[0].m_color.m_rgba, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(ParseFromString)
|
||||
{
|
||||
// String hex sequence #AARRGGBB, uint32 sequence RGBA
|
||||
TEST_EQUAL(std::optional<uint32_t>(0x1FF), kml::gpx::GpxParser::ParseColorFromHexString("000001"), ());
|
||||
TEST_EQUAL(std::optional<uint32_t>(0x100FF), kml::gpx::GpxParser::ParseColorFromHexString("000100"), ());
|
||||
TEST_EQUAL(std::optional<uint32_t>(0x10000FF), kml::gpx::GpxParser::ParseColorFromHexString("010000"), ());
|
||||
TEST_EQUAL(std::optional<uint32_t>(0x1FF), kml::gpx::GpxParser::ParseColorFromHexString("#000001"), ());
|
||||
TEST_EQUAL(std::optional<uint32_t>(0x100FF), kml::gpx::GpxParser::ParseColorFromHexString("#000100"), ());
|
||||
TEST_EQUAL(std::optional<uint32_t>(0x10000FF), kml::gpx::GpxParser::ParseColorFromHexString("#010000"), ());
|
||||
TEST_EQUAL(std::optional<uint32_t>(0x1FF), kml::gpx::GpxParser::ParseColorFromHexString("#FF000001"), ());
|
||||
TEST_EQUAL(std::optional<uint32_t>(0x100FF), kml::gpx::GpxParser::ParseColorFromHexString("#FF000100"), ());
|
||||
TEST_EQUAL(std::optional<uint32_t>(0x10000FF), kml::gpx::GpxParser::ParseColorFromHexString("#FF010000"), ());
|
||||
TEST_EQUAL(std::optional<uint32_t>(0x10000AA), kml::gpx::GpxParser::ParseColorFromHexString("#AA010000"), ());
|
||||
TEST_EQUAL(std::optional<uint32_t>(), kml::gpx::GpxParser::ParseColorFromHexString("DarkRed"), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(MapGarminColor)
|
||||
{
|
||||
TEST_EQUAL("DarkCyan", kml::MapGarminColor(0x008b8bff), ());
|
||||
TEST_EQUAL("White", kml::MapGarminColor(0xffffffff), ());
|
||||
TEST_EQUAL("DarkYellow", kml::MapGarminColor(0xb4b820ff), ());
|
||||
TEST_EQUAL("DarkYellow", kml::MapGarminColor(0xb6b820ff), ());
|
||||
TEST_EQUAL("DarkYellow", kml::MapGarminColor(0xb5b721ff), ());
|
||||
}
|
||||
|
||||
} // namespace gpx_tests
|
||||
159
libs/kml/kml_tests/minzoom_quadtree_tests.cpp
Normal file
159
libs/kml/kml_tests/minzoom_quadtree_tests.cpp
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "kml/minzoom_quadtree.hpp"
|
||||
|
||||
#include "geometry/mercator.hpp"
|
||||
#include "geometry/point2d.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <random>
|
||||
#include <utility>
|
||||
|
||||
namespace
|
||||
{
|
||||
double constexpr kEps = std::numeric_limits<double>::epsilon();
|
||||
|
||||
m2::PointD MakeGlobalPoint(double x, double y)
|
||||
{
|
||||
m2::PointD point;
|
||||
point.x = x;
|
||||
point.y = y;
|
||||
point.x *= mercator::Bounds::kRangeX;
|
||||
point.y *= mercator::Bounds::kRangeY;
|
||||
point.x += mercator::Bounds::kMinX;
|
||||
point.y += mercator::Bounds::kMinY;
|
||||
return point;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
UNIT_TEST(Kml_MinzoomQuadtree_PopulationGrowthRate)
|
||||
{
|
||||
{
|
||||
kml::MinZoomQuadtree<double /* rank */, std::less<double>> minZoomQuadtree{{} /* less */};
|
||||
size_t const kMaxDepth = 5;
|
||||
double const step = 1.0 / (1 << kMaxDepth);
|
||||
for (int x = 0; x < (1 << kMaxDepth); ++x)
|
||||
for (int y = 0; y < (1 << kMaxDepth); ++y)
|
||||
minZoomQuadtree.Add(MakeGlobalPoint((0.5 + x) * step, (0.5 + y) * step), 0.0 /* rank */);
|
||||
double const kCountPerTile = 1.0;
|
||||
std::map<int /* zoom */, size_t> populationCount;
|
||||
auto const incZoomPopulation = [&](double & rank, int zoom)
|
||||
{
|
||||
TEST_ALMOST_EQUAL_ABS(rank, 0.0, kEps, ());
|
||||
++populationCount[zoom];
|
||||
};
|
||||
minZoomQuadtree.SetMinZoom(kCountPerTile, scales::GetUpperStyleScale(), incZoomPopulation);
|
||||
TEST_EQUAL(populationCount.size(), kMaxDepth + 1, (populationCount));
|
||||
|
||||
auto p = populationCount.cbegin();
|
||||
ASSERT(p != populationCount.cend(), ());
|
||||
std::vector<size_t> partialSums;
|
||||
partialSums.push_back(p->second);
|
||||
while (++p != populationCount.cend())
|
||||
partialSums.push_back(partialSums.back() + p->second);
|
||||
TEST_EQUAL(partialSums.front(), 1, ());
|
||||
TEST_EQUAL(partialSums.back(), (1 << (kMaxDepth * 2)), ());
|
||||
auto const isGrowthExponential = [](size_t lhs, size_t rhs) { return rhs != 4 * lhs; };
|
||||
TEST(std::adjacent_find(partialSums.cbegin(), partialSums.cend(), isGrowthExponential) == partialSums.cend(),
|
||||
(partialSums));
|
||||
}
|
||||
|
||||
std::mt19937 g(0);
|
||||
|
||||
auto const gen = [&g] { return std::generate_canonical<double, std::numeric_limits<uint32_t>::digits>(g); };
|
||||
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
kml::MinZoomQuadtree<double /* rank */, std::less<double>> minZoomQuadtree{{} /* less */};
|
||||
|
||||
size_t const kTotalCount = 1 + g() % 10000;
|
||||
for (size_t i = 0; i < kTotalCount; ++i)
|
||||
{
|
||||
auto const x = gen();
|
||||
auto const y = gen();
|
||||
auto const rank = gen();
|
||||
minZoomQuadtree.Add(MakeGlobalPoint(x, y), rank);
|
||||
}
|
||||
|
||||
double const kCountPerTile = 1.0 + kTotalCount * gen() / 2.0;
|
||||
std::map<int /* zoom */, size_t> populationCount;
|
||||
auto const incZoomPopulation = [&](double & /* rank */, int zoom) { ++populationCount[zoom]; };
|
||||
minZoomQuadtree.SetMinZoom(kCountPerTile, scales::GetUpperStyleScale(), incZoomPopulation);
|
||||
|
||||
auto p = populationCount.cbegin();
|
||||
ASSERT(p != populationCount.cend(), ());
|
||||
std::vector<size_t> partialSums;
|
||||
partialSums.push_back(p->second);
|
||||
while (++p != populationCount.cend())
|
||||
partialSums.push_back(partialSums.back() + p->second);
|
||||
TEST_EQUAL(partialSums.back(), kTotalCount, ());
|
||||
|
||||
double areaScale = 1.0;
|
||||
for (size_t i = 0; i < partialSums.size(); ++i)
|
||||
{
|
||||
auto const maxAbsErr = 4.0 * std::ceil(std::sqrt(kCountPerTile * areaScale)) + 4.0;
|
||||
TEST_LESS_OR_EQUAL(partialSums[i], kCountPerTile * areaScale + maxAbsErr,
|
||||
(kCountPerTile, maxAbsErr, partialSums));
|
||||
areaScale *= 4.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(Kml_MinzoomQuadtree_CornerCases)
|
||||
{
|
||||
{
|
||||
kml::MinZoomQuadtree<double /* rank */, std::less<double>> minZoomQuadtree{{} /* less */};
|
||||
minZoomQuadtree.Add(MakeGlobalPoint(0.5, 0.5), 0.0 /* rank */);
|
||||
double const kCountPerTile = 100.0;
|
||||
auto const checkRank = [&](double & rank, int zoom)
|
||||
{
|
||||
TEST_ALMOST_EQUAL_ABS(rank, 0.0, kEps, ());
|
||||
TEST_EQUAL(zoom, 1, ());
|
||||
};
|
||||
minZoomQuadtree.SetMinZoom(kCountPerTile, scales::GetUpperStyleScale(), checkRank);
|
||||
}
|
||||
|
||||
{
|
||||
kml::MinZoomQuadtree<double /* rank */, std::less<double>> minZoomQuadtree{{} /* less */};
|
||||
double const kCountPerTile = 100.0;
|
||||
auto const unreachable = [&](double & /* rank */, int /* zoom */) { TEST(false, ()); };
|
||||
minZoomQuadtree.SetMinZoom(kCountPerTile, scales::GetUpperStyleScale(), unreachable);
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(Kml_MinzoomQuadtree_MaxZoom)
|
||||
{
|
||||
kml::MinZoomQuadtree<double /* rank */, std::less<double>> minZoomQuadtree{{} /* less */};
|
||||
size_t const kMaxDepth = 5;
|
||||
double const step = 1.0 / (1 << kMaxDepth);
|
||||
for (int x = 0; x < (1 << kMaxDepth); ++x)
|
||||
for (int y = 0; y < (1 << kMaxDepth); ++y)
|
||||
minZoomQuadtree.Add(MakeGlobalPoint((0.5 + x) * step, (0.5 + y) * step), 0.0 /* rank */);
|
||||
double const kCountPerTile = 1.0;
|
||||
std::map<int /* zoom */, size_t> populationCount;
|
||||
auto const incZoomPopulation = [&](double & rank, int zoom)
|
||||
{
|
||||
TEST_ALMOST_EQUAL_ABS(rank, 0.0, kEps, ());
|
||||
++populationCount[zoom];
|
||||
};
|
||||
int const kMaxZoom = 4;
|
||||
minZoomQuadtree.SetMinZoom(kCountPerTile, kMaxZoom, incZoomPopulation);
|
||||
TEST_EQUAL(populationCount.size(), kMaxZoom, (populationCount));
|
||||
|
||||
auto p = populationCount.cbegin();
|
||||
ASSERT(p != populationCount.cend(), ());
|
||||
std::vector<size_t> partialSums;
|
||||
partialSums.push_back(p->second);
|
||||
while (++p != populationCount.cend())
|
||||
partialSums.push_back(partialSums.back() + p->second);
|
||||
TEST_EQUAL(partialSums.front(), 1, ());
|
||||
TEST_EQUAL(partialSums.back(), (1 << (kMaxDepth * 2)), ());
|
||||
auto const isGrowthExponential = [](size_t lhs, size_t rhs) { return rhs != 4 * lhs; };
|
||||
TEST(std::adjacent_find(partialSums.cbegin(), std::prev(partialSums.cend()), isGrowthExponential) ==
|
||||
std::prev(partialSums.cend()),
|
||||
(partialSums));
|
||||
TEST_LESS_OR_EQUAL(4 * *std::prev(partialSums.cend(), 2), partialSums.back(), ());
|
||||
}
|
||||
917
libs/kml/kml_tests/serdes_tests.cpp
Normal file
917
libs/kml/kml_tests/serdes_tests.cpp
Normal file
|
|
@ -0,0 +1,917 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "kml/kml_tests/tests_data.hpp"
|
||||
|
||||
#include "kml/serdes.hpp"
|
||||
#include "kml/serdes_binary.hpp"
|
||||
|
||||
#include "map/bookmark_helpers.hpp"
|
||||
|
||||
#include "indexer/classificator_loader.hpp"
|
||||
|
||||
#include "platform/platform.hpp"
|
||||
|
||||
#include "coding/file_reader.hpp"
|
||||
#include "coding/file_writer.hpp"
|
||||
#include "coding/hex.hpp"
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/string_utf8_multilang.hpp"
|
||||
#include "coding/writer.hpp"
|
||||
|
||||
#include "base/file_name_utils.hpp"
|
||||
#include "base/scope_guard.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
// This function can be used to generate textual representation of vector<uint8_t> like you see above.
|
||||
std::string FormatBytesFromBuffer(std::vector<uint8_t> const & buffer)
|
||||
{
|
||||
std::stringstream ss;
|
||||
for (size_t i = 1; i <= buffer.size(); i++)
|
||||
{
|
||||
ss << "0x" << NumToHex(buffer[i - 1]) << ", ";
|
||||
if (i % 16 == 0)
|
||||
ss << "\n";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
auto const kDefaultLang = StringUtf8Multilang::kDefaultCode;
|
||||
auto const kEnLang = StringUtf8Multilang::kEnglishCode;
|
||||
auto const kRuLang = static_cast<int8_t>(8);
|
||||
|
||||
kml::FileData GenerateKmlFileData()
|
||||
{
|
||||
kml::FileData result;
|
||||
result.m_deviceId = "AAAA";
|
||||
result.m_serverId = "AAAA-BBBB-CCCC-DDDD";
|
||||
|
||||
result.m_categoryData.m_name[kDefaultLang] = "Test category";
|
||||
result.m_categoryData.m_name[kRuLang] = "Тестовая категория";
|
||||
result.m_categoryData.m_description[kDefaultLang] = "Test description";
|
||||
result.m_categoryData.m_description[kRuLang] = "Тестовое описание";
|
||||
result.m_categoryData.m_annotation[kDefaultLang] = "Test annotation";
|
||||
result.m_categoryData.m_annotation[kEnLang] = "Test annotation";
|
||||
result.m_categoryData.m_imageUrl = "https://localhost/123.png";
|
||||
result.m_categoryData.m_visible = true;
|
||||
result.m_categoryData.m_authorName = "author";
|
||||
result.m_categoryData.m_authorId = "12345";
|
||||
result.m_categoryData.m_rating = 8.9;
|
||||
result.m_categoryData.m_reviewsNumber = 567;
|
||||
result.m_categoryData.m_lastModified = kml::TimestampClock::from_time_t(1000);
|
||||
result.m_categoryData.m_accessRules = kml::AccessRules::Public;
|
||||
result.m_categoryData.m_tags = {"mountains", "ski", "snowboard"};
|
||||
result.m_categoryData.m_toponyms = {"12345", "54321"};
|
||||
result.m_categoryData.m_languageCodes = {1, 2, 8};
|
||||
result.m_categoryData.m_properties = {{"property1", "value1"}, {"property2", "value2"}};
|
||||
|
||||
kml::BookmarkData bookmarkData;
|
||||
bookmarkData.m_name[kDefaultLang] = "Test bookmark";
|
||||
bookmarkData.m_name[kRuLang] = "Тестовая метка";
|
||||
bookmarkData.m_description[kDefaultLang] = "Test bookmark description";
|
||||
bookmarkData.m_description[kRuLang] = "Тестовое описание метки";
|
||||
bookmarkData.m_featureTypes = {718, 715};
|
||||
bookmarkData.m_customName[kDefaultLang] = "Мое любимое место";
|
||||
bookmarkData.m_customName[kEnLang] = "My favorite place";
|
||||
bookmarkData.m_color = {kml::PredefinedColor::Blue, 0};
|
||||
bookmarkData.m_icon = kml::BookmarkIcon::None;
|
||||
bookmarkData.m_viewportScale = 15;
|
||||
bookmarkData.m_timestamp = kml::TimestampClock::from_time_t(800);
|
||||
bookmarkData.m_point = m2::PointD(45.9242, 56.8679);
|
||||
bookmarkData.m_boundTracks = {0};
|
||||
bookmarkData.m_visible = false;
|
||||
bookmarkData.m_nearestToponym = "12345";
|
||||
bookmarkData.m_minZoom = 10;
|
||||
bookmarkData.m_properties = {{"bm_property1", "value1"}, {"bm_property2", "value2"}, {"score", "5"}};
|
||||
bookmarkData.m_compilations = {1, 2, 3, 4, 5};
|
||||
result.m_bookmarksData.emplace_back(std::move(bookmarkData));
|
||||
|
||||
kml::TrackData trackData;
|
||||
trackData.m_localId = 0;
|
||||
trackData.m_name[kDefaultLang] = "Test track";
|
||||
trackData.m_name[kRuLang] = "Тестовый трек";
|
||||
trackData.m_description[kDefaultLang] = "Test track description";
|
||||
trackData.m_description[kRuLang] = "Тестовое описание трека";
|
||||
trackData.m_layers = {{6.0, {kml::PredefinedColor::None, 0xff0000ff}},
|
||||
{7.0, {kml::PredefinedColor::None, 0x00ff00ff}}};
|
||||
trackData.m_timestamp = kml::TimestampClock::from_time_t(900);
|
||||
|
||||
trackData.m_geometry.AddLine({{{45.9242, 56.8679}, 1}, {{45.2244, 56.2786}, 2}, {{45.1964, 56.9832}, 3}});
|
||||
|
||||
trackData.m_visible = false;
|
||||
trackData.m_nearestToponyms = {"12345", "54321", "98765"};
|
||||
trackData.m_properties = {{"tr_property1", "value1"}, {"tr_property2", "value2"}};
|
||||
result.m_tracksData.emplace_back(std::move(trackData));
|
||||
|
||||
kml::CategoryData compilationData1;
|
||||
compilationData1.m_compilationId = 1;
|
||||
compilationData1.m_type = kml::CompilationType::Collection;
|
||||
compilationData1.m_name[kDefaultLang] = "Test collection";
|
||||
compilationData1.m_name[kRuLang] = "Тестовая коллекция";
|
||||
compilationData1.m_description[kDefaultLang] = "Test collection description";
|
||||
compilationData1.m_description[kRuLang] = "Тестовое описание коллекции";
|
||||
compilationData1.m_annotation[kDefaultLang] = "Test collection annotation";
|
||||
compilationData1.m_annotation[kEnLang] = "Test collection annotation";
|
||||
compilationData1.m_imageUrl = "https://localhost/1234.png";
|
||||
compilationData1.m_visible = true;
|
||||
compilationData1.m_authorName = "author";
|
||||
compilationData1.m_authorId = "54321";
|
||||
compilationData1.m_rating = 5.9;
|
||||
compilationData1.m_reviewsNumber = 333;
|
||||
compilationData1.m_lastModified = kml::TimestampClock::from_time_t(999);
|
||||
compilationData1.m_accessRules = kml::AccessRules::Public;
|
||||
compilationData1.m_tags = {"mountains", "ski"};
|
||||
compilationData1.m_toponyms = {"8", "9"};
|
||||
compilationData1.m_languageCodes = {1, 2, 8};
|
||||
compilationData1.m_properties = {{"property1", "value1"}, {"property2", "value2"}};
|
||||
result.m_compilationsData.push_back(std::move(compilationData1));
|
||||
|
||||
kml::CategoryData compilationData2;
|
||||
compilationData2.m_compilationId = 4;
|
||||
compilationData2.m_type = kml::CompilationType::Category;
|
||||
compilationData2.m_name[kDefaultLang] = "Test category";
|
||||
compilationData2.m_name[kRuLang] = "Тестовая категория";
|
||||
compilationData2.m_description[kDefaultLang] = "Test category description";
|
||||
compilationData2.m_description[kRuLang] = "Тестовое описание категории";
|
||||
compilationData2.m_annotation[kDefaultLang] = "Test category annotation";
|
||||
compilationData2.m_annotation[kEnLang] = "Test category annotation";
|
||||
compilationData2.m_imageUrl = "https://localhost/134.png";
|
||||
compilationData2.m_visible = false;
|
||||
compilationData2.m_authorName = "author";
|
||||
compilationData2.m_authorId = "11111";
|
||||
compilationData2.m_rating = 3.3;
|
||||
compilationData2.m_reviewsNumber = 222;
|
||||
compilationData2.m_lastModified = kml::TimestampClock::from_time_t(323);
|
||||
compilationData2.m_accessRules = kml::AccessRules::Public;
|
||||
compilationData2.m_tags = {"mountains", "bike"};
|
||||
compilationData2.m_toponyms = {"10", "11"};
|
||||
compilationData2.m_languageCodes = {1, 2, 8};
|
||||
compilationData2.m_properties = {{"property1", "value1"}, {"property2", "value2"}};
|
||||
result.m_compilationsData.push_back(std::move(compilationData2));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
kml::FileData GenerateKmlFileDataForTrackWithoutTimestamps()
|
||||
{
|
||||
auto data = GenerateKmlFileData();
|
||||
auto & trackData = data.m_tracksData[0];
|
||||
trackData.m_geometry.Clear();
|
||||
trackData.m_geometry.AddLine({{{45.9242, 56.8679}, 1}, {{45.2244, 56.2786}, 2}, {{45.1964, 56.9832}, 3}});
|
||||
trackData.m_geometry.AddTimestamps({});
|
||||
return data;
|
||||
}
|
||||
|
||||
kml::FileData GenerateKmlFileDataForTrackWithTimestamps()
|
||||
{
|
||||
auto data = GenerateKmlFileData();
|
||||
auto & trackData = data.m_tracksData[0];
|
||||
trackData.m_geometry.Clear();
|
||||
|
||||
// track 1 (without timestamps)
|
||||
trackData.m_geometry.AddLine({{{45.9242, 56.8679}, 1}, {{45.2244, 56.2786}, 2}, {{45.1964, 56.9832}, 3}});
|
||||
trackData.m_geometry.AddTimestamps({});
|
||||
|
||||
// track 2
|
||||
trackData.m_geometry.AddLine({{{45.9242, 56.8679}, 1}, {{45.2244, 56.2786}, 2}, {{45.1964, 56.9832}, 3}});
|
||||
trackData.m_geometry.AddTimestamps({0.0, 1.0, 2.0});
|
||||
|
||||
// track 3
|
||||
trackData.m_geometry.AddLine({{{45.9242, 56.8679}, 1}, {{45.2244, 56.2786}, 2}});
|
||||
trackData.m_geometry.AddTimestamps({0.0, 1.0});
|
||||
return data;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// 1. Check text and binary deserialization from the prepared sources in memory.
|
||||
UNIT_TEST(Kml_Deserialization_Text_Bin_Memory)
|
||||
{
|
||||
UNUSED_VALUE(FormatBytesFromBuffer({}));
|
||||
|
||||
kml::FileData dataFromText;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
kml::DeserializerKml des(dataFromText);
|
||||
MemReader reader(kTextKml, strlen(kTextKml));
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
|
||||
// TODO: uncomment to output bytes to the log.
|
||||
// std::vector<uint8_t> buffer;
|
||||
// {
|
||||
// kml::binary::SerializerKml ser(dataFromText);
|
||||
// MemWriter<decltype(buffer)> sink(buffer);
|
||||
// ser.Serialize(sink);
|
||||
// }
|
||||
// LOG(LINFO, (FormatBytesFromBuffer(buffer)));
|
||||
|
||||
kml::FileData dataFromBin;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
MemReader reader(kBinKml.data(), kBinKml.size());
|
||||
kml::binary::DeserializerKml des(dataFromBin);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
|
||||
TEST_EQUAL(dataFromText, dataFromBin, ());
|
||||
}
|
||||
|
||||
// 2. Check text serialization to the memory blob and compare with prepared data.
|
||||
UNIT_TEST(Kml_Serialization_Text_Memory)
|
||||
{
|
||||
kml::FileData data;
|
||||
{
|
||||
kml::DeserializerKml des(data);
|
||||
MemReader reader(kTextKml, strlen(kTextKml));
|
||||
des.Deserialize(reader);
|
||||
}
|
||||
|
||||
std::string resultBuffer;
|
||||
{
|
||||
MemWriter<decltype(resultBuffer)> sink(resultBuffer);
|
||||
kml::SerializerKml ser(data);
|
||||
ser.Serialize(sink);
|
||||
}
|
||||
|
||||
kml::FileData data2;
|
||||
{
|
||||
kml::DeserializerKml des(data2);
|
||||
MemReader reader(resultBuffer.c_str(), resultBuffer.length());
|
||||
des.Deserialize(reader);
|
||||
}
|
||||
|
||||
TEST_EQUAL(data, data2, ());
|
||||
}
|
||||
|
||||
// 3. Check binary serialization to the memory blob and compare with prepared data.
|
||||
UNIT_TEST(Kml_Serialization_Bin_Memory)
|
||||
{
|
||||
kml::FileData data;
|
||||
{
|
||||
kml::binary::DeserializerKml des(data);
|
||||
MemReader reader(kBinKml.data(), kBinKml.size());
|
||||
des.Deserialize(reader);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> buffer;
|
||||
{
|
||||
kml::binary::SerializerKml ser(data);
|
||||
MemWriter<decltype(buffer)> sink(buffer);
|
||||
ser.Serialize(sink);
|
||||
}
|
||||
|
||||
TEST_EQUAL(kBinKml, buffer, ());
|
||||
|
||||
kml::FileData data2;
|
||||
{
|
||||
kml::binary::DeserializerKml des(data2);
|
||||
MemReader reader(buffer.data(), buffer.size());
|
||||
des.Deserialize(reader);
|
||||
}
|
||||
|
||||
TEST_EQUAL(data, data2, ());
|
||||
}
|
||||
|
||||
// 4. Check deserialization from the text file.
|
||||
UNIT_TEST(Kml_Deserialization_Text_File)
|
||||
{
|
||||
std::string const kmlFile = base::JoinPath(GetPlatform().TmpDir(), "tmp.kml");
|
||||
SCOPE_GUARD(fileGuard, std::bind(&FileWriter::DeleteFileX, kmlFile));
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
FileWriter file(kmlFile);
|
||||
file.Write(kTextKml, strlen(kTextKml));
|
||||
},
|
||||
());
|
||||
|
||||
kml::FileData dataFromFile;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
kml::DeserializerKml des(dataFromFile);
|
||||
FileReader reader(kmlFile);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
|
||||
kml::FileData dataFromText;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
kml::DeserializerKml des(dataFromText);
|
||||
MemReader reader(kTextKml, strlen(kTextKml));
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
TEST_EQUAL(dataFromFile, dataFromText, ());
|
||||
}
|
||||
|
||||
// 5. Check deserialization from the binary file.
|
||||
UNIT_TEST(Kml_Deserialization_Bin_File)
|
||||
{
|
||||
std::string const kmbFile = base::JoinPath(GetPlatform().TmpDir(), "tmp.kmb");
|
||||
SCOPE_GUARD(fileGuard, std::bind(&FileWriter::DeleteFileX, kmbFile));
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
FileWriter file(kmbFile);
|
||||
file.Write(kBinKml.data(), kBinKml.size());
|
||||
},
|
||||
());
|
||||
|
||||
kml::FileData dataFromFile;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
kml::binary::DeserializerKml des(dataFromFile);
|
||||
FileReader reader(kmbFile);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
|
||||
kml::FileData dataFromBin;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
kml::binary::DeserializerKml des(dataFromBin);
|
||||
MemReader reader(kBinKml.data(), kBinKml.size());
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
|
||||
TEST_EQUAL(dataFromFile, dataFromBin, ());
|
||||
}
|
||||
|
||||
// 6. Check serialization to the binary file. Here we use generated data.
|
||||
// The data in RAM must be completely equal to the data in binary file.
|
||||
UNIT_TEST(Kml_Serialization_Bin_File)
|
||||
{
|
||||
auto data = GenerateKmlFileData();
|
||||
|
||||
std::string const kmbFile = base::JoinPath(GetPlatform().TmpDir(), "tmp.kmb");
|
||||
SCOPE_GUARD(fileGuard, std::bind(&FileWriter::DeleteFileX, kmbFile));
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
kml::binary::SerializerKml ser(data);
|
||||
FileWriter writer(kmbFile);
|
||||
ser.Serialize(writer);
|
||||
},
|
||||
());
|
||||
|
||||
kml::FileData dataFromFile;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
kml::binary::DeserializerKml des(dataFromFile);
|
||||
FileReader reader(kmbFile);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
|
||||
TEST_EQUAL(data, dataFromFile, ());
|
||||
}
|
||||
|
||||
// 7. Check serialization to the text file. Here we use generated data.
|
||||
// The text in the file can be not equal to the original generated data, because
|
||||
// text representation does not support all features, e.g. we do not store ids for
|
||||
// bookmarks and tracks.
|
||||
UNIT_TEST(Kml_Serialization_Text_File_Track_Without_Timestamps)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
auto data = GenerateKmlFileDataForTrackWithoutTimestamps();
|
||||
|
||||
std::string const kmlFile = base::JoinPath(GetPlatform().TmpDir(), "tmp.kml");
|
||||
SCOPE_GUARD(fileGuard, std::bind(&FileWriter::DeleteFileX, kmlFile));
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
kml::SerializerKml ser(data);
|
||||
FileWriter sink(kmlFile);
|
||||
ser.Serialize(sink);
|
||||
},
|
||||
());
|
||||
|
||||
// TODO: uncomment to output KML to the log.
|
||||
// std::string buffer;
|
||||
// {
|
||||
// kml::SerializerKml ser(data);
|
||||
// MemWriter<decltype(buffer)> sink(buffer);
|
||||
// ser.Serialize(sink);
|
||||
// }
|
||||
// LOG(LINFO, (buffer));
|
||||
|
||||
kml::FileData dataFromGeneratedFile;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
kml::DeserializerKml des(dataFromGeneratedFile);
|
||||
FileReader reader(kmlFile);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
TEST_EQUAL(dataFromGeneratedFile, data, ());
|
||||
|
||||
kml::FileData dataFromFile;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
kml::DeserializerKml des(dataFromFile);
|
||||
FileReader reader(GetPlatform().TestsDataPathForFile("test_data/kml/generated.kml"));
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
TEST_EQUAL(dataFromFile, data, ());
|
||||
|
||||
std::string dataFromFileBuffer;
|
||||
{
|
||||
MemWriter<decltype(dataFromFileBuffer)> sink(dataFromFileBuffer);
|
||||
kml::SerializerKml ser(dataFromFile);
|
||||
ser.Serialize(sink);
|
||||
}
|
||||
std::string dataFromGeneratedFileBuffer;
|
||||
{
|
||||
MemWriter<decltype(dataFromGeneratedFileBuffer)> sink(dataFromGeneratedFileBuffer);
|
||||
kml::SerializerKml ser(dataFromGeneratedFile);
|
||||
ser.Serialize(sink);
|
||||
}
|
||||
TEST_EQUAL(dataFromFileBuffer, dataFromGeneratedFileBuffer, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Kml_Serialization_Text_File_Tracks_With_Timestamps)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
auto data = GenerateKmlFileDataForTrackWithTimestamps();
|
||||
|
||||
std::string const kmlFile = base::JoinPath(GetPlatform().TmpDir(), "tmp.kml");
|
||||
SCOPE_GUARD(fileGuard, std::bind(&FileWriter::DeleteFileX, kmlFile));
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
kml::SerializerKml ser(data);
|
||||
FileWriter sink(kmlFile);
|
||||
ser.Serialize(sink);
|
||||
},
|
||||
());
|
||||
|
||||
kml::FileData dataFromGeneratedFile;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
kml::DeserializerKml des(dataFromGeneratedFile);
|
||||
FileReader reader(kmlFile);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
TEST_EQUAL(dataFromGeneratedFile, data, ());
|
||||
|
||||
kml::FileData dataFromFile;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
kml::DeserializerKml des(dataFromFile);
|
||||
FileReader reader(GetPlatform().TestsDataPathForFile("test_data/kml/generated_mixed_tracks.kml"));
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
TEST_EQUAL(dataFromFile, data, ());
|
||||
}
|
||||
|
||||
// 8. Check binary deserialization of v.3 format.
|
||||
UNIT_TEST(Kml_Deserialization_From_Bin_V3_And_V4)
|
||||
{
|
||||
kml::FileData dataFromBinV3;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
MemReader reader(kBinKmlV3.data(), kBinKmlV3.size());
|
||||
kml::binary::DeserializerKml des(dataFromBinV3);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
|
||||
kml::FileData dataFromBinV4;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
MemReader reader(kBinKmlV4.data(), kBinKmlV4.size());
|
||||
kml::binary::DeserializerKml des(dataFromBinV4);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
TEST_EQUAL(dataFromBinV3, dataFromBinV4, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Kml_Deserialization_From_Bin_V6_And_V7)
|
||||
{
|
||||
kml::FileData dataFromBinV6;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
MemReader reader(kBinKmlV6.data(), kBinKmlV6.size());
|
||||
kml::binary::DeserializerKml des(dataFromBinV6);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
|
||||
kml::FileData dataFromBinV7;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
MemReader reader(kBinKmlV7.data(), kBinKmlV7.size());
|
||||
kml::binary::DeserializerKml des(dataFromBinV7);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
TEST_EQUAL(dataFromBinV6, dataFromBinV7, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Kml_Deserialization_From_Bin_V7_And_V8)
|
||||
{
|
||||
kml::FileData dataFromBinV7;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
MemReader reader(kBinKmlV7.data(), kBinKmlV7.size());
|
||||
kml::binary::DeserializerKml des(dataFromBinV7);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
|
||||
kml::FileData dataFromBinV8;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
MemReader reader(kBinKmlV8.data(), kBinKmlV8.size());
|
||||
kml::binary::DeserializerKml des(dataFromBinV8);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
TEST_EQUAL(dataFromBinV7, dataFromBinV8, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Kml_Deserialization_From_Bin_V8_And_V8MM)
|
||||
{
|
||||
kml::FileData dataFromBinV8;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
MemReader reader(kBinKmlV8.data(), kBinKmlV8.size());
|
||||
kml::binary::DeserializerKml des(dataFromBinV8);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
|
||||
kml::FileData dataFromBinV8MM;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
MemReader reader(kBinKmlV8MM.data(), kBinKmlV8MM.size());
|
||||
kml::binary::DeserializerKml des(dataFromBinV8MM);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
|
||||
// Can't compare dataFromBinV8.m_categoryData and dataFromBinV8MM.m_categoryData directly
|
||||
// because new format has less properties and different m_id. Compare some properties here:
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_name, dataFromBinV8MM.m_categoryData.m_name, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_description, dataFromBinV8MM.m_categoryData.m_description, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_annotation, dataFromBinV8MM.m_categoryData.m_annotation, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_accessRules, dataFromBinV8MM.m_categoryData.m_accessRules, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_visible, dataFromBinV8MM.m_categoryData.m_visible, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_rating, dataFromBinV8MM.m_categoryData.m_rating, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_reviewsNumber, dataFromBinV8MM.m_categoryData.m_reviewsNumber, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_tags, dataFromBinV8MM.m_categoryData.m_tags, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_properties, dataFromBinV8MM.m_categoryData.m_properties, ());
|
||||
|
||||
TEST_EQUAL(dataFromBinV8.m_bookmarksData, dataFromBinV8MM.m_bookmarksData, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_tracksData, dataFromBinV8MM.m_tracksData, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Kml_Deserialization_From_KMB_V8_And_V9MM)
|
||||
{
|
||||
kml::FileData dataFromBinV8;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
MemReader reader(kBinKmlV8.data(), kBinKmlV8.size());
|
||||
kml::binary::DeserializerKml des(dataFromBinV8);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
|
||||
kml::FileData dataFromBinV9MM;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
MemReader reader(kBinKmlV9MM.data(), kBinKmlV9MM.size());
|
||||
kml::binary::DeserializerKml des(dataFromBinV9MM);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
|
||||
// Can't compare dataFromBinV8.m_categoryData and dataFromBinV9MM.m_categoryData directly
|
||||
// because new format has less properties and different m_id. Compare some properties here:
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_name, dataFromBinV9MM.m_categoryData.m_name, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_description, dataFromBinV9MM.m_categoryData.m_description, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_annotation, dataFromBinV9MM.m_categoryData.m_annotation, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_accessRules, dataFromBinV9MM.m_categoryData.m_accessRules, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_visible, dataFromBinV9MM.m_categoryData.m_visible, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_rating, dataFromBinV9MM.m_categoryData.m_rating, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_reviewsNumber, dataFromBinV9MM.m_categoryData.m_reviewsNumber, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_tags, dataFromBinV9MM.m_categoryData.m_tags, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_properties, dataFromBinV9MM.m_categoryData.m_properties, ());
|
||||
|
||||
dataFromBinV8.m_bookmarksData[0].m_id =
|
||||
dataFromBinV9MM.m_bookmarksData[0].m_id; // V8 and V9MM bookmarks have different IDs. Fix ID value manually.
|
||||
TEST_EQUAL(dataFromBinV8.m_bookmarksData, dataFromBinV9MM.m_bookmarksData, ());
|
||||
|
||||
dataFromBinV8.m_tracksData[0].m_id =
|
||||
dataFromBinV9MM.m_tracksData[0].m_id; // V8 and V9MM tracks have different IDs. Fix ID value manually.
|
||||
TEST_EQUAL(dataFromBinV8.m_tracksData, dataFromBinV9MM.m_tracksData, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Kml_Deserialization_From_KMB_V9MM_With_MultiGeometry)
|
||||
{
|
||||
kml::FileData dataFromBinV9MM;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
MemReader reader(kBinKmlMultiGeometryV9MM.data(), kBinKmlMultiGeometryV9MM.size());
|
||||
kml::binary::DeserializerKml des(dataFromBinV9MM);
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
|
||||
TEST_EQUAL(dataFromBinV9MM.m_tracksData.size(), 1, ());
|
||||
|
||||
// Verify that geometry has two lines
|
||||
auto lines = dataFromBinV9MM.m_tracksData[0].m_geometry.m_lines;
|
||||
TEST_EQUAL(lines.size(), 2, ());
|
||||
|
||||
// Verify that each line has 3 points
|
||||
auto line1 = lines[0];
|
||||
auto line2 = lines[1];
|
||||
|
||||
TEST_EQUAL(line1.size(), 3, ());
|
||||
TEST_EQUAL(line2.size(), 3, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Kml_Ver_2_3)
|
||||
{
|
||||
std::string_view constexpr data = R"(<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kml xmlns="http://www.opengis.net/kml/2.2" version="2.3">
|
||||
<Placemark id="PM005">
|
||||
<Track>
|
||||
<when>2010-05-28T02:02:09Z</when>
|
||||
<when>2010-05-28T02:02:35Z</when>
|
||||
<when>2010-05-28T02:02:44Z</when>
|
||||
<when>2010-05-28T02:02:53Z</when>
|
||||
<when>2010-05-28T02:02:54Z</when>
|
||||
<when>2010-05-28T02:02:55Z</when>
|
||||
<when>2010-05-28T02:02:56Z</when>
|
||||
<coord>-122.207881 37.371915 156.000000</coord>
|
||||
<coord>-122.205712 37.373288 152.000000</coord>
|
||||
<coord>-122.204678 37.373939 147.000000</coord>
|
||||
<coord>-122.203572 37.374630 142.199997</coord>
|
||||
<coord>-122.203451 37.374706 141.800003</coord>
|
||||
<coord>-122.203329 37.374780 141.199997</coord>
|
||||
<coord>-122.203207 37.374857 140.199997</coord>
|
||||
</Track>
|
||||
<gx:MultiTrack>
|
||||
<altitudeMode>absolute</altitudeMode>
|
||||
<gx:interpolate>0</gx:interpolate>
|
||||
<gx:Track>
|
||||
<gx:coord>9.42666332 52.94270656 95</gx:coord>
|
||||
<when>2022-12-25T13:12:01.914Z</when>
|
||||
<gx:coord>9.42682572 52.94270115 94</gx:coord>
|
||||
<when>2022-12-25T13:12:36Z</when>
|
||||
<gx:coord>9.42699411 52.94269624 94</gx:coord>
|
||||
<when>2022-12-25T13:12:38Z</when>
|
||||
<gx:coord>9.42716915 52.94268793 95</gx:coord>
|
||||
<when>2022-12-25T13:12:40Z</when>
|
||||
<gx:coord>9.42736231 52.94266046 95</gx:coord>
|
||||
<when>2022-12-25T13:12:42Z</when>
|
||||
<gx:coord>9.42757536 52.94266963 96</gx:coord>
|
||||
<when>2022-12-25T13:12:44Z</when>
|
||||
<ExtendedData>
|
||||
<SchemaData schemaUrl="#geotrackerTrackSchema">
|
||||
<gx:SimpleArrayData name="speed">
|
||||
<gx:value>0</gx:value>
|
||||
<gx:value>3.71</gx:value>
|
||||
<gx:value>5.22</gx:value>
|
||||
<gx:value>6.16</gx:value>
|
||||
<gx:value>7.1</gx:value>
|
||||
<gx:value>7.28</gx:value>
|
||||
</gx:SimpleArrayData>
|
||||
<gx:SimpleArrayData name="course">
|
||||
<gx:value />
|
||||
<gx:value>1.57</gx:value>
|
||||
<gx:value>1.62</gx:value>
|
||||
<gx:value>1.64</gx:value>
|
||||
<gx:value>1.69</gx:value>
|
||||
<gx:value>1.56</gx:value>
|
||||
</gx:SimpleArrayData>
|
||||
</SchemaData>
|
||||
</ExtendedData>
|
||||
</gx:Track>
|
||||
</gx:MultiTrack>
|
||||
</Placemark>
|
||||
</kml>)";
|
||||
|
||||
kml::FileData fData;
|
||||
TEST_NO_THROW({ kml::DeserializerKml(fData).Deserialize(MemReader(data)); }, ());
|
||||
|
||||
TEST_EQUAL(fData.m_tracksData.size(), 1, ());
|
||||
auto const & geom = fData.m_tracksData[0].m_geometry;
|
||||
auto const & lines = geom.m_lines;
|
||||
auto const & timestamps = geom.m_timestamps;
|
||||
TEST_EQUAL(lines.size(), 2, ());
|
||||
TEST_EQUAL(lines[0].size(), 7, ());
|
||||
TEST_EQUAL(lines[1].size(), 6, ());
|
||||
TEST(geom.HasTimestamps(), ());
|
||||
TEST(geom.HasTimestampsFor(0), ());
|
||||
TEST(geom.HasTimestampsFor(1), ());
|
||||
TEST_EQUAL(timestamps.size(), 2, ());
|
||||
TEST_EQUAL(timestamps[0].size(), 7, ());
|
||||
TEST_EQUAL(timestamps[1].size(), 6, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Kml_Placemark_contains_both_Bookmark_and_Track_data)
|
||||
{
|
||||
std::string_view constexpr input = R"(<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kml xmlns="http://www.opengis.net/kml/2.2">
|
||||
<Placemark>
|
||||
<MultiGeometry>
|
||||
<Point>
|
||||
<coordinates>28.968447783842,41.009030507129,0</coordinates>
|
||||
</Point>
|
||||
<LineString>
|
||||
<coordinates>28.968447783842,41.009030507129,0 28.965858,41.018449,0</coordinates>
|
||||
</LineString>
|
||||
</MultiGeometry>
|
||||
</Placemark>
|
||||
<Placemark>
|
||||
<MultiGeometry>
|
||||
<LineString>
|
||||
<coordinates>28.968447783842,41.009030507129,0 28.965858,41.018449,0</coordinates>
|
||||
</LineString>
|
||||
<Point>
|
||||
<coordinates>28.968447783842,41.009030507129,0</coordinates>
|
||||
</Point>
|
||||
</MultiGeometry>
|
||||
</Placemark>
|
||||
</kml>)";
|
||||
|
||||
kml::FileData fData;
|
||||
TEST_NO_THROW({ kml::DeserializerKml(fData).Deserialize(MemReader(input)); }, ());
|
||||
|
||||
TEST_EQUAL(fData.m_bookmarksData.size(), 2, ());
|
||||
TEST_EQUAL(fData.m_tracksData.size(), 2, ());
|
||||
|
||||
TEST(!fData.m_tracksData[0].m_geometry.HasTimestamps(), ());
|
||||
TEST(!fData.m_tracksData[1].m_geometry.HasTimestamps(), ());
|
||||
}
|
||||
|
||||
// See https://github.com/organicmaps/organicmaps/issues/5800
|
||||
UNIT_TEST(Fix_Invisible_Color_Bug_In_Gpx_Tracks)
|
||||
{
|
||||
std::string_view constexpr input = R"(<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kml xmlns="http://earth.google.com/kml/2.2">
|
||||
<Document>
|
||||
<name>2023-08-20 Malente Radtour</name>
|
||||
<visibility>1</visibility>
|
||||
<Placemark>
|
||||
<name>2023-08-20 Malente Radtour</name>
|
||||
<Style><LineStyle>
|
||||
<color>01000000</color>
|
||||
<width>3</width>
|
||||
</LineStyle></Style>
|
||||
<LineString><coordinates>10.565979,54.16597,26 10.565956,54.165997,26</coordinates></LineString>
|
||||
</Placemark>
|
||||
<Placemark>
|
||||
<name>Test default colors and width</name>
|
||||
<LineString><coordinates>10.465979,54.16597,26 10.465956,54.165997,26</coordinates></LineString>
|
||||
</Placemark>
|
||||
</Document>
|
||||
</kml>)";
|
||||
|
||||
kml::FileData fData;
|
||||
TEST_NO_THROW({ kml::DeserializerKml(fData).Deserialize(MemReader(input)); }, ());
|
||||
|
||||
TEST_EQUAL(fData.m_tracksData.size(), 2, ());
|
||||
TEST_EQUAL(fData.m_tracksData[0].m_layers.size(), 1, ());
|
||||
auto const & layer = fData.m_tracksData[0].m_layers[0];
|
||||
TEST_EQUAL(layer.m_color.m_rgba, kml::kDefaultTrackColor, ("Wrong transparency should be fixed"));
|
||||
TEST_EQUAL(layer.m_lineWidth, 3, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Kml_Tracks_With_Different_Points_And_Timestamps_Order)
|
||||
{
|
||||
kml::FileData dataFromFile;
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
kml::DeserializerKml des(dataFromFile);
|
||||
FileReader reader(
|
||||
GetPlatform().TestsDataPathForFile("test_data/kml/track_with_timestams_different_orders.kml"));
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
|
||||
TEST_EQUAL(dataFromFile.m_tracksData.size(), 1, ());
|
||||
auto const & geom = dataFromFile.m_tracksData[0].m_geometry;
|
||||
TEST_EQUAL(geom.m_lines.size(), 4, ());
|
||||
TEST_EQUAL(geom.m_timestamps.size(), 4, ());
|
||||
TEST_EQUAL(geom.m_lines[0], geom.m_lines[1], ());
|
||||
TEST_EQUAL(geom.m_lines[0], geom.m_lines[2], ());
|
||||
TEST_EQUAL(geom.m_lines[0], geom.m_lines[3], ());
|
||||
TEST_EQUAL(geom.m_timestamps[0], geom.m_timestamps[1], ());
|
||||
TEST_EQUAL(geom.m_timestamps[0], geom.m_timestamps[2], ());
|
||||
TEST_EQUAL(geom.m_timestamps[0], geom.m_timestamps[3], ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Kml_Track_Points_And_Timestamps_Sizes_Mismatch)
|
||||
{
|
||||
kml::FileData dataFromFile;
|
||||
TEST_ANY_THROW(
|
||||
{
|
||||
kml::DeserializerKml des(dataFromFile);
|
||||
FileReader reader(GetPlatform().TestsDataPathForFile("test_data/kml/track_with_timestamps_mismatch.kml"));
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
TEST_EQUAL(dataFromFile.m_tracksData.size(), 0, ());
|
||||
}
|
||||
|
||||
// https://github.com/organicmaps/organicmaps/issues/9290
|
||||
UNIT_TEST(Kml_Import_OpenTracks)
|
||||
{
|
||||
std::string_view constexpr input = R"(<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kml xmlns="http://earth.google.com/kml/2.2">
|
||||
<Placemark>
|
||||
<Track>
|
||||
<when>2010-05-28T02:00Z</when>
|
||||
<when>2010-05-28T02:01Z</when>
|
||||
<when>2010-05-28T02:02Z</when>
|
||||
<when>2010-05-28T02:03Z</when>
|
||||
<when>2010-05-28T02:04Z</when>
|
||||
<coord/>
|
||||
<coord>-122.205712 37.373288 152.000000</coord>
|
||||
<coord>Abra-cadabra</coord>
|
||||
<coord>-122.203572 37.374630 142.199997</coord>
|
||||
<coord/>
|
||||
</Track>
|
||||
</Placemark>
|
||||
</kml>)";
|
||||
|
||||
kml::FileData fData;
|
||||
TEST_NO_THROW({ kml::DeserializerKml(fData).Deserialize(MemReader(input)); }, ());
|
||||
|
||||
{
|
||||
TEST_EQUAL(fData.m_tracksData.size(), 1, ());
|
||||
auto const & geom = fData.m_tracksData[0].m_geometry;
|
||||
TEST_EQUAL(geom.m_lines.size(), 1, ());
|
||||
TEST_EQUAL(geom.m_lines.size(), geom.m_timestamps.size(), ());
|
||||
TEST_EQUAL(geom.m_lines[0].size(), 2, ());
|
||||
TEST_EQUAL(geom.m_lines[0].size(), geom.m_timestamps[0].size(), ());
|
||||
TEST_EQUAL(geom.m_timestamps[0][0], base::StringToTimestamp("2010-05-28T02:01Z"), ());
|
||||
TEST_EQUAL(geom.m_timestamps[0][1], base::StringToTimestamp("2010-05-28T02:03Z"), ());
|
||||
}
|
||||
|
||||
fData = {};
|
||||
TEST_NO_THROW(
|
||||
{
|
||||
kml::DeserializerKml des(fData);
|
||||
FileReader reader(GetPlatform().TestsDataPathForFile("test_data/kml/track_from_OpenTracks.kml"));
|
||||
des.Deserialize(reader);
|
||||
},
|
||||
());
|
||||
|
||||
{
|
||||
TEST_EQUAL(fData.m_tracksData.size(), 1, ());
|
||||
auto const & geom = fData.m_tracksData[0].m_geometry;
|
||||
TEST_EQUAL(geom.m_lines.size(), 1, ());
|
||||
TEST_EQUAL(geom.m_lines.size(), geom.m_timestamps.size(), ());
|
||||
TEST_GREATER(geom.m_lines[0].size(), 10, ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(Kml_BadTracks)
|
||||
{
|
||||
std::string_view constexpr input = R"(<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kml xmlns="http://earth.google.com/kml/2.2">
|
||||
<Placemark>
|
||||
<Track>
|
||||
<when>2010-05-28T02:00Z</when>
|
||||
<coord>-122.205712 37.373288 152.000000</coord>
|
||||
</Track>
|
||||
<gx:Track>
|
||||
<gx:coord>9.42666332 52.94270656 95</gx:coord>
|
||||
<when>2022-12-25T13:12:01.914Z</when>
|
||||
</gx:Track>
|
||||
<gx:Track>
|
||||
<gx:coord>9.42666332 52.94270656 95</gx:coord>
|
||||
<when>2022-12-25T13:12:01.914Z</when>
|
||||
<gx:coord>9.42682572 52.94270115 94</gx:coord>
|
||||
<when>2022-12-25T13:12:36Z</when>
|
||||
</gx:Track>
|
||||
</Placemark>
|
||||
</kml>)";
|
||||
|
||||
kml::FileData fData;
|
||||
TEST_NO_THROW({ kml::DeserializerKml(fData).Deserialize(MemReader(input)); }, ());
|
||||
|
||||
{
|
||||
TEST_EQUAL(fData.m_tracksData.size(), 1, ());
|
||||
auto const & geom = fData.m_tracksData[0].m_geometry;
|
||||
TEST_EQUAL(geom.m_lines.size(), 1, ());
|
||||
TEST_EQUAL(geom.m_lines.size(), geom.m_timestamps.size(), ());
|
||||
TEST_EQUAL(geom.m_lines[0].size(), 2, ());
|
||||
TEST_EQUAL(geom.m_lines[0].size(), geom.m_timestamps[0].size(), ());
|
||||
}
|
||||
}
|
||||
1478
libs/kml/kml_tests/tests_data.hpp
Normal file
1478
libs/kml/kml_tests/tests_data.hpp
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue