From 06931b7640f9d0c04205838fcb834491b8a697a4 Mon Sep 17 00:00:00 2001
From: Rainer Kartmann <rainer.kartmann@kit.edu>
Date: Tue, 29 Aug 2023 18:34:38 +0200
Subject: [PATCH] Add hasInstance(), hasSnapshot(), findLatestInstance(),
 findLatestSnapshot() without arguments

---
 .../libraries/armem/core/base/EntityBase.h    |  47 +--
 .../armem/core/base/EntitySnapshotBase.h      |   7 +
 .../armem/core/base/detail/iteration_mixins.h | 150 ++++----
 .../armem/core/base/detail/lookup_mixins.h    | 206 ++++++++++-
 .../libraries/armem/core/error/ArMemError.cpp |  19 +
 .../libraries/armem/core/error/ArMemError.h   |  18 +
 .../libraries/armem/test/ArMemGetFindTest.cpp | 341 ++++++++++++++----
 7 files changed, 595 insertions(+), 193 deletions(-)

diff --git a/source/RobotAPI/libraries/armem/core/base/EntityBase.h b/source/RobotAPI/libraries/armem/core/base/EntityBase.h
index ed76ae911..e44b1af6b 100644
--- a/source/RobotAPI/libraries/armem/core/base/EntityBase.h
+++ b/source/RobotAPI/libraries/armem/core/base/EntityBase.h
@@ -24,7 +24,7 @@ namespace armarx::armem::base
      * @brief An entity over a period of time.
      *
      * An entity should be a physical thing or abstract concept existing
-     * (and potentially evolving) over some time.
+     * (and potentially evolving) over time.
      *
      * Examples are:
      * - objects (the green box)
@@ -43,7 +43,9 @@ namespace armarx::armem::base
     class EntityBase :
         public detail::MemoryContainerBase<std::map<Time, _EntitySnapshotT>, _Derived>,
         public detail::ForEachEntityInstanceMixin<_Derived>,
-        public detail::GetFindInstanceMixin<_Derived>
+        public detail::GetFindInstanceMixin<_Derived>,
+        public detail::GetLatestInstanceMixin<_Derived>,
+        public detail::GetLatestSnapshotMixin<_Derived>
     {
         using Base = detail::MemoryContainerBase<std::map<Time, _EntitySnapshotT>, _Derived>;
 
@@ -99,15 +101,24 @@ namespace armarx::armem::base
             return this->id().entityName;
         }
 
-        // Has child by key
-        /// Indicates whether a history entry for the given time exists.
+        // Has any child
+        /// Indicate any snapshot exists.
+        bool
+        hasSnapshot() const
+        {
+            return not this->empty();
+        }
+
+        // Has child with key
+        /// Indicate whether a snapshot at the given time exists.
         bool
         hasSnapshot(const Time& time) const
         {
             return this->findSnapshot(time) != nullptr;
         }
 
-        // Has child by MemoryID
+        // Has child with MemoryID
+        /// Indicate whether a snapshot with the given ID exists.
         bool
         hasSnapshot(const MemoryID& snapshotID) const
         {
@@ -226,31 +237,6 @@ namespace armarx::armem::base
             return this->empty() ? nullptr : &this->_container.rbegin()->second;
         }
 
-        /**
-         * @brief Return the snapshot with the most recent timestamp.
-         * @return The latest snapshot.
-         * @throw `armem::error::EntityHistoryEmpty` If the history is empty.
-         */
-        EntitySnapshotT&
-        getLatestSnapshot()
-        {
-            return const_cast<EntitySnapshotT&>(
-                const_cast<const EntityBase*>(this)->getLatestSnapshot());
-        }
-
-        const EntitySnapshotT&
-        getLatestSnapshot() const
-        {
-            if (const EntitySnapshotT* snapshot = this->findLatestSnapshot())
-            {
-                return *snapshot;
-            }
-            else
-            {
-                throw armem::error::EntityHistoryEmpty(name(), "when getting the latest snapshot.");
-            }
-        }
-
         /**
          * @brief Return the snapshot with the least recent timestamp.
          * @return The first snapshot or nullptr if the entity is empty.
@@ -380,6 +366,7 @@ namespace armarx::armem::base
             return snapshot ? snapshot->findInstance(instanceIndex) : nullptr;
         }
 
+
 #if 0 // Do not offer this yet.
         auto* findLatestInstanceData(int instanceIndex = 0)
         {
diff --git a/source/RobotAPI/libraries/armem/core/base/EntitySnapshotBase.h b/source/RobotAPI/libraries/armem/core/base/EntitySnapshotBase.h
index 614393f4a..a2412f4c8 100644
--- a/source/RobotAPI/libraries/armem/core/base/EntitySnapshotBase.h
+++ b/source/RobotAPI/libraries/armem/core/base/EntitySnapshotBase.h
@@ -67,6 +67,13 @@ namespace armarx::armem::base
             return this->id().timestamp;
         }
 
+        /// Indicate whether this snapshot has any instance.
+        bool
+        hasInstance() const
+        {
+            return not this->empty();
+        }
+
         // Has child by key
         bool
         hasInstance(int index) const
diff --git a/source/RobotAPI/libraries/armem/core/base/detail/iteration_mixins.h b/source/RobotAPI/libraries/armem/core/base/detail/iteration_mixins.h
index b686b1cc7..4945da9a9 100644
--- a/source/RobotAPI/libraries/armem/core/base/detail/iteration_mixins.h
+++ b/source/RobotAPI/libraries/armem/core/base/detail/iteration_mixins.h
@@ -5,13 +5,12 @@
 
 #include <RobotAPI/libraries/armem/core/MemoryID.h>
 
-
 namespace
 {
-    template<typename F, typename Ret, typename A, typename... Rest>
+    template <typename F, typename Ret, typename A, typename... Rest>
     A helper(Ret (F::*)(A, Rest...));
 
-    template<typename F, typename Ret, typename A, typename... Rest>
+    template <typename F, typename Ret, typename A, typename... Rest>
     A helper(Ret (F::*)(A, Rest...) const);
 
     // volatile or lvalue/rvalue *this not required for lambdas (phew)
@@ -19,12 +18,12 @@ namespace
     template <typename FuncT>
     struct first_argument
     {
-        using type = decltype( helper(&FuncT::operator()) );
+        using type = decltype(helper(&FuncT::operator()));
     };
 
     template <typename FuncT>
     using first_argument_t = typename first_argument<FuncT>::type;
-}
+} // namespace
 
 namespace armarx::armem::base::detail
 {
@@ -33,9 +32,10 @@ namespace armarx::armem::base::detail
 
     // Handle functions with different return type.
     template <class FunctionT, class ChildT>
-    bool call(FunctionT&& func, ChildT&& child)
+    bool
+    call(FunctionT&& func, ChildT&& child)
     {
-        if constexpr(std::is_same_v<decltype(func(child)), bool>)
+        if constexpr (std::is_same_v<decltype(func(child)), bool>)
         {
             if (!func(child))
             {
@@ -50,10 +50,10 @@ namespace armarx::armem::base::detail
         }
     }
 
-
     // Single-valued containers.
     template <class ContainerT, class FunctionT>
-    bool forEachChildSingle(ContainerT& container, FunctionT&& func)
+    bool
+    forEachChildSingle(ContainerT& container, FunctionT&& func)
     {
         for (auto& child : container)
         {
@@ -65,10 +65,10 @@ namespace armarx::armem::base::detail
         return true;
     }
 
-
     // Pair-valued containers.
     template <class ContainerT, class FunctionT>
-    bool forEachChildPair(ContainerT& container, FunctionT&& func)
+    bool
+    forEachChildPair(ContainerT& container, FunctionT&& func)
     {
         for (auto& [_, child] : container)
         {
@@ -80,22 +80,25 @@ namespace armarx::armem::base::detail
         return true;
     }
 
-
     // see: https://en.cppreference.com/w/cpp/types/void_t
 
     // primary template handles types that have no nested ::type member:
-    template< class, class = void >
-    struct has_mapped_type : std::false_type { };
+    template <class, class = void>
+    struct has_mapped_type : std::false_type
+    {
+    };
 
     // specialization recognizes types that do have a nested ::type member:
-    template< class T >
-    struct has_mapped_type<T, std::void_t<typename T::mapped_type>> : std::true_type { };
-
+    template <class T>
+    struct has_mapped_type<T, std::void_t<typename T::mapped_type>> : std::true_type
+    {
+    };
 
     template <class ContainerT, class FunctionT>
-    bool forEachChild(ContainerT& container, FunctionT&& func)
+    bool
+    forEachChild(ContainerT& container, FunctionT&& func)
     {
-        if constexpr(has_mapped_type<ContainerT>::value)
+        if constexpr (has_mapped_type<ContainerT>::value)
         {
             return forEachChildPair(container, func);
         }
@@ -105,20 +108,15 @@ namespace armarx::armem::base::detail
         }
     }
 
-
     template <class FunctionT, class ParentT, class ChildT>
-    bool forEachInstanceIn(
-            const MemoryID& id,
-            FunctionT&& func,
-            ParentT& parent,
-            bool single,
-            ChildT* child
-            )
+    bool
+    forEachInstanceIn(const MemoryID& id,
+                      FunctionT&& func,
+                      ParentT& parent,
+                      bool single,
+                      ChildT* child)
     {
-        auto childFn = [&id,&func](auto& child)
-        {
-            return child.forEachInstanceIn(id, func);
-        };
+        auto childFn = [&id, &func](auto& child) { return child.forEachInstanceIn(id, func); };
         if (single)
         {
             return child ? childFn(*child) : true;
@@ -129,8 +127,6 @@ namespace armarx::armem::base::detail
         }
     }
 
-
-
     // We use auto instead of, e.g. DerivedT::EntitySnapshotT,
     // as we cannot use the typedef before DerivedT was completely defined.
 
@@ -143,26 +139,22 @@ namespace armarx::armem::base::detail
          * @param func Function like: bool process(EntityInstanceT& instance)>
          */
         template <class InstanceFunctionT>
-        bool forEachInstance(InstanceFunctionT&& func)
+        bool
+        forEachInstance(InstanceFunctionT&& func)
         {
             return static_cast<DerivedT*>(this)->forEachSnapshot(
-                       [&func](auto & snapshot) -> bool
-            {
-                return snapshot.forEachInstance(func);
-            });
+                [&func](auto& snapshot) -> bool { return snapshot.forEachInstance(func); });
         }
 
         /**
          * @param func Function like: bool process(const EntityInstanceT& instance)
          */
         template <class InstanceFunctionT>
-        bool forEachInstance(InstanceFunctionT&& func) const
+        bool
+        forEachInstance(InstanceFunctionT&& func) const
         {
             return static_cast<const DerivedT*>(this)->forEachSnapshot(
-                       [&func](const auto & snapshot) -> bool
-            {
-                return snapshot.forEachInstance(func);
-            });
+                [&func](const auto& snapshot) -> bool { return snapshot.forEachInstance(func); });
         }
 
         /**
@@ -180,19 +172,19 @@ namespace armarx::armem::base::detail
          * @param func Function like: `bool process(const my::arondto::CoolData& data)`
          */
         template <class AronDtoFunctionT>
-        bool forEachInstanceAs(AronDtoFunctionT&& func) const
+        bool
+        forEachInstanceAs(AronDtoFunctionT&& func) const
         {
             return static_cast<const DerivedT*>(this)->forEachInstance(
-                       [&func](const auto & instance) -> bool
-            {
-                using AronDtoT = typename std::remove_reference_t<first_argument_t<AronDtoFunctionT>>;
-                return func(instance.template dataAs<AronDtoT>());
-            });
+                [&func](const auto& instance) -> bool
+                {
+                    using AronDtoT =
+                        typename std::remove_reference_t<first_argument_t<AronDtoFunctionT>>;
+                    return func(instance.template dataAs<AronDtoT>());
+                });
         }
-
     };
 
-
     template <class DerivedT>
     struct ForEachEntitySnapshotMixin
     {
@@ -200,30 +192,25 @@ namespace armarx::armem::base::detail
          * @param func Function like: bool process(EntitySnapshotT& snapshot)>
          */
         template <class SnapshotFunctionT>
-        bool forEachSnapshot(SnapshotFunctionT&& func)
+        bool
+        forEachSnapshot(SnapshotFunctionT&& func)
         {
             return static_cast<DerivedT*>(this)->forEachEntity(
-                       [&func](auto & entity) -> bool
-            {
-                return entity.forEachSnapshot(func);
-            });
+                [&func](auto& entity) -> bool { return entity.forEachSnapshot(func); });
         }
 
         /**
          * @param func Function like: bool process(const EntitySnapshotT& snapshot)
          */
         template <class SnapshotFunctionT>
-        bool forEachSnapshot(SnapshotFunctionT&& func) const
+        bool
+        forEachSnapshot(SnapshotFunctionT&& func) const
         {
             return static_cast<const DerivedT*>(this)->forEachEntity(
-                       [&func](const auto & entity) -> bool
-            {
-                return entity.forEachSnapshot(func);
-            });
+                [&func](const auto& entity) -> bool { return entity.forEachSnapshot(func); });
         }
     };
 
-
     template <class DerivedT>
     struct ForEachEntityMixin
     {
@@ -231,30 +218,27 @@ namespace armarx::armem::base::detail
          * @param func Function like: bool process(EntityT& entity)>
          */
         template <class FunctionT>
-        bool forEachEntity(FunctionT&& func)
+        bool
+        forEachEntity(FunctionT&& func)
         {
             return static_cast<DerivedT*>(this)->forEachProviderSegment(
-                       [&func](auto & providerSegment) -> bool
-            {
-                return providerSegment.forEachEntity(func);
-            });
+                [&func](auto& providerSegment) -> bool
+                { return providerSegment.forEachEntity(func); });
         }
 
         /**
          * @param func Function like: bool process(const EntityT& entity)
          */
         template <class FunctionT>
-        bool forEachEntity(FunctionT&& func) const
+        bool
+        forEachEntity(FunctionT&& func) const
         {
             return static_cast<const DerivedT*>(this)->forEachProviderSegment(
-                       [&func](const auto & providerSegment) -> bool
-            {
-                return providerSegment.forEachEntity(func);
-            });
+                [&func](const auto& providerSegment) -> bool
+                { return providerSegment.forEachEntity(func); });
         }
     };
 
-
     template <class DerivedT>
     struct ForEachProviderSegmentMixin
     {
@@ -262,27 +246,25 @@ namespace armarx::armem::base::detail
          * @param func Function like: bool process(ProviderSegmentT& providerSegment)>
          */
         template <class FunctionT>
-        bool forEachProviderSegment(FunctionT&& func)
+        bool
+        forEachProviderSegment(FunctionT&& func)
         {
             return static_cast<DerivedT*>(this)->forEachCoreSegment(
-                       [&func](auto & coreSegment) -> bool
-            {
-                return coreSegment.forEachProviderSegment(func);
-            });
+                [&func](auto& coreSegment) -> bool
+                { return coreSegment.forEachProviderSegment(func); });
         }
 
         /**
          * @param func Function like: bool process(const ProviderSegmentT& providerSegment)
          */
         template <class FunctionT>
-        bool forEachProviderSegment(FunctionT&& func) const
+        bool
+        forEachProviderSegment(FunctionT&& func) const
         {
             return static_cast<const DerivedT*>(this)->forEachCoreSegment(
-                       [&func](const auto & coreSegment) -> bool
-            {
-                return coreSegment.forEachProviderSegment(func);
-            });
+                [&func](const auto& coreSegment) -> bool
+                { return coreSegment.forEachProviderSegment(func); });
         }
     };
 
-}
+} // namespace armarx::armem::base::detail
diff --git a/source/RobotAPI/libraries/armem/core/base/detail/lookup_mixins.h b/source/RobotAPI/libraries/armem/core/base/detail/lookup_mixins.h
index ce63b1ee7..618b8e9fc 100644
--- a/source/RobotAPI/libraries/armem/core/base/detail/lookup_mixins.h
+++ b/source/RobotAPI/libraries/armem/core/base/detail/lookup_mixins.h
@@ -51,8 +51,30 @@ namespace armarx::armem::base::detail
     template <class DerivedT>
     struct GetFindInstanceMixin
     {
-        // Relies on this->find/getSnapshot()
+        // Relies on this->find/get/forEachInstance()
 
+        /**
+         * @brief Indicate whether this container contains at least one entity instance.
+         * @return True if there is at least one entity instance in this container.
+         */
+        bool
+        hasInstance() const
+        {
+            bool has = false;
+            derived<DerivedT>(this).forEachInstance(
+                [&has](const auto& snapshot)
+                {
+                    has = true;
+                    return false;
+                });
+            return has;
+        }
+
+        /**
+         * @brief Indicate whether this container has an instance with the given ID.
+         * @param instanceID The instance ID.
+         * @return ... WIP
+         */
         bool
         hasInstance(const MemoryID& instanceID) const
         {
@@ -82,7 +104,7 @@ namespace armarx::armem::base::detail
          * @brief Retrieve an entity instance.
          * @param id The instance ID.
          * @return The instance if it is found.
-         * @throw `armem::error::ArMemError` if it is missing.
+         * @throw armem::error::ArMemError if it is missing.
          */
         auto&
         getInstance(const MemoryID& instanceID)
@@ -98,20 +120,118 @@ namespace armarx::armem::base::detail
     };
 
     template <class DerivedT>
-    struct GetFindSnapshotMixin
+    struct GetLatestInstanceMixin
     {
-        // Relies on this->find/getEntity()
+        // Relies on findLatestInstance()
+
+        /**
+         * @brief Retrieve the latest entity instance in this container.
+         * @param instanceIndex The instance's index in the latest snapshot.
+         * @return The latest entity instance.
+         * @throw armem::error::ArMemError If there is no entity instance.
+         */
+        auto&
+        getLatestInstance(int instanceIndex = 0)
+        {
+            auto* instance = derived<DerivedT>(this).findLatestInstance();
+            if (not instance)
+            {
+                throw armem::error::NoSuchEntries(
+                    "entity instances", DerivedT::getLevelName(), derived<DerivedT>(this).id());
+            }
+            return *instance;
+        }
 
+        const auto&
+        getLatestInstance(int instanceIndex = 0) const
+        {
+            const auto* instance = derived<DerivedT>(this).findLatestInstance();
+            if (not instance)
+            {
+                throw armem::error::NoSuchEntries(
+                    "entity instances", DerivedT::getLevelName(), derived<DerivedT>(this).id());
+            }
+            return *instance;
+        }
+    };
+
+    template <class DerivedT>
+    struct GetLatestSnapshotMixin
+    {
+        // Relies on findLatestSnapshot()
+
+        /**
+         * @brief Retrieve the latest entity snapshot in this container.
+         * @param snapshotIndex The snapshot's index in the latest snapshot.
+         * @return The latest entity snapshot.
+         * @throw armem::error::ArMemError If there is no entity snapshot.
+         */
+        auto&
+        getLatestSnapshot(int snapshotIndex = 0)
+        {
+            auto* snapshot = derived<DerivedT>(this).findLatestSnapshot();
+            if (not snapshot)
+            {
+                throw armem::error::NoSuchEntries(
+                    "entity snapshots", DerivedT::getLevelName(), derived<DerivedT>(this).id());
+            }
+            return *snapshot;
+        }
+
+        const auto&
+        getLatestSnapshot(int snapshotIndex = 0) const
+        {
+            const auto* snapshot = derived<DerivedT>(this).findLatestSnapshot();
+            if (not snapshot)
+            {
+                throw armem::error::NoSuchEntries(
+                    "entity snapshots", DerivedT::getLevelName(), derived<DerivedT>(this).id());
+            }
+            return *snapshot;
+        }
+    };
+
+    template <class DerivedT>
+    struct GetFindSnapshotMixin :
+        public GetLatestInstanceMixin<DerivedT>,
+        public GetLatestSnapshotMixin<DerivedT>
+    {
+        // Relies on this->find/getEntity, forEachSnapshot()
+
+        /**
+         * @brief Indicate whether this container contains at least one entity snapshot.
+         * @return True if there is at least one entity snapshot in this container.
+         */
+        bool
+        hasSnapshot() const
+        {
+            bool has = false;
+            derived<DerivedT>(this).forEachSnapshot(
+                [&has](const auto& snapshot)
+                {
+                    has = true;
+                    return false;
+                });
+            return has;
+        }
+
+        /**
+         * @brief Indicates whether a snapshot with the given ID exists in this container.
+         * @param snapshotID The snapshot ID.
+         * @return True if the snapshot exists, false otherwise.
+         */
         bool
         hasSnapshot(const MemoryID& snapshotID) const
         {
             return derived<DerivedT>(this).findSnapshot(snapshotID) != nullptr;
         }
 
+        // Snapshot by ID
+
         /**
          * @brief Find an entity snapshot.
          * @param id The snapshot ID.
-         * @return The snapshot or nullptr if it is missing.
+         * @return The snapshot, or nullptr if it is missing.
          */
         auto*
         findSnapshot(const MemoryID& snapshotID)
@@ -131,7 +251,7 @@ namespace armarx::armem::base::detail
          * @brief Retrieve an entity snapshot.
          * @param id The snapshot ID.
          * @return The snapshot if it is found.
-         * @throw `armem::error::ArMemError` if it is missing.
+         * @throw armem::error::ArMemError if it is missing.
          */
         auto&
         getSnapshot(const MemoryID& snapshotID)
@@ -145,8 +265,14 @@ namespace armarx::armem::base::detail
             return derived<DerivedT>(this).getEntity(snapshotID).getSnapshot(snapshotID);
         }
 
-        // More elaborate cases
+        // Latest snapshot in entity
 
+        /**
+         * @brief Find the latest snapshot in the given entity.
+         * @param entityID The entity's ID.
+         * @return A pointer to the latest snapshot in the specified entity, or nullptr if the
+         * entity does not exist or has no snapshot.
+         */
         auto*
         findLatestSnapshot(const MemoryID& entityID)
         {
@@ -161,6 +287,54 @@ namespace armarx::armem::base::detail
             return entity ? entity->findLatestSnapshot() : nullptr;
         }
 
+        // Latest snapshot in container.
+
+        /**
+         * @brief Find the latest snapshot in this container.
+         * @return A pointer to the latest instance, or nullptr if there is no snapshot.
+         */
+        const auto*
+        findLatestSnapshot() const
+        {
+            const typename DerivedT::EntitySnapshotT* latestSnapshot = nullptr;
+            derived<DerivedT>(this).forEachEntity(
+                [&latestSnapshot](const auto& entity)
+                {
+                    const auto* snapshot = entity.findLatestSnapshot();
+                    if (latestSnapshot == nullptr)
+                    {
+                        latestSnapshot = snapshot;
+                    }
+                    else if (snapshot and snapshot->time() > latestSnapshot->time())
+                    {
+                        latestSnapshot = snapshot;
+                    }
+                });
+            return latestSnapshot;
+        }
+
+        auto*
+        findLatestSnapshot()
+        {
+            typename DerivedT::EntitySnapshotT* latestSnapshot = nullptr;
+            derived<DerivedT>(this).forEachEntity(
+                [&latestSnapshot](auto& entity)
+                {
+                    auto* snapshot = entity.findLatestSnapshot();
+                    if (latestSnapshot == nullptr)
+                    {
+                        latestSnapshot = snapshot;
+                    }
+                    else if (snapshot and snapshot->time() > latestSnapshot->time())
+                    {
+                        latestSnapshot = snapshot;
+                    }
+                });
+            return latestSnapshot;
+        }
+
+        // Latest instance.
+
         auto*
         findLatestInstance(const MemoryID& entityID, int instanceIndex = 0)
         {
@@ -174,6 +348,20 @@ namespace armarx::armem::base::detail
             auto* snapshot = derived<DerivedT>(this).findLatestSnapshot(entityID);
             return snapshot ? snapshot->findInstance(instanceIndex) : nullptr;
         }
+
+        const auto*
+        findLatestInstance(int instanceIndex = 0) const
+        {
+            auto* snapshot = derived<DerivedT>(this).findLatestSnapshot();
+            return snapshot ? snapshot->findInstance(instanceIndex) : nullptr;
+        }
+
+        auto*
+        findLatestInstance(int instanceIndex = 0)
+        {
+            auto* snapshot = derived<DerivedT>(this).findLatestSnapshot();
+            return snapshot ? snapshot->findInstance(instanceIndex) : nullptr;
+        }
     };
 
     template <class DerivedT>
@@ -210,7 +398,7 @@ namespace armarx::armem::base::detail
          * @brief Retrieve an entity.
          * @param id The entity ID.
          * @return The entity if it is found.
-         * @throw `armem::error::ArMemError` if it is missing.
+         * @throw armem::error::ArMemError if it is missing.
          */
         auto&
         getEntity(const MemoryID& entityID)
@@ -259,7 +447,7 @@ namespace armarx::armem::base::detail
          * @brief Retrieve a provider segment.
          * @param id The provider segment ID.
          * @return The provider segment if it is found.
-         * @throw `armem::error::ArMemError` if it is missing.
+         * @throw armem::error::ArMemError if it is missing.
          */
         auto&
         getProviderSegment(const MemoryID& providerSegmentID)
diff --git a/source/RobotAPI/libraries/armem/core/error/ArMemError.cpp b/source/RobotAPI/libraries/armem/core/error/ArMemError.cpp
index 6197ded3c..354b95712 100644
--- a/source/RobotAPI/libraries/armem/core/error/ArMemError.cpp
+++ b/source/RobotAPI/libraries/armem/core/error/ArMemError.cpp
@@ -99,6 +99,25 @@ namespace armarx::armem::error
         return ss.str();
     }
 
+    NoSuchEntries::NoSuchEntries(const std::string& missingTerm,
+                                 const std::string& containerTerm,
+                                 const MemoryID& containerID,
+                                 const std::string& message) :
+        ArMemError(makeMsg(missingTerm, containerTerm, containerID, message))
+    {
+    }
+
+    std::string
+    NoSuchEntries::makeMsg(const std::string& missingTerm,
+                           const std::string& containerTerm,
+                           const MemoryID& containerID,
+                           const std::string& message)
+    {
+        std::stringstream ss;
+        ss << "No " << missingTerm << " in " << containerTerm << " " << containerID << ".";
+        return ss.str();
+    }
+
     MissingData::MissingData(const std::string& missingTerm,
                              const std::string& missingName,
                              const std::string& ownTerm,
diff --git a/source/RobotAPI/libraries/armem/core/error/ArMemError.h b/source/RobotAPI/libraries/armem/core/error/ArMemError.h
index 20a97a1fc..69ab7d4dd 100644
--- a/source/RobotAPI/libraries/armem/core/error/ArMemError.h
+++ b/source/RobotAPI/libraries/armem/core/error/ArMemError.h
@@ -98,6 +98,24 @@ namespace armarx::armem::error
                                    size_t size);
     };
 
+    /**
+     * @brief Indicates that an operation requiring at least one element to exist
+     * failed because there were no such entries.
+     */
+    class NoSuchEntries : public ArMemError
+    {
+    public:
+        NoSuchEntries(const std::string& missingTerm,
+                      const std::string& containerTerm,
+                      const MemoryID& containerID,
+                      const std::string& message = "");
+
+        static std::string makeMsg(const std::string& missingTerm,
+                                   const std::string& containerTerm,
+                                   const MemoryID& containerID,
+                                   const std::string& message = "");
+    };
+
     /**
      * @brief Indicates that a container did have an entry, but the entry's data was
      * null when trying to access it.
diff --git a/source/RobotAPI/libraries/armem/test/ArMemGetFindTest.cpp b/source/RobotAPI/libraries/armem/test/ArMemGetFindTest.cpp
index f03b02052..95cf79299 100644
--- a/source/RobotAPI/libraries/armem/test/ArMemGetFindTest.cpp
+++ b/source/RobotAPI/libraries/armem/test/ArMemGetFindTest.cpp
@@ -14,7 +14,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  * @package    RobotAPI::ArmarXObjects::armem
- * @author     Simon Ottenhaus ( simon dot ottenhaus at kit dot edu )
+ * @author     Rainer Kartmann ( raier dot kartmann at kit dot edu )
  * @date       2020
  * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
  *             GNU General Public License
@@ -24,29 +24,36 @@
 
 #define ARMARX_BOOST_TEST
 
-#include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
-#include <RobotAPI/libraries/armem/core/error.h>
-#include <RobotAPI/libraries/armem/core/operations.h>
+#include <iostream>
 
 #include <RobotAPI/Test.h>
-
-#include <iostream>
+#include <RobotAPI/libraries/armem/core/error.h>
+#include <RobotAPI/libraries/armem/core/operations.h>
+#include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
 
 
 namespace armem = armarx::armem;
 namespace wm = armarx::armem::wm;
 namespace aron = armarx::aron;
 
-
 namespace ArMemGetFindTest
 {
     struct Fixture
     {
         wm::EntitySnapshot snapshot;
+        wm::EntitySnapshot snapshotEmpty;
+
         wm::Entity entity;
+        wm::Entity entityEmpty;
+
         wm::ProviderSegment provSeg;
+        wm::ProviderSegment provSegEmpty;
+
         wm::CoreSegment coreSeg;
+        wm::CoreSegment coreSegEmpty;
+
         wm::Memory memory;
+        wm::Memory memoryEmpty;
 
         armem::MemoryID instanceID;
         armem::MemoryID snapshotID;
@@ -58,24 +65,38 @@ namespace ArMemGetFindTest
         Fixture()
         {
             {
+                snapshotEmpty.time() = armem::Time(armem::Duration::MicroSeconds(500));
+
                 snapshot.time() = armem::Time(armem::Duration::MicroSeconds(1000));
                 snapshot.addInstance();
             }
             {
+                entityEmpty.name() = "entity empty";
+
                 entity.name() = "entity";
                 entity.addSnapshot(snapshot);
+                entity.addSnapshot(snapshotEmpty);
             }
             {
+                provSegEmpty.name() = "provider segment empty";
+
                 provSeg.name() = "provider segment";
                 provSeg.addEntity(entity);
+                provSeg.addEntity(entityEmpty);
             }
             {
+                coreSegEmpty.name() = "core segment empty";
+
                 coreSeg.name() = "core segment";
                 coreSeg.addProviderSegment(provSeg);
+                coreSeg.addProviderSegment(provSegEmpty);
             }
             {
+                memoryEmpty.name() = "memory empty";
+
                 memory.name() = "memory";
                 memory.addCoreSegment(coreSeg);
+                memory.addCoreSegment(coreSegEmpty);
             }
 
             memoryID = memory.id();
@@ -85,22 +106,18 @@ namespace ArMemGetFindTest
             snapshotID = entityID.withTimestamp(snapshot.time());
             instanceID = snapshotID.withInstanceIndex(0);
         }
+
         ~Fixture()
         {
         }
 
-
         template <class ParentT>
-        void test_get_find_instance_by_id(ParentT&& parent)
-        {
-            _test_get_find_instance_by_id(const_cast<const ParentT&>(parent));
-            _test_get_find_instance_by_id(const_cast<ParentT&>(parent));
-        }
-        template <class ParentT>
-        void _test_get_find_instance_by_id(ParentT&& parent)
+        void
+        _test_get_find_instance_by_id(ParentT&& parent)
         {
             BOOST_TEST_CONTEXT("Parent: " << armem::print(parent))
             {
+                BOOST_CHECK_EQUAL(parent.hasInstance(), true);
                 BOOST_CHECK_EQUAL(parent.hasInstance(snapshotID.withInstanceIndex(0)), true);
                 BOOST_CHECK_EQUAL(parent.hasInstance(snapshotID.withInstanceIndex(1)), false);
 
@@ -108,106 +125,240 @@ namespace ArMemGetFindTest
                 BOOST_CHECK_EQUAL(parent.findInstance(snapshotID.withInstanceIndex(1)), nullptr);
 
                 BOOST_CHECK_NO_THROW(parent.getInstance(snapshotID.withInstanceIndex(0)));
-                BOOST_CHECK_THROW(parent.getInstance(snapshotID.withInstanceIndex(1)), armem::error::MissingEntry);
+                BOOST_CHECK_THROW(parent.getInstance(snapshotID.withInstanceIndex(1)),
+                                  armem::error::MissingEntry);
             }
         }
 
         template <class ParentT>
-        void test_get_find_snapshot_by_id(ParentT&& parent)
+        void
+        test_get_find_instance_by_id(ParentT&& parent)
         {
-            _test_get_find_snapshot_by_id(const_cast<const ParentT&>(parent));
-            _test_get_find_snapshot_by_id(const_cast<ParentT&>(parent));
+            _test_get_find_instance_by_id(const_cast<const ParentT&>(parent));
+            _test_get_find_instance_by_id(const_cast<ParentT&>(parent));
         }
+
         template <class ParentT>
-        void _test_get_find_snapshot_by_id(ParentT&& parent)
+        void
+        _test_get_find_latest_instance(ParentT&& parent)
         {
             BOOST_TEST_CONTEXT("Parent: " << armem::print(parent))
             {
-                BOOST_CHECK_EQUAL(parent.hasSnapshot(entityID.withTimestamp(armem::Time(armem::Duration::MicroSeconds(1000)))), true);
-                BOOST_CHECK_EQUAL(parent.hasSnapshot(entityID.withTimestamp(armem::Time(armem::Duration::MicroSeconds(2000)))), false);
+                BOOST_CHECK_EQUAL(parent.hasInstance(), true);
+                BOOST_CHECK_NE(parent.findLatestInstance(), nullptr);
+                BOOST_CHECK_NO_THROW(parent.getLatestInstance());
+            }
+        }
 
-                BOOST_CHECK_NE(parent.findSnapshot(entityID.withTimestamp(armem::Time(armem::Duration::MicroSeconds(1000)))), nullptr);
-                BOOST_CHECK_EQUAL(parent.findSnapshot(entityID.withTimestamp(armem::Time(armem::Duration::MicroSeconds(2000)))), nullptr);
+        template <class ParentT>
+        void
+        test_get_find_latest_instance(ParentT&& parent)
+        {
+            _test_get_find_latest_instance(const_cast<const ParentT&>(parent));
+            _test_get_find_latest_instance(const_cast<ParentT&>(parent));
+        }
 
-                BOOST_CHECK_NO_THROW(parent.getSnapshot(entityID.withTimestamp(armem::Time(armem::Duration::MicroSeconds(1000)))));
-                BOOST_CHECK_THROW(parent.getSnapshot(entityID.withTimestamp(armem::Time(armem::Duration::MicroSeconds(2000)))), armem::error::MissingEntry);
+        template <class ParentT>
+        void
+        _test_get_find_latest_instance_when_empty(ParentT&& parent)
+        {
+            BOOST_TEST_CONTEXT("Parent: " << armem::print(parent))
+            {
+                BOOST_CHECK_EQUAL(parent.hasInstance(), false);
+                BOOST_CHECK_EQUAL(parent.findLatestInstance(), nullptr);
+                BOOST_CHECK_THROW(parent.getLatestInstance(), armem::error::NoSuchEntries);
             }
         }
 
+        template <class ParentT>
+        void
+        test_get_find_latest_instance_when_empty(ParentT&& parent)
+        {
+            _test_get_find_latest_instance_when_empty(const_cast<const ParentT&>(parent));
+            _test_get_find_latest_instance_when_empty(const_cast<ParentT&>(parent));
+        }
 
         template <class ParentT>
-        void test_get_find_entity_by_id(ParentT&& parent)
+        void
+        _test_get_find_snapshot_by_id(ParentT&& parent)
         {
-            _test_get_find_entity_by_id(const_cast<const ParentT&>(parent));
-            _test_get_find_entity_by_id(const_cast<ParentT&>(parent));
+            BOOST_TEST_CONTEXT("Parent: " << armem::print(parent))
+            {
+                BOOST_CHECK_EQUAL(parent.hasSnapshot(), true);
+
+                BOOST_CHECK_EQUAL(parent.hasSnapshot(entityID.withTimestamp(
+                                      armem::Time(armem::Duration::MicroSeconds(1000)))),
+                                  true);
+                BOOST_CHECK_EQUAL(parent.hasSnapshot(entityID.withTimestamp(
+                                      armem::Time(armem::Duration::MicroSeconds(2000)))),
+                                  false);
+
+                BOOST_CHECK_NE(parent.findSnapshot(entityID.withTimestamp(
+                                   armem::Time(armem::Duration::MicroSeconds(1000)))),
+                               nullptr);
+                BOOST_CHECK_EQUAL(parent.findSnapshot(entityID.withTimestamp(
+                                      armem::Time(armem::Duration::MicroSeconds(2000)))),
+                                  nullptr);
+
+                BOOST_CHECK_NO_THROW(parent.getSnapshot(
+                    entityID.withTimestamp(armem::Time(armem::Duration::MicroSeconds(1000)))));
+                BOOST_CHECK_THROW(parent.getSnapshot(entityID.withTimestamp(
+                                      armem::Time(armem::Duration::MicroSeconds(2000)))),
+                                  armem::error::MissingEntry);
+            }
+        }
+
+        template <class ParentT>
+        void
+        test_get_find_snapshot_by_id(ParentT&& parent)
+        {
+            _test_get_find_snapshot_by_id(const_cast<const ParentT&>(parent));
+            _test_get_find_snapshot_by_id(const_cast<ParentT&>(parent));
         }
+
         template <class ParentT>
-        void _test_get_find_entity_by_id(ParentT&& parent)
+        void
+        _test_get_find_entity_by_id(ParentT&& parent)
         {
             BOOST_TEST_CONTEXT("Parent: " << armem::print(parent))
             {
                 BOOST_CHECK_EQUAL(parent.hasEntity(provSegID.withEntityName("entity")), true);
-                BOOST_CHECK_EQUAL(parent.hasEntity(provSegID.withEntityName("other entity")), false);
+                BOOST_CHECK_EQUAL(parent.hasEntity(provSegID.withEntityName("other entity")),
+                                  false);
 
                 BOOST_CHECK_NE(parent.findEntity(provSegID.withEntityName("entity")), nullptr);
-                BOOST_CHECK_EQUAL(parent.findEntity(provSegID.withEntityName("other entity")), nullptr);
+                BOOST_CHECK_EQUAL(parent.findEntity(provSegID.withEntityName("other entity")),
+                                  nullptr);
 
                 BOOST_CHECK_NO_THROW(parent.getEntity(provSegID.withEntityName("entity")));
-                BOOST_CHECK_THROW(parent.getEntity(provSegID.withEntityName("other entity")), armem::error::MissingEntry);
+                BOOST_CHECK_THROW(parent.getEntity(provSegID.withEntityName("other entity")),
+                                  armem::error::MissingEntry);
             }
         }
 
         template <class ParentT>
-        void test_get_find_provider_segment_by_id(ParentT&& parent)
+        void
+        _test_get_find_latest_snapshot(ParentT&& parent)
         {
-            _test_get_find_provider_segment_by_id(const_cast<const ParentT&>(parent));
-            _test_get_find_provider_segment_by_id(const_cast<ParentT&>(parent));
+            BOOST_TEST_CONTEXT("Parent: " << armem::print(parent))
+            {
+                BOOST_CHECK_EQUAL(parent.hasSnapshot(), true);
+                BOOST_CHECK_NE(parent.findLatestSnapshot(), nullptr);
+                BOOST_CHECK_NO_THROW(parent.getLatestSnapshot());
+            }
         }
+
         template <class ParentT>
-        void _test_get_find_provider_segment_by_id(ParentT&& parent)
+        void
+        test_get_find_latest_snapshot(ParentT&& parent)
+        {
+            _test_get_find_latest_snapshot(const_cast<const ParentT&>(parent));
+            _test_get_find_latest_snapshot(const_cast<ParentT&>(parent));
+        }
+
+        template <class ParentT>
+        void
+        _test_get_find_latest_snapshot_when_empty(ParentT&& parent)
         {
             BOOST_TEST_CONTEXT("Parent: " << armem::print(parent))
             {
-                BOOST_CHECK_EQUAL(parent.hasProviderSegment(provSegID.withProviderSegmentName("provider segment")), true);
-                BOOST_CHECK_EQUAL(parent.hasProviderSegment(provSegID.withProviderSegmentName("other provider segment")), false);
-
-                BOOST_CHECK_NE(parent.findProviderSegment(provSegID.withProviderSegmentName("provider segment")), nullptr);
-                BOOST_CHECK_EQUAL(parent.findProviderSegment(provSegID.withProviderSegmentName("other provider segment")), nullptr);
-
-                BOOST_CHECK_NO_THROW(parent.getProviderSegment(provSegID.withProviderSegmentName("provider segment")));
-                BOOST_CHECK_THROW(parent.getProviderSegment(provSegID.withProviderSegmentName("other provider segment")), armem::error::MissingEntry);
+                BOOST_CHECK_EQUAL(parent.hasSnapshot(), false);
+                BOOST_CHECK_EQUAL(parent.findLatestSnapshot(), nullptr);
+                BOOST_CHECK_THROW(parent.getLatestSnapshot(), armem::error::NoSuchEntries);
             }
         }
 
         template <class ParentT>
-        void test_get_find_core_segment_by_id(ParentT&& parent)
+        void
+        test_get_find_latest_snapshot_when_empty(ParentT&& parent)
         {
-            _test_get_find_core_segment_by_id(const_cast<const ParentT&>(parent));
-            _test_get_find_core_segment_by_id(const_cast<ParentT&>(parent));
+            _test_get_find_latest_snapshot_when_empty(const_cast<const ParentT&>(parent));
+            _test_get_find_latest_snapshot_when_empty(const_cast<ParentT&>(parent));
         }
+
         template <class ParentT>
-        void _test_get_find_core_segment_by_id(ParentT&& parent)
+        void
+        test_get_find_entity_by_id(ParentT&& parent)
+        {
+            _test_get_find_entity_by_id(const_cast<const ParentT&>(parent));
+            _test_get_find_entity_by_id(const_cast<ParentT&>(parent));
+        }
+
+        template <class ParentT>
+        void
+        _test_get_find_provider_segment_by_id(ParentT&& parent)
         {
             BOOST_TEST_CONTEXT("Parent: " << armem::print(parent))
             {
-                BOOST_CHECK_EQUAL(parent.hasCoreSegment(provSegID.withCoreSegmentName("core segment")), true);
-                BOOST_CHECK_EQUAL(parent.hasCoreSegment(provSegID.withCoreSegmentName("other core segment")), false);
+                BOOST_CHECK_EQUAL(parent.hasProviderSegment(
+                                      provSegID.withProviderSegmentName("provider segment")),
+                                  true);
+                BOOST_CHECK_EQUAL(parent.hasProviderSegment(
+                                      provSegID.withProviderSegmentName("other provider segment")),
+                                  false);
+
+                BOOST_CHECK_NE(parent.findProviderSegment(
+                                   provSegID.withProviderSegmentName("provider segment")),
+                               nullptr);
+                BOOST_CHECK_EQUAL(parent.findProviderSegment(
+                                      provSegID.withProviderSegmentName("other provider segment")),
+                                  nullptr);
+
+                BOOST_CHECK_NO_THROW(parent.getProviderSegment(
+                    provSegID.withProviderSegmentName("provider segment")));
+                BOOST_CHECK_THROW(parent.getProviderSegment(
+                                      provSegID.withProviderSegmentName("other provider segment")),
+                                  armem::error::MissingEntry);
+            }
+        }
 
-                BOOST_CHECK_NE(parent.findCoreSegment(provSegID.withCoreSegmentName("core segment")), nullptr);
-                BOOST_CHECK_EQUAL(parent.findCoreSegment(provSegID.withCoreSegmentName("other core segment")), nullptr);
+        template <class ParentT>
+        void
+        test_get_find_provider_segment_by_id(ParentT&& parent)
+        {
+            _test_get_find_provider_segment_by_id(const_cast<const ParentT&>(parent));
+            _test_get_find_provider_segment_by_id(const_cast<ParentT&>(parent));
+        }
 
-                BOOST_CHECK_NO_THROW(parent.getCoreSegment(provSegID.withCoreSegmentName("core segment")));
-                BOOST_CHECK_THROW(parent.getCoreSegment(provSegID.withCoreSegmentName("other core segment")), armem::error::MissingEntry);
+        template <class ParentT>
+        void
+        _test_get_find_core_segment_by_id(ParentT&& parent)
+        {
+            BOOST_TEST_CONTEXT("Parent: " << armem::print(parent))
+            {
+                BOOST_CHECK_EQUAL(
+                    parent.hasCoreSegment(provSegID.withCoreSegmentName("core segment")), true);
+                BOOST_CHECK_EQUAL(
+                    parent.hasCoreSegment(provSegID.withCoreSegmentName("other core segment")),
+                    false);
+
+                BOOST_CHECK_NE(
+                    parent.findCoreSegment(provSegID.withCoreSegmentName("core segment")), nullptr);
+                BOOST_CHECK_EQUAL(
+                    parent.findCoreSegment(provSegID.withCoreSegmentName("other core segment")),
+                    nullptr);
+
+                BOOST_CHECK_NO_THROW(
+                    parent.getCoreSegment(provSegID.withCoreSegmentName("core segment")));
+                BOOST_CHECK_THROW(
+                    parent.getCoreSegment(provSegID.withCoreSegmentName("other core segment")),
+                    armem::error::MissingEntry);
             }
         }
+
+        template <class ParentT>
+        void
+        test_get_find_core_segment_by_id(ParentT&& parent)
+        {
+            _test_get_find_core_segment_by_id(const_cast<const ParentT&>(parent));
+            _test_get_find_core_segment_by_id(const_cast<ParentT&>(parent));
+        }
     };
-}
+} // namespace ArMemGetFindTest
 
 
 BOOST_FIXTURE_TEST_SUITE(ArMemGetFindTest, Fixture)
 
-
-
 BOOST_AUTO_TEST_CASE(test_snapshot_get_find_instance_by_key)
 {
     BOOST_CHECK_EQUAL(snapshot.hasInstance(0), true);
@@ -220,20 +371,20 @@ BOOST_AUTO_TEST_CASE(test_snapshot_get_find_instance_by_key)
     BOOST_CHECK_THROW(snapshot.getInstance(1), armem::error::MissingEntry);
 }
 
-
 BOOST_AUTO_TEST_CASE(test_entity_get_find_snapshot_by_key)
 {
     BOOST_CHECK_EQUAL(entity.hasSnapshot(armem::Time(armem::Duration::MicroSeconds(1000))), true);
     BOOST_CHECK_EQUAL(entity.hasSnapshot(armem::Time(armem::Duration::MicroSeconds(2000))), false);
 
     BOOST_CHECK_NE(entity.findSnapshot(armem::Time(armem::Duration::MicroSeconds(1000))), nullptr);
-    BOOST_CHECK_EQUAL(entity.findSnapshot(armem::Time(armem::Duration::MicroSeconds(2000))), nullptr);
+    BOOST_CHECK_EQUAL(entity.findSnapshot(armem::Time(armem::Duration::MicroSeconds(2000))),
+                      nullptr);
 
     BOOST_CHECK_NO_THROW(entity.getSnapshot(armem::Time(armem::Duration::MicroSeconds(1000))));
-    BOOST_CHECK_THROW(entity.getSnapshot(armem::Time(armem::Duration::MicroSeconds(2000))), armem::error::MissingEntry);
+    BOOST_CHECK_THROW(entity.getSnapshot(armem::Time(armem::Duration::MicroSeconds(2000))),
+                      armem::error::MissingEntry);
 }
 
-
 BOOST_AUTO_TEST_CASE(test_provider_segment_get_find_entity_by_key)
 {
     BOOST_CHECK_EQUAL(provSeg.hasEntity("entity"), true);
@@ -246,7 +397,6 @@ BOOST_AUTO_TEST_CASE(test_provider_segment_get_find_entity_by_key)
     BOOST_CHECK_THROW(provSeg.getEntity("other entity"), armem::error::MissingEntry);
 }
 
-
 BOOST_AUTO_TEST_CASE(test_core_segment_get_find_provider_segment_by_key)
 {
     BOOST_CHECK_EQUAL(coreSeg.hasProviderSegment("provider segment"), true);
@@ -256,10 +406,10 @@ BOOST_AUTO_TEST_CASE(test_core_segment_get_find_provider_segment_by_key)
     BOOST_CHECK_EQUAL(coreSeg.findProviderSegment("other provider segment"), nullptr);
 
     BOOST_CHECK_NO_THROW(coreSeg.getProviderSegment("provider segment"));
-    BOOST_CHECK_THROW(coreSeg.getProviderSegment("other provider segment"), armem::error::MissingEntry);
+    BOOST_CHECK_THROW(coreSeg.getProviderSegment("other provider segment"),
+                      armem::error::MissingEntry);
 }
 
-
 BOOST_AUTO_TEST_CASE(test_memory_get_find_core_segment_by_key)
 {
     BOOST_CHECK_EQUAL(memory.hasCoreSegment("core segment"), true);
@@ -272,66 +422,119 @@ BOOST_AUTO_TEST_CASE(test_memory_get_find_core_segment_by_key)
     BOOST_CHECK_THROW(memory.getCoreSegment("other core segment"), armem::error::MissingEntry);
 }
 
-
-
 BOOST_AUTO_TEST_CASE(test_snapshot_get_find_instance_by_id)
 {
     test_get_find_instance_by_id(snapshot);
 }
+
 BOOST_AUTO_TEST_CASE(test_entity_get_find_instance_by_id)
 {
     test_get_find_instance_by_id(entity);
 }
+
 BOOST_AUTO_TEST_CASE(test_provider_segment_get_find_instance_by_id)
 {
     test_get_find_instance_by_id(provSeg);
 }
+
 BOOST_AUTO_TEST_CASE(test_core_segment_get_find_instance_by_id)
 {
     test_get_find_instance_by_id(coreSeg);
 }
+
 BOOST_AUTO_TEST_CASE(test_memory_get_find_instance_by_id)
 {
     test_get_find_instance_by_id(memory);
 }
 
+BOOST_AUTO_TEST_CASE(test_entity_get_find_latest_instance)
+{
+    test_get_find_latest_instance(entity);
+    test_get_find_latest_instance_when_empty(entityEmpty);
+}
+
+BOOST_AUTO_TEST_CASE(test_provider_segment_get_find_latest_instance)
+{
+    test_get_find_latest_instance(provSeg);
+    test_get_find_latest_instance_when_empty(provSegEmpty);
+}
+
+BOOST_AUTO_TEST_CASE(test_core_segment_get_find_latest_instance)
+{
+    test_get_find_latest_instance(coreSeg);
+    test_get_find_latest_instance_when_empty(coreSegEmpty);
+}
+
+BOOST_AUTO_TEST_CASE(test_memory_get_find_latest_instance)
+{
+    test_get_find_latest_instance(memory);
+    test_get_find_latest_instance_when_empty(memoryEmpty);
+}
 
 BOOST_AUTO_TEST_CASE(test_entity_get_find_snapshot_by_id)
 {
     test_get_find_snapshot_by_id(entity);
 }
+
 BOOST_AUTO_TEST_CASE(test_provider_segment_get_find_snapshot_by_id)
 {
     test_get_find_snapshot_by_id(provSeg);
 }
+
 BOOST_AUTO_TEST_CASE(test_core_segment_get_find_snapshot_by_id)
 {
     test_get_find_snapshot_by_id(coreSeg);
 }
+
 BOOST_AUTO_TEST_CASE(test_memory_get_find_snapshot_by_id)
 {
     test_get_find_snapshot_by_id(memory);
 }
 
+BOOST_AUTO_TEST_CASE(test_entity_get_find_latest_snapshot)
+{
+    test_get_find_latest_snapshot(entity);
+    test_get_find_latest_snapshot_when_empty(entityEmpty);
+}
+
+BOOST_AUTO_TEST_CASE(test_provider_segment_get_find_latest_snapshot)
+{
+    test_get_find_latest_snapshot(provSeg);
+    test_get_find_latest_snapshot_when_empty(provSegEmpty);
+}
+
+BOOST_AUTO_TEST_CASE(test_core_segment_get_find_latest_snapshot)
+{
+    test_get_find_latest_snapshot(coreSeg);
+    test_get_find_latest_snapshot_when_empty(coreSegEmpty);
+}
+
+BOOST_AUTO_TEST_CASE(test_memory_get_find_latest_snapshot)
+{
+    test_get_find_latest_snapshot(memory);
+    test_get_find_latest_snapshot_when_empty(memoryEmpty);
+}
 
 BOOST_AUTO_TEST_CASE(test_provider_segment_get_find_entity_by_id)
 {
     test_get_find_entity_by_id(provSeg);
 }
+
 BOOST_AUTO_TEST_CASE(test_core_segment_get_find_entity_by_id)
 {
     test_get_find_entity_by_id(coreSeg);
 }
+
 BOOST_AUTO_TEST_CASE(test_memory_get_find_entity_by_id)
 {
     test_get_find_entity_by_id(memory);
 }
 
-
 BOOST_AUTO_TEST_CASE(test_core_segment_get_find_provider_segment_by_id)
 {
     test_get_find_provider_segment_by_id(coreSeg);
 }
+
 BOOST_AUTO_TEST_CASE(test_memory_get_find_provider_segment_by_id)
 {
     test_get_find_provider_segment_by_id(memory);
@@ -342,6 +545,4 @@ BOOST_AUTO_TEST_CASE(test_memory_get_find_core_segment_by_id)
     test_get_find_core_segment_by_id(memory);
 }
 
-
-
 BOOST_AUTO_TEST_SUITE_END()
-- 
GitLab