From 4f6d7b7d904f55ab26e0ce2cba35d31a8beee6cd Mon Sep 17 00:00:00 2001
From: Frank Berghaus <frank.berghaus@cern.ch>
Date: Mon, 7 Dec 2020 17:29:43 +0100
Subject: [PATCH] Add unit tests for the ByteStreamMetadataTool

Test the functionality of the ByteStreamMetadataTool. The tool should do
nothing wihtout complaint for empty input. The tool should transcribes a
ByteStreamMetadata object from input into a container in output. The
tool should transcribe a ByteStreamMetadataContainer from input to
output. Should there already be content in the output, matching content
should be ignored and new content should be appended.
---
 Event/ByteStreamCnvSvc/CMakeLists.txt         |  11 +
 .../test/ByteStreamMetadataTool_test.cxx      | 228 ++++++++++++++++++
 .../ByteStreamData/ByteStreamMetadata.h       |  23 ++
 3 files changed, 262 insertions(+)
 create mode 100644 Event/ByteStreamCnvSvc/test/ByteStreamMetadataTool_test.cxx

diff --git a/Event/ByteStreamCnvSvc/CMakeLists.txt b/Event/ByteStreamCnvSvc/CMakeLists.txt
index 7a5351199fc..57168223b5f 100644
--- a/Event/ByteStreamCnvSvc/CMakeLists.txt
+++ b/Event/ByteStreamCnvSvc/CMakeLists.txt
@@ -78,6 +78,17 @@ atlas_add_test( ByteStreamConfigTest
    SCRIPT "python -m ByteStreamCnvSvc.ByteStreamConfig"
    POST_EXEC_SCRIPT nopost.sh )
 
+atlas_add_test( ByteStreamMetadataToolTest
+  SOURCES test/ByteStreamMetadataTool_test.cxx
+  LINK_LIBRARIES
+    AthenaKernel
+    AthenaBaseComps
+    ByteStreamData
+    GaudiKernel
+    GoogleTestTools
+    TestTools )
+
+
 # Install files from the package:
 atlas_install_python_modules( python/*.py POST_BUILD_CMD ${ATLAS_FLAKE8} )
 atlas_install_joboptions( share/*.py )
diff --git a/Event/ByteStreamCnvSvc/test/ByteStreamMetadataTool_test.cxx b/Event/ByteStreamCnvSvc/test/ByteStreamMetadataTool_test.cxx
new file mode 100644
index 00000000000..ae3c031be7a
--- /dev/null
+++ b/Event/ByteStreamCnvSvc/test/ByteStreamMetadataTool_test.cxx
@@ -0,0 +1,228 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+ */
+/** Tests for ByteStreamMetadata management.
+ *
+ * The various operations that should be performed by the
+ * ByteStreamMetadataTool when transferring objects from the input to the
+ * metadata store for use by clients.
+ *
+ * @author Frank Berghaus <fberghaus@anl.gov>
+ * @date Dec 4, 2020
+ */
+#include <ostream>
+#include <memory>
+#include <set>
+
+#include "GoogleTestTools/InitGaudiGoogleTest.h"
+#include "TestTools/initGaudi.h"
+
+#include "GaudiKernel/ISvcLocator.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "GaudiKernel/ToolHandle.h"
+
+#include "AthenaKernel/IMetaDataTool.h"
+#include "StoreGate/StoreGateSvc.h"
+#include "StoreGate/setupStoreGate.h"
+#include "../src/ByteStreamMetadataTool.h"
+#include "ByteStreamData/ByteStreamMetadata.h"
+#include "ByteStreamData/ByteStreamMetadataContainer.h"
+
+
+namespace Athena_test {
+
+  class ByteStreamMetadataToolTest : public InitGaudiGoogleTest {
+   public:
+    ByteStreamMetadataToolTest() : InitGaudiGoogleTest( MSG::INFO ) {}
+
+    void SetUp() override {
+      assert(m_inputStore.retrieve().isSuccess());
+      assert(m_metaStore.retrieve().isSuccess());
+
+      assert(m_tool.retrieve().isSuccess());
+      assert(m_tool->initialize().isSuccess());
+    }
+
+    ToolHandle< IMetaDataTool > m_tool{"ByteStreamMetadataTool"};
+    ServiceHandle< StoreGateSvc > m_inputStore{
+      "StoreGateSvc/InputMetaDataStore", "ByteStreamMetadataToolTest"};
+    ServiceHandle< StoreGateSvc > m_metaStore{
+      "StoreGateSvc/MetaDataStore", "ByteStreamMetadataToolTest"};
+
+    const ByteStreamMetadata testObject{
+      1u,
+      50u,
+      50u,
+      1u,
+      1u,
+      1ul<<31,
+      1ul<<33,
+      1u,
+      6500u,
+      "testObject", // GUID
+      "stream",
+      "project",
+      1u,
+      std::vector<std::string>()};
+
+    const ByteStreamMetadata diffObject{
+      2u,
+      20u,
+      20u,
+      1u,
+      1u,
+      1ul<<30,
+      1ul<<32,
+      1u,
+      6500u,
+      "diffObject", // GUID
+      "stream2",
+      "project",
+      2u,
+      std::vector<std::string>()};
+  };
+
+  /**
+   * An empty input store should not offend the tool and do nothing
+   */
+  TEST_F(ByteStreamMetadataToolTest, emptyInput) {
+    EXPECT_TRUE(m_tool->beginInputFile().isSuccess());
+    EXPECT_TRUE(
+        !m_metaStore->contains< ByteStreamMetadataContainer >(
+            "ByteStreamMetadata"));
+  }
+
+  /**
+   * Test tool with ByteStreamMetadata object in input
+   *
+   * Add a ByteStreamMetadata object to input. Tool should generate a
+   * ByteStreamMetadataContainer that one entry in the output
+   */
+  TEST_F(ByteStreamMetadataToolTest, objectInput) {
+    auto testBSM = std::make_unique< ByteStreamMetadata >(testObject);
+    const ByteStreamMetadata * in = testBSM.get();
+    assert(
+        m_inputStore->record< ByteStreamMetadata >(
+            std::move(testBSM), "Test").isSuccess());
+    EXPECT_TRUE(m_tool->beginInputFile().isSuccess());
+    EXPECT_TRUE(
+        m_metaStore->contains< ByteStreamMetadataContainer >(
+            "Test"));
+    auto bsmc =
+        m_metaStore->tryConstRetrieve< ByteStreamMetadataContainer >("Test");
+    assert(bsmc != nullptr);
+    size_t expectedSize = 1;
+    EXPECT_EQ(bsmc->size(), expectedSize);
+    const ByteStreamMetadata * out = bsmc->at(0);
+    EXPECT_EQ(*in, *out);
+    assert(m_inputStore->clearStore().isSuccess());
+    assert(m_metaStore->clearStore().isSuccess());
+  }
+
+  /**
+   * Test tool with ByteStreamMetadataContainer in input
+   *
+   * Add a ByteStreamMetadataContainer object to input. Tool should generate a
+   * ByteStreamMetadataContainer with equal entries
+   */
+  TEST_F(ByteStreamMetadataToolTest, containerInput) {
+    auto testBSMC = std::make_unique< ByteStreamMetadataContainer >();
+    testBSMC->push_back(std::make_unique< ByteStreamMetadata >(testObject));
+    const ByteStreamMetadataContainer * in = testBSMC.get();
+    assert(
+        m_inputStore->record< ByteStreamMetadataContainer >(
+            std::move(testBSMC), "Test").isSuccess());
+    EXPECT_TRUE(m_tool->beginInputFile().isSuccess());
+    EXPECT_TRUE(
+        m_metaStore->contains< ByteStreamMetadataContainer >(
+            "Test"));
+    auto out =
+        m_metaStore->tryConstRetrieve< ByteStreamMetadataContainer >("Test");
+    assert(out != nullptr);
+    EXPECT_EQ(in->size(), out->size());
+    EXPECT_EQ(*in->at(0), *out->at(0));
+    assert(m_inputStore->clearStore().isSuccess());
+    assert(m_metaStore->clearStore().isSuccess());
+  }
+
+  /**
+   * Test tool with equal object in input and output
+   *
+   * An input object equal to one that already exists in MetaDataStore should
+   * result in no new addition
+   */
+  TEST_F(ByteStreamMetadataToolTest, inputSame) {
+    auto inputBSMC = std::make_unique< ByteStreamMetadataContainer >();
+    inputBSMC->push_back(std::make_unique< ByteStreamMetadata >(testObject));
+    assert(
+        m_inputStore->record< ByteStreamMetadataContainer >(
+            std::move(inputBSMC), "Test").isSuccess());
+
+    auto copyBSMC = std::make_unique< ByteStreamMetadataContainer >();
+    copyBSMC->push_back(std::make_unique< ByteStreamMetadata >(testObject));
+    size_t expectedSize = copyBSMC->size();
+    assert(
+        m_metaStore->record< ByteStreamMetadataContainer >(
+            std::move(copyBSMC), "Test").isSuccess());
+
+    EXPECT_TRUE(m_tool->beginInputFile().isSuccess());
+    EXPECT_TRUE(
+        m_metaStore->contains< ByteStreamMetadataContainer >(
+            "Test"));
+    auto out =
+        m_metaStore->tryConstRetrieve< ByteStreamMetadataContainer >("Test");
+    assert(out != nullptr);
+    EXPECT_EQ(out->size(), expectedSize);
+
+    assert(m_inputStore->clearStore().isSuccess());
+    assert(m_metaStore->clearStore().isSuccess());
+  }
+
+  /**
+   * Test tool adding new objects from input to exisint output
+   *
+   * An input object not equal to one that already exists should result in a
+   * and additional entry in the MetaDataStore container
+   */
+  TEST_F(ByteStreamMetadataToolTest, inputNew) {
+    auto inputBSMC = std::make_unique< ByteStreamMetadataContainer >();
+    inputBSMC->push_back(std::make_unique< ByteStreamMetadata >(testObject));
+    assert(
+        m_inputStore->record< ByteStreamMetadataContainer >(
+            std::move(inputBSMC), "Test").isSuccess());
+
+    auto oldBSMC = std::make_unique< ByteStreamMetadataContainer >();
+    oldBSMC->push_back(std::make_unique< ByteStreamMetadata >(diffObject));
+    size_t expectedSize = 1 + oldBSMC->size();
+    assert(
+        m_metaStore->record< ByteStreamMetadataContainer >(
+            std::move(oldBSMC), "Test").isSuccess());
+
+    EXPECT_TRUE(m_tool->beginInputFile().isSuccess());
+    EXPECT_TRUE(
+        m_metaStore->contains< ByteStreamMetadataContainer >(
+            "Test"));
+    auto out =
+        m_metaStore->tryConstRetrieve< ByteStreamMetadataContainer >("Test");
+    assert(out != nullptr);
+    EXPECT_EQ(out->size(), expectedSize);
+
+    assert(m_inputStore->clearStore().isSuccess());
+    assert(m_metaStore->clearStore().isSuccess());
+  }
+
+}  // namespace Athena_test
+
+int main(int argc, char ** argv) {
+  ISvcLocator * svcLocator = nullptr;
+  if (!Athena_test::initGaudi(svcLocator)) {
+    std::cerr << "This test can not be run" << std::endl;
+    return 1;
+  }
+  assert(svcLocator);
+
+  Athena_test::setupStoreGate(argv[0]);
+  ::testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/Event/ByteStreamData/ByteStreamData/ByteStreamMetadata.h b/Event/ByteStreamData/ByteStreamData/ByteStreamMetadata.h
index bb8db3e2d1c..fe33d3ca88f 100644
--- a/Event/ByteStreamData/ByteStreamData/ByteStreamMetadata.h
+++ b/Event/ByteStreamData/ByteStreamData/ByteStreamMetadata.h
@@ -115,6 +115,29 @@ private:
  */
 std::ostream& operator<<(std::ostream& os, const ByteStreamMetadata& bsmd);
 
+/**
+ * Compare ByteStreamMetadata objects for equality
+ *
+ * Implementation of standard comparison operator. Uses the public interface of
+ * @c ByteStreamMetadata to compare GUIDs. It returns true if the GUIDs are
+ * equal, false otherwise.
+ */
+inline bool
+    operator==(const ByteStreamMetadata& lhs, const ByteStreamMetadata& rhs) {
+      return lhs.getGuid() == rhs.getGuid();
+    }
+
+/**
+ * Compare ByteStreamMetadata objects for inequality
+ *
+ * Implementation of standard comparison operator. Uses the public interface of
+ * @c ByteStreamMetadata to compare GUIDs. It returns true if the GUIDs are not
+ * equal, false if they are.
+ */
+inline bool
+    operator!=(const ByteStreamMetadata& lhs, const ByteStreamMetadata& rhs) {
+      return lhs.getGuid() != rhs.getGuid();
+    }
 
 #include "AthenaKernel/CLASS_DEF.h"
 CLASS_DEF(ByteStreamMetadata, 170625359, 1)
-- 
GitLab