From 2d93f4947130960937129a8c47ddc00741b53079 Mon Sep 17 00:00:00 2001
From: Tadej Novak <tadej.novak@cern.ch>
Date: Sun, 29 Nov 2020 21:15:19 +0100
Subject: [PATCH] Fix standalone DecorHandles

---
 .../AsgDataHandles/DecorKeyHelpers.h          |   5 +-
 .../AsgDataHandles/ReadDecorHandle.h          |  40 +++--
 .../AsgDataHandles/ReadDecorHandle.icc        |  58 ++++---
 .../AsgDataHandles/ReadDecorHandleKey.h       |  70 ++++++--
 .../AsgDataHandles/ReadDecorHandleKey.icc     | 105 ++++++++++--
 .../AsgDataHandles/ReadHandleKey.icc          |  26 +--
 .../AsgDataHandles/WriteDecorHandle.h         |  46 +++--
 .../AsgDataHandles/WriteDecorHandle.icc       |  95 +++++++----
 .../AsgDataHandles/WriteDecorHandleKey.h      |  62 +++----
 .../AsgDataHandles/WriteDecorHandleKey.icc    |  97 +++++------
 .../AsgDataHandles/CMakeLists.txt             |   2 +-
 .../AsgDataHandles/Root/VarHandleKey.cxx      |   4 +-
 .../AsgExampleTools/DataHandleTestTool.h      |   2 +
 .../AsgExampleTools/CMakeLists.txt            |   8 +
 .../Root/DataHandleTestTool.cxx               |   8 +-
 .../test/gt_DataHandlesTest.cxx               |  16 ++
 .../test/gt_DataHandlesUnitTest.cxx           | 161 ++++++++++++++++++
 17 files changed, 587 insertions(+), 218 deletions(-)
 create mode 100644 Control/AthToolSupport/AsgExampleTools/test/gt_DataHandlesUnitTest.cxx

diff --git a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/DecorKeyHelpers.h b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/DecorKeyHelpers.h
index 75ddb7fefd8..349c710ae2e 100644
--- a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/DecorKeyHelpers.h
+++ b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/DecorKeyHelpers.h
@@ -18,7 +18,7 @@ inline std::string contKeyFromKey (const std::string& key)
 {
   const auto split = key.rfind ('.');
   if (split == std::string::npos)
-    throw std::runtime_error ("decor key does not contain a .: " + key);
+    return key;
   return key.substr (0, split);
 }
 
@@ -26,9 +26,10 @@ inline std::string decorKeyFromKey (const std::string& key)
 {
   const auto split = key.rfind ('.');
   if (split == std::string::npos)
-    throw std::runtime_error ("decor key does not contain a .: " + key);
+    return "";
   return key.substr (split + 1);
 }
+
 }
 
 #endif
diff --git a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadDecorHandle.h b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadDecorHandle.h
index 6184d1dc8c6..a4174f284db 100644
--- a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadDecorHandle.h
+++ b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadDecorHandle.h
@@ -22,7 +22,7 @@
 #include "AsgDataHandles/ReadDecorHandleKey.h"
 #include "AsgDataHandles/ReadHandle.h"
 #include "AsgDataHandles/DecorKeyHelpers.h"
-// #include "AthContainers/AuxElement.h"
+#include "AthContainers/AuxElement.h"
 // #include "GaudiKernel/EventContext.h"
 // #include <type_traits>
 
@@ -72,21 +72,21 @@ public:
   explicit ReadDecorHandle (const ReadDecorHandleKey<T>& key);
 
 
-//   /**
-//    * @brief Constructor from a ReadDecorHandleKey and an explicit event context.
-//    * @param key The key object holding the clid/key.
-//    * @param ctx The event context.
-//    *
-//    * This will raise an exception if the StoreGate key is blank,
-//    * or if the event store cannot be found.
-//    *
-//    * If the default event store has been requested, then the thread-specific
-//    * store from the event context will be used.
-//    */
-//   explicit ReadDecorHandle (const ReadDecorHandleKey<T>& key,
-//                             const EventContext& ctx);
+  /**
+   * @brief Constructor from a ReadDecorHandleKey and an explicit event context.
+   * @param key The key object holding the clid/key.
+   * @param ctx The event context.
+   *
+   * This will raise an exception if the StoreGate key is blank,
+   * or if the event store cannot be found.
+   *
+   * If the default event store has been requested, then the thread-specific
+   * store from the event context will be used.
+   */
+  explicit ReadDecorHandle (const ReadDecorHandleKey<T>& key,
+                            const EventContext& ctx);
+
 
-  
 //   /**
 //    * @brief Copy constructor.
 //    */
@@ -159,6 +159,12 @@ public:
 //    */
 //   SG::auxid_t auxid() const;
 
+
+  /**
+   * @brief Return the name of the decoration alias (CONT.DECOR).
+   */
+  std::string decorKey() const;
+
   
 private:
   /** 
@@ -187,6 +193,10 @@ private:
   const SG::AuxVectorData* vectorData();
 
 
+  /// Name of the decoration alias.
+  std::string m_decorKey;
+
+
   /// Accessor for the aux data item.
   accessor_t m_acc;
 };
diff --git a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadDecorHandle.icc b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadDecorHandle.icc
index eda87fd6121..bda9623c1eb 100644
--- a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadDecorHandle.icc
+++ b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadDecorHandle.icc
@@ -21,30 +21,32 @@ namespace SG {
  */
 template <class T, class D>
 ReadDecorHandle<T, D>::ReadDecorHandle (const ReadDecorHandleKey<T>& key)
-  : Base (key),
+  : Base (key.contHandleKey()),
+    m_decorKey (key.key()),
     m_acc (SG::decorKeyFromKey (key.key()))
 {
 }
 
 
-// /**
-//  * @brief Constructor from a ReadDecorHandleKey and an explicit event context.
-//  * @param key The key object holding the clid/key.
-//  * @param ctx The event context.
-//  *
-//  * This will raise an exception if the StoreGate key is blank,
-//  * or if the event store cannot be found.
-//  *
-//  * If the default event store has been requested, then the thread-specific
-//  * store from the event context will be used.
-//  */
-// template <class T, class D>
-// ReadDecorHandle<T, D>::ReadDecorHandle (const ReadDecorHandleKey<T>& key,
-//                                         const EventContext& ctx)
-//   : Base (key, ctx),
-//     m_acc (SG::decorKeyFromKey (key.key()))
-// {
-// }
+/**
+ * @brief Constructor from a ReadDecorHandleKey and an explicit event context.
+ * @param key The key object holding the clid/key.
+ * @param ctx The event context.
+ *
+ * This will raise an exception if the StoreGate key is blank,
+ * or if the event store cannot be found.
+ *
+ * If the default event store has been requested, then the thread-specific
+ * store from the event context will be used.
+ */
+template <class T, class D>
+ReadDecorHandle<T, D>::ReadDecorHandle (const ReadDecorHandleKey<T>& key,
+                                        const EventContext& ctx)
+  : Base (key.contHandleKey(), ctx),
+    m_decorKey (key.key()),
+    m_acc (SG::decorKeyFromKey (key.key()))
+{
+}
 
 
 // /**
@@ -53,6 +55,7 @@ ReadDecorHandle<T, D>::ReadDecorHandle (const ReadDecorHandleKey<T>& key)
 // template <class T, class D>
 // ReadDecorHandle<T, D>::ReadDecorHandle (const ReadDecorHandle& rhs)
 //   : Base (rhs),
+//     m_decorKey (rhs.m_decorKey),
 //     m_acc (rhs.m_acc)
 // {
 // }
@@ -64,6 +67,7 @@ ReadDecorHandle<T, D>::ReadDecorHandle (const ReadDecorHandleKey<T>& key)
 // template <class T, class D>
 // ReadDecorHandle<T, D>::ReadDecorHandle (ReadDecorHandle&& rhs)
 //   : Base (std::move (rhs)),
+//     m_decorKey (std::move (rhs.m_decorKey)),
 //     m_acc (std::move (rhs.m_acc))
 // {
 // }
@@ -77,6 +81,7 @@ ReadDecorHandle<T, D>::ReadDecorHandle (const ReadDecorHandleKey<T>& key)
 // {
 //   if (this != &rhs) {
 //     *static_cast<Base*>(this) = rhs;
+//     m_decorKey = rhs.m_decorKey;
 //     m_acc = rhs.m_acc;
 //   }
 //   return *this;
@@ -91,6 +96,7 @@ ReadDecorHandle<T, D>::ReadDecorHandle (const ReadDecorHandleKey<T>& key)
 // {
 //   if (this != &rhs) {
 //     *static_cast<Base*>(this) = std::move (rhs);
+//     m_decorKey = std::move (rhs.m_decorKey);
 //     m_acc = std::move (rhs.m_acc);
 //   }
 //   return *this;
@@ -106,9 +112,10 @@ ReadDecorHandle<T, D>::ReadDecorHandle (const ReadDecorHandleKey<T>& key)
  * Const method; the handle does not change as a result of this.
  */
 template <class T, class D>
+inline
 bool ReadDecorHandle<T, D>::isPresent() const
 {
-  return this->isPresent_impl (contKeyFromKey (this->key()));
+  return Base::isPresent();
 }
 
 
@@ -178,6 +185,17 @@ ReadDecorHandle<T, D>::operator() (size_t i)
 // }
 
 
+/**
+ * @brief Return the name of the decoration alias (CONT.DECOR).
+ */
+template <class T, class D>
+inline
+std::string ReadDecorHandle<T, D>::decorKey() const
+{
+  return m_decorKey;
+}
+
+
 /** 
  * @brief Return the referenced object as a @c SG::AuxVectorData.
  *        Specialization for the case of a standalone object
diff --git a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadDecorHandleKey.h b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadDecorHandleKey.h
index 83402156e06..ecdd8b19b45 100644
--- a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadDecorHandleKey.h
+++ b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadDecorHandleKey.h
@@ -49,17 +49,17 @@ public:
 //   typedef typename SG::TopBase<T>::type topbase_t;
 
 
-//   /**
-//    * @brief Constructor.
-//    * @param key The StoreGate key for the object.
-//    * @param storeName Name to use for the store, if it's not encoded in sgkey.
-//    *
-//    * The provided key may actually start with the name of the store,
-//    * separated by a "+":  "MyStore+Obj".  If no "+" is present
-//    * the store named by @c storeName is used.
-//    */
-//   ReadDecorHandleKey (const std::string& key = "",
-//                       const std::string& storeName = StoreID::storeName(StoreID::EVENT_STORE));
+  /**
+   * @brief Constructor.
+   * @param key The StoreGate key for the object.
+   * @param storeName Name to use for the store, if it's not encoded in sgkey.
+   *
+   * The provided key may actually start with the name of the store,
+   * separated by a "+":  "MyStore+Obj".  If no "+" is present
+   * the store named by @c storeName is used.
+   */
+  ReadDecorHandleKey (const std::string& key = "");
+                      // const std::string& storeName = StoreID::storeName(StoreID::EVENT_STORE));
 
 
   /**
@@ -81,9 +81,30 @@ public:
                       const K& key = {},
                       const std::string& doc = "");
 
-  
-  /// Can get this from the base class.
-  using Base::operator=;
+
+  /**
+   * @brief Change the key of the object to which we're referring.
+   * @param sgkey The StoreGate key for the object.
+   * 
+   * The provided key may actually start with the name of the store,
+   * separated by a "+":  "MyStore+Obj".  If no "+" is present,
+   * the store is not changed.
+   */
+  ReadDecorHandleKey& operator= (const std::string& sgkey);
+
+
+  /**
+   * @brief Change the key of the object to which we're referring.
+   * @param sgkey The StoreGate key for the object.
+   * 
+   * The provided key may actually start with the name of the store,
+   * separated by a "+":  "MyStore+Obj".  If no "+" is present
+   * the store is not changed.  A key name that starts with a slash
+   * is interpreted as a hierarchical key name, not an empty store name.
+   *
+   * Returns failure the key string format is bad.
+   */
+  virtual StatusCode assign (const std::string& sgkey) override;
 
 
 //   /**
@@ -92,6 +113,27 @@ public:
 //    * Overridden here to return the CLID for @c T instead of @c topbase_t.
 //    */
 //   CLID clid() const;
+
+
+  /**
+   * @brief If this object is used as a property, then this should be called
+   *        during the initialize phase.  It will fail if the requested
+   *        StoreGate service cannot be found or if the key is blank.
+   * @param used If false, then this handle is not to be used.
+   *             Instead of normal initialization, the key will be cleared.
+   */
+  StatusCode initialize (bool used = true);
+
+
+  /**
+   * @brief Return the handle key for the container.
+   */
+  const ReadHandleKey<T>& contHandleKey() const;
+
+
+private:
+  /// The container handle.
+  ReadHandleKey<T> m_contHandleKey;
 };
 
 
diff --git a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadDecorHandleKey.icc b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadDecorHandleKey.icc
index 457db4d3ade..c71902c5e2e 100644
--- a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadDecorHandleKey.icc
+++ b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadDecorHandleKey.icc
@@ -10,26 +10,30 @@
  *        ReadDecorHandle is made.
  */
 
+#include <AsgDataHandles/DecorKeyHelpers.h>
+
 
 namespace SG {
 
 
-// /**
-//  * @brief Constructor.
-//  * @param key The StoreGate key for the object.
-//  * @param storeName Name to use for the store, if it's not encoded in sgkey.
-//  *
-//  * The provided key may actually start with the name of the store,
-//  * separated by a "+":  "MyStore+Obj".  If no "+" is present
-//  * the store named by @c storeName is used.
-//  */
-// template <class T>
-// inline
-// ReadDecorHandleKey<T>::ReadDecorHandleKey (const std::string& key /*= ""*/,
-//                                            const std::string& storeName /*= StoreID::storeName(StoreID::EVENT_STORE)*/)
-//   : Base (ClassID_traits<topbase_t>::ID(), key, storeName)
-// {
-// }
+/**
+ * @brief Constructor.
+ * @param key The StoreGate key for the object.
+ * @param storeName Name to use for the store, if it's not encoded in sgkey.
+ *
+ * The provided key may actually start with the name of the store,
+ * separated by a "+":  "MyStore+Obj".  If no "+" is present
+ * the store named by @c storeName is used.
+ */
+template <class T>
+inline
+ReadDecorHandleKey<T>::ReadDecorHandleKey (const std::string& key /*= ""*/)
+                                          //  const std::string& storeName /*= StoreID::storeName(StoreID::EVENT_STORE)*/)
+  // : Base (ClassID_traits<topbase_t>::ID(), key, storeName),
+  : Base (key),
+    m_contHandleKey (contKeyFromKey (key)/*, storeName*/)
+{
+}
 
 
 /**
@@ -52,8 +56,48 @@ ReadDecorHandleKey<T>::ReadDecorHandleKey( OWNER* owner,
                                            const std::string& name,
                                            const K& key /*={}*/,
                                            const std::string& doc /*=""*/)
-  : Base (owner, name, key, doc)
+  : Base (key),
+    m_contHandleKey (contKeyFromKey (key)/*, StoreID::storeName(StoreID::EVENT_STORE) */)
+{
+  owner->declareProperty(name, *this, doc);
+}
+
+
+/**
+ * @brief Change the key of the object to which we're referring.
+ * @param sgkey The StoreGate key for the object.
+ * 
+ * The provided key may actually start with the name of the store,
+ * separated by a "+":  "MyStore+Obj".  If no "+" is present,
+ * the store is not changed.
+ */
+template <class T>
+ReadDecorHandleKey<T>&
+ReadDecorHandleKey<T>::operator= (const std::string& sgkey)
 {
+  m_contHandleKey = contKeyFromKey (sgkey);
+  Base::operator= (sgkey);
+  return *this;
+}
+
+
+/**
+ * @brief Change the key of the object to which we're referring.
+ * @param sgkey The StoreGate key for the object.
+ * 
+ * The provided key may actually start with the name of the store,
+ * separated by a "+":  "MyStore+Obj".  If no "+" is present
+ * the store is not changed.  A key name that starts with a "+"
+ * is interpreted as a hierarchical key name, not an empty store name.
+ *
+ * Returns failure the key string format is bad.
+ */
+template <class T>
+StatusCode ReadDecorHandleKey<T>::assign (const std::string& sgkey)
+{
+  if (m_contHandleKey.assign (contKeyFromKey (sgkey)).isFailure())
+    return StatusCode::FAILURE;
+  return Base::assign (sgkey);
 }
 
 
@@ -70,4 +114,31 @@ ReadDecorHandleKey<T>::ReadDecorHandleKey( OWNER* owner,
 // }
 
 
+/**
+ * @brief If this object is used as a property, then this should be called
+ *        during the initialize phase.  It will fail if the requested
+ *        StoreGate service cannot be found or if the key is blank.
+ *
+ * @param used If false, then this handle is not to be used.
+ *             Instead of normal initialization, the key will be cleared.
+ */
+template <class T>
+StatusCode ReadDecorHandleKey<T>::initialize (bool used /*= true*/)
+{
+  if (m_contHandleKey.initialize (used).isFailure())
+    return StatusCode::FAILURE;
+  return Base::initialize (used);
+}
+
+
+/**
+ * @brief Return the handle key for the container.
+ */
+template <class T>
+const ReadHandleKey<T>& ReadDecorHandleKey<T>::contHandleKey() const
+{
+  return m_contHandleKey;
+}
+
+
 } // namespace SG
diff --git a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadHandleKey.icc b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadHandleKey.icc
index be2422d1c43..9878c897f3e 100644
--- a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadHandleKey.icc
+++ b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/ReadHandleKey.icc
@@ -31,19 +31,19 @@ ReadHandleKey<T>::ReadHandleKey (const std::string& key)
 }
 
 
-// /**
-//  * @brief Auto-declaring Property constructor.
-//  * @param owner Owning component.
-//  * @param name Name of the Property.
-//  * @param key  Default StoreGate key for the object.
-//  * @param doc Documentation string.
-//  *
-//  * Will associate the named Property with this RHK via declareProperty.
-//  *
-//  * The provided key may actually start with the name of the store,
-//  * separated by a "+":  "MyStore+Obj".  If no "+" is present
-//  * the store named by @c storeName is used.
-//  */
+/**
+ * @brief Auto-declaring Property constructor.
+ * @param owner Owning component.
+ * @param name Name of the Property.
+ * @param key  Default StoreGate key for the object.
+ * @param doc Documentation string.
+ *
+ * Will associate the named Property with this RHK via declareProperty.
+ *
+ * The provided key may actually start with the name of the store,
+ * separated by a "+":  "MyStore+Obj".  If no "+" is present
+ * the store named by @c storeName is used.
+ */
 template <class T>
 template <class OWNER, class K>
 inline
diff --git a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/WriteDecorHandle.h b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/WriteDecorHandle.h
index 7e113d0899f..e93296a892c 100644
--- a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/WriteDecorHandle.h
+++ b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/WriteDecorHandle.h
@@ -68,19 +68,20 @@ public:
   explicit WriteDecorHandle (const WriteDecorHandleKey<T>& key);
 
 
-//   /**
-//    * @brief Constructor from a ReadDecorHandleKey and an explicit event context.
-//    * @param key The key object holding the clid/key.
-//    * @param ctx The event context.
-//    *
-//    * This will raise an exception if the StoreGate key is blank,
-//    * or if the event store cannot be found.
-//    *
-//    * If the default event store has been requested, then the thread-specific
-//    * store from the event context will be used.
-//    */
-//   explicit WriteDecorHandle (const WriteDecorHandleKey<T>& key,
-//                              const EventContext& ctx);
+  /**
+   * @brief Constructor from a ReadDecorHandleKey and an explicit event context.
+   * @param key The key object holding the clid/key.
+   * @param ctx The event context.
+   *
+   * This will raise an exception if the StoreGate key is blank,
+   * or if the event store cannot be found.
+   *
+   * If the default event store has been requested, then the thread-specific
+   * store from the event context will be used.
+   */
+  explicit WriteDecorHandle (const WriteDecorHandleKey<T>& key,
+                             const EventContext& ctx);
+
 
 //   /**
 //    * @brief Copy constructor.
@@ -172,7 +173,19 @@ public:
 //    */
 //   SG::auxid_t auxid() const;
 
-  
+
+  // /**
+  //  * @brief Return the mode (read/write/update) for this handle.
+  //  */
+  // Gaudi::DataHandle::Mode mode() const;
+
+
+  /**
+   * @brief Return the name of the decoration alias (CONT.DECOR).
+   */
+  std::string decorKey() const;
+
+
 // private:
 //   /**
 //    * @brief Retrieve an object from StoreGate.
@@ -228,9 +241,8 @@ public:
 //   const SG::AuxVectorData* vectorData();
 
 
-//   /// Handle for reading the referenced object using its original name
-//   /// (not the alias).
-//   SG::ReadHandle<T> m_contHandle;
+  /// Name of the decoration alias: CONT.DECOR.
+  std::string m_decorKey;
 
 
   /// Accessor for the aux data item.
diff --git a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/WriteDecorHandle.icc b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/WriteDecorHandle.icc
index 485db240290..76b4eb52854 100644
--- a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/WriteDecorHandle.icc
+++ b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/WriteDecorHandle.icc
@@ -24,34 +24,34 @@ namespace SG {
  */
 template <class T, class D>
 WriteDecorHandle<T, D>::WriteDecorHandle (const WriteDecorHandleKey<T>& key)
-  : Base (key, nullptr),
-    // m_contHandle (key.contHandleKey()),
+  : Base (key.contHandleKey(), nullptr),
+    m_decorKey (key.key()),
     m_acc (SG::decorKeyFromKey (key.key()))
     // m_madeAlias (false)
 {
 }
 
 
-// /**
-//  * @brief Constructor from a ReadDecorHandleKey and an explicit event context.
-//  * @param key The key object holding the clid/key.
-//  * @param ctx The event context.
-//  *
-//  * This will raise an exception if the StoreGate key is blank,
-//  * or if the event store cannot be found.
-//  *
-//  * If the default event store has been requested, then the thread-specific
-//  * store from the event context will be used.
-//  */
-// template <class T, class D>
-// WriteDecorHandle<T, D>::WriteDecorHandle (const WriteDecorHandleKey<T>& key,
-//                                           const EventContext& ctx)
-//   : Base (key, &ctx),
-//     m_contHandle (key.contHandleKey(), ctx),
-//     m_acc (SG::decorKeyFromKey (key.key())),
-//     m_madeAlias (false)
-// {
-// }
+/**
+ * @brief Constructor from a ReadDecorHandleKey and an explicit event context.
+ * @param key The key object holding the clid/key.
+ * @param ctx The event context.
+ *
+ * This will raise an exception if the StoreGate key is blank,
+ * or if the event store cannot be found.
+ *
+ * If the default event store has been requested, then the thread-specific
+ * store from the event context will be used.
+ */
+template <class T, class D>
+WriteDecorHandle<T, D>::WriteDecorHandle (const WriteDecorHandleKey<T>& key,
+                                          const EventContext& ctx)
+  : Base (key.contHandleKey(), &ctx),
+    m_decorKey (key.key()),
+    m_acc (SG::decorKeyFromKey (key.key()))
+    // m_madeAlias (false)
+{
+}
 
 
 // /**
@@ -60,7 +60,7 @@ WriteDecorHandle<T, D>::WriteDecorHandle (const WriteDecorHandleKey<T>& key)
 // template <class T, class D>
 // WriteDecorHandle<T, D>::WriteDecorHandle (const WriteDecorHandle& rhs)
 //   : Base (rhs),
-//     m_contHandle (rhs.m_contHandle),
+//     m_decorKey (rhs.m_decorKey),
 //     m_acc (rhs.m_acc),
 //     m_madeAlias (rhs.m_madeAlias)
 // {
@@ -73,7 +73,7 @@ WriteDecorHandle<T, D>::WriteDecorHandle (const WriteDecorHandleKey<T>& key)
 // template <class T, class D>
 // WriteDecorHandle<T, D>::WriteDecorHandle (WriteDecorHandle&& rhs)
 //   : Base (std::move (rhs)),
-//     m_contHandle (std::move (rhs.m_contHandle)),
+//     m_decorKey (std::move (rhs.m_decorKey)),
 //     m_acc (std::move (rhs.m_acc)),
 //     m_madeAlias (rhs.m_madeAlias)
 // {
@@ -107,7 +107,7 @@ WriteDecorHandle<T, D>::WriteDecorHandle (const WriteDecorHandleKey<T>& key)
 //   if (this != &rhs) {
 //     *static_cast<Base*>(this) = rhs;
 //     m_acc = rhs.m_acc;
-//     m_contHandle = rhs.m_contHandle;
+//     m_decorKey = rhs.m_decorKey;
 //     m_madeAlias = rhs.m_madeAlias;
 //   }
 //   return *this;
@@ -123,7 +123,7 @@ WriteDecorHandle<T, D>::WriteDecorHandle (const WriteDecorHandleKey<T>& key)
 //   if (this != &rhs) {
 //     *static_cast<Base*>(this) = std::move (rhs);
 //     m_acc = std::move (rhs.m_acc);
-//     m_contHandle = std::move (rhs.m_contHandle);
+//     m_decorKey = std::move (rhs.m_decorKey);
 //     m_madeAlias = rhs.m_madeAlias;
 //     rhs.m_madeAlias = false;
 //   }
@@ -142,7 +142,7 @@ WriteDecorHandle<T, D>::WriteDecorHandle (const WriteDecorHandleKey<T>& key)
 // template <class T, class D>
 // bool WriteDecorHandle<T, D>::isPresent() const
 // {
-//   return m_contHandle.isPresent();
+//   return Base::isPresent();
 // }
 
 
@@ -159,8 +159,6 @@ WriteDecorHandle<T, D>::WriteDecorHandle (const WriteDecorHandleKey<T>& key)
 // StatusCode WriteDecorHandle<T, D>::setProxyDict (IProxyDict* store)
 // {
 //   m_madeAlias = false;
-//   if (m_contHandle.setProxyDict (store).isFailure())
-//     return StatusCode::FAILURE;
 //   return Base::setProxyDict (store);
 // }
 
@@ -217,8 +215,9 @@ WriteDecorHandle<T, D>::operator() (const AuxElement& e)
 // inline
 // bool WriteDecorHandle<T, D>::isAvailable (std::true_type)
 // {
-//   if (this->m_ptr) {
-//     const SG::AuxVectorData* obj = static_cast<const T*>(this->m_ptr)->container();
+//   const T* ptr = this->ptr();
+//   if (ptr) {
+//     const SG::AuxVectorData* obj = ptr->container();
 //     if (obj) {
 //       return obj->isAvailable (m_acc.auxid());
 //     }
@@ -238,8 +237,9 @@ WriteDecorHandle<T, D>::operator() (const AuxElement& e)
 // inline
 // bool WriteDecorHandle<T, D>::isAvailable (std::false_type)
 // {
-//   if (this->m_ptr) {
-//     return static_cast<const T*>(this->m_ptr)->isAvailable (m_acc.auxid());
+//   const T* ptr = this->ptr();
+//   if (ptr) {
+//     return ptr->isAvailable (m_acc.auxid());
 //   }
 
 //   return false;
@@ -273,6 +273,28 @@ WriteDecorHandle<T, D>::operator() (const AuxElement& e)
 // }
 
 
+// /**
+//  * @brief Return the mode (read/write/update) for this handle.
+//  */
+// template <class T, class D>
+// inline
+// Gaudi::DataHandle::Mode WriteDecorHandle<T, D>::mode() const
+// {
+//   return Gaudi::DataHandle::Writer;
+// }
+
+
+/**
+ * @brief Return the name of the decoration alias (CONT.DECOR).
+ */
+template <class T, class D>
+inline
+std::string WriteDecorHandle<T, D>::decorKey() const
+{
+  return m_decorKey;
+}
+
+
 // /**
 //  * @brief Retrieve an object from StoreGate.
 //  * @param quiet If true, suppress failure messages.
@@ -285,11 +307,14 @@ WriteDecorHandle<T, D>::operator() (const AuxElement& e)
 // {
 //   if (this->m_ptr && this->m_madeAlias)
 //     return this->m_ptr;
-//   if (m_contHandle.alias (WriteHandleKey<T> (this->key())).isFailure())
-//     return nullptr;
 //   if (!this->m_ptr) {
 //     ReadHandle<T>::typeless_dataPointer_impl (quiet);
 //   }
+//   if (!this->m_ptr) {
+//     return nullptr;
+//   }
+//   if (this->alias (WriteHandleKey<T> (this->m_decorKey)).isFailure())
+//     return nullptr;
 //   // Important to call the base class method above before calling vectorData;
 //   // otherwise, we'll get an infinite recursion.
 //   // Also don't call getDecorationArray if the container is empty.
diff --git a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/WriteDecorHandleKey.h b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/WriteDecorHandleKey.h
index 2f3bf2a7e96..ec654aea611 100644
--- a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/WriteDecorHandleKey.h
+++ b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/WriteDecorHandleKey.h
@@ -21,8 +21,8 @@
 
 
 #include "AsgDataHandles/DecorKeyHelpers.h"
+#include "AsgDataHandles/ReadHandleKey.h"
 #include "AsgDataHandles/WriteHandleKey.h"
-// #include "StoreGate/ReadHandleKey.h"
 
 
 // class AthAlgorithm;
@@ -81,10 +81,10 @@ public:
    * the store named by @c storeName is used.
    */
   template <class OWNER, class K>
-  WriteDecorHandleKey( OWNER* owner,
-                      const std::string& name,
-                      const K& key = {},
-                      const std::string& doc = "");
+  WriteDecorHandleKey (OWNER* owner,
+                       const std::string& name,
+                       const K& key = {},
+                       const std::string& doc = "");
 
 
   /**
@@ -98,34 +98,34 @@ public:
   WriteDecorHandleKey& operator= (const std::string& sgkey);
 
 
-//   /**
-//    * @brief Change the key of the object to which we're referring.
-//    * @param sgkey The StoreGate key for the object.
-//    * 
-//    * The provided key may actually start with the name of the store,
-//    * separated by a "+":  "MyStore+Obj".  If no "+" is present
-//    * the store is not changed.  A key name that starts with a slash
-//    * is interpreted as a hierarchical key name, not an empty store name.
-//    *
-//    * Returns failure the key string format is bad.
-//    */
-//   virtual StatusCode assign (const std::string& sgkey) override;
+  /**
+   * @brief Change the key of the object to which we're referring.
+   * @param sgkey The StoreGate key for the object.
+   * 
+   * The provided key may actually start with the name of the store,
+   * separated by a "+":  "MyStore+Obj".  If no "+" is present
+   * the store is not changed.  A key name that starts with a slash
+   * is interpreted as a hierarchical key name, not an empty store name.
+   *
+   * Returns failure the key string format is bad.
+   */
+  virtual StatusCode assign (const std::string& sgkey) override;
 
   
-//   /**
-//    * @brief If this object is used as a property, then this should be called
-//    *        during the initialize phase.  It will fail if the requested
-//    *        StoreGate service cannot be found or if the key is blank.
-//    * @param used If false, then this handle is not to be used.
-//    *             Instead of normal initialization, the key will be cleared.
-//    */
-//   StatusCode initialize (bool used = true);
+  /**
+   * @brief If this object is used as a property, then this should be called
+   *        during the initialize phase.  It will fail if the requested
+   *        StoreGate service cannot be found or if the key is blank.
+   * @param used If false, then this handle is not to be used.
+   *             Instead of normal initialization, the key will be cleared.
+   */
+  StatusCode initialize (bool used = true);
 
 
-//   /**
-//    * @brief Return the handle key for the container.
-//    */
-//   const ReadHandleKey<T>& contHandleKey() const;
+  /**
+   * @brief Return the handle key for the container.
+   */
+  const ReadHandleKey<T>& contHandleKey() const;
 
 
 // private:
@@ -141,8 +141,8 @@ public:
 //   ReadHandleKey<T>& contHandleKey_nc();
 
 
-//   /// The container handle.
-//   ReadHandleKey<T> m_contHandleKey;
+  /// The container handle.
+  ReadHandleKey<T> m_contHandleKey;
 };
 
 
diff --git a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/WriteDecorHandleKey.icc b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/WriteDecorHandleKey.icc
index 3195daa225c..20a8004d243 100644
--- a/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/WriteDecorHandleKey.icc
+++ b/Control/AthToolSupport/AsgDataHandles/AsgDataHandles/WriteDecorHandleKey.icc
@@ -11,7 +11,7 @@
  */
 
 
-// #include "StoreGate/tools/DecorKeyHelpers.h"
+#include "AsgDataHandles/DecorKeyHelpers.h"
 // #include "GaudiKernel/IDataHandleHolder.h"
 
 
@@ -43,8 +43,8 @@ namespace SG {
 template <class T>
 WriteDecorHandleKey<T>::WriteDecorHandleKey (const std::string& key /*= ""*/) :
                                              // const std::string& storeName /*= "StoreGateSvc"*/) :
-  Base (key/*, storeName*/)
-  // m_contHandleKey (contKeyFromKey (key)/*, storeName*/)
+  Base (key/*, storeName*/),
+  m_contHandleKey (contKeyFromKey (key)/*, storeName*/)
 {
 }
 
@@ -69,9 +69,10 @@ WriteDecorHandleKey<T>::WriteDecorHandleKey( OWNER* owner,
                                              const std::string& name,
                                              const K& key /*={}*/,
                                              const std::string& doc /*=""*/)
-  : Base (owner, name, key, doc)
-    // m_contHandleKey (contKeyFromKey (key), StoreID::storeName(StoreID::EVENT_STORE) )
+  : Base (key),
+    m_contHandleKey (contKeyFromKey (key)/*, StoreID::storeName(StoreID::EVENT_STORE) */)
 {
+  owner->declareProperty(name, *this, doc);
 }
 
 
@@ -87,58 +88,58 @@ template <class T>
 WriteDecorHandleKey<T>&
 WriteDecorHandleKey<T>::operator= (const std::string& sgkey)
 {
-  // m_contHandleKey = contKeyFromKey (sgkey);
+  m_contHandleKey = contKeyFromKey (sgkey);
   Base::operator= (sgkey);
   return *this;
 }
 
 
-// /**
-//  * @brief Change the key of the object to which we're referring.
-//  * @param sgkey The StoreGate key for the object.
-//  * 
-//  * The provided key may actually start with the name of the store,
-//  * separated by a "+":  "MyStore+Obj".  If no "+" is present
-//  * the store is not changed.  A key name that starts with a "+"
-//  * is interpreted as a hierarchical key name, not an empty store name.
-//  *
-//  * Returns failure the key string format is bad.
-//  */
-// template <class T>
-// StatusCode WriteDecorHandleKey<T>::assign (const std::string& sgkey)
-// {
-//   if (m_contHandleKey.assign (contKeyFromKey (sgkey)).isFailure())
-//     return StatusCode::FAILURE;
-//   return Base::assign (sgkey);
-// }
+/**
+ * @brief Change the key of the object to which we're referring.
+ * @param sgkey The StoreGate key for the object.
+ * 
+ * The provided key may actually start with the name of the store,
+ * separated by a "+":  "MyStore+Obj".  If no "+" is present
+ * the store is not changed.  A key name that starts with a "+"
+ * is interpreted as a hierarchical key name, not an empty store name.
+ *
+ * Returns failure the key string format is bad.
+ */
+template <class T>
+StatusCode WriteDecorHandleKey<T>::assign (const std::string& sgkey)
+{
+  if (m_contHandleKey.assign (contKeyFromKey (sgkey)).isFailure())
+    return StatusCode::FAILURE;
+  return Base::assign (sgkey);
+}
 
   
-// /**
-//  * @brief If this object is used as a property, then this should be called
-//  *        during the initialize phase.  It will fail if the requested
-//  *        StoreGate service cannot be found or if the key is blank.
-//  *
-//  * @param used If false, then this handle is not to be used.
-//  *             Instead of normal initialization, the key will be cleared.
-//  */
-// template <class T>
-// StatusCode WriteDecorHandleKey<T>::initialize (bool used /*= true*/)
-// {
-//   detail::registerWriteDecorHandleKey (this->owner(), m_contHandleKey.fullKey());
-//   if (m_contHandleKey.initialize (used).isFailure())
-//     return StatusCode::FAILURE;
-//   return Base::initialize (used);
-// }
+/**
+ * @brief If this object is used as a property, then this should be called
+ *        during the initialize phase.  It will fail if the requested
+ *        StoreGate service cannot be found or if the key is blank.
+ *
+ * @param used If false, then this handle is not to be used.
+ *             Instead of normal initialization, the key will be cleared.
+ */
+template <class T>
+StatusCode WriteDecorHandleKey<T>::initialize (bool used /*= true*/)
+{
+  // detail::registerWriteDecorHandleKey (this->owner(), m_contHandleKey.fullKey());
+  if (m_contHandleKey.initialize (used).isFailure())
+    return StatusCode::FAILURE;
+  return Base::initialize (used);
+}
 
 
-// /**
-//  * @brief Return the handle key for the container.
-//  */
-// template <class T>
-// const ReadHandleKey<T>& WriteDecorHandleKey<T>::contHandleKey() const
-// {
-//   return m_contHandleKey;
-// }
+/**
+ * @brief Return the handle key for the container.
+ */
+template <class T>
+const ReadHandleKey<T>& WriteDecorHandleKey<T>::contHandleKey() const
+{
+  return m_contHandleKey;
+}
 
 
 // /**
diff --git a/Control/AthToolSupport/AsgDataHandles/CMakeLists.txt b/Control/AthToolSupport/AsgDataHandles/CMakeLists.txt
index 704ebcb25f5..893eb01e1fc 100644
--- a/Control/AthToolSupport/AsgDataHandles/CMakeLists.txt
+++ b/Control/AthToolSupport/AsgDataHandles/CMakeLists.txt
@@ -19,6 +19,6 @@ atlas_add_library( AsgDataHandlesLib
    AsgDataHandles/*.h AsgDataHandles/*.icc Root/*.cxx
    PUBLIC_HEADERS AsgDataHandles
    PRIVATE_INCLUDE_DIRS
-   LINK_LIBRARIES AsgMessagingLib xAODRootAccessInterfaces )
+   LINK_LIBRARIES AthContainers AsgMessagingLib xAODRootAccessInterfaces )
 
 endif()
diff --git a/Control/AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx b/Control/AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx
index 9ad4a6667f0..a32781e4c17 100644
--- a/Control/AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx
+++ b/Control/AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx
@@ -67,7 +67,9 @@ VarHandleKey::VarHandleKey (const std::string& sgkey)
  */
 VarHandleKey& VarHandleKey::operator= (const std::string& sgkey)
 {
-  m_sgKey = sgkey;
+  if (assign (sgkey).isFailure ()) {
+    throw std::runtime_error (std::string("Could not assign VarHandleKey with key ") + sgkey);
+  }
   return *this;
 }
 
diff --git a/Control/AthToolSupport/AsgExampleTools/AsgExampleTools/DataHandleTestTool.h b/Control/AthToolSupport/AsgExampleTools/AsgExampleTools/DataHandleTestTool.h
index e851fa666e9..91f001438ec 100644
--- a/Control/AthToolSupport/AsgExampleTools/AsgExampleTools/DataHandleTestTool.h
+++ b/Control/AthToolSupport/AsgExampleTools/AsgExampleTools/DataHandleTestTool.h
@@ -53,7 +53,9 @@ namespace asg
   public:
 #ifndef SIMULATIONBASE
     SG::ReadHandleKey<xAOD::MuonContainer> m_readKey {this, "readKey", "Muons", "regular read key"};
+    SG::ReadHandleKey<xAOD::MuonContainer> m_readKeyEmpty {this, "readKeyEmpty", "", "regular read key (empty by default)"};
     SG::ReadDecorHandleKey<xAOD::MuonContainer> m_readDecorKey {this, "readDecorKey", "Muons.pt", "read decor key"};
+    SG::ReadDecorHandleKey<xAOD::MuonContainer> m_readDecorKeyEmpty {this, "readDecorKeyEmpty", "", "read decor key (empty by default)"};
     SG::ReadHandleKeyArray<xAOD::MuonContainer> m_readKeyArray {this, "readKeyArray", {}, "array read key"};
     SG::WriteHandleKey<xAOD::MuonContainer> m_writeKey {this, "writeKey", "", "regular write key"};
     SG::WriteDecorHandleKey<xAOD::MuonContainer> m_writeDecorKey {this, "writeDecorKey", "", "write decor key"};
diff --git a/Control/AthToolSupport/AsgExampleTools/CMakeLists.txt b/Control/AthToolSupport/AsgExampleTools/CMakeLists.txt
index 96e3f8515f2..d1b02221d1c 100644
--- a/Control/AthToolSupport/AsgExampleTools/CMakeLists.txt
+++ b/Control/AthToolSupport/AsgExampleTools/CMakeLists.txt
@@ -98,6 +98,14 @@ if (NOT SIMULATIONBASE)
      set (extra_libs )
    endif()
 
+   if( XAOD_STANDALONE )
+      atlas_add_test( gt_DataHandlesUnitTest
+         SOURCES test/gt_DataHandlesUnitTest.cxx
+         INCLUDE_DIRS ${GTEST_INCLUDE_DIRS}
+         LINK_LIBRARIES ${GTEST_LIBRARIES} AsgDataHandlesLib AsgTestingLib xAODRootAccess)
+      set_tests_properties (AsgExampleTools_gt_DataHandlesUnitTest_ctest PROPERTIES LABELS "AsgDataHandles;AsgExampleTools" )
+   endif()
+
    atlas_add_test( gt_DataHandlesTest
       SOURCES test/gt_DataHandlesTest.cxx
       INCLUDE_DIRS ${GTEST_INCLUDE_DIRS}
diff --git a/Control/AthToolSupport/AsgExampleTools/Root/DataHandleTestTool.cxx b/Control/AthToolSupport/AsgExampleTools/Root/DataHandleTestTool.cxx
index 4248f17db32..d7b17616e43 100644
--- a/Control/AthToolSupport/AsgExampleTools/Root/DataHandleTestTool.cxx
+++ b/Control/AthToolSupport/AsgExampleTools/Root/DataHandleTestTool.cxx
@@ -55,12 +55,12 @@ namespace asg
   {
 #ifndef SIMULATIONBASE
     ANA_CHECK (m_readKey.initialize ());
+    ANA_CHECK (m_readKeyEmpty.initialize (!m_readKeyEmpty.empty ()));
     ANA_CHECK (m_readDecorKey.initialize ());
-    if (!m_writeKey.empty())
-      ANA_CHECK (m_writeKey.initialize ());
+    ANA_CHECK (m_readDecorKeyEmpty.initialize (!m_readDecorKeyEmpty.empty ()));
+    ANA_CHECK (m_writeKey.initialize (!m_writeKey.empty()));
     ANA_CHECK (m_readKeyArray.initialize());
-    if (!m_writeDecorKey.empty())
-      ANA_CHECK (m_writeDecorKey.initialize ());
+    ANA_CHECK (m_writeDecorKey.initialize (!m_writeDecorKey.empty ()));
 #endif
     return StatusCode::SUCCESS;
   }
diff --git a/Control/AthToolSupport/AsgExampleTools/test/gt_DataHandlesTest.cxx b/Control/AthToolSupport/AsgExampleTools/test/gt_DataHandlesTest.cxx
index b95079f43ba..e2a09e7af42 100644
--- a/Control/AthToolSupport/AsgExampleTools/test/gt_DataHandlesTest.cxx
+++ b/Control/AthToolSupport/AsgExampleTools/test/gt_DataHandlesTest.cxx
@@ -14,6 +14,7 @@
 #include <AsgMessaging/MessageCheck.h>
 #include <AsgTesting/UnitTest.h>
 #include <AsgExampleTools/IDataHandleTestTool.h>
+#include <TClass.h>
 #include <TFile.h>
 #include <cmath>
 #include <gtest/gtest.h>
@@ -40,6 +41,10 @@ namespace asg
   {
     static void SetUpTestCase ()
     {
+      // Access the dictionary
+      ASSERT_NE (TClass::GetClass ("xAOD::MuonContainer"), nullptr);
+      ASSERT_NE (TClass::GetClass ("asg::DataHandleTestTool"), nullptr);
+
       const char *test_file = getenv ("ASG_TEST_FILE_MC");
       ASSERT_NE (nullptr, test_file);
       file.reset (TFile::Open (test_file, "READ"));
@@ -149,6 +154,17 @@ namespace asg
     ASSERT_SUCCESS (config.makeTool (tool, cleanup));
     tool->runTest ();
   }
+
+
+
+  // empty initial handles
+  TEST_F (DataHandlesTest, empty_initial_handles)
+  {
+    config.setPropertyFromString ("readKeyEmpty", "Muons");
+    config.setPropertyFromString ("readDecorKeyEmpty", "Muons.eta");
+    ASSERT_SUCCESS (config.makeTool (tool, cleanup));
+    tool->runTest ();
+  }
 }
 
 ATLAS_GOOGLE_TEST_MAIN
diff --git a/Control/AthToolSupport/AsgExampleTools/test/gt_DataHandlesUnitTest.cxx b/Control/AthToolSupport/AsgExampleTools/test/gt_DataHandlesUnitTest.cxx
new file mode 100644
index 00000000000..8951cc9e64f
--- /dev/null
+++ b/Control/AthToolSupport/AsgExampleTools/test/gt_DataHandlesUnitTest.cxx
@@ -0,0 +1,161 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <AsgDataHandles/ReadDecorHandle.h>
+#include <AsgDataHandles/ReadDecorHandleKey.h>
+#include <AsgDataHandles/ReadHandle.h>
+#include <AsgDataHandles/ReadHandleKey.h>
+#include <AsgDataHandles/WriteDecorHandle.h>
+#include <AsgDataHandles/WriteDecorHandleKey.h>
+#include <AsgDataHandles/WriteHandle.h>
+#include <AsgDataHandles/WriteHandleKey.h>
+#include <AsgTesting/UnitTest.h>
+#include <AsgTools/CurrentContext.h>
+#include <xAODCore/CLASS_DEF.h>
+#include <xAODRootAccess/TEvent.h>
+#include <gtest/gtest.h>
+
+
+class MyObj
+{
+public:
+  MyObj(int x=0) : x(x) {}
+  int x;
+};
+CLASS_DEF (MyObj, 293847295, 1)
+
+
+namespace asg
+{
+  struct DataHandlesUnitTest : public ::testing::Test
+  {
+    virtual void SetUp () override
+    {
+    }
+
+    xAOD::TEvent event;
+  };
+
+  // ReadHandle
+  TEST_F (DataHandlesUnitTest, ReadHandle)
+  {
+    SG::ReadHandleKey<MyObj> k1 ("aaa");
+    // ASSERT_EQ (k1.clid(), 293847295);
+    ASSERT_EQ (k1.key(), "aaa");
+    ASSERT_SUCCESS (k1.initialize());
+
+    k1 = "aab";
+    // ASSERT_EQ (k1.clid(), 293847295);
+    ASSERT_EQ (k1.key(), "aab");
+
+    SG::ReadHandleKey<MyObj> k2 ("asd");
+    ASSERT_SUCCESS (k2.initialize());
+    SG::ReadHandle<MyObj> h2 (k2);
+    // ASSERT_EQ (h2.clid(), 293847295);
+    ASSERT_EQ (h2.key(), "asd");
+
+    const EventContext &ctx3 = Gaudi::Hive::currentContext();
+    SG::ReadHandle<MyObj> h3 (k2, ctx3);
+    // ASSERT_EQ (h3.clid(), 293847295);
+    ASSERT_EQ (h3.key(), "asd");
+  }
+
+  // WriteHandle
+  TEST_F (DataHandlesUnitTest, WriteHandle)
+  {
+    SG::WriteHandleKey<MyObj> k1 ("aaa");
+    // ASSERT_EQ (k1.clid(), 293847295);
+    ASSERT_EQ (k1.key(), "aaa");
+    ASSERT_SUCCESS (k1.initialize());
+
+    k1 = "aab";
+    // ASSERT_EQ (k1.clid(), 293847295);
+    ASSERT_EQ (k1.key(), "aab");
+
+    SG::WriteHandleKey<MyObj> k2 ("asd");
+    ASSERT_SUCCESS (k2.initialize());
+    SG::WriteHandle<MyObj> h2 (k2);
+    // ASSERT_EQ (h2.clid(), 293847295);
+    ASSERT_EQ (h2.key(), "asd");
+
+    const EventContext &ctx3 = Gaudi::Hive::currentContext();
+    SG::WriteHandle<MyObj> h3 (k2, ctx3);
+    // ASSERT_EQ (h3.clid(), 293847295);
+    ASSERT_EQ (h3.key(), "asd");
+  }
+
+
+  // ReadDecorHandle
+  TEST_F (DataHandlesUnitTest, ReadDecorHandle)
+  {
+    SG::ReadDecorHandleKey<MyObj> k1 ("aaa.dec");
+    // ASSERT_EQ (k1.clid(), 293847295);
+    ASSERT_EQ (k1.key(), "aaa.dec");
+    ASSERT_SUCCESS (k1.initialize());
+
+    // ASSERT_EQ (k1.contHandleKey().clid(), 293847295);
+    ASSERT_EQ (k1.contHandleKey().key(), "aaa");
+
+    k1 = "bbb.foo";
+    ASSERT_EQ (k1.key(), "bbb.foo");
+    ASSERT_EQ (k1.contHandleKey().key(), "bbb");
+
+    ASSERT_SUCCESS (k1.assign ("ccc.fee"));
+    ASSERT_EQ (k1.key(), "ccc.fee");
+    ASSERT_EQ (k1.contHandleKey().key(), "ccc");
+
+    SG::ReadDecorHandleKey<MyObj> k2 ("asd.aaa");
+    ASSERT_SUCCESS (k2.initialize());
+
+    SG::ReadDecorHandle<MyObj, int> h1 (k2);
+    // ASSERT_EQ (h1.clid(), 293847295);
+    ASSERT_EQ (h1.key(), "asd");
+    ASSERT_EQ (h1.decorKey(), "asd.aaa");
+    ASSERT_FALSE (h1.isPresent());
+
+    const EventContext &ctx2 = Gaudi::Hive::currentContext();
+    SG::ReadDecorHandle<MyObj, int> h2 (k2, ctx2);
+    // ASSERT_EQ (h2.clid(), 293847295);
+    ASSERT_EQ (h2.key(), "asd");
+    ASSERT_EQ (h2.decorKey(), "asd.aaa");
+  }
+
+  // WriteDecorHandle
+  TEST_F (DataHandlesUnitTest, WriteDecorHandle)
+  {
+    SG::WriteDecorHandleKey<MyObj> k1 ("aaa.dec");
+    // ASSERT_EQ (k1.clid(), 293847295);
+    ASSERT_EQ (k1.key(), "aaa.dec");
+    ASSERT_SUCCESS (k1.initialize());
+
+    // ASSERT_EQ (k1.contHandleKey().clid(), 293847295);
+    ASSERT_EQ (k1.contHandleKey().key(), "aaa");
+
+    k1 = "bbb.foo";
+    ASSERT_EQ (k1.key(), "bbb.foo");
+    ASSERT_EQ (k1.contHandleKey().key(), "bbb");
+
+    ASSERT_SUCCESS (k1.assign ("ccc.fee"));
+    ASSERT_EQ (k1.key(), "ccc.fee");
+    ASSERT_EQ (k1.contHandleKey().key(), "ccc");
+
+    SG::WriteDecorHandleKey<MyObj> k2 ("asd.aaa");
+    ASSERT_SUCCESS (k2.initialize());
+
+    SG::WriteDecorHandle<MyObj, int> h1 (k2);
+    // ASSERT_EQ (h1.clid(), 293847295);
+    ASSERT_EQ (h1.key(), "asd");
+    ASSERT_EQ (h1.decorKey(), "asd.aaa");
+    ASSERT_FALSE (h1.isPresent());
+
+    const EventContext &ctx2 = Gaudi::Hive::currentContext();
+    SG::WriteDecorHandle<MyObj, int> h2 (k2, ctx2);
+    // ASSERT_EQ (h2.clid(), 293847295);
+    ASSERT_EQ (h2.key(), "asd");
+    ASSERT_EQ (h2.decorKey(), "asd.aaa");
+  }
+
+}
+
+ATLAS_GOOGLE_TEST_MAIN
-- 
GitLab