Sort all includes in src/gromacs
[alexxy/gromacs.git] / src / gromacs / selection / tests / selectioncollection.cpp
index 419e62f960d69448ef3483dd6d1b696b92930c67..9e6fd86281b473c7d77929ad4c57422547526ea8 100644 (file)
@@ -1,10 +1,10 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2013, by the GROMACS development team, led by
- * David van der Spoel, Berk Hess, Erik Lindahl, and including many
- * others, as listed in the AUTHORS file in the top-level source
- * directory and at http://www.gromacs.org.
+ * Copyright (c) 2010,2011,2012,2013,2014, 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.
  *
  * GROMACS is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
  * \author Teemu Murtola <teemu.murtola@gmail.com>
  * \ingroup module_selection
  */
+#include "gmxpre.h"
+
+#include "gromacs/selection/selectioncollection.h"
+
 #include <gtest/gtest.h>
 
+#include "gromacs/fileio/trx.h"
 #include "gromacs/options/basicoptions.h"
 #include "gromacs/options/options.h"
 #include "gromacs/selection/indexutil.h"
-#include "gromacs/selection/selectioncollection.h"
 #include "gromacs/selection/selection.h"
+#include "gromacs/topology/topology.h"
+#include "gromacs/utility/arrayref.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/flags.h"
 #include "gromacs/utility/gmxregex.h"
@@ -91,12 +97,15 @@ class SelectionCollectionTest : public ::testing::Test
 
 int SelectionCollectionTest::s_debugLevel = 0;
 
+// \cond/\endcond do not seem to work here with Doxygen 1.8.5 parser.
+#ifndef DOXYGEN
 GMX_TEST_OPTIONS(SelectionCollectionTestOptions, options)
 {
     options->addOption(gmx::IntegerOption("seldebug")
                            .store(&SelectionCollectionTest::s_debugLevel)
                            .description("Set selection debug level"));
 }
+#endif
 
 SelectionCollectionTest::SelectionCollectionTest()
     : top_(NULL), frame_(NULL), grps_(NULL)
@@ -170,36 +179,20 @@ class SelectionCollectionDataTest : public SelectionCollectionTest
 
         void setFlags(TestFlags flags) { flags_ = flags; }
 
-        template <size_t count>
-        void runTest(int natoms, const char *const (&selections)[count])
-        {
-            runTest(natoms, selections, count);
-        }
-        template <size_t count>
-        void runTest(const char *filename, const char *const (&selections)[count])
-        {
-            runTest(filename, selections, count);
-        }
-
-        template <size_t count>
-        void runParser(const char *const (&selections)[count])
-        {
-            runParser(selections, count);
-        }
-
+        void runParser(const gmx::ConstArrayRef<const char *> &selections);
         void runCompiler();
         void runEvaluate();
         void runEvaluateFinal();
 
+        void runTest(int                                     natoms,
+                     const gmx::ConstArrayRef<const char *> &selections);
+        void runTest(const char                             *filename,
+                     const gmx::ConstArrayRef<const char *> &selections);
+
     private:
         static void checkSelection(gmx::test::TestReferenceChecker *checker,
                                    const gmx::Selection &sel, TestFlags flags);
 
-        void runTest(int natoms, const char *const *selections, size_t count);
-        void runTest(const char *filename, const char *const *selections,
-                     size_t count);
-        void runParser(const char *const *selections, size_t count);
-
         void checkCompiled();
 
         gmx::test::TestReferenceData    data_;
@@ -261,15 +254,15 @@ SelectionCollectionDataTest::checkSelection(
 
 
 void
-SelectionCollectionDataTest::runParser(const char *const *selections,
-                                       size_t             count)
+SelectionCollectionDataTest::runParser(
+        const gmx::ConstArrayRef<const char *> &selections)
 {
     using gmx::test::TestReferenceChecker;
 
     TestReferenceChecker compound(checker_.checkCompound("ParsedSelections", "Parsed"));
     size_t               varcount = 0;
     count_ = 0;
-    for (size_t i = 0; i < count; ++i)
+    for (size_t i = 0; i < selections.size(); ++i)
     {
         SCOPED_TRACE(std::string("Parsing selection \"")
                      + selections[i] + "\"");
@@ -368,21 +361,20 @@ SelectionCollectionDataTest::runEvaluateFinal()
 
 
 void
-SelectionCollectionDataTest::runTest(int natoms, const char * const *selections,
-                                     size_t count)
+SelectionCollectionDataTest::runTest(
+        int natoms, const gmx::ConstArrayRef<const char *> &selections)
 {
-    ASSERT_NO_FATAL_FAILURE(runParser(selections, count));
+    ASSERT_NO_FATAL_FAILURE(runParser(selections));
     ASSERT_NO_FATAL_FAILURE(setAtomCount(natoms));
     ASSERT_NO_FATAL_FAILURE(runCompiler());
 }
 
 
 void
-SelectionCollectionDataTest::runTest(const char         *filename,
-                                     const char * const *selections,
-                                     size_t              count)
+SelectionCollectionDataTest::runTest(
+        const char *filename, const gmx::ConstArrayRef<const char *> &selections)
 {
-    ASSERT_NO_FATAL_FAILURE(runParser(selections, count));
+    ASSERT_NO_FATAL_FAILURE(runParser(selections));
     ASSERT_NO_FATAL_FAILURE(loadTopology(filename));
     ASSERT_NO_FATAL_FAILURE(runCompiler());
     if (flags_.test(efTestEvaluation))
@@ -429,6 +421,15 @@ TEST_F(SelectionCollectionTest, ParsesSelectionsFromFile)
     EXPECT_STREQ("resname RB RC", sel_[1].selectionText());
 }
 
+TEST_F(SelectionCollectionTest, HandlesAtypicalWhitespace)
+{
+    ASSERT_NO_THROW_GMX(sel_ = sc_.parseFromString("atomnr\n1\r\nto\t10;\vatomnr 3\f to 14\r"));
+    ASSERT_EQ(2U, sel_.size());
+    EXPECT_STREQ("atomnr 1 to 10", sel_[0].selectionText());
+    // TODO: Get rid of the trailing whitespace.
+    EXPECT_STREQ("atomnr 3 to 14 ", sel_[1].selectionText());
+}
+
 TEST_F(SelectionCollectionTest, HandlesInvalidRegularExpressions)
 {
     ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
@@ -468,12 +469,6 @@ TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue3)
                      gmx::InvalidInputError);
 }
 
-TEST_F(SelectionCollectionTest, HandlesHelpKeywordInInvalidContext)
-{
-    EXPECT_THROW_GMX(sc_.parseFromString("resname help"),
-                     gmx::InvalidInputError);
-}
-
 // TODO: Tests for more parser errors
 
 TEST_F(SelectionCollectionTest, HandlesUnknownGroupReferenceParser1)
@@ -509,16 +504,44 @@ TEST_F(SelectionCollectionTest, HandlesUnknownGroupReferenceDelayed2)
 TEST_F(SelectionCollectionTest, HandlesUnsortedGroupReference)
 {
     ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
-    EXPECT_THROW_GMX(sc_.parseFromString("group \"GrpUnsorted\""),
+    EXPECT_THROW_GMX(sc_.parseFromString("atomnr 1 to 3 and group \"GrpUnsorted\""),
+                     gmx::InconsistentInputError);
+    EXPECT_THROW_GMX(sc_.parseFromString("group 2 or atomnr 2 to 5"),
+                     gmx::InconsistentInputError);
+    EXPECT_THROW_GMX(sc_.parseFromString("within 1 of group 2"),
                      gmx::InconsistentInputError);
-    EXPECT_THROW_GMX(sc_.parseFromString("2"), gmx::InconsistentInputError);
 }
 
 TEST_F(SelectionCollectionTest, HandlesUnsortedGroupReferenceDelayed)
 {
-    ASSERT_NO_THROW_GMX(sc_.parseFromString("group 2; group \"GrpUnsorted\""));
+    ASSERT_NO_THROW_GMX(sc_.parseFromString("atomnr 1 to 3 and group \"GrpUnsorted\""));
+    ASSERT_NO_THROW_GMX(sc_.parseFromString("atomnr 1 to 3 and group 2"));
+    EXPECT_THROW_GMX(loadIndexGroups("simple.ndx"), gmx::InconsistentInputError);
+    // TODO: Add a separate check in the selection compiler for a safer API
+    // (makes sense in the future if the compiler needs the information for
+    // other purposes as well).
+    // EXPECT_THROW_GMX(sc_.compile(), gmx::APIError);
+}
+
+TEST_F(SelectionCollectionTest, HandlesOutOfRangeAtomIndexInGroup)
+{
+    ASSERT_NO_THROW_GMX(sc_.setTopology(NULL, 5));
+    ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
+    EXPECT_THROW_GMX(sc_.parseFromString("group \"GrpB\""), gmx::InconsistentInputError);
+}
+
+TEST_F(SelectionCollectionTest, HandlesOutOfRangeAtomIndexInGroupDelayed)
+{
+    ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
+    ASSERT_NO_THROW_GMX(sc_.parseFromString("group \"GrpB\""));
+    EXPECT_THROW_GMX(sc_.setTopology(NULL, 5), gmx::InconsistentInputError);
+}
+
+TEST_F(SelectionCollectionTest, HandlesOutOfRangeAtomIndexInGroupDelayed2)
+{
+    ASSERT_NO_THROW_GMX(sc_.setTopology(NULL, 5));
+    ASSERT_NO_THROW_GMX(sc_.parseFromString("group \"GrpB\""));
     EXPECT_THROW_GMX(loadIndexGroups("simple.ndx"), gmx::InconsistentInputError);
-    EXPECT_THROW_GMX(sc_.compile(), gmx::APIError);
 }
 
 TEST_F(SelectionCollectionTest, RecoversFromMissingMoleculeInfo)
@@ -564,7 +587,35 @@ TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation3)
     EXPECT_THROW_GMX(sc_.evaluate(frame_, NULL), gmx::InconsistentInputError);
 }
 
-// TODO: Tests for evaluation errors
+TEST_F(SelectionCollectionTest, HandlesFramesWithTooSmallAtomSubsets)
+{
+    ASSERT_NO_THROW_GMX(sc_.parseFromString("atomnr 3 to 10"));
+    ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
+    ASSERT_NO_THROW_GMX(sc_.compile());
+    frame_->natoms = 8;
+    EXPECT_THROW_GMX(sc_.evaluate(frame_, NULL), gmx::InconsistentInputError);
+}
+
+TEST_F(SelectionCollectionTest, HandlesFramesWithTooSmallAtomSubsets2)
+{
+    // Evaluating the positions will require atoms 1-9.
+    ASSERT_NO_THROW_GMX(sc_.parseFromString("whole_res_com of atomnr 2 5 7"));
+    ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
+    ASSERT_NO_THROW_GMX(sc_.compile());
+    frame_->natoms = 8;
+    EXPECT_THROW_GMX(sc_.evaluate(frame_, NULL), gmx::InconsistentInputError);
+}
+
+TEST_F(SelectionCollectionTest, HandlesFramesWithTooSmallAtomSubsets3)
+{
+    ASSERT_NO_THROW_GMX(sc_.parseFromString("mindistance from atomnr 1 to 5 < 2"));
+    ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
+    ASSERT_NO_THROW_GMX(sc_.compile());
+    frame_->natoms = 10;
+    EXPECT_THROW_GMX(sc_.evaluate(frame_, NULL), gmx::InconsistentInputError);
+}
+
+// TODO: Tests for more evaluation errors
 
 
 /********************************************************************
@@ -943,6 +994,40 @@ TEST_F(SelectionCollectionDataTest, HandlesIndexGroupsInSelectionsDelayed)
     ASSERT_NO_FATAL_FAILURE(runCompiler());
 }
 
+TEST_F(SelectionCollectionDataTest, HandlesUnsortedIndexGroupsInSelections)
+{
+    static const char * const selections[] = {
+        "foo = group \"GrpUnsorted\"",
+        "group \"GrpUnsorted\"",
+        "GrpUnsorted",
+        "2",
+        "res_cog of group \"GrpUnsorted\"",
+        "group \"GrpUnsorted\" permute 2 1",
+        "foo"
+    };
+    setFlags(TestFlags() | efTestPositionAtoms | efTestPositionMapping
+             | efTestSelectionNames);
+    ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
+    runTest("simple.gro", selections);
+}
+
+TEST_F(SelectionCollectionDataTest, HandlesUnsortedIndexGroupsInSelectionsDelayed)
+{
+    static const char * const selections[] = {
+        "foo = group \"GrpUnsorted\"",
+        "group \"GrpUnsorted\"",
+        "GrpUnsorted",
+        "2",
+        "res_cog of group \"GrpUnsorted\"",
+        "group \"GrpUnsorted\" permute 2 1",
+        "foo"
+    };
+    ASSERT_NO_FATAL_FAILURE(runParser(selections));
+    ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
+    ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
+    ASSERT_NO_FATAL_FAILURE(runCompiler());
+}
+
 TEST_F(SelectionCollectionDataTest, HandlesConstantPositions)
 {
     static const char * const selections[] = {