diff --git a/base/atomic_shared_ptr.hpp b/base/atomic_shared_ptr.hpp index a4e5b51fb9..3059f0dc09 100644 --- a/base/atomic_shared_ptr.hpp +++ b/base/atomic_shared_ptr.hpp @@ -22,6 +22,6 @@ public: private: ValueType m_wrapped = std::make_shared(); - DISALLOW_COPY(AtomicSharedPtr); + DISALLOW_COPY_AND_MOVE(AtomicSharedPtr); }; } // namespace base diff --git a/coding/serdes_json.hpp b/coding/serdes_json.hpp index 85041b79b0..088c9910b6 100644 --- a/coding/serdes_json.hpp +++ b/coding/serdes_json.hpp @@ -6,6 +6,7 @@ #include "3party/jansson/myjansson.hpp" +#include #include #include #include @@ -22,9 +23,9 @@ namespace impl { template auto is_iterable_checker(int) -> decltype( - std::begin(std::declval()), - std::end(std::declval()), - ++std::declval())) &>(), + std::begin(std::declval()), + std::end(std::declval()), + ++std::declval())) &>(), std::true_type {}); template diff --git a/map/framework.hpp b/map/framework.hpp index 21b1d3b0e1..a55b64defe 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -287,6 +287,7 @@ public: /// Shows group or leaf mwm on the map. void ShowNode(storage::TCountryId const & countryId); + // TipsApi::Delegate override. /// Checks, whether the country which contains the specified point is loaded. bool IsCountryLoaded(m2::PointD const & pt) const override; /// Checks, whether the country is loaded. @@ -361,6 +362,7 @@ public: search::Results::ConstIter end, bool clear, booking::filter::Types types) override; void ClearViewportSearchResults() override; + // SearchApi::Delegate and TipsApi::Delegate override. boost::optional GetCurrentPosition() const override; bool ParseSearchQueryCommand(search::SearchParams const & params) override; search::ProductInfo GetProductInfo(search::Result const & result) const override; @@ -886,5 +888,6 @@ private: public: TipsApi const & GetTipsApi() const; + // TipsApi::Delegate override. bool HaveTransit(m2::PointD const & pt) const override; }; diff --git a/map/map_tests/tips_tests.cpp b/map/map_tests/tips_tests.cpp index bf0b01f489..2bd615b31a 100644 --- a/map/map_tests/tips_tests.cpp +++ b/map/map_tests/tips_tests.cpp @@ -7,6 +7,9 @@ #include "metrics/eye.hpp" #include +#include + +#include using namespace eye; @@ -17,45 +20,54 @@ void MakeLastShownTipAvailableByTime() auto const info = Eye::Instance().GetInfo(); auto editableInfo = *info; auto & tips = editableInfo.m_tips; - tips.m_lastShown = Time(TipsApi::GetShowAnyTipPeriod() + std::chrono::seconds(1)); - tips.m_shownTips.back().m_lastShown = + tips.back().m_lastShownTime = Time(TipsApi::GetShowSameTipPeriod() + std::chrono::seconds(1)); EyeForTesting::SetInfo(editableInfo); } -TipsApi::Tip GetTipForTesting(TipsApi::Duration showAnyTipPeriod, - TipsApi::Duration showSameTipPeriod) +boost::optional GetTipForTesting(TipsApi::Duration showAnyTipPeriod, + TipsApi::Duration showSameTipPeriod) { - TipsApi::Conditions conditions = { - {[] { return true; }, [] { return true; }, [] { return true; }, [] { return true; }}}; + // Do not use additional conditions for testing. + TipsApi::Conditions conditions = + {{ + // Condition for Tips::Type::BookmarksCatalog type. + [] { return true; }, + // Condition for Tips::Type::BookingHotels type. + [] { return true; }, + // Condition for Tips::Type::DiscoverButton type. + [] { return true; }, + // Condition for Tips::Type::MapsLayers type. + [] { return true; } + }}; return TipsApi::GetTipForTesting(showAnyTipPeriod, showSameTipPeriod, conditions); } -TipsApi::Tip GetTipForTesting() +boost::optional GetTipForTesting() { return GetTipForTesting(TipsApi::GetShowAnyTipPeriod(), TipsApi::GetShowSameTipPeriod()); } -void ShowTipWithClickCountTest(Tips::Event eventType, size_t maxClickCount) +void ShowTipWithClickCountTest(Tip::Event eventType, size_t maxClickCount) { - std::vector usedTips; + std::vector usedTips; auto previousTip = GetTipForTesting(); TEST(previousTip.is_initialized(), ()); - TEST_NOT_EQUAL(previousTip.get(), Tips::Type::Count, ()); + TEST_NOT_EQUAL(previousTip.get(), Tip::Type::Count, ()); - auto const totalTipsCount = static_cast(Tips::Type::Count); + auto const totalTipsCount = static_cast(Tip::Type::Count); for (size_t i = 0; i < totalTipsCount; ++i) { auto tip = GetTipForTesting(); TEST(tip.is_initialized(), ()); - TEST_NOT_EQUAL(tip.get(), Tips::Type::Count, ()); + TEST_NOT_EQUAL(tip.get(), Tip::Type::Count, ()); EyeForTesting::AppendTip(tip.get(), eventType); - boost::optional secondTip; + boost::optional secondTip; for (size_t j = 1; j < maxClickCount; ++j) { MakeLastShownTipAvailableByTime(); @@ -81,9 +93,9 @@ UNIT_CLASS_TEST(ScopedEyeForTesting, ShowAnyTipPeriod_Test) auto firstTip = GetTipForTesting(); TEST(firstTip.is_initialized(), ()); - TEST_NOT_EQUAL(firstTip.get(), Tips::Type::Count, ()); + TEST_NOT_EQUAL(firstTip.get(), Tip::Type::Count, ()); - EyeForTesting::AppendTip(firstTip.get(), Tips::Event::GotitClicked); + EyeForTesting::AppendTip(firstTip.get(), Tip::Event::GotitClicked); auto secondTip = GetTipForTesting(); @@ -92,28 +104,28 @@ UNIT_CLASS_TEST(ScopedEyeForTesting, ShowAnyTipPeriod_Test) UNIT_CLASS_TEST(ScopedEyeForTesting, ShowFirstTip_Test) { - std::vector usedTips; + std::vector usedTips; auto previousTip = GetTipForTesting(); TEST(previousTip.is_initialized(), ()); - TEST_NOT_EQUAL(previousTip.get(), Tips::Type::Count, ()); + TEST_NOT_EQUAL(previousTip.get(), Tip::Type::Count, ()); - auto const totalTipsCount = static_cast(Tips::Type::Count); + auto const totalTipsCount = static_cast(Tip::Type::Count); for (size_t i = 0; i < totalTipsCount; ++i) { auto tip = GetTipForTesting({}, TipsApi::GetShowSameTipPeriod()); TEST(tip.is_initialized(), ()); - TEST_NOT_EQUAL(tip.get(), Tips::Type::Count, ()); + TEST_NOT_EQUAL(tip.get(), Tip::Type::Count, ()); auto const it = std::find(usedTips.cbegin(), usedTips.cend(), tip.get()); TEST(it == usedTips.cend(), ()); if (i % 2 == 0) - EyeForTesting::AppendTip(tip.get(), Tips::Event::ActionClicked); + EyeForTesting::AppendTip(tip.get(), Tip::Event::ActionClicked); else - EyeForTesting::AppendTip(tip.get(), Tips::Event::GotitClicked); + EyeForTesting::AppendTip(tip.get(), Tip::Event::GotitClicked); TEST(!GetTipForTesting().is_initialized(), ()); @@ -126,11 +138,11 @@ UNIT_CLASS_TEST(ScopedEyeForTesting, ShowFirstTip_Test) UNIT_CLASS_TEST(ScopedEyeForTesting, ShowTipAndActionClicked_Test) { - ShowTipWithClickCountTest(Tips::Event::ActionClicked, TipsApi::GetActionClicksCountToDisable()); + ShowTipWithClickCountTest(Tip::Event::ActionClicked, TipsApi::GetActionClicksCountToDisable()); } UNIT_CLASS_TEST(ScopedEyeForTesting, ShowTipAndGotitClicked_Test) { - ShowTipWithClickCountTest(Tips::Event::GotitClicked, TipsApi::GetGotitClicksCountToDisable()); + ShowTipWithClickCountTest(Tip::Event::GotitClicked, TipsApi::GetGotitClicksCountToDisable()); } } // namespace diff --git a/map/tips_api.cpp b/map/tips_api.cpp index 5c1c477bd0..dadd2a6665 100644 --- a/map/tips_api.cpp +++ b/map/tips_api.cpp @@ -4,7 +4,6 @@ #include "platform/platform.hpp" -#include #include using namespace eye; @@ -12,41 +11,49 @@ using namespace eye; namespace { // The app shouldn't show any screen at all more frequently than once in 3 days. -auto const kShowAnyTipPeriod = std::chrono::hours(24) * 3; +auto constexpr kShowAnyTipPeriod = std::chrono::hours(24) * 3; // The app shouldn't show the same screen more frequently than 1 month. -auto const kShowSameTipPeriod = std::chrono::hours(24) * 30; +auto constexpr kShowSameTipPeriod = std::chrono::hours(24) * 30; // If a user clicks on the action areas (highlighted or blue button) // the appropriate screen will never be shown again. -size_t const kActionClicksCountToDisable = 1; +size_t constexpr kActionClicksCountToDisable = 1; // If a user clicks 3 times on the button GOT IT the appropriate screen will never be shown again. -size_t const kGotitClicksCountToDisable = 3; +size_t constexpr kGotitClicksCountToDisable = 3; -size_t ToIndex(Tips::Type type) +size_t ToIndex(Tip::Type type) { return static_cast(type); } -TipsApi::Tip GetTipImpl(TipsApi::Duration showAnyTipPeriod, TipsApi::Duration showSameTipPeriod, - TipsApi::Conditions const & triggers) +boost::optional GetTipImpl(TipsApi::Duration showAnyTipPeriod, + TipsApi::Duration showSameTipPeriod, + TipsApi::Conditions const & triggers) { auto const info = Eye::Instance().GetInfo(); auto const & tips = info->m_tips; - auto const totalTipsCount = static_cast(Tips::Type::Count); + auto constexpr totalTipsCount = static_cast(Tip::Type::Count); - if (Clock::now() - tips.m_lastShown <= showAnyTipPeriod) + Time lastShownTime; + for (auto const & tip : tips) + { + if (lastShownTime < tip.m_lastShownTime) + lastShownTime = tip.m_lastShownTime; + } + + if (Clock::now() - lastShownTime <= showAnyTipPeriod) return {}; // If some tips are never shown. - if (tips.m_shownTips.size() < totalTipsCount) + if (tips.size() < totalTipsCount) { - using Candidate = std::pair; + using Candidate = std::pair; std::array candidates; for (size_t i = 0; i < totalTipsCount; ++i) { - candidates[i] = {static_cast(i), true}; + candidates[i] = {static_cast(i), true}; } - for (auto const & shownTip : tips.m_shownTips) + for (auto const & shownTip : tips) { candidates[ToIndex(shownTip.m_type)].second = false; } @@ -58,11 +65,11 @@ TipsApi::Tip GetTipImpl(TipsApi::Duration showAnyTipPeriod, TipsApi::Duration sh } } - for (auto const & shownTip : tips.m_shownTips) + for (auto const & shownTip : tips) { - if (shownTip.m_eventCounters.Get(Tips::Event::ActionClicked) < kActionClicksCountToDisable && - shownTip.m_eventCounters.Get(Tips::Event::GotitClicked) < kGotitClicksCountToDisable && - Clock::now() - shownTip.m_lastShown > showSameTipPeriod && + if (shownTip.m_eventCounters.Get(Tip::Event::ActionClicked) < kActionClicksCountToDisable && + shownTip.m_eventCounters.Get(Tip::Event::GotitClicked) < kGotitClicksCountToDisable && + Clock::now() - shownTip.m_lastShownTime > showSameTipPeriod && triggers[ToIndex(shownTip.m_type)]()) { return shownTip.m_type; @@ -131,14 +138,15 @@ void TipsApi::SetDelegate(std::unique_ptr delegate) m_delegate = std::move(delegate); } -TipsApi::Tip TipsApi::GetTip() const +boost::optional TipsApi::GetTip() const { return GetTipImpl(GetShowAnyTipPeriod(), GetShowSameTipPeriod(), m_conditions); } // static -TipsApi::Tip TipsApi::GetTipForTesting(Duration showAnyTipPeriod, Duration showSameTipPeriod, - Conditions const & triggers) +boost::optional TipsApi::GetTipForTesting(Duration showAnyTipPeriod, + Duration showSameTipPeriod, + Conditions const & triggers) { return GetTipImpl(showAnyTipPeriod, showSameTipPeriod, triggers); } diff --git a/map/tips_api.hpp b/map/tips_api.hpp index c48ba90af3..e974be12d3 100644 --- a/map/tips_api.hpp +++ b/map/tips_api.hpp @@ -2,7 +2,10 @@ #include "metrics/eye_info.hpp" +#include "geometry/point2d.hpp" + #include +#include #include #include #include @@ -12,14 +15,15 @@ class TipsApi { public: - using Tip = boost::optional; using Duration = std::chrono::duration; using Condition = std::function; - using Conditions = std::array(eye::Tips::Type::Count)>; + using Conditions = std::array(eye::Tip::Type::Count)>; class Delegate { public: + virtual ~Delegate() = default; + virtual boost::optional GetCurrentPosition() const = 0; virtual bool IsCountryLoaded(m2::PointD const & pt) const = 0; virtual bool HaveTransit(m2::PointD const & pt) const = 0; @@ -33,10 +37,11 @@ public: TipsApi(); void SetDelegate(std::unique_ptr delegate); - Tip GetTip() const; + boost::optional GetTip() const; - static Tip GetTipForTesting(Duration showAnyTipPeriod, Duration showSameTipPeriod, - Conditions const & triggers); + static boost::optional GetTipForTesting(Duration showAnyTipPeriod, + Duration showSameTipPeriod, + Conditions const & triggers); private: std::unique_ptr m_delegate; diff --git a/metrics/eye.cpp b/metrics/eye.cpp index 7015a86dd5..ea36704131 100644 --- a/metrics/eye.cpp +++ b/metrics/eye.cpp @@ -9,6 +9,9 @@ #include "base/logging.hpp" #include +#include +#include +#include using namespace eye; @@ -17,9 +20,7 @@ namespace void Load(Info & info) { std::vector fileData; - Storage::Load(Storage::GetEyeFilePath(), fileData); - - if (fileData.empty()) + if (!Storage::Load(Storage::GetEyeFilePath(), fileData)) { info = {}; return; @@ -70,34 +71,30 @@ void Eye::Save(InfoType const & info) m_info.Set(info); } -void Eye::AppendTip(Tips::Type type, Tips::Event event) +void Eye::AppendTip(Tip::Type type, Tip::Event event) { auto const info = m_info.Get(); - auto editableInfo = make_shared(*info); + auto editableInfo = std::make_shared(*info); auto & editableTips = editableInfo->m_tips; - auto & shownTips = editableTips.m_shownTips; - - ++(editableTips.m_totalShownTipsCount); - editableTips.m_lastShown = Clock::now(); - - auto it = std::find_if(shownTips.begin(), shownTips.end(), [type](Tips::Info const & tipsInfo) + auto it = std::find_if(editableTips.begin(), editableTips.end(), [type](Tip const & tip) { - return tipsInfo.m_type == type; + return tip.m_type == type; }); - if (it != shownTips.cend()) + auto const now = Clock::now(); + if (it != editableTips.cend()) { it->m_eventCounters.Increment(event); - it->m_lastShown = editableTips.m_lastShown; + it->m_lastShownTime = now; } else { - Tips::Info tipInfo; - tipInfo.m_type = type; - tipInfo.m_eventCounters.Increment(event); - tipInfo.m_lastShown = editableTips.m_lastShown; - shownTips.emplace_back(std::move(tipInfo)); + Tip tip; + tip.m_type = type; + tip.m_eventCounters.Increment(event); + tip.m_lastShownTime = now; + editableTips.emplace_back(std::move(tip)); } Save(editableInfo); @@ -105,7 +102,7 @@ void Eye::AppendTip(Tips::Type type, Tips::Event event) // Eye::Event methods ------------------------------------------------------------------------------ // static -void Eye::Event::TipShown(Tips::Type type, Tips::Event event) +void Eye::Event::TipShown(Tip::Type type, Tip::Event event) { Platform().RunTask(Platform::Thread::File, [type, event] { diff --git a/metrics/eye.hpp b/metrics/eye.hpp index 7ec0d6a5e2..06d0b2b5a8 100644 --- a/metrics/eye.hpp +++ b/metrics/eye.hpp @@ -20,7 +20,7 @@ public: class Event { public: - static void TipShown(Tips::Type type, Tips::Event event); + static void TipShown(Tip::Type type, Tip::Event event); }; static Eye & Instance(); @@ -33,7 +33,7 @@ private: void Save(InfoType const & info); // Event processing: - void AppendTip(Tips::Type type, Tips::Event event); + void AppendTip(Tip::Type type, Tip::Event event); base::AtomicSharedPtr m_info; diff --git a/metrics/eye_info.hpp b/metrics/eye_info.hpp index fd51afd163..eb51753778 100644 --- a/metrics/eye_info.hpp +++ b/metrics/eye_info.hpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -66,7 +67,7 @@ enum class Version : int8_t using Clock = std::chrono::system_clock; using Time = Clock::time_point; -struct Tips +struct Tip { // The order is important. // New types must be added before Type::Count item. @@ -88,25 +89,16 @@ struct Tips Count }; - struct Info - { - DECLARE_VISITOR(visitor(m_type, "type"), visitor(m_eventCounters, "event_counters"), - visitor(m_lastShown, "last_shown")) + DECLARE_VISITOR(visitor(m_type, "type"), visitor(m_eventCounters, "event_counters"), + visitor(m_lastShownTime, "last_shown_time")) - Type m_type; - Counters m_eventCounters; - Time m_lastShown; - }; - - DECLARE_VISITOR(visitor(m_shownTips, "last_shown_tips"), - visitor(m_totalShownTipsCount, "total_shown_tips_count"), - visitor(m_lastShown, "last_shown")) - - std::vector m_shownTips; - uint32_t m_totalShownTipsCount = 0; - Time m_lastShown; + Type m_type; + Counters m_eventCounters; + Time m_lastShownTime; }; +using Tips = std::vector; + struct InfoV0 { static Version GetVersion() { return Version::V0; } @@ -117,25 +109,25 @@ struct InfoV0 using Info = InfoV0; -inline std::string DebugPrint(Tips::Type const & type) +inline std::string DebugPrint(Tip::Type const & type) { switch (type) { - case Tips::Type::BookmarksCatalog: return "BookmarksCatalog"; - case Tips::Type::BookingHotels: return "BookingHotels"; - case Tips::Type::DiscoverButton: return "DiscoverButton"; - case Tips::Type::MapsLayers: return "MapsLayers"; - case Tips::Type::Count: return "Count"; + case Tip::Type::BookmarksCatalog: return "BookmarksCatalog"; + case Tip::Type::BookingHotels: return "BookingHotels"; + case Tip::Type::DiscoverButton: return "DiscoverButton"; + case Tip::Type::MapsLayers: return "MapsLayers"; + case Tip::Type::Count: return "Count"; } } -inline std::string DebugPrint(Tips::Event const & type) +inline std::string DebugPrint(Tip::Event const & type) { switch (type) { - case Tips::Event::ActionClicked: return "ActionClicked"; - case Tips::Event::GotitClicked: return "GotitClicked"; - case Tips::Event::Count: return "Count"; + case Tip::Event::ActionClicked: return "ActionClicked"; + case Tip::Event::GotitClicked: return "GotitClicked"; + case Tip::Event::Count: return "Count"; } } } // namespace eye diff --git a/metrics/eye_serdes.cpp b/metrics/eye_serdes.cpp index edb6ee44b3..2851f13b53 100644 --- a/metrics/eye_serdes.cpp +++ b/metrics/eye_serdes.cpp @@ -31,10 +31,9 @@ void Serdes::Deserialize(std::vector const & bytes, Info & result) MemReader reader(bytes.data(), bytes.size()); NonOwningReaderSource source(reader); - using VersionType = std::underlying_type_t; - VersionType version = static_cast(Version::Unknown); + auto version = static_cast(Version::Unknown); ReadPrimitiveFromSource(source, version); - if (version == static_cast(Version::V0)) + if (version == static_cast(Version::V0)) { try { diff --git a/metrics/eye_storage.cpp b/metrics/eye_storage.cpp index 4bba92b3db..e195fb15a6 100644 --- a/metrics/eye_storage.cpp +++ b/metrics/eye_storage.cpp @@ -9,6 +9,8 @@ #include "base/logging.hpp" +#include + namespace eye { // static @@ -37,7 +39,7 @@ bool Storage::Save(std::string const & filePath, std::vector const & src } // static -void Storage::Load(std::string const & filePath, std::vector & dst) +bool Storage::Load(std::string const & filePath, std::vector & dst) { try { @@ -51,6 +53,9 @@ void Storage::Load(std::string const & filePath, std::vector & dst) catch (FileReader::Exception const &) { dst.clear(); + return false; } + + return true; } } // namespace eye diff --git a/metrics/eye_storage.hpp b/metrics/eye_storage.hpp index 540b4eb7bd..3e2bcfce0d 100644 --- a/metrics/eye_storage.hpp +++ b/metrics/eye_storage.hpp @@ -1,6 +1,8 @@ #pragma once +#include #include +#include namespace eye { @@ -9,6 +11,6 @@ class Storage public: static std::string GetEyeFilePath(); static bool Save(std::string const & filePath, std::vector const & src); - static void Load(std::string const & filePath, std::vector & dst); + static bool Load(std::string const & filePath, std::vector & dst); }; } // namespace eye diff --git a/metrics/metrics_tests/eye_tests.cpp b/metrics/metrics_tests/eye_tests.cpp index fb29e950a1..2c51f8473a 100644 --- a/metrics/metrics_tests/eye_tests.cpp +++ b/metrics/metrics_tests/eye_tests.cpp @@ -7,6 +7,10 @@ #include "metrics/metrics_tests_support/eye_for_testing.hpp" +#include +#include +#include + using namespace eye; namespace @@ -14,27 +18,37 @@ namespace Info MakeDefaultInfoForTesting() { Info info; - info.m_tips.m_lastShown = Clock::now(); - ++(info.m_tips.m_totalShownTipsCount); - - Tips::Info tipInfo; - tipInfo.m_type = Tips::Type::DiscoverButton; - tipInfo.m_eventCounters.Increment(Tips::Event::GotitClicked); - tipInfo.m_lastShown = Clock::now(); - info.m_tips.m_shownTips.emplace_back(std::move(tipInfo)); + Tip tip; + tip.m_type = Tip::Type::DiscoverButton; + tip.m_eventCounters.Increment(Tip::Event::GotitClicked); + tip.m_lastShownTime = Time(std::chrono::hours(101010)); + info.m_tips.emplace_back(std::move(tip)); return info; } -void CompareWithDefaultInfo(Info const & lhs, Info const & rhs) +void CompareWithDefaultInfo(Info const & lhs) { - TEST_EQUAL(lhs.m_tips.m_lastShown, rhs.m_tips.m_lastShown, ()); - TEST_EQUAL(lhs.m_tips.m_totalShownTipsCount, rhs.m_tips.m_totalShownTipsCount, ()); - TEST_EQUAL(lhs.m_tips.m_shownTips.size(), rhs.m_tips.m_shownTips.size(), ()); - TEST(lhs.m_tips.m_shownTips[0].m_type == rhs.m_tips.m_shownTips[0].m_type, ()); - TEST_EQUAL(lhs.m_tips.m_shownTips[0].m_lastShown, rhs.m_tips.m_shownTips[0].m_lastShown, ()); - TEST_EQUAL(lhs.m_tips.m_shownTips[0].m_eventCounters.Get(Tips::Event::GotitClicked), - rhs.m_tips.m_shownTips[0].m_eventCounters.Get(Tips::Event::GotitClicked), ()); + auto const rhs = MakeDefaultInfoForTesting(); + + TEST_EQUAL(lhs.m_tips.size(), 1, ()); + TEST_EQUAL(lhs.m_tips.size(), rhs.m_tips.size(), ()); + TEST_EQUAL(lhs.m_tips[0].m_type, rhs.m_tips[0].m_type, ()); + TEST_EQUAL(lhs.m_tips[0].m_lastShownTime, rhs.m_tips[0].m_lastShownTime, ()); + TEST_EQUAL(lhs.m_tips[0].m_eventCounters.Get(Tip::Event::GotitClicked), + rhs.m_tips[0].m_eventCounters.Get(Tip::Event::GotitClicked), ()); +} + +Time GetLastShownTipTime(Tips const & tips) +{ + Time lastShownTime; + for (auto const & tip : tips) + { + if (lastShownTime < tip.m_lastShownTime) + lastShownTime = tip.m_lastShownTime; + } + + return lastShownTime; } } // namespace @@ -47,23 +61,22 @@ UNIT_TEST(Eye_SerdesTest) Info d; eye::Serdes::Deserialize(s, d); - CompareWithDefaultInfo(info, d); + CompareWithDefaultInfo(d); } UNIT_CLASS_TEST(ScopedEyeForTesting, SaveLoadTest) { auto const info = MakeDefaultInfoForTesting(); - std::string const kEyeFileName = "eye"; std::vector s; eye::Serdes::Serialize(info, s); - eye::Storage::Save(eye::Storage::GetEyeFilePath(), s); + TEST(eye::Storage::Save(eye::Storage::GetEyeFilePath(), s), ()); s.clear(); - eye::Storage::Load(eye::Storage::GetEyeFilePath(), s); + TEST(eye::Storage::Load(eye::Storage::GetEyeFilePath(), s), ()); Info d; eye::Serdes::Deserialize(s, d); - CompareWithDefaultInfo(info, d); + CompareWithDefaultInfo(d); } UNIT_CLASS_TEST(ScopedEyeForTesting, AppendTipTest) @@ -72,58 +85,57 @@ UNIT_CLASS_TEST(ScopedEyeForTesting, AppendTipTest) auto const initialInfo = Eye::Instance().GetInfo(); auto const & initialTips = initialInfo->m_tips; - TEST(initialTips.m_shownTips.empty(), ()); - TEST_EQUAL(initialTips.m_totalShownTipsCount, 0, ()); - TEST_EQUAL(initialTips.m_lastShown.time_since_epoch().count(), 0, ()); + TEST(initialTips.empty(), ()); + TEST_EQUAL(GetLastShownTipTime(initialTips).time_since_epoch().count(), 0, ()); } { - EyeForTesting::AppendTip(Tips::Type::DiscoverButton, Tips::Event::GotitClicked); + EyeForTesting::AppendTip(Tip::Type::DiscoverButton, Tip::Event::GotitClicked); auto const info = Eye::Instance().GetInfo(); auto const & tips = info->m_tips; + auto const lastShownTipTime = GetLastShownTipTime(tips); - TEST_EQUAL(tips.m_shownTips.size(), 1, ()); - TEST_NOT_EQUAL(tips.m_shownTips[0].m_lastShown.time_since_epoch().count(), 0, ()); - TEST_EQUAL(tips.m_shownTips[0].m_type, Tips::Type::DiscoverButton, ()); - TEST_EQUAL(tips.m_shownTips[0].m_eventCounters.Get(Tips::Event::GotitClicked), 1, ()); - TEST_EQUAL(tips.m_shownTips[0].m_eventCounters.Get(Tips::Event::ActionClicked), 0, ()); - TEST_EQUAL(tips.m_totalShownTipsCount, 1, ()); - TEST_NOT_EQUAL(tips.m_lastShown.time_since_epoch().count(), 0, ()); - TEST_EQUAL(tips.m_shownTips[0].m_lastShown, tips.m_lastShown, ()); + TEST_EQUAL(tips.size(), 1, ()); + TEST_NOT_EQUAL(tips[0].m_lastShownTime.time_since_epoch().count(), 0, ()); + TEST_EQUAL(tips[0].m_type, Tip::Type::DiscoverButton, ()); + TEST_EQUAL(tips[0].m_eventCounters.Get(Tip::Event::GotitClicked), 1, ()); + TEST_EQUAL(tips[0].m_eventCounters.Get(Tip::Event::ActionClicked), 0, ()); + TEST_NOT_EQUAL(lastShownTipTime.time_since_epoch().count(), 0, ()); + TEST_EQUAL(tips[0].m_lastShownTime, lastShownTipTime, ()); } Time prevShowTime; { - EyeForTesting::AppendTip(Tips::Type::MapsLayers, Tips::Event::ActionClicked); + EyeForTesting::AppendTip(Tip::Type::MapsLayers, Tip::Event::ActionClicked); auto const info = Eye::Instance().GetInfo(); auto const & tips = info->m_tips; + auto const lastShownTipTime = GetLastShownTipTime(tips); - TEST_EQUAL(tips.m_shownTips.size(), 2, ()); - TEST_NOT_EQUAL(tips.m_shownTips[1].m_lastShown.time_since_epoch().count(), 0, ()); - TEST_EQUAL(tips.m_shownTips[1].m_type, Tips::Type::MapsLayers, ()); - TEST_EQUAL(tips.m_shownTips[1].m_eventCounters.Get(Tips::Event::GotitClicked), 0, ()); - TEST_EQUAL(tips.m_shownTips[1].m_eventCounters.Get(Tips::Event::ActionClicked), 1, ()); - TEST_EQUAL(tips.m_totalShownTipsCount, 2, ()); - TEST_NOT_EQUAL(tips.m_lastShown.time_since_epoch().count(), 0, ()); - TEST_EQUAL(tips.m_shownTips[1].m_lastShown, tips.m_lastShown, ()); + TEST_EQUAL(tips.size(), 2, ()); + TEST_NOT_EQUAL(tips[1].m_lastShownTime.time_since_epoch().count(), 0, ()); + TEST_EQUAL(tips[1].m_type, Tip::Type::MapsLayers, ()); + TEST_EQUAL(tips[1].m_eventCounters.Get(Tip::Event::GotitClicked), 0, ()); + TEST_EQUAL(tips[1].m_eventCounters.Get(Tip::Event::ActionClicked), 1, ()); + TEST_NOT_EQUAL(lastShownTipTime.time_since_epoch().count(), 0, ()); + TEST_EQUAL(tips[1].m_lastShownTime, lastShownTipTime, ()); - prevShowTime = tips.m_lastShown; + prevShowTime = lastShownTipTime; } { - EyeForTesting::AppendTip(Tips::Type::MapsLayers, Tips::Event::GotitClicked); + EyeForTesting::AppendTip(Tip::Type::MapsLayers, Tip::Event::GotitClicked); auto const info = Eye::Instance().GetInfo(); auto const & tips = info->m_tips; + auto const lastShownTipTime = GetLastShownTipTime(tips); - TEST_EQUAL(tips.m_shownTips.size(), 2, ()); - TEST_NOT_EQUAL(tips.m_shownTips[1].m_lastShown.time_since_epoch().count(), 0, ()); - TEST_EQUAL(tips.m_shownTips[1].m_type, Tips::Type::MapsLayers, ()); - TEST_EQUAL(tips.m_shownTips[1].m_eventCounters.Get(Tips::Event::GotitClicked), 1, ()); - TEST_EQUAL(tips.m_shownTips[1].m_eventCounters.Get(Tips::Event::ActionClicked), 1, ()); - TEST_EQUAL(tips.m_totalShownTipsCount, 3, ()); - TEST_NOT_EQUAL(tips.m_lastShown.time_since_epoch().count(), 0, ()); - TEST_EQUAL(tips.m_shownTips[1].m_lastShown, tips.m_lastShown, ()); - TEST_NOT_EQUAL(prevShowTime, tips.m_lastShown, ()); + TEST_EQUAL(tips.size(), 2, ()); + TEST_NOT_EQUAL(tips[1].m_lastShownTime.time_since_epoch().count(), 0, ()); + TEST_EQUAL(tips[1].m_type, Tip::Type::MapsLayers, ()); + TEST_EQUAL(tips[1].m_eventCounters.Get(Tip::Event::GotitClicked), 1, ()); + TEST_EQUAL(tips[1].m_eventCounters.Get(Tip::Event::ActionClicked), 1, ()); + TEST_NOT_EQUAL(lastShownTipTime.time_since_epoch().count(), 0, ()); + TEST_EQUAL(tips[1].m_lastShownTime, lastShownTipTime, ()); + TEST_NOT_EQUAL(prevShowTime, lastShownTipTime, ()); } } diff --git a/metrics/metrics_tests_support/eye_for_testing.cpp b/metrics/metrics_tests_support/eye_for_testing.cpp index 9131dd38c5..8411811391 100644 --- a/metrics/metrics_tests_support/eye_for_testing.cpp +++ b/metrics/metrics_tests_support/eye_for_testing.cpp @@ -5,6 +5,8 @@ #include "coding/internal/file_data.hpp" +#include + namespace eye { // static @@ -19,7 +21,7 @@ void EyeForTesting::ResetEye() } // static -void EyeForTesting::AppendTip(Tips::Type type, Tips::Event event) +void EyeForTesting::AppendTip(Tip::Type type, Tip::Event event) { Eye::Instance().AppendTip(type, event); } @@ -27,6 +29,6 @@ void EyeForTesting::AppendTip(Tips::Type type, Tips::Event event) // static void EyeForTesting::SetInfo(Info const & info) { - Eye::Instance().m_info.Set(make_shared(info)); + Eye::Instance().m_info.Set(std::make_shared(info)); } } // namespace eye diff --git a/metrics/metrics_tests_support/eye_for_testing.hpp b/metrics/metrics_tests_support/eye_for_testing.hpp index 448d063e55..09c515c463 100644 --- a/metrics/metrics_tests_support/eye_for_testing.hpp +++ b/metrics/metrics_tests_support/eye_for_testing.hpp @@ -8,7 +8,7 @@ class EyeForTesting { public: static void ResetEye(); - static void AppendTip(Tips::Type type, Tips::Event event); + static void AppendTip(Tip::Type type, Tip::Event event); static void SetInfo(Info const & info); };