Add preprocessing and integration test for transformation coordinate
[alexxy/gromacs.git] / src / gromacs / gmxpreprocess / tests / readir.cpp
index 71771bcccb91c79a7cf599aaf7ca6b265e3a6c36..586c95f99ccd5991d23124007678a93494c83769 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * 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.
@@ -71,8 +71,7 @@ namespace test
 class GetIrTest : public ::testing::Test
 {
 public:
-    GetIrTest() : opts_(), wi_(init_warning(FALSE, 0)), wiGuard_(wi_)
-
+    GetIrTest() : wi_(init_warning(FALSE, 0)), wiGuard_(wi_)
     {
         snew(opts_.include, STRLEN);
         snew(opts_.define, STRLEN);
@@ -83,31 +82,60 @@ public:
         sfree(opts_.include);
         sfree(opts_.define);
     }
+
+    //! Tells whether warnings and/or errors are expected from inputrec parsing and checking, and whether we should compare the output
+    enum class TestBehavior
+    {
+        NoErrorAndCompareOutput,      //!< Expect no warnings/error and compare output
+        NoErrorAndDoNotCompareOutput, //!< Expect no warnings/error and do not compare output
+        ErrorAndCompareOutput,        //!< Expect at least one warning/error and compare output
+        ErrorAndDoNotCompareOutput //!< Expect at least one warning/error and do not compare output
+    };
+
     /*! \brief Test mdp reading and writing
      *
      * \todo Modernize read_inp and write_inp to use streams,
      * which will make these tests run faster, because they don't
      * use disk files. */
-    void runTest(const std::string& inputMdpFileContents)
+    void runTest(const std::string& inputMdpFileContents,
+                 const TestBehavior testBehavior = TestBehavior::NoErrorAndCompareOutput)
     {
-        auto inputMdpFilename  = fileManager_.getTemporaryFilePath("input.mdp");
-        auto outputMdpFilename = fileManager_.getTemporaryFilePath("output.mdp");
+        const bool expectError = testBehavior == TestBehavior::ErrorAndCompareOutput
+                                 || testBehavior == TestBehavior::ErrorAndDoNotCompareOutput;
+        const bool compareOutput = testBehavior == TestBehavior::ErrorAndCompareOutput
+                                   || testBehavior == TestBehavior::NoErrorAndCompareOutput;
 
+        std::string inputMdpFilename = fileManager_.getTemporaryFilePath("input.mdp");
+        std::string outputMdpFilename;
+        if (compareOutput)
+        {
+            outputMdpFilename = fileManager_.getTemporaryFilePath("output.mdp");
+        }
         TextWriter::writeFileFromString(inputMdpFilename, inputMdpFileContents);
 
-        get_ir(inputMdpFilename.c_str(), outputMdpFilename.c_str(), &mdModules_, &ir_, &opts_,
-               WriteMdpHeader::no, wi_);
+        get_ir(inputMdpFilename.c_str(),
+               outputMdpFilename.empty() ? nullptr : outputMdpFilename.c_str(),
+               &mdModules_,
+               &ir_,
+               &opts_,
+               WriteMdpHeader::no,
+               wi_);
 
-        check_ir(inputMdpFilename.c_str(), mdModules_.notifier(), &ir_, &opts_, wi_);
+        check_ir(inputMdpFilename.c_str(), mdModules_.notifiers(), &ir_, &opts_, wi_);
         // Now check
-        bool                 failure = warning_errors_exist(wi_);
-        TestReferenceData    data;
-        TestReferenceChecker checker(data.rootChecker());
-        checker.checkBoolean(failure, "Error parsing mdp file");
-        warning_reset(wi_);
-
-        auto outputMdpContents = TextReader::readFileToString(outputMdpFilename);
-        checker.checkString(outputMdpContents, "OutputMdpFile");
+        bool failure = warning_errors_exist(wi_);
+        EXPECT_EQ(failure, expectError);
+
+        if (compareOutput)
+        {
+            TestReferenceData    data;
+            TestReferenceChecker checker(data.rootChecker());
+            checker.checkBoolean(failure, "Error parsing mdp file");
+            warning_reset(wi_);
+
+            auto outputMdpContents = TextReader::readFileToString(outputMdpFilename);
+            checker.checkString(outputMdpContents, "OutputMdpFile");
+        }
     }
 
     TestFileManager                    fileManager_;
@@ -176,6 +204,40 @@ TEST_F(GetIrTest, AcceptsEmptyLines)
     runTest(inputMdpFile);
 }
 
+TEST_F(GetIrTest, MtsCheckNstcalcenergy)
+{
+    const char* inputMdpFile[] = {
+        "mts = yes", "mts-levels = 2", "mts-level2-factor = 2", "nstcalcenergy = 5"
+    };
+    runTest(joinStrings(inputMdpFile, "\n"), TestBehavior::ErrorAndDoNotCompareOutput);
+}
+
+TEST_F(GetIrTest, MtsCheckNstenergy)
+{
+    const char* inputMdpFile[] = {
+        "mts = yes", "mts-levels = 2", "mts-level2-factor = 2", "nstenergy = 5"
+    };
+    runTest(joinStrings(inputMdpFile, "\n"), TestBehavior::ErrorAndDoNotCompareOutput);
+}
+
+TEST_F(GetIrTest, MtsCheckNstpcouple)
+{
+    const char* inputMdpFile[] = { "mts = yes",
+                                   "mts-levels = 2",
+                                   "mts-level2-factor = 2",
+                                   "pcoupl = Berendsen",
+                                   "nstpcouple = 5" };
+    runTest(joinStrings(inputMdpFile, "\n"), TestBehavior::ErrorAndDoNotCompareOutput);
+}
+
+TEST_F(GetIrTest, MtsCheckNstdhdl)
+{
+    const char* inputMdpFile[] = {
+        "mts = yes", "mts-level2-factor = 2", "free-energy = yes", "nstdhdl = 5"
+    };
+    runTest(joinStrings(inputMdpFile, "\n"), TestBehavior::ErrorAndDoNotCompareOutput);
+}
+
 // These tests observe how the electric-field keys behave, since they
 // are currently the only ones using the new Options-style handling.
 TEST_F(GetIrTest, AcceptsElectricField)
@@ -221,5 +283,73 @@ TEST_F(GetIrTest, AcceptsMimic)
     runTest(joinStrings(inputMdpFile, "\n"));
 }
 
+#if HAVE_MUPARSER
+
+TEST_F(GetIrTest, AcceptsTransformationCoord)
+{
+    const char* inputMdpFile[] = {
+        "pull = yes",
+        "pull-ngroups = 2",
+        "pull-ncoords = 2",
+        "pull-coord1-geometry = distance",
+        "pull-coord1-groups = 1 2",
+        "pull-coord1-k = 1",
+        "pull-coord2-geometry = transformation",
+        "pull-coord2-expression = 1/(1+x1)",
+        "pull-coord2-k = 10",
+    };
+    runTest(joinStrings(inputMdpFile, "\n"), TestBehavior::NoErrorAndDoNotCompareOutput);
+}
+
+TEST_F(GetIrTest, InvalidTransformationCoordWithConstraint)
+{
+    const char* inputMdpFile[] = {
+        "pull = yes",
+        "pull-ncoords = 1",
+        "pull-coord1-geometry = transformation",
+        "pull-coord1-type = constraint", // INVALID
+        "pull-coord1-expression = 10",
+    };
+    runTest(joinStrings(inputMdpFile, "\n"), TestBehavior::ErrorAndDoNotCompareOutput);
+}
+
+TEST_F(GetIrTest, InvalidPullCoordWithConstraintInTransformationExpression)
+{
+    const char* inputMdpFile[] = {
+        "pull = yes",
+        "pull-ngroups = 2",
+        "pull-ncoords = 2",
+        "pull-coord1-geometry = distance",
+        "pull-coord1-type = constraint", // INVALID
+        "pull-coord1-groups = 1 2",
+        "pull-coord2-geometry = transformation",
+        "pull-coord2-expression = x1",
+    };
+    runTest(joinStrings(inputMdpFile, "\n"), TestBehavior::ErrorAndDoNotCompareOutput);
+}
+
+TEST_F(GetIrTest, InvalidTransformationCoordDxValue)
+{
+    const char* inputMdpFile[] = {
+        "pull = yes",
+        "pull-ncoords = 1",
+        "pull-coord1-geometry = transformation",
+        "pull-coord1-expression = 10",
+        "pull-coord1-dx = 0", // INVALID
+    };
+    runTest(joinStrings(inputMdpFile, "\n"), TestBehavior::ErrorAndDoNotCompareOutput);
+}
+
+TEST_F(GetIrTest, MissingTransformationCoordExpression)
+{
+    const char* inputMdpFile[] = {
+        "pull = yes",
+        "pull-ncoords = 1",
+        "pull-coord1-geometry = transformation",
+    };
+    runTest(joinStrings(inputMdpFile, "\n"), TestBehavior::ErrorAndDoNotCompareOutput);
+}
+#endif // HAVE_MUPARSER
+
 } // namespace test
 } // namespace gmx