Permit tests to specify the refdata filename
authorMark Abraham <mark.j.abraham@gmail.com>
Tue, 2 Nov 2021 12:57:07 +0000 (13:57 +0100)
committerMark Abraham <mark.j.abraham@gmail.com>
Fri, 5 Nov 2021 08:55:00 +0000 (08:55 +0000)
When the same test data is re-used for multiple test cases it is
wasteful to serialize that data many times. This functionality permits
test cases to choose their own refdata file name, perhaps derived from
the actual test name. This means the tests can run efficiently, don't
needlessly proliferate lots of data, and express directly in the code
that multiple test cases produce the same data.

Refs #4255

src/testutils/include/testutils/refdata.h
src/testutils/refdata.cpp

index e57b96769004ef258f462cf4360ea3d2785015c2..f3ae67b578582e1e243bb3cd10c5f96d39c27c0f 100644 (file)
@@ -40,6 +40,7 @@
  * See \ref page_refdata for more details.
  *
  * \author Teemu Murtola <teemu.murtola@gmail.com>
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
  * \inlibraryapi
  * \ingroup module_testutils
  */
@@ -195,6 +196,17 @@ public:
      * Initializes the reference data in the global mode.
      */
     TestReferenceData();
+    /*! \brief Initializes the reference data in the global mode while
+     * providing the test name.
+     *
+     * Providing a name for the test, rather than using the default
+     * name generated by GoogleTest, is useful when many tests should
+     * share common reference data because e.g. they are
+     * value-parameterized over multiple equivalent implementations or
+     * run modes. The name should include a filename suffix
+     * e.g. `.xml` and refers to a file that will be found in the
+     * `refdata` subdirectory for the test case. */
+    explicit TestReferenceData(std::string testNameOverride);
     /*! \brief
      * Initializes the reference data in a specific mode.
      *
index 075a028761ae41b642f1b492fe090530c245c332..3c72514481cab29dbfbffc189f2734696ae7376d 100644 (file)
@@ -38,6 +38,7 @@
  * Implements classes and functions from refdata.h.
  *
  * \author Teemu Murtola <teemu.murtola@gmail.com>
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
  * \ingroup module_testutils
  */
 #include "gmxpre.h"
@@ -49,6 +50,7 @@
 
 #include <algorithm>
 #include <limits>
+#include <optional>
 #include <string>
 
 #include <gtest/gtest.h>
@@ -93,7 +95,7 @@ class TestReferenceDataImpl
 {
 public:
     //! Initializes a checker in the given mode.
-    TestReferenceDataImpl(ReferenceDataMode mode, bool bSelfTestMode);
+    TestReferenceDataImpl(ReferenceDataMode mode, bool bSelfTestMode, std::optional<std::string> testNameOverride);
 
     //! Performs final reference data processing when test ends.
     void onTestEnd(bool testPassed) const;
@@ -165,10 +167,11 @@ ReferenceDataMode getReferenceDataMode()
 }
 
 //! Returns a reference to the global reference data object.
-TestReferenceDataImplPointer initReferenceDataInstance()
+TestReferenceDataImplPointer initReferenceDataInstance(std::optional<std::string> testNameOverride)
 {
     GMX_RELEASE_ASSERT(!g_referenceData, "Test cannot create multiple TestReferenceData instances");
-    g_referenceData.reset(new internal::TestReferenceDataImpl(getReferenceDataMode(), false));
+    g_referenceData.reset(new internal::TestReferenceDataImpl(
+            getReferenceDataMode(), false, std::move(testNameOverride)));
     return g_referenceData;
 }
 
@@ -182,7 +185,7 @@ TestReferenceDataImplPointer initReferenceDataInstanceForSelfTest(ReferenceDataM
         g_referenceData->onTestEnd(true);
         g_referenceData.reset();
     }
-    g_referenceData.reset(new internal::TestReferenceDataImpl(mode, true));
+    g_referenceData.reset(new internal::TestReferenceDataImpl(mode, true, std::nullopt));
     return g_referenceData;
 }
 
@@ -287,12 +290,16 @@ void initReferenceData(IOptionsContainer* options)
 namespace internal
 {
 
-TestReferenceDataImpl::TestReferenceDataImpl(ReferenceDataMode mode, bool bSelfTestMode) :
+TestReferenceDataImpl::TestReferenceDataImpl(ReferenceDataMode          mode,
+                                             bool                       bSelfTestMode,
+                                             std::optional<std::string> testNameOverride) :
     updateMismatchingEntries_(false), bSelfTestMode_(bSelfTestMode), bInUse_(false)
 {
     const std::string dirname  = bSelfTestMode ? TestFileManager::getGlobalOutputTempDirectory()
                                                : TestFileManager::getInputDataDirectory();
-    const std::string filename = TestFileManager::getTestSpecificFileName(".xml");
+    const std::string filename = testNameOverride.has_value()
+                                         ? testNameOverride.value()
+                                         : TestFileManager::getTestSpecificFileName(".xml");
     fullFilename_              = Path::join(dirname, "refdata", filename);
 
     switch (mode)
@@ -678,9 +685,14 @@ ReferenceDataEntry* TestReferenceChecker::Impl::findOrCreateEntry(const char* ty
  * TestReferenceData
  */
 
-TestReferenceData::TestReferenceData() : impl_(initReferenceDataInstance()) {}
+TestReferenceData::TestReferenceData() : impl_(initReferenceDataInstance(std::nullopt)) {}
 
 
+TestReferenceData::TestReferenceData(std::string testNameOverride) :
+    impl_(initReferenceDataInstance(std::move(testNameOverride)))
+{
+}
+
 TestReferenceData::TestReferenceData(ReferenceDataMode mode) :
     impl_(initReferenceDataInstanceForSelfTest(mode))
 {