2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2010,2011,2012,2013, by the GROMACS development team, led by
5 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
6 * others, as listed in the AUTHORS file in the top-level source
7 * directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
37 * Tests selection parsing and compilation.
39 * \author Teemu Murtola <teemu.murtola@gmail.com>
40 * \ingroup module_selection
42 #include <gtest/gtest.h>
44 #include "gromacs/options/basicoptions.h"
45 #include "gromacs/options/options.h"
46 #include "gromacs/selection/selectioncollection.h"
47 #include "gromacs/selection/selection.h"
48 #include "gromacs/utility/exceptions.h"
49 #include "gromacs/utility/flags.h"
50 #include "gromacs/utility/gmxregex.h"
51 #include "gromacs/utility/stringutil.h"
53 #include "testutils/refdata.h"
54 #include "testutils/testasserts.h"
55 #include "testutils/testfilemanager.h"
56 #include "testutils/testoptions.h"
63 /********************************************************************
64 * Test fixture for selection testing
67 class SelectionCollectionTest : public ::testing::Test
70 static void SetUpTestCase();
72 static int s_debugLevel;
74 SelectionCollectionTest();
76 void setAtomCount(int natoms)
78 ASSERT_NO_THROW_GMX(sc_.setTopology(NULL, natoms));
80 void loadTopology(const char *filename);
82 gmx::SelectionCollection sc_;
83 gmx::SelectionList sel_;
88 gmx::test::TopologyManager topManager_;
91 int SelectionCollectionTest::s_debugLevel = 0;
93 void SelectionCollectionTest::SetUpTestCase()
95 gmx::Options options(NULL, NULL);
96 options.addOption(gmx::IntegerOption("seldebug").store(&s_debugLevel));
97 gmx::test::parseTestOptions(&options);
100 SelectionCollectionTest::SelectionCollectionTest()
101 : top_(NULL), frame_(NULL)
103 topManager_.requestFrame();
104 sc_.setDebugLevel(s_debugLevel);
105 sc_.setReferencePosType("atom");
106 sc_.setOutputPosType("atom");
110 SelectionCollectionTest::loadTopology(const char *filename)
112 topManager_.loadTopology(filename);
113 top_ = topManager_.topology();
114 frame_ = topManager_.frame();
116 ASSERT_NO_THROW_GMX(sc_.setTopology(top_, -1));
120 /********************************************************************
121 * Test fixture for selection testing with reference data
124 class SelectionCollectionDataTest : public SelectionCollectionTest
129 efTestEvaluation = 1<<0,
130 efTestPositionAtoms = 1<<1,
131 efTestPositionCoordinates = 1<<2,
132 efTestPositionMapping = 1<<3,
133 efTestPositionMasses = 1<<4,
134 efTestPositionCharges = 1<<5,
135 efDontTestCompiledAtoms = 1<<8
137 typedef gmx::FlagsTemplate<TestFlag> TestFlags;
139 SelectionCollectionDataTest()
140 : checker_(data_.rootChecker()), count_(0), framenr_(0)
144 void setFlags(TestFlags flags) { flags_ = flags; }
146 template <size_t count>
147 void runTest(int natoms, const char *const (&selections)[count])
149 runTest(natoms, selections, count);
151 template <size_t count>
152 void runTest(const char *filename, const char *const (&selections)[count])
154 runTest(filename, selections, count);
157 template <size_t count>
158 void runParser(const char *const (&selections)[count])
160 runParser(selections, count);
165 void runEvaluateFinal();
168 static void checkSelection(gmx::test::TestReferenceChecker *checker,
169 const gmx::Selection &sel, TestFlags flags);
171 void runTest(int natoms, const char *const *selections, size_t count);
172 void runTest(const char *filename, const char *const *selections,
174 void runParser(const char *const *selections, size_t count);
176 void checkCompiled();
178 gmx::test::TestReferenceData data_;
179 gmx::test::TestReferenceChecker checker_;
187 SelectionCollectionDataTest::checkSelection(
188 gmx::test::TestReferenceChecker *checker,
189 const gmx::Selection &sel, TestFlags flags)
191 using gmx::test::TestReferenceChecker;
194 gmx::ConstArrayRef<int> atoms = sel.atomIndices();
195 checker->checkSequence(atoms.begin(), atoms.end(), "Atoms");
197 if (flags.test(efTestPositionAtoms)
198 || flags.test(efTestPositionCoordinates)
199 || flags.test(efTestPositionMapping)
200 || flags.test(efTestPositionMasses)
201 || flags.test(efTestPositionCharges))
203 TestReferenceChecker compound(
204 checker->checkSequenceCompound("Positions", sel.posCount()));
205 for (int i = 0; i < sel.posCount(); ++i)
207 TestReferenceChecker poscompound(compound.checkCompound("Position", NULL));
208 const gmx::SelectionPosition &p = sel.position(i);
209 if (flags.test(efTestPositionAtoms))
211 gmx::ConstArrayRef<int> atoms = p.atomIndices();
212 poscompound.checkSequence(atoms.begin(), atoms.end(), "Atoms");
214 if (flags.test(efTestPositionCoordinates))
216 poscompound.checkVector(p.x(), "Coordinates");
218 if (flags.test(efTestPositionMapping))
220 poscompound.checkInteger(p.refId(), "RefId");
221 poscompound.checkInteger(p.mappedId(), "MappedId");
223 if (flags.test(efTestPositionMasses))
225 poscompound.checkReal(p.mass(), "Mass");
227 if (flags.test(efTestPositionCharges))
229 poscompound.checkReal(p.charge(), "Charge");
237 SelectionCollectionDataTest::runParser(const char *const *selections,
240 using gmx::test::TestReferenceChecker;
242 TestReferenceChecker compound(checker_.checkCompound("ParsedSelections", "Parsed"));
245 for (size_t i = 0; i < count; ++i)
247 SCOPED_TRACE(std::string("Parsing selection \"")
248 + selections[i] + "\"");
249 gmx::SelectionList result;
250 ASSERT_NO_THROW_GMX(result = sc_.parseFromString(selections[i]));
251 sel_.insert(sel_.end(), result.begin(), result.end());
252 if (sel_.size() == count_)
254 std::string id = gmx::formatString("Variable%d", static_cast<int>(varcount + 1));
255 TestReferenceChecker varcompound(
256 compound.checkCompound("ParsedVariable", id.c_str()));
257 varcompound.checkString(selections[i], "Input");
262 std::string id = gmx::formatString("Selection%d", static_cast<int>(count_ + 1));
263 TestReferenceChecker selcompound(
264 compound.checkCompound("ParsedSelection", id.c_str()));
265 selcompound.checkString(selections[i], "Input");
266 selcompound.checkString(sel_[count_].name(), "Name");
267 selcompound.checkString(sel_[count_].selectionText(), "Text");
268 selcompound.checkBoolean(sel_[count_].isDynamic(), "Dynamic");
276 SelectionCollectionDataTest::runCompiler()
278 ASSERT_NO_THROW_GMX(sc_.compile());
279 ASSERT_EQ(count_, sel_.size());
285 SelectionCollectionDataTest::checkCompiled()
287 using gmx::test::TestReferenceChecker;
288 const TestFlags mask = ~TestFlags(efTestPositionCoordinates);
290 TestReferenceChecker compound(checker_.checkCompound("CompiledSelections", "Compiled"));
291 for (size_t i = 0; i < count_; ++i)
293 SCOPED_TRACE(std::string("Checking selection \"") +
294 sel_[i].selectionText() + "\"");
295 std::string id = gmx::formatString("Selection%d", static_cast<int>(i + 1));
296 TestReferenceChecker selcompound(
297 compound.checkCompound("Selection", id.c_str()));
298 if (!flags_.test(efDontTestCompiledAtoms))
300 checkSelection(&selcompound, sel_[i], flags_ & mask);
307 SelectionCollectionDataTest::runEvaluate()
309 using gmx::test::TestReferenceChecker;
312 ASSERT_NO_THROW_GMX(sc_.evaluate(frame_, NULL));
313 std::string frame = gmx::formatString("Frame%d", framenr_);
314 TestReferenceChecker compound(
315 checker_.checkCompound("EvaluatedSelections", frame.c_str()));
316 for (size_t i = 0; i < count_; ++i)
318 SCOPED_TRACE(std::string("Checking selection \"") +
319 sel_[i].selectionText() + "\"");
320 std::string id = gmx::formatString("Selection%d", static_cast<int>(i + 1));
321 TestReferenceChecker selcompound(
322 compound.checkCompound("Selection", id.c_str()));
323 checkSelection(&selcompound, sel_[i], flags_);
329 SelectionCollectionDataTest::runEvaluateFinal()
331 ASSERT_NO_THROW_GMX(sc_.evaluateFinal(framenr_));
337 SelectionCollectionDataTest::runTest(int natoms, const char * const *selections,
340 ASSERT_NO_FATAL_FAILURE(runParser(selections, count));
341 ASSERT_NO_FATAL_FAILURE(setAtomCount(natoms));
342 ASSERT_NO_FATAL_FAILURE(runCompiler());
347 SelectionCollectionDataTest::runTest(const char *filename,
348 const char * const *selections,
351 ASSERT_NO_FATAL_FAILURE(runParser(selections, count));
352 ASSERT_NO_FATAL_FAILURE(loadTopology(filename));
353 ASSERT_NO_FATAL_FAILURE(runCompiler());
354 if (flags_.test(efTestEvaluation))
356 ASSERT_NO_FATAL_FAILURE(runEvaluate());
357 ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
362 /********************************************************************
363 * Tests for SelectionCollection functionality without reference data
366 TEST_F(SelectionCollectionTest, HandlesNoSelections)
368 EXPECT_FALSE(sc_.requiresTopology());
369 EXPECT_NO_THROW_GMX(sc_.compile());
372 TEST_F(SelectionCollectionTest, HandlesVelocityAndForceRequests)
374 ASSERT_NO_THROW_GMX(sel_ = sc_.parseFromString("atomnr 1 to 10; none"));
375 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
376 ASSERT_EQ(2U, sel_.size());
377 ASSERT_NO_THROW_GMX(sel_[0].setEvaluateVelocities(true));
378 ASSERT_NO_THROW_GMX(sel_[1].setEvaluateVelocities(true));
379 ASSERT_NO_THROW_GMX(sel_[0].setEvaluateForces(true));
380 ASSERT_NO_THROW_GMX(sel_[1].setEvaluateForces(true));
381 ASSERT_NO_THROW_GMX(sc_.compile());
382 EXPECT_TRUE(sel_[0].hasVelocities());
383 EXPECT_TRUE(sel_[1].hasVelocities());
384 EXPECT_TRUE(sel_[0].hasForces());
385 EXPECT_TRUE(sel_[1].hasForces());
388 TEST_F(SelectionCollectionTest, ParsesSelectionsFromFile)
390 ASSERT_NO_THROW_GMX(sel_ = sc_.parseFromFile(
391 gmx::test::TestFileManager::getInputFilePath("selfile.dat")));
392 // These should match the contents of selfile.dat
393 ASSERT_EQ(2U, sel_.size());
394 EXPECT_STREQ("resname RA RB", sel_[0].selectionText());
395 EXPECT_STREQ("resname RB RC", sel_[1].selectionText());
398 TEST_F(SelectionCollectionTest, HandlesInvalidRegularExpressions)
400 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
402 sc_.parseFromString("resname ~ \"R[A\"");
404 }, gmx::InvalidInputError);
407 TEST_F(SelectionCollectionTest, HandlesUnsupportedRegularExpressions)
409 if (!gmx::Regex::isSupported())
411 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
413 sc_.parseFromString("resname \"R[AD]\"");
415 }, gmx::InvalidInputError);
419 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue)
421 EXPECT_THROW_GMX(sc_.parseFromString("mindist from atomnr 1 cutoff"),
422 gmx::InvalidInputError);
425 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue2)
427 EXPECT_THROW_GMX(sc_.parseFromString("within 1 of"),
428 gmx::InvalidInputError);
431 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue3)
433 EXPECT_THROW_GMX(sc_.parseFromString("within of atomnr 1"),
434 gmx::InvalidInputError);
437 TEST_F(SelectionCollectionTest, HandlesHelpKeywordInInvalidContext)
439 EXPECT_THROW_GMX(sc_.parseFromString("resname help"),
440 gmx::InvalidInputError);
443 // TODO: Tests for more parser errors
445 TEST_F(SelectionCollectionTest, RecoversFromUnknownGroupReference)
447 ASSERT_NO_THROW_GMX(sc_.parseFromString("group \"foo\""));
448 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
449 EXPECT_THROW_GMX(sc_.setIndexGroups(NULL), gmx::InvalidInputError);
450 EXPECT_THROW_GMX(sc_.compile(), gmx::APIError);
453 TEST_F(SelectionCollectionTest, RecoversFromMissingMoleculeInfo)
455 ASSERT_NO_THROW_GMX(sc_.parseFromString("molindex 1 to 5"));
456 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
457 EXPECT_THROW_GMX(sc_.compile(), gmx::InconsistentInputError);
460 TEST_F(SelectionCollectionTest, RecoversFromMissingAtomTypes)
462 ASSERT_NO_THROW_GMX(sc_.parseFromString("type CA"));
463 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
464 EXPECT_THROW_GMX(sc_.compile(), gmx::InconsistentInputError);
467 TEST_F(SelectionCollectionTest, RecoversFromMissingPDBInfo)
469 ASSERT_NO_THROW_GMX(sc_.parseFromString("altloc A"));
470 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
471 EXPECT_THROW_GMX(sc_.compile(), gmx::InconsistentInputError);
474 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation)
476 ASSERT_NO_THROW_GMX(sc_.parseFromString("all permute 1 1"));
477 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
478 EXPECT_THROW_GMX(sc_.compile(), gmx::InvalidInputError);
481 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation2)
483 ASSERT_NO_THROW_GMX(sc_.parseFromString("all permute 3 2 1"));
484 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
485 EXPECT_THROW_GMX(sc_.compile(), gmx::InconsistentInputError);
488 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation3)
490 ASSERT_NO_THROW_GMX(sc_.parseFromString("x < 1.5 permute 3 2 1"));
491 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
492 ASSERT_NO_THROW_GMX(sc_.compile());
493 EXPECT_THROW_GMX(sc_.evaluate(frame_, NULL), gmx::InconsistentInputError);
496 // TODO: Tests for evaluation errors
499 /********************************************************************
500 * Tests for selection keywords
503 TEST_F(SelectionCollectionDataTest, HandlesAllNone)
505 static const char * const selections[] = {
509 runTest(10, selections);
512 TEST_F(SelectionCollectionDataTest, HandlesAtomnr)
514 static const char * const selections[] = {
515 "atomnr 1 to 3 6 to 8",
519 runTest(10, selections);
522 TEST_F(SelectionCollectionDataTest, HandlesResnr)
524 static const char * const selections[] = {
528 runTest("simple.gro", selections);
531 TEST_F(SelectionCollectionDataTest, HandlesResIndex)
533 static const char * const selections[] = {
537 runTest("simple.pdb", selections);
540 // TODO: Add test for "molindex"
542 TEST_F(SelectionCollectionDataTest, HandlesAtomname)
544 static const char * const selections[] = {
548 runTest("simple.gro", selections);
551 TEST_F(SelectionCollectionDataTest, HandlesPdbAtomname)
553 static const char * const selections[] = {
559 runTest("simple.pdb", selections);
562 // TODO: Add test for atomtype
564 TEST_F(SelectionCollectionDataTest, HandlesChain)
566 static const char * const selections[] = {
570 runTest("simple.pdb", selections);
573 TEST_F(SelectionCollectionDataTest, HandlesMass)
575 static const char * const selections[] = {
578 ASSERT_NO_FATAL_FAILURE(runParser(selections));
579 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
580 for (int i = 0; i < top_->atoms.nr; ++i)
582 top_->atoms.atom[i].m = 1.0 + i;
584 ASSERT_NO_FATAL_FAILURE(runCompiler());
587 TEST_F(SelectionCollectionDataTest, HandlesCharge)
589 static const char * const selections[] = {
592 ASSERT_NO_FATAL_FAILURE(runParser(selections));
593 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
594 for (int i = 0; i < top_->atoms.nr; ++i)
596 top_->atoms.atom[i].q = i / 10.0;
598 ASSERT_NO_FATAL_FAILURE(runCompiler());
601 TEST_F(SelectionCollectionDataTest, HandlesAltLoc)
603 static const char * const selections[] = {
607 runTest("simple.pdb", selections);
610 TEST_F(SelectionCollectionDataTest, HandlesInsertCode)
612 static const char * const selections[] = {
616 runTest("simple.pdb", selections);
619 TEST_F(SelectionCollectionDataTest, HandlesOccupancy)
621 static const char * const selections[] = {
625 runTest("simple.pdb", selections);
628 TEST_F(SelectionCollectionDataTest, HandlesBeta)
630 static const char * const selections[] = {
634 runTest("simple.pdb", selections);
637 TEST_F(SelectionCollectionDataTest, HandlesResname)
639 static const char * const selections[] = {
643 runTest("simple.gro", selections);
646 TEST_F(SelectionCollectionDataTest, HandlesCoordinateKeywords)
648 static const char * const selections[] = {
653 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
654 runTest("simple.gro", selections);
658 TEST_F(SelectionCollectionDataTest, HandlesSameResidue)
660 static const char * const selections[] = {
661 "same residue as atomnr 1 4 12"
663 runTest("simple.gro", selections);
667 TEST_F(SelectionCollectionDataTest, HandlesSameResidueName)
669 static const char * const selections[] = {
670 "same resname as atomnr 1 14"
672 runTest("simple.gro", selections);
676 TEST_F(SelectionCollectionDataTest, HandlesPositionKeywords)
678 static const char * const selections[] = {
680 "res_cog of name CB and resnr 1 3",
681 "whole_res_cog of name CB and resnr 1 3",
682 "part_res_cog of x < 3",
683 "dyn_res_cog of x < 3"
685 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
686 | efTestPositionAtoms);
687 runTest("simple.gro", selections);
691 TEST_F(SelectionCollectionDataTest, HandlesDistanceKeyword)
693 static const char * const selections[] = {
694 "distance from cog of resnr 1 < 2"
696 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
697 runTest("simple.gro", selections);
701 TEST_F(SelectionCollectionDataTest, HandlesMinDistanceKeyword)
703 static const char * const selections[] = {
704 "mindistance from resnr 1 < 2"
706 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
707 runTest("simple.gro", selections);
711 TEST_F(SelectionCollectionDataTest, HandlesWithinKeyword)
713 static const char * const selections[] = {
714 "within 1 of resnr 2"
716 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
717 runTest("simple.gro", selections);
721 TEST_F(SelectionCollectionDataTest, HandlesInSolidAngleKeyword)
723 // Both of these should evaluate to empty on a correct implementation.
724 static const char * const selections[] = {
725 "resname TP and not insolidangle center cog of resname C span resname R cutoff 20",
726 "resname TN and insolidangle center cog of resname C span resname R cutoff 20"
728 setFlags(TestFlags() | efDontTestCompiledAtoms | efTestEvaluation);
729 runTest("sphere.gro", selections);
733 TEST_F(SelectionCollectionDataTest, HandlesPermuteModifier)
735 static const char * const selections[] = {
737 "res_cog of resnr 1 to 4 permute 2 1",
738 "name CB S1 and res_cog x < 3 permute 2 1"
740 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
741 | efTestPositionAtoms | efTestPositionMapping);
742 runTest("simple.gro", selections);
746 TEST_F(SelectionCollectionDataTest, HandlesPlusModifier)
748 static const char * const selections[] = {
749 "name S2 plus name S1",
750 "res_cog of resnr 2 plus res_cog of resnr 1 plus res_cog of resnr 3",
751 "name S1 and y < 3 plus res_cog of x < 2.5"
753 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
754 | efTestPositionAtoms | efTestPositionMapping);
755 runTest("simple.gro", selections);
759 TEST_F(SelectionCollectionDataTest, HandlesMergeModifier)
761 static const char * const selections[] = {
762 "name S2 merge name S1",
763 "resnr 1 2 and name S2 merge resnr 1 2 and name S1 merge res_cog of resnr 1 2",
764 "name S1 and x < 2.5 merge res_cog of x < 2.5"
766 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
767 | efTestPositionAtoms | efTestPositionMapping);
768 runTest("simple.gro", selections);
772 /********************************************************************
773 * Tests for generic selection evaluation
776 TEST_F(SelectionCollectionDataTest, ComputesMassesAndCharges)
778 static const char * const selections[] = {
783 setFlags(TestFlags() | efTestEvaluation | efTestPositionAtoms
784 | efTestPositionMasses | efTestPositionCharges);
785 ASSERT_NO_FATAL_FAILURE(runParser(selections));
786 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
787 for (int i = 0; i < top_->atoms.nr; ++i)
789 top_->atoms.atom[i].m = 1.0 + i / 100.0;
790 top_->atoms.atom[i].q = -(1.0 + i / 100.0);
792 ASSERT_NO_FATAL_FAILURE(runCompiler());
793 ASSERT_NO_FATAL_FAILURE(runEvaluate());
794 ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
797 TEST_F(SelectionCollectionDataTest, ComputesMassesAndChargesWithoutTopology)
799 static const char * const selections[] = {
800 "atomnr 1 to 3 8 to 9",
804 setFlags(TestFlags() | efTestPositionAtoms
805 | efTestPositionMasses | efTestPositionCharges);
806 runTest(10, selections);
810 /********************************************************************
811 * Tests for selection syntactic constructs
814 TEST_F(SelectionCollectionDataTest, HandlesConstantPositions)
816 static const char * const selections[] = {
819 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
820 runTest("simple.gro", selections);
824 TEST_F(SelectionCollectionDataTest, HandlesWithinConstantPositions)
826 static const char * const selections[] = {
827 "within 1 of [2, 1, 0]"
829 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
830 runTest("simple.gro", selections);
834 TEST_F(SelectionCollectionDataTest, HandlesForcedStringMatchingMode)
836 static const char * const selections[] = {
840 runTest("simple.gro", selections);
844 TEST_F(SelectionCollectionDataTest, HandlesWildcardMatching)
846 static const char * const selections[] = {
850 runTest("simple.gro", selections);
854 TEST_F(SelectionCollectionDataTest, HandlesRegexMatching)
856 static const char * const selections[] = {
858 "resname ~ \"R[BD]\""
860 if (gmx::Regex::isSupported())
862 runTest("simple.gro", selections);
867 TEST_F(SelectionCollectionDataTest, HandlesBasicBoolean)
869 static const char * const selections[] = {
870 "atomnr 1 to 5 and atomnr 2 to 7",
871 "atomnr 1 to 5 or not atomnr 3 to 8",
872 "not not atomnr 1 to 5 and atomnr 2 to 6 and not not atomnr 3 to 7",
873 "atomnr 1 to 5 and (atomnr 2 to 7 and atomnr 3 to 6)",
874 "x < 5 and atomnr 1 to 5 and y < 3 and atomnr 2 to 4"
876 runTest(10, selections);
880 TEST_F(SelectionCollectionDataTest, HandlesDynamicAtomValuedParameters)
882 static const char * const selections[] = {
883 "same residue as (atomnr 3 5 13 or y > 5)",
884 "(resnr 1 3 5 or x > 10) and same residue as (atomnr 3 5 13 or y > 5)"
886 setFlags(TestFlags() | efTestEvaluation);
887 runTest("simple.gro", selections);
891 TEST_F(SelectionCollectionDataTest, HandlesNumericComparisons)
893 static const char * const selections[] = {
900 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
901 runTest("simple.gro", selections);
905 TEST_F(SelectionCollectionDataTest, HandlesArithmeticExpressions)
907 static const char * const selections[] = {
913 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
914 runTest("simple.gro", selections);
918 TEST_F(SelectionCollectionDataTest, HandlesNumericVariables)
920 static const char * const selections[] = {
926 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
927 runTest("simple.gro", selections);
931 TEST_F(SelectionCollectionDataTest, HandlesComplexNumericVariables)
933 static const char * const selections[] = {
935 "resname RA and value <= 4",
936 "resname RA RB and x < 3 and value <= 4",
938 "resname RA and index < 3",
939 "resname RB and y < 3 and index < 6"
941 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
942 runTest("simple.gro", selections);
946 TEST_F(SelectionCollectionDataTest, HandlesPositionVariables)
948 static const char * const selections[] = {
949 "foo = res_cog of resname RA",
952 "bar = cog of resname RA",
956 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
957 runTest("simple.gro", selections);
961 TEST_F(SelectionCollectionDataTest, HandlesConstantPositionInVariable)
963 static const char * const selections[] = {
964 "constpos = [1.0, 2.5, 0.5]",
966 "within 2 of constpos"
968 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
969 | efTestPositionAtoms);
970 runTest("simple.gro", selections);
974 TEST_F(SelectionCollectionDataTest, HandlesNumericConstantsInVariables)
976 static const char * const selections[] = {
981 "x + constreal1 < constreal2"
983 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
984 runTest("simple.gro", selections);
988 /********************************************************************
989 * Tests for complex boolean syntax
992 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysis)
994 static const char * const selections[] = {
995 "atomnr 1 to 5 and atomnr 2 to 7 and x < 2",
996 "atomnr 1 to 5 and (atomnr 4 to 7 or x < 2)",
997 "atomnr 1 to 5 and y < 3 and (atomnr 4 to 7 or x < 2)",
998 "atomnr 1 to 5 and not (atomnr 4 to 7 or x < 2)",
999 "atomnr 1 to 5 or (atomnr 4 to 6 and (atomnr 5 to 7 or x < 2))"
1001 runTest(10, selections);
1005 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithVariables)
1007 static const char * const selections[] = {
1008 "foo = atomnr 4 to 7 or x < 2",
1009 "atomnr 1 to 4 and foo",
1010 "atomnr 2 to 6 and y < 3 and foo",
1011 "atomnr 6 to 10 and not foo"
1013 runTest(10, selections);
1017 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithMoreVariables)
1019 static const char * const selections[] = {
1020 "foo = atomnr 4 to 7",
1021 "bar = foo and x < 2",
1022 "bar2 = foo and y < 2",
1023 "atomnr 1 to 4 and bar",
1024 "atomnr 2 to 6 and y < 3 and bar2",
1025 "atomnr 6 to 10 and not foo"
1027 runTest(10, selections);
1031 /********************************************************************
1032 * Tests for complex subexpression cases
1034 * These tests use some knowledge of the implementation to trigger different
1035 * paths in the code.
1038 TEST_F(SelectionCollectionDataTest, HandlesUnusedVariables)
1040 static const char * const selections[] = {
1041 "unused1 = atomnr 1 to 3",
1042 "foo = atomnr 4 to 7",
1043 "atomnr 1 to 6 and foo",
1044 "unused2 = atomnr 3 to 5"
1046 runTest(10, selections);
1050 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithStaticEvaluationGroups)
1052 static const char * const selections[] = {
1053 "foo = atomnr 4 to 7 and x < 2",
1054 "atomnr 1 to 5 and foo",
1055 "atomnr 3 to 7 and foo"
1057 runTest(10, selections);
1061 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithMixedEvaluationGroups)
1063 static const char * const selections[] = {
1064 "foo = atomnr 4 to 7 and x < 2",
1065 "atomnr 1 to 6 and foo",
1069 runTest(10, selections);
1073 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithMixedEvaluationGroups2)
1075 static const char * const selections[] = {
1076 "foo = atomnr 1 to 8 and x < 10",
1077 "atomnr 1 to 5 and y < 10 and foo",
1080 setFlags(TestFlags() | efTestEvaluation);
1081 runTest("simple.gro", selections);