Generalize constraints on MPI rank counts for tests
[alexxy/gromacs.git] / src / testutils / testinit.cpp
index 753b814a0f3669d90f5a31ef8b80b335b47d1ccc..e04b49bec5da4fbc7e58cb724933ef3c1c998f02 100644 (file)
@@ -2,7 +2,7 @@
  * This file is part of the GROMACS molecular simulation package.
  *
  * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
- * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020,2021, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -42,7 +42,7 @@
  */
 #include "gmxpre.h"
 
-#include "testinit.h"
+#include "testutils/testinit.h"
 
 #include <cstdio>
 #include <cstdlib>
 #include "gromacs/utility/programcontext.h"
 #include "gromacs/utility/textwriter.h"
 
-#include "testutils/mpi_printer.h"
+#include "testutils/mpitest.h"
 #include "testutils/refdata.h"
 #include "testutils/test_hardware_environment.h"
 #include "testutils/testfilemanager.h"
 #include "testutils/testoptions.h"
 
+#include "mpi_printer.h"
+
 namespace gmx
 {
 namespace test
@@ -87,7 +89,7 @@ namespace
  *
  * This context overrides the installationPrefix() implementation to always
  * load data files from the source directory, as the test binaries are never
- * installed.  It also support overriding the directory through a command-line
+ * installed.  It also supports overriding the directory through a command-line
  * option to the test binary.
  *
  * \ingroup module_testutils
@@ -101,8 +103,7 @@ public:
      * \param[in] context  Current \Gromacs program context.
      */
     explicit TestProgramContext(const IProgramContext& context) :
-        context_(context),
-        dataPath_(CMAKE_SOURCE_DIR)
+        context_(context), dataPath_(CMAKE_SOURCE_DIR)
     {
     }
 
@@ -142,6 +143,29 @@ void printHelp(const Options& options)
 // Never releases ownership.
 std::unique_ptr<TestProgramContext> g_testContext;
 
+/*! \brief Makes GoogleTest non-failures more verbose
+ *
+ * By default, GoogleTest does not echo messages appended to explicit
+ * assertions of success with SUCCEEDED() e.g.
+ *
+ *    GTEST_SKIP() << "reason why";
+ *
+ * produces no output. This test listener changes that behavior, so
+ * that the message is echoed.
+ *
+ * When run with multiple ranks, only the master rank should use this
+ * listener, else the output can be very noisy. */
+class SuccessListener : public testing::EmptyTestEventListener
+{
+    void OnTestPartResult(const testing::TestPartResult& result) override
+    {
+        if (result.type() == testing::TestPartResult::kSuccess)
+        {
+            printf("%s\n", result.message());
+        }
+    }
+};
+
 } // namespace
 
 //! \cond internal
@@ -152,11 +176,10 @@ void initTestUtils(const char* dataPath,
                    int*        argc,
                    char***     argv)
 {
-#if !defined NDEBUG                                                                         \
-        && !((defined __clang__ || (defined(__GNUC__) && !defined(__ICC) && __GNUC__ == 7)) \
-             && defined __OPTIMIZE__)
-    gmx_feenableexcept();
-#endif
+    if (gmxShouldEnableFPExceptions())
+    {
+        gmx_feenableexcept();
+    }
     const CommandLineProgramContext& context = initForCommandLine(argc, argv);
     try
     {
@@ -171,7 +194,8 @@ void initTestUtils(const char* dataPath,
                         "NOTE: You are running %s on %d MPI ranks, "
                         "but it is does not contain MPI-enabled tests. "
                         "The test will now exit.\n",
-                        context.programName(), gmx_node_num());
+                        context.programName(),
+                        gmx_node_num());
             }
             finalizeForCommandLine();
             std::exit(1);
@@ -198,6 +222,7 @@ void initTestUtils(const char* dataPath,
 
         bool        bHelp = false;
         std::string sourceRoot;
+        bool        echoReasons = false;
         Options     options;
         // TODO: A single option that accepts multiple names would be nicer.
         // Also, we recognize -help, but GTest doesn't, which leads to a bit
@@ -209,6 +234,8 @@ void initTestUtils(const char* dataPath,
         // TODO: Make this into a FileNameOption (or a DirectoryNameOption).
         options.addOption(
                 StringOption("src-root").store(&sourceRoot).description("Override source tree location (for data files)"));
+        options.addOption(
+                BooleanOption("echo-reasons").store(&echoReasons).description("When succeeding or skipping a test, echo the reason"));
         // The potential MPI test event listener must be initialized first,
         // because it should appear in the start of the event listener list,
         // before other event listeners that may generate test failures
@@ -240,6 +267,11 @@ void initTestUtils(const char* dataPath,
             g_testContext->overrideSourceRoot(sourceRoot);
             TestFileManager::setInputDataDirectory(Path::join(sourceRoot, dataPath));
         }
+        // Echo success messages only from the master MPI rank
+        if (echoReasons && (gmx_node_rank() == 0))
+        {
+            testing::UnitTest::GetInstance()->listeners().Append(new SuccessListener);
+        }
     }
     catch (const std::exception& ex)
     {