diff --git a/defines.hpp b/defines.hpp index 0465b0c87d..a111a72ece 100644 --- a/defines.hpp +++ b/defines.hpp @@ -62,4 +62,4 @@ /// How many langs we're supporting on indexing stage #define MAX_SUPPORTED_LANGUAGES 64 - +#define GPS_TRACK_FILENAME "gpstrack.bin" diff --git a/map/framework.cpp b/map/framework.cpp index 3ef36424f2..6a32663153 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -17,6 +17,7 @@ #include "search/search_engine.hpp" #include "search/search_query_factory.hpp" +#include "drape_frontend/gps_track_point.hpp" #include "drape_frontend/gui/country_status_helper.hpp" #include "drape_frontend/visual_params.hpp" #include "drape_frontend/watch/cpu_drawer.hpp" @@ -148,10 +149,7 @@ void Framework::OnLocationUpdate(GpsInfo const & info) m_routingSession.IsNavigable(), routeMatchingInfo)); if (m_gpsTrackingEnabled) - { - m2::PointD const point = MercatorBounds::FromLatLon(ms::LatLon(info.m_latitude, info.m_longitude)); - m_gpsTrack.AddPoint(point, info.m_speed, info.m_timestamp); - } + m_gpsTrack.AddPoint(info); } void Framework::OnCompassUpdate(CompassInfo const & info) @@ -204,6 +202,7 @@ void Framework::StopLocationFollow() Framework::Framework() : m_bmManager(*this) , m_gpsTrackingEnabled(false) + , m_gpsTrack(GetDefaultGpsTrack()) , m_fixedSearchResults(0) { m_activeMaps.reset(new ActiveMapsLayout(*this)); @@ -1320,7 +1319,7 @@ void Framework::CreateDrapeEngine(ref_ptr contextFactory, } if (m_gpsTrackingEnabled) - m_gpsTrack.SetCallback(bind(&df::DrapeEngine::UpdateGpsTrackPoints, m_drapeEngine.get(), _1, _2), true /* sendAll */); + m_gpsTrack.SetCallback(bind(&Framework::OnUpdateGpsTrackPointsCallback, this, _1, _2)); } ref_ptr Framework::GetDrapeEngine() @@ -1330,7 +1329,7 @@ ref_ptr Framework::GetDrapeEngine() void Framework::DestroyDrapeEngine() { - m_gpsTrack.SetCallback(nullptr, false /* sendAll */); + m_gpsTrack.SetCallback(nullptr); m_drapeEngine.reset(); } @@ -1354,12 +1353,12 @@ void Framework::EnableGpsTracking(bool enabled) m_gpsTrack.Clear(); if (m_drapeEngine) - m_gpsTrack.SetCallback(bind(&df::DrapeEngine::UpdateGpsTrackPoints, m_drapeEngine.get(), _1, _2), true /* sendAll */); + m_gpsTrack.SetCallback(bind(&Framework::OnUpdateGpsTrackPointsCallback, this, _1, _2)); } else { // Reset callback first to prevent notification about removed points on Clear - m_gpsTrack.SetCallback(nullptr, false /* sendAll */); + m_gpsTrack.SetCallback(nullptr); m_gpsTrack.Clear(); if (m_drapeEngine) @@ -1382,6 +1381,35 @@ hours Framework::GetGpsTrackingDuration() const return m_gpsTrack.GetDuration(); } +void Framework::OnUpdateGpsTrackPointsCallback(vector> && toAdd, + pair const & toRemove) +{ + ASSERT(m_drapeEngine.get() != nullptr, ()); + + vector pointsAdd; + pointsAdd.reserve(toAdd.size()); + for (auto const & ip : toAdd) + { + df::GpsTrackPoint pt; + pt.m_id = ip.first; + pt.m_speedMPS = ip.second.m_speed; + pt.m_timestamp = ip.second.m_timestamp; + pt.m_point = MercatorBounds::FromLatLon(ip.second.m_latitude, ip.second.m_longitude); + pointsAdd.emplace_back(pt); + } + + vector indicesRemove; + if (toRemove.first != GpsTrack::kInvalidId) + { + ASSERT_LESS_OR_EQUAL(toRemove.first, toRemove.second, ()); + indicesRemove.reserve(toRemove.second - toRemove.first + 1); + for (size_t i = toRemove.first; i <= toRemove.second; ++i) + indicesRemove.emplace_back(i); + } + + m_drapeEngine->UpdateGpsTrackPoints(move(pointsAdd), move(indicesRemove)); +} + void Framework::SetMapStyle(MapStyle mapStyle) { // Store current map style before classificator reloading diff --git a/map/framework.hpp b/map/framework.hpp index da8a613abe..77e96eb1fb 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -6,13 +6,12 @@ #include "map/bookmark_manager.hpp" #include "map/country_tree.hpp" #include "map/feature_vec_model.hpp" -#include "map/gps_track_container.hpp" +#include "map/gps_track.hpp" #include "map/mwm_url.hpp" #include "map/track.hpp" #include "drape_frontend/gui/skin.hpp" #include "drape_frontend/drape_engine.hpp" -#include "drape_frontend/gps_track_point.hpp" #include "drape_frontend/user_event_stream.hpp" #include "drape_frontend/watch/frame_image.hpp" @@ -130,8 +129,8 @@ protected: BookmarkManager m_bmManager; - GpsTrackContainer m_gpsTrack; atomic m_gpsTrackingEnabled; + GpsTrack & m_gpsTrack; /// This function is called by m_storage when latest local files /// were changed. @@ -351,6 +350,9 @@ private: void OnUpdateCountryIndex(storage::TIndex const & currentIndex, m2::PointF const & pt); void UpdateCountryInfo(storage::TIndex const & countryIndex, bool isCurrentCountry); + void OnUpdateGpsTrackPointsCallback(vector> && toAdd, + pair const & toRemove); + public: using TSearchRequest = search::QuerySaver::TSearchRequest; diff --git a/map/gps_track.cpp b/map/gps_track.cpp new file mode 100644 index 0000000000..365f289fc9 --- /dev/null +++ b/map/gps_track.cpp @@ -0,0 +1,317 @@ +#include "map/gps_track.hpp" + +#include "coding/file_name_utils.hpp" + +#include "platform/platform.hpp" + +#include "base/assert.hpp" +#include "base/logging.hpp" + +#include "defines.hpp" + +namespace +{ + +size_t const kGpsCollectionMaxItemCount = 100000; +size_t const kGpsFileMaxItemCount = 100000; +hours const kDefaultDuration = hours(24); + +} // namespace + +size_t const GpsTrack::kInvalidId = GpsTrackCollection::kInvalidId; + +GpsTrack::GpsTrack(string const & filePath) + : m_filePath(filePath) + , m_duration(kDefaultDuration) +{ +} + +void GpsTrack::AddPoint(location::GpsTrackInfo const & info) +{ + lock_guard lg(m_guard); + + InitFile(); + + // Write point to the file. + // If file exception happens, then drop file. + if (m_file) + { + try + { + size_t evictedId; + m_file->Append(info, evictedId); + } + catch (RootException & e) + { + LOG(LINFO, ("GpsTrackFile.Append has caused exception:", e.Msg())); + m_file.reset(); + } + } + + if (!m_collection) + return; + + // Write point to the collection + pair evictedIds; + size_t const addedId = m_collection->Add(info, evictedIds); + if (addedId == GpsTrackCollection::kInvalidId) + return; // nothing was added + + if (!m_callback) + return; + + vector> toAdd; + toAdd.emplace_back(addedId, info); + + m_callback(move(toAdd), move(evictedIds)); +} + +void GpsTrack::AddPoints(vector const & points) +{ + if (points.empty()) + return; + + lock_guard lg(m_guard); + + InitFile(); + + // Write point to the file. + // If file exception happens, then drop file. + if (m_file) + { + try + { + for (auto const & point : points) + { + size_t evictedId; + m_file->Append(point, evictedId); + } + } + catch (RootException & e) + { + LOG(LINFO, ("GpsTrackFile.Append has caused exception:", e.Msg())); + m_file.reset(); + } + } + + if (!m_collection) + return; + + // Add points + pair evictedIds; + pair const addedIds = m_collection->Add(points, evictedIds); + if (addedIds.first == GpsTrackCollection::kInvalidId) + return; // nothing was added + + if (!m_callback) + return; + + size_t const addedCount = addedIds.second - addedIds.first + 1; + ASSERT_GREATER_OR_EQUAL(m_collection->GetSize(), addedCount, ()); + + // Not all points from infos could be added to collection due to timestamp consequence restriction. + // Get added points from collection. + vector> toAdd; + toAdd.reserve(addedCount); + m_collection->ForEach([&toAdd](location::GpsTrackInfo const & point, size_t id)->bool + { + toAdd.emplace_back(id, point); + return true; + }, m_collection->GetSize() - addedCount); + ASSERT_EQUAL(toAdd.size(), addedCount, ()); + + m_callback(move(toAdd), evictedIds); +} + +void GpsTrack::Clear() +{ + lock_guard lg(m_guard); + + InitFile(); + + if (m_file) + { + try + { + m_file->Clear(); + } + catch (RootException & e) + { + LOG(LINFO, ("GpsTrackFile.Clear has caused exception:", e.Msg())); + m_file.reset(); + } + } + + if (!m_collection) + return; + + auto const evictedIds = m_collection->Clear(); + if (evictedIds.first == GpsTrackCollection::kInvalidId) + return; // nothing was removed + + if (!m_callback) + return; + + m_callback(vector>(), evictedIds); +} + +void GpsTrack::SetDuration(hours duration) +{ + lock_guard lg(m_guard); + + m_duration = duration; + + if (!m_collection) + return; + + auto const evictedIds = m_collection->SetDuration(duration); + if (evictedIds.first == GpsTrackCollection::kInvalidId) + return; // nothing was removed + + if (!m_callback) + return; + + m_callback(vector>(), evictedIds); +} + +hours GpsTrack::GetDuration() const +{ + lock_guard lg(m_guard); + + return m_duration; +} + +void GpsTrack::SetCallback(TGpsTrackDiffCallback callback) +{ + lock_guard lg(m_guard); + + m_callback = callback; + + if (!callback) + return; + + InitCollection(); + + SendInitialSnapshot(); +} + +void GpsTrack::InitFile() +{ + // Must be called under m_guard lock + + if (m_file) + return; + + m_file = make_unique(); + + // Open or create gps track file + try + { + if (!m_file->Open(m_filePath, kGpsFileMaxItemCount)) + { + if (!m_file->Create(m_filePath, kGpsFileMaxItemCount)) + { + LOG(LINFO, ("Cannot open or create GpsTrackFile:", m_filePath)); + m_file.reset(); + } + else + { + LOG(LINFO, ("GpsTrackFile has been created:", m_filePath)); + } + } + } + catch (GpsTrackFile::CorruptedFileException &) + { + // File has been corrupted. + // Drop any data from the file. + try + { + LOG(LINFO, ("File is corrupted, create new:", m_filePath)); + if (!m_file->Create(m_filePath, kGpsFileMaxItemCount)) + { + LOG(LINFO, ("Cannot create GpsTrackFile:", m_filePath)); + m_file.reset(); + } + else + { + LOG(LINFO, ("GpsTrackFile has been created:", m_filePath)); + } + } + catch (RootException & e) + { + LOG(LINFO, ("GpsTrackFile.Create has caused exception:", e.Msg())); + m_file.reset(); + } + } + catch (RootException & e) + { + LOG(LINFO, ("GpsTrackFile has caused exception:", e.Msg())); + m_file.reset(); + } +} + +void GpsTrack::InitCollection() +{ + // Must be called under m_guard lock + + if (m_collection) + return; + + m_collection = make_unique(kGpsCollectionMaxItemCount, m_duration); + + InitFile(); + + if (!m_file) + return; + + try + { + // Read points from file to the collection + m_file->ForEach([this](location::GpsTrackInfo const & info, size_t /* id */)->bool + { + pair evictedIds; + m_collection->Add(info, evictedIds); + return true; + }); + } + catch (GpsTrackFile::CorruptedFileException &) + { + LOG(LINFO, ("GpsTrackFile is corrupted, clear it:", m_filePath)); + m_collection->Clear(); + try + { + m_file->Clear(); + } + catch (RootException & e) + { + LOG(LINFO, ("GpsTrackFile.Clear caused exception:", e.Msg())); + m_file.reset(); + } + } +} + +void GpsTrack::SendInitialSnapshot() +{ + if (!m_callback) + return; + + // Get points from collection to send them to the callback + vector> toAdd; + toAdd.reserve(m_collection->GetSize()); + m_collection->ForEach([&toAdd](location::GpsTrackInfo const & info, size_t id)->bool + { + toAdd.emplace_back(id, info); + return true; + }); + + if (toAdd.empty()) + return; // nothing to send + + m_callback(move(toAdd), make_pair(kInvalidId, kInvalidId)); +} + +GpsTrack & GetDefaultGpsTrack() +{ + static GpsTrack instance(my::JoinFoldersToPath(GetPlatform().WritableDir(), GPS_TRACK_FILENAME)); + return instance; +} diff --git a/map/gps_track.hpp b/map/gps_track.hpp new file mode 100644 index 0000000000..febfb252c4 --- /dev/null +++ b/map/gps_track.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include "map/gps_track_collection.hpp" +#include "map/gps_track_file.hpp" + +#include "std/mutex.hpp" +#include "std/unique_ptr.hpp" + +class GpsTrack final +{ +public: + static size_t const kInvalidId; // = numeric_limits::max(); + + GpsTrack(string const & filePath); + + /// Adds point or collection of points to gps tracking + void AddPoint(location::GpsTrackInfo const & point); + void AddPoints(vector const & points); + + /// Clears any previous tracking info + void Clear(); + + /// Sets tracking duration in hours. + /// @note Callback is called with 'toRemove' points, if some points were removed. + /// By default, duration is 24h. + void SetDuration(hours duration); + + /// Returns track duraion in hours + hours GetDuration() const; + + /// Notification callback about a change of the gps track. + /// @param toAdd - collection of points and ids to add. + /// @param toRemove - range of point indices to remove, or pair(kInvalidId,kInvalidId) if nothing to remove + /// @note Calling of a GpsTrack's function from the callback causes deadlock. + using TGpsTrackDiffCallback = std::function> && toAdd, + pair const & toRemove)>; + + /// Sets callback on change of gps track. + /// @param callback - callback callable object + /// @note Only one callback is supported at time. + /// @note When sink is attached, it receives all points in 'toAdd' at first time, + /// next time callbacks it receives only modifications. It simplifies getter/callback model. + void SetCallback(TGpsTrackDiffCallback callback); + +private: + void InitFile(); + void InitCollection(); + void SendInitialSnapshot(); + + string const m_filePath; + + mutable mutex m_guard; + + hours m_duration; + + unique_ptr m_file; + + unique_ptr m_collection; + + TGpsTrackDiffCallback m_callback; +}; + +GpsTrack & GetDefaultGpsTrack(); diff --git a/map/gps_track_container.cpp b/map/gps_track_container.cpp deleted file mode 100644 index c5edc043aa..0000000000 --- a/map/gps_track_container.cpp +++ /dev/null @@ -1,184 +0,0 @@ -#include "map/gps_track_container.hpp" - -#include "base/logging.hpp" - -namespace -{ - -uint32_t constexpr kDefaultMaxSize = 100000; -hours constexpr kDefaultDuration = hours(24); - -uint32_t constexpr kSecondsPerHour = 60 * 60; - -} // namespace - -GpsTrackContainer::GpsTrackContainer() - : m_trackDuration(kDefaultDuration) - , m_maxSize(kDefaultMaxSize) - , m_counter(0) -{ -} - -void GpsTrackContainer::SetDuration(hours duration) -{ - lock_guard lg(m_guard); - - m_trackDuration = duration; - - vector removed; - RemoveOldPoints(removed); - - if (m_callback && !removed.empty()) - m_callback(vector(), move(removed)); -} - -hours GpsTrackContainer::GetDuration() const -{ - lock_guard lg(m_guard); - - return m_trackDuration; -} - -void GpsTrackContainer::SetMaxSize(size_t maxSize) -{ - lock_guard lg(m_guard); - - m_maxSize = maxSize; - - vector removed; - RemoveOldPoints(removed); - - if (m_callback && !removed.empty()) - m_callback(vector(), move(removed)); -} - -size_t GpsTrackContainer::GetMaxSize() const -{ - lock_guard lg(m_guard); - - return m_maxSize; -} - -void GpsTrackContainer::SetCallback(TGpsTrackDiffCallback callback, bool sendAll) -{ - lock_guard lg(m_guard); - - m_callback = callback; - - if (!m_callback || !sendAll || m_points.empty()) - return; - - vector added; - CopyPoints(added); - - m_callback(move(added), vector()); -} - -uint32_t GpsTrackContainer::AddPoint(m2::PointD const & point, double speedMPS, double timestamp) -{ - lock_guard lg(m_guard); - - // Do not process points which are come with timestamp earlier than timestamp of the last point - // because it is probably some error in logic or gps error, because valid gps must provide UTC time which is growing. - if (!m_points.empty() && timestamp < m_points.back().m_timestamp) - { - LOG(LINFO, ("Incorrect GPS timestamp sequence")); - return kInvalidId; - } - - GpsTrackPoint gtp; - gtp.m_timestamp = timestamp; - gtp.m_point = point; - gtp.m_speedMPS = speedMPS; - gtp.m_id = m_counter; - - m_points.push_back(gtp); - ++m_counter; - - vector added; - added.emplace_back(gtp); - - vector removed; - RemoveOldPoints(removed); - - if (m_callback) - m_callback(move(added), move(removed)); - - return gtp.m_id; -} - -void GpsTrackContainer::GetPoints(vector & points) const -{ - lock_guard lg(m_guard); - - CopyPoints(points); -} - -void GpsTrackContainer::Clear() -{ - lock_guard lg(m_guard); - - vector removed; - - if (m_callback) - { - removed.reserve(m_points.size()); - for_each(m_points.begin(), m_points.end(), [&](GpsTrackPoint const & pt){ removed.emplace_back(pt.m_id); }); - } - - // We do not use 'clear' because it does not guarantee memory cleaning, - // Instead, we use move from an empty queue - m_points = deque(); - - if (m_callback && !removed.empty()) - m_callback(vector(), move(removed)); -} - -void GpsTrackContainer::RemoveOldPoints(vector & removedIds) -{ - // Must be called under m_guard lock - - if (m_points.empty()) - return; - - time_t const lowerBorder = m_points.back().m_timestamp - kSecondsPerHour * m_trackDuration.count(); - - if (m_points.front().m_timestamp < lowerBorder) - { - GpsTrackPoint pt; - pt.m_timestamp = lowerBorder; - - auto const itr = lower_bound(m_points.begin(), m_points.end(), pt, - [](GpsTrackPoint const & a, GpsTrackPoint const & b) -> bool - { - return a.m_timestamp < b.m_timestamp; - }); - - if (itr != m_points.begin()) - { - removedIds.reserve(removedIds.size() + distance(m_points.begin(), itr)); - for (auto i = m_points.begin(); i != itr; ++i) - removedIds.emplace_back(i->m_id); - - m_points.erase(m_points.begin(), itr); - } - } - - if (m_points.size() > m_maxSize) - { - auto const itr = m_points.begin() + m_points.size() - m_maxSize; - - removedIds.reserve(removedIds.size() + distance(m_points.begin(), itr)); - for (auto i = m_points.begin(); i != itr; ++i) - removedIds.emplace_back(i->m_id); - - m_points.erase(m_points.begin(), itr); - } -} - -void GpsTrackContainer::CopyPoints(vector & points) const -{ - // Must be called under m_guard lock - - points = vector(m_points.begin(), m_points.end()); -} diff --git a/map/gps_track_container.hpp b/map/gps_track_container.hpp deleted file mode 100644 index aa4a7a4b50..0000000000 --- a/map/gps_track_container.hpp +++ /dev/null @@ -1,107 +0,0 @@ -#pragma once - -// NOTE! -// Temporary, to avoid cyclic dependencies between map and drape projects, -// we declared GpsTrackPoint in the drape project. -// Ideally, drape must use declaration GpsTrackPoint, instead of declaring it there. -#include "drape_frontend/gps_track_point.hpp" - -#include "std/chrono.hpp" -#include "std/deque.hpp" -#include "std/function.hpp" -#include "std/mutex.hpp" - -class GpsTrackContainer final -{ -public: - using GpsTrackPoint = df::GpsTrackPoint; - // See note above - /* - struct GpsTrackPoint - { - // Timestamp of the point, seconds from 1st Jan 1970 - double m_timestamp; - - // Point in the Mercator projection - m2::PointD m_point; - - // Speed in the point, M/S - double m_speedMPS; - - // Unique identifier of the point - uint32_t m_id; - }; - */ - - static uint32_t constexpr kInvalidId = numeric_limits::max(); - - /// Notification callback about a change of the gps track. - /// @param toAdd - collection of points to add. - /// @param toRemove - collection of point indices to remove. - /// @note Calling of a GpsTrackContainer's function from the callback causes deadlock. - using TGpsTrackDiffCallback = std::function && toAdd, vector && toRemove)>; - - GpsTrackContainer(); - - /// Sets track duration in hours. - /// @note Callback is called with 'toRemove' points, if some points were removed. - /// By default, duration is 24h. - void SetDuration(hours duration); - - /// Returns track duraion in hours - hours GetDuration() const; - - /// Sets max number of points in the track. - /// @note Callback is called with 'toRemove' points, if some points were removed. - /// By default, max size is 100k. - void SetMaxSize(size_t maxSize); - - /// Returns max number of points in the track - size_t GetMaxSize() const; - - /// Sets callback on change of gps track. - /// @param callback - callback callable object - /// @param sendAll - If it is true then callback is called with all points as 'toAdd' points, if there are points. - /// If helps to avoid race condition and complex synchronizations if we called getter GetGpsTrackPoints - /// and waited for notification OnGpsTrackChanged. If it is false, then there is no ant callback and client is responsible - /// for getting of initial state and syncing it with callbacks. - /// @note Only one callback is supported at time. - void SetCallback(TGpsTrackDiffCallback callback, bool sendAll); - - /// Adds new point in the track. - /// @param point - new point in the Mercator projection. - /// @param speedMPS - current speed in the new point in M/S. - /// @param timestamp - timestamp of the point. - /// @note Callback is called with 'toAdd' and 'toRemove' points. - /// @returns the point unique identifier or kInvalidId if point has incorrect time. - uint32_t AddPoint(m2::PointD const & point, double speedMPS, double timestamp); - - /// Returns points snapshot from the container. - /// @param points - output for collection of points. - void GetPoints(vector & points) const; - - /// Clears collection of point in the track. - /// @note Callback is called with 'toRemove' points, if need. - void Clear(); - -private: - void RemoveOldPoints(vector & removedIds); - void CopyPoints(vector & points) const; - - mutable mutex m_guard; - - TGpsTrackDiffCallback m_callback; - - // Max duration of track, by default is 24h. - hours m_trackDuration; - - // Max number of points in track, by default is 100k. - size_t m_maxSize; - - // Collection of points, by nature is asc. sorted by m_timestamp. - // Max size of m_points is adjusted by m_trackDuration and m_maxSize. - deque m_points; - - // Simple counter which is used to generate point unique ids. - uint32_t m_counter; -}; diff --git a/map/gps_track_file.hpp b/map/gps_track_file.hpp index 16cff84283..b6f9d14d38 100644 --- a/map/gps_track_file.hpp +++ b/map/gps_track_file.hpp @@ -16,7 +16,6 @@ public: DECLARE_EXCEPTION(ReadFileException, RootException); DECLARE_EXCEPTION(CorruptedFileException, RootException); - /// Invalid identifier for point static size_t const kInvalidId; // = numeric_limits::max(); using TItem = location::GpsTrackInfo; diff --git a/map/map.pro b/map/map.pro index 678e4a1238..79af5b4c07 100644 --- a/map/map.pro +++ b/map/map.pro @@ -21,8 +21,8 @@ HEADERS += \ framework.hpp \ ge0_parser.hpp \ geourl_process.hpp \ + gps_track.hpp \ gps_track_collection.hpp \ - gps_track_container.hpp \ gps_track_file.hpp \ mwm_url.hpp \ storage_bridge.hpp \ @@ -43,8 +43,8 @@ SOURCES += \ framework.cpp \ ge0_parser.cpp \ geourl_process.cpp \ + gps_track.cpp \ gps_track_collection.cpp \ - gps_track_container.cpp \ gps_track_file.cpp \ mwm_url.cpp \ storage_bridge.cpp \ diff --git a/map/map_tests/gps_track_container_test.cpp b/map/map_tests/gps_track_container_test.cpp deleted file mode 100644 index 20c7a1279e..0000000000 --- a/map/map_tests/gps_track_container_test.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include "testing/testing.hpp" - -#include "map/gps_track_container.hpp" - -#include "std/bind.hpp" - -namespace -{ - -uint32_t constexpr kSecondsPerHour = 60 * 60; - -struct GpsTrackContainerCallback -{ -public: - void OnChange(vector && toAdd, vector && toRemove) - { - m_toAdd.insert(m_toAdd.end(), toAdd.begin(), toAdd.end()); - m_toRemove.insert(m_toRemove.end(), toRemove.begin(), toRemove.end()); - } - vector m_toAdd; - vector m_toRemove; -}; - -} // namespace - -UNIT_TEST(GpsTrackContainer_Test) -{ - GpsTrackContainer gpstrack; - - time_t timestamp = system_clock::to_time_t(system_clock::now()); - - uint32_t id0 = gpstrack.AddPoint(m2::PointD(0,0), 0.0, timestamp); - uint32_t id1 = gpstrack.AddPoint(m2::PointD(1,1), 1.0, timestamp + kSecondsPerHour); - uint32_t id2 = gpstrack.AddPoint(m2::PointD(2,2), 2.0, timestamp + 2 * kSecondsPerHour); - - // Set callback and expect toAdd callback with all points - - GpsTrackContainerCallback callback; - gpstrack.SetCallback(bind(&GpsTrackContainerCallback::OnChange, ref(callback), _1, _2), true /* sendAll */); - - TEST(callback.m_toRemove.empty(), ()); - - TEST_EQUAL(3, callback.m_toAdd.size(), ()); - TEST_EQUAL(id0, callback.m_toAdd[0].m_id, ()); - TEST_EQUAL(id1, callback.m_toAdd[1].m_id, ()); - TEST_EQUAL(id2, callback.m_toAdd[2].m_id, ()); - - callback.m_toAdd.clear(); - callback.m_toRemove.clear(); - - // Add point in 25h (duration is 24h) and expect point id0 is popped and point id25 is added - - uint32_t id25 = gpstrack.AddPoint(m2::PointD(25,25), 25.0, timestamp + 25 * kSecondsPerHour); - - TEST_EQUAL(1, callback.m_toAdd.size(), ()); - TEST_EQUAL(id25, callback.m_toAdd[0].m_id, ()); - - TEST_EQUAL(1, callback.m_toRemove.size(), ()); - TEST_EQUAL(id0, callback.m_toRemove[0], ()); - - callback.m_toAdd.clear(); - callback.m_toRemove.clear(); - - // Set duration in 2h and expect points id1 and id2 are popped - - gpstrack.SetDuration(hours(2)); - - TEST(callback.m_toAdd.empty(), ()); - - TEST_EQUAL(2, callback.m_toRemove.size(), ()); - TEST_EQUAL(id1, callback.m_toRemove[0], ()); - TEST_EQUAL(id2, callback.m_toRemove[1], ()); - - callback.m_toAdd.clear(); - callback.m_toRemove.clear(); - - // and test there is only id25 point in the track - - vector points; - gpstrack.GetPoints(points); - - TEST_EQUAL(1, points.size(), ()); - TEST_EQUAL(id25, points[0].m_id, ()); -} diff --git a/map/map_tests/map_tests.pro b/map/map_tests/map_tests.pro index 2adb196e82..57f280f850 100644 --- a/map/map_tests/map_tests.pro +++ b/map/map_tests/map_tests.pro @@ -31,7 +31,6 @@ SOURCES += \ bookmarks_test.cpp \ ge0_parser_tests.cpp \ geourl_test.cpp \ - gps_track_container_test.cpp \ gps_track_collection_test.cpp \ gps_track_file_test.cpp \ kmz_unarchive_test.cpp \