diff options
author | Arsentiy Milchakov <milcars@mapswithme.com> | 2017-08-16 16:10:37 +0300 |
---|---|---|
committer | Yuri Gorshenin <mipt.vi002@gmail.com> | 2017-08-16 16:20:50 +0300 |
commit | b3ab518fd70f72420f4278d7053ecaf880001817 (patch) | |
tree | e5f656564c51ce6c4ee102cf3db488d6f2822c6f /local_ads | |
parent | 948bcf950d8091b1db1960a814992d0062f10f6a (diff) |
[local_ads] campaign ser/des fixes + tests
Diffstat (limited to 'local_ads')
-rw-r--r-- | local_ads/campaign_serialization.cpp | 140 | ||||
-rw-r--r-- | local_ads/local_ads_tests/campaign_serialization_test.cpp | 25 |
2 files changed, 85 insertions, 80 deletions
diff --git a/local_ads/campaign_serialization.cpp b/local_ads/campaign_serialization.cpp index 8dcce2e803..1d583f3657 100644 --- a/local_ads/campaign_serialization.cpp +++ b/local_ads/campaign_serialization.cpp @@ -1,8 +1,12 @@ #include "local_ads/campaign_serialization.hpp" -#include "coding/varint.hpp" #include "coding/byte_stream.hpp" +#include "coding/reader.hpp" +#include "coding/varint.hpp" +#include "coding/write_to_sink.hpp" +#include "base/exception.hpp" +#include "base/logging.hpp" #include "base/stl_add.hpp" #include <climits> @@ -14,6 +18,8 @@ namespace { using namespace local_ads; +DECLARE_EXCEPTION(UnknownVersion, RootException); + auto const kHalfByteShift = CHAR_BIT / 2; auto const kHalfByteMaxValue = 15; auto const kLowerMask = 0x0F; @@ -22,44 +28,25 @@ auto const kMinZoomLevel = 10; auto const kMaxZoomLevel = 17; auto const kMaxPriority = 7; -template<typename T> -constexpr bool IsEnumOrIntegral() +template <typename Integral, typename Source, + typename std::enable_if<std::is_integral<Integral>::value, void *>::type = nullptr> +std::vector<Integral> ReadVarUintArray(Source & s, size_t chunksNumber) { - return std::is_integral<T>::value || std::is_enum<T>::value; -} - -template<typename ByteStream, typename T, - typename std::enable_if<IsEnumOrIntegral<T>(), void>::type * = nullptr> -void Write(ByteStream & s, T t) -{ - s.Write(&t, sizeof(T)); -} + std::vector<Integral> result; + for (size_t i = 0; i < chunksNumber; ++i) + result.emplace_back(static_cast<Integral>(ReadVarUint<uint64_t>(s))); -template<typename T, typename ByteStream, - typename std::enable_if<IsEnumOrIntegral<T>(), void>::type * = nullptr> -T Read(ByteStream & s) -{ - T t; - s.Read(static_cast<void*>(&t), sizeof(t)); - return t; + return result; } -template<typename Integral, - typename ByteStream, - typename std::enable_if<std::is_integral<Integral>::value, void*>::type = nullptr> -std::vector<Integral> ReadData(ByteStream & s, size_t chunksNumber) +template <typename Integral, typename Source> +std::vector<Integral> ReadArray(Source & s, size_t chunksNumber) { std::vector<Integral> result; - result.reserve(chunksNumber); - auto const streamBegin = s.PtrUC(); - auto const afterLastReadByte = ReadVarUint64Array( - streamBegin, - chunksNumber, - MakeBackInsertFunctor(result) - ); - - ASSERT_EQUAL(result.size(), chunksNumber, ()); - s.Advance(static_cast<decltype(streamBegin)>(afterLastReadByte) - streamBegin); + for (size_t i = 0; i < chunksNumber; ++i) + { + result.emplace_back(ReadPrimitiveFromSource<Integral>(s)); + } return result; } @@ -68,31 +55,28 @@ std::vector<uint8_t> SerializeV1(std::vector<Campaign> const & campaigns) { std::vector<uint8_t> buff; PushBackByteSink<decltype(buff)> dst(buff); - Write(dst, Version::V1); - Write(dst, campaigns.size()); + WriteToSink(dst, Version::V1); + WriteToSink(dst, campaigns.size()); for (auto const & c : campaigns) WriteVarUint(dst, c.m_featureId); for (auto const & c : campaigns) WriteVarUint(dst, c.m_iconId); for (auto const & c : campaigns) - Write(dst, c.m_daysBeforeExpired); + WriteVarUint(dst, c.m_daysBeforeExpired); return buff; } std::vector<Campaign> DeserializeV1(std::vector<uint8_t> const & bytes) { - ArrayByteSource src(bytes.data()); - CHECK_EQUAL(Read<Version>(src), Version::V1, ()); - auto const chunksNumber = Read<uint64_t>(src); + ReaderSource<MemReaderWithExceptions> src({bytes.data(), bytes.size()}); - auto const featureIds = ReadData<uint32_t>(src, chunksNumber); - auto const icons = ReadData<uint16_t>(src, chunksNumber); - auto const expirations = ReadData<uint8_t>(src, chunksNumber); + CHECK_EQUAL(ReadPrimitiveFromSource<Version>(src), Version::V1, ()); + auto const chunksNumber = ReadPrimitiveFromSource<uint64_t>(src); - CHECK_EQUAL(featureIds.size(), chunksNumber, ()); - CHECK_EQUAL(icons.size(), chunksNumber, ()); - CHECK_EQUAL(expirations.size(), chunksNumber, ()); + auto const featureIds = ReadVarUintArray<uint32_t>(src, chunksNumber); + auto const icons = ReadVarUintArray<uint16_t>(src, chunksNumber); + auto const expirations = ReadVarUintArray<uint8_t>(src, chunksNumber); std::vector<Campaign> campaigns; campaigns.reserve(chunksNumber); @@ -135,35 +119,32 @@ std::vector<uint8_t> SerializeV2(std::vector<Campaign> const & campaigns) { std::vector<uint8_t> buff; PushBackByteSink<decltype(buff)> dst(buff); - Write(dst, Version::V2); - Write(dst, campaigns.size()); + WriteToSink(dst, Version::V2); + WriteToSink(dst, campaigns.size()); for (auto const & c : campaigns) WriteVarUint(dst, c.m_featureId); for (auto const & c : campaigns) WriteVarUint(dst, c.m_iconId); for (auto const & c : campaigns) - Write(dst, c.m_daysBeforeExpired); + WriteVarUint(dst, c.m_daysBeforeExpired); for (auto const & c : campaigns) - Write(dst, PackZoomAndPriority(c.m_minZoomLevel, c.m_priority)); + WriteToSink(dst, PackZoomAndPriority(c.m_minZoomLevel, c.m_priority)); return buff; } std::vector<Campaign> DeserializeV2(std::vector<uint8_t> const & bytes) { - ArrayByteSource src(bytes.data()); - CHECK_EQUAL(Read<Version>(src), Version::V2, ()); - auto const chunksNumber = Read<uint64_t>(src); + ReaderSource<MemReaderWithExceptions> src({bytes.data(), bytes.size()}); + + CHECK_EQUAL(ReadPrimitiveFromSource<Version>(src), Version::V2, ()); + auto const chunksNumber = ReadPrimitiveFromSource<uint64_t>(src); - auto const featureIds = ReadData<uint32_t>(src, chunksNumber); - auto const icons = ReadData<uint16_t>(src, chunksNumber); - auto const expirations = ReadData<uint8_t>(src, chunksNumber); - auto const zoomAndPriority = ReadData<uint8_t>(src, chunksNumber); + auto const featureIds = ReadVarUintArray<uint32_t>(src, chunksNumber); + auto const icons = ReadVarUintArray<uint16_t>(src, chunksNumber); + auto const expirations = ReadVarUintArray<uint8_t>(src, chunksNumber); - CHECK_EQUAL(featureIds.size(), chunksNumber, ()); - CHECK_EQUAL(icons.size(), chunksNumber, ()); - CHECK_EQUAL(expirations.size(), chunksNumber, ()); - CHECK_EQUAL(zoomAndPriority.size(), chunksNumber, ()); + auto const zoomAndPriority = ReadArray<uint8_t>(src, chunksNumber); std::vector<Campaign> campaigns; campaigns.reserve(chunksNumber); @@ -187,11 +168,18 @@ namespace local_ads { std::vector<uint8_t> Serialize(std::vector<Campaign> const & campaigns, Version const version) { - switch (version) + try { - case Version::V1: return SerializeV1(campaigns); - case Version::V2: return SerializeV2(campaigns); - default: ASSERT(false, ("Unknown version")); + switch (version) + { + case Version::V1: return SerializeV1(campaigns); + case Version::V2: return SerializeV2(campaigns); + default: MYTHROW(UnknownVersion, (version)); + } + } + catch (RootException const & e) + { + LOG(LERROR, ("Cannot to serialize campaigns", e.what(), e.Msg())); } return {}; @@ -204,14 +192,26 @@ std::vector<uint8_t> Serialize(std::vector<Campaign> const & campaigns) std::vector<Campaign> Deserialize(std::vector<uint8_t> const & bytes) { - ArrayByteSource src(bytes.data()); - auto const version = Read<Version>(src); + try + { + ReaderSource<MemReaderWithExceptions> src({bytes.data(), bytes.size()}); - switch (version) + auto const version = ReadPrimitiveFromSource<Version>(src); + + switch (version) + { + case Version::V1: return DeserializeV1(bytes); + case Version::V2: return DeserializeV2(bytes); + default: MYTHROW(UnknownVersion, (version)); + } + } + catch (RootException const & e) { - case Version::V1: return DeserializeV1(bytes); - case Version::V2: return DeserializeV2(bytes); - default: ASSERT(false, ("Unknown version")); + LOG(LERROR, ("Cannot to deserialize received data", e.what(), e.Msg())); + } + catch (std::bad_alloc const & e) + { + LOG(LERROR, ("Cannot to allocate memory for local ads campaigns", e.what())); } return {}; diff --git a/local_ads/local_ads_tests/campaign_serialization_test.cpp b/local_ads/local_ads_tests/campaign_serialization_test.cpp index 4cec8f9ab0..a111539555 100644 --- a/local_ads/local_ads_tests/campaign_serialization_test.cpp +++ b/local_ads/local_ads_tests/campaign_serialization_test.cpp @@ -2,6 +2,7 @@ #include "local_ads/campaign_serialization.hpp" +#include <limits> #include <random> #include <vector> @@ -9,6 +10,9 @@ using namespace local_ads; namespace { +template <typename T> +using Limits = typename std::numeric_limits<T>; + bool TestSerialization(std::vector<Campaign> const & cs, Version const v) { auto const bytes = Serialize(cs, v); @@ -19,9 +23,9 @@ std::vector<Campaign> GenerateCampaignsV1(size_t number) { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution<> featureIds(1, 600000); - std::uniform_int_distribution<> icons(1, 4096); - std::uniform_int_distribution<> expirationDays(1, 30); + std::uniform_int_distribution<> featureIds(1, Limits<uint32_t>::max()); + std::uniform_int_distribution<> icons(1, Limits<uint16_t>::max()); + std::uniform_int_distribution<> expirationDays(1, Limits<uint8_t>::max()); std::vector<Campaign> cs; while (number--) @@ -38,9 +42,9 @@ std::vector<Campaign> GenerateCampaignsV2(size_t number) { int kSeed = 42; std::mt19937 gen(kSeed); - std::uniform_int_distribution<> featureIds(1, 600000); - std::uniform_int_distribution<> icons(1, 4096); - std::uniform_int_distribution<> expirationDays(1, 30); + std::uniform_int_distribution<> featureIds(1, Limits<uint32_t>::max()); + std::uniform_int_distribution<> icons(1, Limits<uint16_t>::max()); + std::uniform_int_distribution<> expirationDays(1, Limits<uint8_t>::max()); std::uniform_int_distribution<> zoomLevels(10, 17); std::uniform_int_distribution<> priorities(0, 7); @@ -61,14 +65,15 @@ std::vector<Campaign> GenerateCampaignsV2(size_t number) UNIT_TEST(Serialization_Smoke) { TEST(TestSerialization({ - {10, 10, 10}, - {1000, 100, 20}, + {0, 0, 0}, + {Limits<uint32_t>::max(), Limits<uint16_t>::max(), Limits<uint8_t>::max()}, {120003, 456, 15} }, Version::V1), ()); TEST(TestSerialization({ - {10, 10, 10, 10, 0}, - {1000, 100, 20, 17, 7}, + {0, 0, 0, 10, 0}, + {Limits<uint32_t>::max(), Limits<uint16_t>::max(), Limits<uint8_t>::max()}, + {1000, 100, 255, 17, 7}, {120003, 456, 15, 13, 6} }, Version::V2), ()); |