Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
19
tools/track_analyzing/track_analyzing_tests/CMakeLists.txt
Normal file
19
tools/track_analyzing/track_analyzing_tests/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
project(track_analyzing_tests)
|
||||
|
||||
set(SRC
|
||||
../track_analyzer/cmd_balance_csv.cpp
|
||||
../track_analyzer/cmd_balance_csv.hpp
|
||||
../track_analyzer/utils.cpp
|
||||
../track_analyzer/utils.hpp
|
||||
balance_tests.cpp
|
||||
statistics_tests.cpp
|
||||
track_archive_reader_tests.cpp
|
||||
)
|
||||
|
||||
omim_add_test(${PROJECT_NAME} ${SRC})
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
map
|
||||
tracking
|
||||
track_analyzing
|
||||
)
|
||||
256
tools/track_analyzing/track_analyzing_tests/balance_tests.cpp
Normal file
256
tools/track_analyzing/track_analyzing_tests/balance_tests.cpp
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "track_analyzing/track_analyzer/cmd_balance_csv.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace std;
|
||||
using namespace track_analyzing;
|
||||
|
||||
string const csv =
|
||||
R"(user,mwm,hw type,surface type,maxspeed km/h,is city road,is one way,is day,lat lon,distance,time,mean speed km/h,turn from smaller to bigger,turn from bigger to smaller,from link,to link,intersection with big,intersection with small,intersection with link
|
||||
I:D923B4DC-09E0-4B0B-B7F8-153965396B55,New Zealand,highway-trunk,psurface-paved_good,80,0,0,1,-41.4832 173.844,163.984,6,98.3902,0,0,0,0,0,1,0
|
||||
I:D923B4DC-09E0-4B0B-B7F8-153965396B55,New Zealand,highway-trunk,psurface-paved_good,80,0,0,1,-41.4831 173.845,2274.59,108,75.8196,0,0,0,0,0,4,0
|
||||
A:b6e31294-5c90-4105-9f7b-51a382eabfa0,Poland,highway-primary,psurface-paved_good,50,0,0,0,53.8524 21.3061,1199.34,60,71.9604,0,0,0,0,0,10,0)";
|
||||
|
||||
UNIT_TEST(FillTableTestEmpty)
|
||||
{
|
||||
std::stringstream ss;
|
||||
std::vector<TableRow> table;
|
||||
MwmToDataPoints matchedDataPoints;
|
||||
|
||||
// Stream without csv header.
|
||||
FillTable(ss, matchedDataPoints, table);
|
||||
TEST(table.empty(), ());
|
||||
TEST(matchedDataPoints.empty(), ());
|
||||
|
||||
// Stream with only csv header.
|
||||
ss << "mwm,number\n";
|
||||
FillTable(ss, matchedDataPoints, table);
|
||||
TEST(table.empty(), ());
|
||||
TEST(matchedDataPoints.empty(), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(FillTableTest)
|
||||
{
|
||||
std::stringstream ss;
|
||||
std::vector<TableRow> table;
|
||||
MwmToDataPoints matchedDataPoints;
|
||||
|
||||
ss << csv;
|
||||
FillTable(ss, matchedDataPoints, table);
|
||||
|
||||
MwmToDataPoints const expectedMatchedDataPoints = {{"New Zealand", 2 /* data points */},
|
||||
{"Poland", 1 /* data points */}};
|
||||
std::vector<TableRow> expectedTable = {
|
||||
{"I:D923B4DC-09E0-4B0B-B7F8-153965396B55", "New Zealand", "highway-trunk", "psurface-paved_good", "80", "0", "0",
|
||||
"1", "-41.4832 173.844", "163.984", "6", "98.3902", "0", "0", "0", "0", "0", "1", "0"},
|
||||
{"I:D923B4DC-09E0-4B0B-B7F8-153965396B55", "New Zealand", "highway-trunk", "psurface-paved_good", "80", "0", "0",
|
||||
"1", "-41.4831 173.845", "2274.59", "108", "75.8196", "0", "0", "0", "0", "0", "4", "0"},
|
||||
{"A:b6e31294-5c90-4105-9f7b-51a382eabfa0", "Poland", "highway-primary", "psurface-paved_good", "50", "0", "0",
|
||||
"0", "53.8524 21.3061", "1199.34", "60", "71.9604", "0", "0", "0", "0", "0", "10", "0"}};
|
||||
|
||||
TEST_EQUAL(matchedDataPoints, expectedMatchedDataPoints, ());
|
||||
TEST_EQUAL(table, expectedTable, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(AreKeysEqualEmptyMapsTest)
|
||||
{
|
||||
TEST(AreKeysEqual(MwmToDataPoints(), MwmToDataPoints()), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(AreKeysEqualTest)
|
||||
{
|
||||
MwmToDataPoints const map1 = {{"Russia_Moscow", 5 /* data points */}, {"San Marino", 7 /* data points */}};
|
||||
MwmToDataPoints map2 = {{"Russia_Moscow", 7 /* data points*/}, {"San Marino", 9 /* data points */}};
|
||||
TEST(AreKeysEqual(map1, map2), ());
|
||||
|
||||
map2["Slovakia"] = 3;
|
||||
TEST(!AreKeysEqual(map1, map2), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(RemoveKeysSmallValueEmptyTest)
|
||||
{
|
||||
MwmToDataPoints checkedMap;
|
||||
MwmToDataPoints additionalMap;
|
||||
RemoveKeysSmallValue(checkedMap, additionalMap, 10 /* ignoreDataPointNumber */);
|
||||
TEST(checkedMap.empty(), (checkedMap.size()));
|
||||
TEST(additionalMap.empty(), (checkedMap.size()));
|
||||
}
|
||||
|
||||
UNIT_TEST(RemoveKeysSmallValueTest)
|
||||
{
|
||||
MwmToDataPoints checkedMap = {{"Russia_Moscow", 3 /* data points */}, {"San Marino", 5 /* data points */}};
|
||||
MwmToDataPoints additionalMap = {{"Russia_Moscow", 7 /* data points*/}, {"San Marino", 9 /* data points */}};
|
||||
RemoveKeysSmallValue(checkedMap, additionalMap, 4 /* ignoreDataPointNumber */);
|
||||
|
||||
MwmToDataPoints expectedCheckedMap = {{"San Marino", 5 /* data points */}};
|
||||
MwmToDataPoints expectedAdditionalMap = {{"San Marino", 9 /* data points */}};
|
||||
|
||||
TEST_EQUAL(checkedMap, expectedCheckedMap, ());
|
||||
TEST_EQUAL(additionalMap, expectedAdditionalMap, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(GetMwmToDataPointFractionTest)
|
||||
{
|
||||
MwmToDataPoints const numberMapping = {{"Russia_Moscow", 100 /* data points */},
|
||||
{"San Marino", 50 /* data points */},
|
||||
{"Slovakia", 50 /* data points */}};
|
||||
auto const fractionMapping = GetMwmToDataPointFraction(numberMapping);
|
||||
|
||||
MwmToDataPointFraction expectedFractionMapping{
|
||||
{"Russia_Moscow", 0.5 /* fraction */}, {"San Marino", 0.25 /* fraction */}, {"Slovakia", 0.25 /* fraction */}};
|
||||
TEST_EQUAL(fractionMapping, expectedFractionMapping, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(CalcsMatchedDataPointsToKeepDistributionTest)
|
||||
{
|
||||
{
|
||||
MwmToDataPoints const matchedDataPoints = {{"Russia_Moscow", 400 /* data points */},
|
||||
{"San Marino", 400 /* data points */},
|
||||
{"Slovakia", 200 /* data points */}};
|
||||
MwmToDataPointFraction const distributionFraction = {{"Russia_Moscow", 0.8 /* data points */},
|
||||
{"San Marino", 0.1 /* data points */},
|
||||
{"Slovakia", 0.1 /* data points */}};
|
||||
MwmToDataPoints expected = {{"Russia_Moscow", 400 /* data points */},
|
||||
{"San Marino", 50 /* data points */},
|
||||
{"Slovakia", 50 /* data points */}};
|
||||
MwmToDataPoints const matchedDataPointsToKeepDistribution =
|
||||
CalcsMatchedDataPointsToKeepDistribution(matchedDataPoints, distributionFraction);
|
||||
TEST_EQUAL(matchedDataPointsToKeepDistribution, expected, ());
|
||||
}
|
||||
{
|
||||
MwmToDataPoints const matchedDataPoints = {{"Russia_Moscow", 800 /* data points */},
|
||||
{"San Marino", 100 /* data points */},
|
||||
{"Slovakia", 100 /* data points */}};
|
||||
MwmToDataPointFraction const distributionFraction = {{"Russia_Moscow", 0.2 /* data points */},
|
||||
{"San Marino", 0.4 /* data points */},
|
||||
{"Slovakia", 0.4 /* data points */}};
|
||||
MwmToDataPoints expected = {{"Russia_Moscow", 50 /* data points */},
|
||||
{"San Marino", 100 /* data points */},
|
||||
{"Slovakia", 100 /* data points */}};
|
||||
MwmToDataPoints const matchedDataPointsToKeepDistribution =
|
||||
CalcsMatchedDataPointsToKeepDistribution(matchedDataPoints, distributionFraction);
|
||||
TEST_EQUAL(matchedDataPointsToKeepDistribution, expected, ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(BalancedDataPointNumberTheSameTest)
|
||||
{
|
||||
MwmToDataPoints const distribution = {{"Russia_Moscow", 100 /* data points */},
|
||||
{"San Marino", 50 /* data points */},
|
||||
{"Slovakia", 50 /* data points */}};
|
||||
MwmToDataPoints const matchedDataPoints = {
|
||||
{"Russia_Moscow", 10 /* data points */}, {"San Marino", 5 /* data points */}, {"Slovakia", 5 /* data points */}};
|
||||
{
|
||||
// Case when the distribution is not changed. All mwms lose the same percent of data points.
|
||||
auto distr = distribution;
|
||||
auto matched = matchedDataPoints;
|
||||
auto const balancedDataPointNumber =
|
||||
BalancedDataPointNumber(std::move(matched), std::move(distr), 0 /* ignoreDataPointsNumber */);
|
||||
TEST_EQUAL(balancedDataPointNumber, matchedDataPoints, ());
|
||||
}
|
||||
|
||||
{
|
||||
// Case when the distribution is not changed. All mwms lose
|
||||
// the same percent of data points. But mwms with small number of points are moved.
|
||||
auto distr = distribution;
|
||||
auto matched = matchedDataPoints;
|
||||
auto const balancedDataPointNumber =
|
||||
BalancedDataPointNumber(std::move(matched), std::move(distr), 7 /* ignoreDataPointsNumber */);
|
||||
MwmToDataPoints expectedBalancedDataPointNumber = {{"Russia_Moscow", 10 /* data points */}};
|
||||
TEST_EQUAL(balancedDataPointNumber, expectedBalancedDataPointNumber, ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(BalancedDataPointNumberTest)
|
||||
{
|
||||
MwmToDataPoints distribution = {{"Russia_Moscow", 6000 /* data points */},
|
||||
{"San Marino", 3000 /* data points */},
|
||||
{"Slovakia", 1000 /* data points */}};
|
||||
MwmToDataPoints matchedDataPoints = {{"Russia_Moscow", 500 /* data points */},
|
||||
{"San Marino", 300 /* data points */},
|
||||
{"Slovakia", 10 /* data points */}};
|
||||
{
|
||||
auto distr = distribution;
|
||||
auto matched = matchedDataPoints;
|
||||
auto const balancedDataPointNumber =
|
||||
BalancedDataPointNumber(std::move(matched), std::move(distr), 7 /* ignoreDataPointsNumber */);
|
||||
MwmToDataPoints expectedBalancedDataPointNumber = {{"Russia_Moscow", 60 /* data points */},
|
||||
{"San Marino", 30 /* data points */},
|
||||
{"Slovakia", 10 /* data points */}};
|
||||
TEST_EQUAL(balancedDataPointNumber, expectedBalancedDataPointNumber, ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(BalancedDataPointNumberUint64Test)
|
||||
{
|
||||
MwmToDataPoints distribution = {{"Russia_Moscow", 6'000'000'000'000 /* data points */},
|
||||
{"San Marino", 3'000'000'000'000 /* data points */},
|
||||
{"Slovakia", 1'000'000'000'000 /* data points */}};
|
||||
MwmToDataPoints matchedDataPoints = {{"Russia_Moscow", 500'000'000'000 /* data points */},
|
||||
{"San Marino", 300'000'000'000 /* data points */},
|
||||
{"Slovakia", 10'000'000'000 /* data points */}};
|
||||
{
|
||||
auto distr = distribution;
|
||||
auto matched = matchedDataPoints;
|
||||
auto const balancedDataPointNumber =
|
||||
BalancedDataPointNumber(std::move(matched), std::move(distr), 7'000'000'000 /* ignoreDataPointsNumber */);
|
||||
MwmToDataPoints expectedBalancedDataPointNumber = {{"Russia_Moscow", 60'000'000'000 /* data points */},
|
||||
{"San Marino", 30'000'000'000 /* data points */},
|
||||
{"Slovakia", 10'000'000'000 /* data points */}};
|
||||
TEST_EQUAL(balancedDataPointNumber, expectedBalancedDataPointNumber, ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(FilterTableTest)
|
||||
{
|
||||
std::stringstream ss;
|
||||
std::vector<TableRow> csvTable;
|
||||
MwmToDataPoints matchedDataPoints;
|
||||
|
||||
ss << csv;
|
||||
FillTable(ss, matchedDataPoints, csvTable);
|
||||
|
||||
auto const calcRecords = [](vector<TableRow> const & t, string const & mwmName)
|
||||
{
|
||||
return count_if(t.cbegin(), t.cend(),
|
||||
[&mwmName](TableRow const & row) { return row[kMwmNameCsvColumn] == mwmName; });
|
||||
};
|
||||
|
||||
{
|
||||
auto table = csvTable;
|
||||
MwmToDataPoints const balancedDataPointNumbers = {{"New Zealand", 2 /* data points */},
|
||||
{"Poland", 1 /* data points */}};
|
||||
FilterTable(balancedDataPointNumbers, table);
|
||||
TEST_EQUAL(table.size(), 3, ());
|
||||
TEST_EQUAL(calcRecords(table, "New Zealand"), 2, ());
|
||||
TEST_EQUAL(calcRecords(table, "Poland"), 1, ());
|
||||
}
|
||||
|
||||
{
|
||||
auto table = csvTable;
|
||||
MwmToDataPoints const balancedDataPointNumbers = {{"New Zealand", 1 /* data points */},
|
||||
{"Poland", 1 /* data points */}};
|
||||
FilterTable(balancedDataPointNumbers, table);
|
||||
TEST_EQUAL(table.size(), 2, ());
|
||||
TEST_EQUAL(calcRecords(table, "New Zealand"), 1, ());
|
||||
TEST_EQUAL(calcRecords(table, "Poland"), 1, ());
|
||||
}
|
||||
|
||||
{
|
||||
auto table = csvTable;
|
||||
MwmToDataPoints const balancedDataPointNumbers = {{"New Zealand", 2 /* data points */}};
|
||||
FilterTable(balancedDataPointNumbers, table);
|
||||
TEST_EQUAL(table.size(), 2, ());
|
||||
TEST_EQUAL(calcRecords(table, "New Zealand"), 2, ());
|
||||
TEST_EQUAL(calcRecords(table, "Poland"), 0, ());
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
166
tools/track_analyzing/track_analyzing_tests/statistics_tests.cpp
Normal file
166
tools/track_analyzing/track_analyzing_tests/statistics_tests.cpp
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "track_analyzing/track_analyzer/utils.hpp"
|
||||
|
||||
#include "storage/routing_helpers.hpp"
|
||||
#include "storage/storage.hpp"
|
||||
|
||||
#include "routing/segment.hpp"
|
||||
|
||||
#include "traffic/speed_groups.hpp"
|
||||
|
||||
#include "platform/country_file.hpp"
|
||||
|
||||
#include "geometry/latlon.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace platform;
|
||||
using namespace routing;
|
||||
using namespace storage;
|
||||
using namespace track_analyzing;
|
||||
using namespace traffic;
|
||||
|
||||
void TestSerializationToCsv(Stats::NameToCountMapping const & mapping)
|
||||
{
|
||||
std::stringstream ss;
|
||||
MappingToCsv("mwm", mapping, false /* printPercentage */, ss);
|
||||
|
||||
Stats::NameToCountMapping readMapping;
|
||||
MappingFromCsv(ss, readMapping);
|
||||
|
||||
TEST_EQUAL(mapping, readMapping, (ss.str()));
|
||||
}
|
||||
|
||||
UNIT_TEST(AddDataPointsTest)
|
||||
{
|
||||
Stats stats;
|
||||
stats.AddDataPoints("mwm1", "country1", 3);
|
||||
stats.AddDataPoints("mwm1", "country1", 1);
|
||||
stats.AddDataPoints("mwm2", "country1", 5);
|
||||
stats.AddDataPoints("mwm3", "country3", 7);
|
||||
|
||||
Stats const expected = {{{"mwm1", 4}, {"mwm2", 5}, {"mwm3", 7} /* Mwm to number */},
|
||||
{{"country1", 9}, {"country3", 7} /* Country to number */}};
|
||||
|
||||
TEST_EQUAL(stats, expected, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(AddStatTest)
|
||||
{
|
||||
Stats stats1 = {{{"Belarus_Minsk Region", 1}, {"Uzbekistan", 7}, {"Russia_Moscow", 5} /* Mwm to number */},
|
||||
{{"Russian Federation", 10}, {"Poland", 5} /* Country to number */}};
|
||||
|
||||
Stats const stats2 = {{{"Belarus_Minsk Region", 2} /* Mwm to number */},
|
||||
{{"Russian Federation", 1}, {"Belarus", 8} /* Country to number */}};
|
||||
|
||||
stats1.Add(stats2);
|
||||
|
||||
Stats const expected = {{{"Belarus_Minsk Region", 3}, {"Uzbekistan", 7}, {"Russia_Moscow", 5} /* Mwm to number */},
|
||||
{{"Russian Federation", 11}, {"Poland", 5}, {"Belarus", 8} /* Country to number */}};
|
||||
|
||||
TEST_EQUAL(stats1, expected, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(AddTracksStatsTest)
|
||||
{
|
||||
DataPoint const dp1(1 /* timestamp */, ms::LatLon(), static_cast<uint8_t>(SpeedGroup::G5));
|
||||
DataPoint const dp2(2 /* timestamp */, ms::LatLon(), static_cast<uint8_t>(SpeedGroup::G5));
|
||||
DataPoint const dp3(3 /* timestamp */, ms::LatLon(), static_cast<uint8_t>(SpeedGroup::G5));
|
||||
DataPoint const dp4(4 /* timestamp */, ms::LatLon(), static_cast<uint8_t>(SpeedGroup::G5));
|
||||
|
||||
uint32_t constexpr kDataPointNumber = 4;
|
||||
|
||||
std::string const kMwmName = "Italy_Sardinia";
|
||||
|
||||
Track const track1 = {dp1, dp2};
|
||||
Track const track2 = {dp3};
|
||||
Track const track3 = {dp4};
|
||||
|
||||
UserToTrack const userToTrack = {{"id1", track1}, {"id2", track2}, {"id3", track3}};
|
||||
|
||||
Storage storage;
|
||||
auto numMwmIds = CreateNumMwmIds(storage);
|
||||
MwmToTracks const mwmToTracks = {{numMwmIds->GetId(CountryFile(kMwmName)), userToTrack}};
|
||||
|
||||
Stats stats;
|
||||
stats.AddTracksStats(mwmToTracks, *numMwmIds, storage);
|
||||
|
||||
Stats::NameToCountMapping const expectedMwmToTotalDataMapping = {{kMwmName, kDataPointNumber}};
|
||||
TEST_EQUAL(stats.GetMwmToTotalDataPointsForTesting(), expectedMwmToTotalDataMapping, ());
|
||||
|
||||
Stats::NameToCountMapping expectedCountryToTotalDataMapping = {{"Italy", kDataPointNumber}};
|
||||
TEST_EQUAL(stats.GetCountryToTotalDataPointsForTesting(), expectedCountryToTotalDataMapping, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(MappingToCsvTest)
|
||||
{
|
||||
Stats::NameToCountMapping const mapping = {{{"Belarus_Minsk Region", 2}, {"Uzbekistan", 5}, {"Russia_Moscow", 3}}};
|
||||
{
|
||||
std::ostringstream ss;
|
||||
MappingToCsv("mwm", mapping, true /* printPercentage */, ss);
|
||||
std::string const expected = R"(mwm,number,percent
|
||||
Uzbekistan,5,50
|
||||
Russia_Moscow,3,30
|
||||
Belarus_Minsk Region,2,20
|
||||
)";
|
||||
TEST_EQUAL(ss.str(), expected, ());
|
||||
}
|
||||
{
|
||||
std::ostringstream ss;
|
||||
MappingToCsv("mwm", mapping, false /* printPercentage */, ss);
|
||||
std::string const expected = R"(mwm,number
|
||||
Uzbekistan,5
|
||||
Russia_Moscow,3
|
||||
Belarus_Minsk Region,2
|
||||
)";
|
||||
TEST_EQUAL(ss.str(), expected, ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(MappingToCsvUint64Test)
|
||||
{
|
||||
Stats::NameToCountMapping const mapping = {{"Belarus_Minsk Region", 5'000'000'000}, {"Uzbekistan", 15'000'000'000}};
|
||||
std::stringstream ss;
|
||||
MappingToCsv("mwm", mapping, true /* printPercentage */, ss);
|
||||
std::string const expected = R"(mwm,number,percent
|
||||
Uzbekistan,15000000000,75
|
||||
Belarus_Minsk Region,5000000000,25
|
||||
)";
|
||||
TEST_EQUAL(ss.str(), expected, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(SerializationToCsvTest)
|
||||
{
|
||||
Stats::NameToCountMapping const mapping1 = {
|
||||
{"Belarus_Minsk Region", 2}, {"Uzbekistan", 5}, {"Russia_Moscow", 1}, {"Russia_Moscow Oblast_East", 2}};
|
||||
TestSerializationToCsv(mapping1);
|
||||
|
||||
Stats::NameToCountMapping const mapping2 = {{{"Belarus_Minsk Region", 2}, {"Uzbekistan", 5}, {"Russia_Moscow", 3}}};
|
||||
TestSerializationToCsv(mapping2);
|
||||
}
|
||||
|
||||
UNIT_TEST(SerializationToCsvWithZeroValueTest)
|
||||
{
|
||||
Stats::NameToCountMapping const mapping = {{"Russia_Moscow Oblast_East", 2}, {"Poland_Lesser Poland Voivodeship", 0}};
|
||||
Stats::NameToCountMapping const expected = {{"Russia_Moscow Oblast_East", 2}};
|
||||
|
||||
std::stringstream ss;
|
||||
MappingToCsv("mwm", mapping, false /* printPercentage */, ss);
|
||||
|
||||
Stats::NameToCountMapping readMapping;
|
||||
MappingFromCsv(ss, readMapping);
|
||||
|
||||
TEST_EQUAL(readMapping, expected, (ss.str()));
|
||||
}
|
||||
|
||||
UNIT_TEST(SerializationToCsvUint64Test)
|
||||
{
|
||||
Stats::NameToCountMapping const mapping = {
|
||||
{"Belarus_Minsk Region", 20'000'000'000}, {"Uzbekistan", 5}, {"Russia_Moscow", 7'000'000'000}};
|
||||
TestSerializationToCsv(mapping);
|
||||
}
|
||||
} // namespace
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "track_analyzing/temporary_file.hpp"
|
||||
#include "track_analyzing/track_archive_reader.hpp"
|
||||
|
||||
#include "tracking/archival_file.hpp"
|
||||
#include "tracking/archival_reporter.hpp"
|
||||
#include "tracking/archive.hpp"
|
||||
|
||||
#include "coding/hex.hpp"
|
||||
#include "coding/zip_creator.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "3party/minizip/minizip.hpp"
|
||||
|
||||
namespace track_analyzing
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
std::string GetToken(std::string const & str, size_t offset, std::string const & delimiter);
|
||||
std::string ParseString(std::string const & str, std::string const & delimiter, size_t & offset);
|
||||
|
||||
bool HasZipSignature(std::string const & binaryData);
|
||||
|
||||
struct UserTrackInfo
|
||||
{
|
||||
std::string m_userId;
|
||||
Track m_track;
|
||||
};
|
||||
|
||||
std::optional<UserTrackInfo> ParseLogRecord(std::string const & record, TemporaryFile & tmpArchiveFile);
|
||||
std::optional<std::string> ParseMultipartData(std::string const & binaryData);
|
||||
bool ParseTrackFile(unzip::File & zipReader, Track & trackData) noexcept;
|
||||
template <typename Reader, typename Pack>
|
||||
bool ReadTrackFromArchive(char const * data, size_t dataSize, Track & trackData) noexcept;
|
||||
} // namespace details
|
||||
} // namespace track_analyzing
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace std;
|
||||
using namespace track_analyzing;
|
||||
using namespace track_analyzing::details;
|
||||
|
||||
constexpr double kAccuracyEps = 1e-4;
|
||||
|
||||
UNIT_TEST(UnpackTrackArchiveDataTest)
|
||||
{
|
||||
// Step 1: Test data
|
||||
Track testTrack;
|
||||
testTrack.emplace_back(1577826000, ms::LatLon(55.270, 37.400), 0 /* G0 speed group */);
|
||||
testTrack.emplace_back(1577826001, ms::LatLon(55.270, 37.401), 0 /* G0 speed group */);
|
||||
testTrack.emplace_back(1577826002, ms::LatLon(55.271, 37.402), 0 /* G0 speed group */);
|
||||
testTrack.emplace_back(1577826003, ms::LatLon(55.272, 37.403), 0 /* G0 speed group */);
|
||||
testTrack.emplace_back(1577826005, ms::LatLon(55.273, 37.404), 0 /* G0 speed group */);
|
||||
|
||||
string const testUserId("0PpaB8NpazZYafAxUAphkuMY51w=");
|
||||
|
||||
// Step 2: Generate archive
|
||||
string const archiveFileName = tracking::archival_file::GetArchiveFilename(
|
||||
1 /* protocolVersion */, std::chrono::seconds(1577826000), routing::RouterType::Vehicle);
|
||||
|
||||
// Step 2.1: Fill archive with data points
|
||||
tracking::ArchiveCar archive(tracking::kItemsForDump, tracking::kMinDelaySecondsCar);
|
||||
for (auto const & point : testTrack)
|
||||
{
|
||||
archive.Add(point.m_latLon.m_lat, point.m_latLon.m_lon, uint32_t(point.m_timestamp),
|
||||
traffic::SpeedGroup(point.m_traffic));
|
||||
}
|
||||
|
||||
// Step 2.2: Store track file
|
||||
{
|
||||
FileWriter archiveWriter(archiveFileName);
|
||||
TEST_EQUAL(archive.Write(archiveWriter), true, ("Unable to write track file"));
|
||||
archiveWriter.Flush();
|
||||
}
|
||||
|
||||
// Step 2.2: Archive track files batch
|
||||
vector<string> trackFiles;
|
||||
trackFiles.push_back(archiveFileName);
|
||||
string const containerFileName("test_track_archive.zip");
|
||||
TEST_EQUAL(CreateZipFromFiles(trackFiles, containerFileName, CompressionLevel::NoCompression), true,
|
||||
("Unable to create tracks archive"));
|
||||
FileWriter::DeleteFileX(archiveFileName);
|
||||
|
||||
// Step 2.3: Read batch archive content
|
||||
vector<char> buffer;
|
||||
{
|
||||
FileReader containerReader(containerFileName);
|
||||
buffer.resize(containerReader.Size());
|
||||
containerReader.Read(0 /* file begin */, buffer.data(), buffer.size());
|
||||
}
|
||||
FileWriter::DeleteFileX(containerFileName);
|
||||
|
||||
// Step 2.4: Wrap as multipart data
|
||||
stringstream multipartStream;
|
||||
multipartStream << "------0000000000000\r\n";
|
||||
multipartStream << "Content-Disposition: form-data; name=\"file\"; filename=\"" << containerFileName << "\"\r\n";
|
||||
multipartStream << "Content-Type: application/zip\r\n";
|
||||
multipartStream << "\r\n";
|
||||
multipartStream.write(buffer.data(), buffer.size());
|
||||
multipartStream << "\r\n";
|
||||
multipartStream << "------0000000000000--\r\n";
|
||||
|
||||
string multipartData = multipartStream.str();
|
||||
|
||||
stringstream logStream;
|
||||
logStream << testUserId << "\t1\t1577826010\t" << multipartData.size() << "\t" << ToHex(multipartData);
|
||||
|
||||
string const logRecord = logStream.str();
|
||||
|
||||
// Unpack log record
|
||||
TemporaryFile tmpArchiveFile("tmp-unittest", ".zip");
|
||||
|
||||
optional<track_analyzing::details::UserTrackInfo> data = ParseLogRecord(logRecord, tmpArchiveFile);
|
||||
TEST_EQUAL(bool(data), true, ("Unable parse track archive record"));
|
||||
|
||||
TEST_EQUAL(data->m_userId, testUserId, ());
|
||||
|
||||
TEST_EQUAL(data->m_track.size(), testTrack.size(), ());
|
||||
for (size_t i = 0; i < testTrack.size(); ++i)
|
||||
{
|
||||
TEST_EQUAL(data->m_track[i].m_timestamp, testTrack[i].m_timestamp, ());
|
||||
TEST_ALMOST_EQUAL_ABS(data->m_track[i].m_latLon.m_lat, testTrack[i].m_latLon.m_lat, kAccuracyEps, ());
|
||||
TEST_ALMOST_EQUAL_ABS(data->m_track[i].m_latLon.m_lon, testTrack[i].m_latLon.m_lon, kAccuracyEps, ());
|
||||
TEST_EQUAL(data->m_track[i].m_traffic, testTrack[i].m_traffic, ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(ParseMultipartDataTest)
|
||||
{
|
||||
string const multipartData(
|
||||
"------1599512558929\r\n"
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"1_1599034479_2.track.zip\"\r\n"
|
||||
"Content-Type: application/zip\r\n"
|
||||
"\r\n"
|
||||
"PK\x03\x04\x14\x00\x00\x00\b\x00\x00\x00 \x00\x8D\xF4\x84~2\x00\x00\x00-"
|
||||
"\x00\x00\x00B\x00\x00\x00/storage/emulated/0/MapsWithMe/tracks_archive/1"
|
||||
"_1599034479_2.track\x01-\x00\xD2\xFFx\xDA;\xF6\xB6q\r\xCF\xAE\xFD;z9v,"
|
||||
"\xDA\xFB\x8B\xB5\xE3\xCA\xBF\xFF\xEC\xDF\xDF\x35\x34pLel\x00\x02\x0E0"
|
||||
"\xC1\x34\x84\x99\x00\xC8\xEAX\xF0PK\x01\x02\x00\x00\x14\x00\x00\x00\b"
|
||||
"\x00\x00\x00 \x00\x8D\xF4\x84~2\x00\x00\x00-\x00\x00\x00B\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00/storage/emulate"
|
||||
"d/0/MapsWithMe/tracks_archive/1_1599034479_2.trackPK\x05\x06\x00\x00\x00"
|
||||
"\x00\x01\x00\x01\x00p\x00\x00\x00\x92\x00\x00\x00\x00\x00\r\n"
|
||||
"------1599512558929--\r\n");
|
||||
string const expectedContent(
|
||||
"PK\x03\x04\x14\x00\x00\x00\b\x00\x00\x00 \x00\x8D\xF4\x84~2\x00\x00\x00-"
|
||||
"\x00\x00\x00B\x00\x00\x00/storage/emulated/0/MapsWithMe/tracks_archive/1"
|
||||
"_1599034479_2.track\x01-\x00\xD2\xFFx\xDA;\xF6\xB6q\r\xCF\xAE\xFD;z9v,"
|
||||
"\xDA\xFB\x8B\xB5\xE3\xCA\xBF\xFF\xEC\xDF\xDF\x35\x34pLel\x00\x02\x0E0"
|
||||
"\xC1\x34\x84\x99\x00\xC8\xEAX\xF0PK\x01\x02\x00\x00\x14\x00\x00\x00\b"
|
||||
"\x00\x00\x00 \x00\x8D\xF4\x84~2\x00\x00\x00-\x00\x00\x00B\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00/storage/emulate"
|
||||
"d/0/MapsWithMe/tracks_archive/1_1599034479_2.trackPK\x05\x06\x00\x00\x00"
|
||||
"\x00\x01\x00\x01\x00p\x00\x00\x00\x92\x00\x00\x00\x00\x00\r\n");
|
||||
|
||||
optional<string> content = ParseMultipartData(multipartData);
|
||||
TEST_EQUAL(bool(content), true, ());
|
||||
TEST_EQUAL(*content, expectedContent, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(ParseStringTest)
|
||||
{
|
||||
string const str("--token\r\nLine1\r\nMulti\nline\r\nPrefix\rline\r\n\r\n--token--\r\n");
|
||||
string const delimiter("\r\n");
|
||||
size_t offset = 0;
|
||||
|
||||
TEST_EQUAL(ParseString(str, delimiter, offset), "--token", ());
|
||||
TEST_EQUAL(ParseString(str, delimiter, offset), "Line1", ());
|
||||
TEST_EQUAL(ParseString(str, delimiter, offset), "Multi\nline", ());
|
||||
TEST_EQUAL(ParseString(str, delimiter, offset), "Prefix\rline", ());
|
||||
TEST_EQUAL(ParseString(str, delimiter, offset), "", ());
|
||||
TEST_EQUAL(ParseString(str, delimiter, offset), "--token--", ());
|
||||
TEST_EQUAL(offset, str.size(), ());
|
||||
|
||||
TEST_EQUAL(ParseString(str, delimiter, offset), "", ());
|
||||
TEST_EQUAL(offset, str.size(), ());
|
||||
|
||||
TEST_EQUAL(ParseString(str, delimiter, offset), "", ());
|
||||
TEST_EQUAL(offset, str.size(), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(ParseFullStringTest)
|
||||
{
|
||||
string const str("no delimiter");
|
||||
string const delimiter("\r\n");
|
||||
size_t offset = 0;
|
||||
|
||||
TEST_EQUAL(ParseString(str, delimiter, offset), str, ());
|
||||
TEST_EQUAL(offset, str.size(), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(CheckZipSignatureTest)
|
||||
{
|
||||
string const zipLikeContent("\x50\x4b\x03\x04\x00\x00\x00\x00");
|
||||
TEST_EQUAL(HasZipSignature(zipLikeContent), true, ());
|
||||
|
||||
string const nonzipContent("------1599512558929\r\n------1599512558929--\r\n");
|
||||
TEST_EQUAL(HasZipSignature(nonzipContent), false, ());
|
||||
|
||||
string const shortString("yes");
|
||||
TEST_EQUAL(HasZipSignature(nonzipContent), false, ());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Loading…
Add table
Add a link
Reference in a new issue