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 int s_debugLevel;
72 SelectionCollectionTest();
74 void setAtomCount(int natoms)
76 ASSERT_NO_THROW_GMX(sc_.setTopology(NULL, natoms));
78 void loadTopology(const char *filename);
81 gmx::test::TopologyManager topManager_;
82 gmx::SelectionCollection sc_;
83 gmx::SelectionList sel_;
88 int SelectionCollectionTest::s_debugLevel = 0;
90 GMX_TEST_OPTIONS(SelectionCollectionTestOptions, options)
92 options->addOption(gmx::IntegerOption("seldebug")
93 .store(&SelectionCollectionTest::s_debugLevel)
94 .description("Set selection debug level"));
97 SelectionCollectionTest::SelectionCollectionTest()
98 : top_(NULL), frame_(NULL)
100 topManager_.requestFrame();
101 sc_.setDebugLevel(s_debugLevel);
102 sc_.setReferencePosType("atom");
103 sc_.setOutputPosType("atom");
107 SelectionCollectionTest::loadTopology(const char *filename)
109 topManager_.loadTopology(filename);
114 SelectionCollectionTest::setTopology()
116 top_ = topManager_.topology();
117 frame_ = topManager_.frame();
119 ASSERT_NO_THROW_GMX(sc_.setTopology(top_, -1));
123 /********************************************************************
124 * Test fixture for selection testing with reference data
127 class SelectionCollectionDataTest : public SelectionCollectionTest
132 efTestEvaluation = 1<<0,
133 efTestPositionAtoms = 1<<1,
134 efTestPositionCoordinates = 1<<2,
135 efTestPositionMapping = 1<<3,
136 efTestPositionMasses = 1<<4,
137 efTestPositionCharges = 1<<5,
138 efDontTestCompiledAtoms = 1<<8
140 typedef gmx::FlagsTemplate<TestFlag> TestFlags;
142 SelectionCollectionDataTest()
143 : checker_(data_.rootChecker()), count_(0), framenr_(0)
147 void setFlags(TestFlags flags) { flags_ = flags; }
149 template <size_t count>
150 void runTest(int natoms, const char *const (&selections)[count])
152 runTest(natoms, selections, count);
154 template <size_t count>
155 void runTest(const char *filename, const char *const (&selections)[count])
157 runTest(filename, selections, count);
160 template <size_t count>
161 void runParser(const char *const (&selections)[count])
163 runParser(selections, count);
168 void runEvaluateFinal();
171 static void checkSelection(gmx::test::TestReferenceChecker *checker,
172 const gmx::Selection &sel, TestFlags flags);
174 void runTest(int natoms, const char *const *selections, size_t count);
175 void runTest(const char *filename, const char *const *selections,
177 void runParser(const char *const *selections, size_t count);
179 void checkCompiled();
181 gmx::test::TestReferenceData data_;
182 gmx::test::TestReferenceChecker checker_;
190 SelectionCollectionDataTest::checkSelection(
191 gmx::test::TestReferenceChecker *checker,
192 const gmx::Selection &sel, TestFlags flags)
194 using gmx::test::TestReferenceChecker;
197 gmx::ConstArrayRef<int> atoms = sel.atomIndices();
198 checker->checkSequence(atoms.begin(), atoms.end(), "Atoms");
200 if (flags.test(efTestPositionAtoms)
201 || flags.test(efTestPositionCoordinates)
202 || flags.test(efTestPositionMapping)
203 || flags.test(efTestPositionMasses)
204 || flags.test(efTestPositionCharges))
206 TestReferenceChecker compound(
207 checker->checkSequenceCompound("Positions", sel.posCount()));
208 for (int i = 0; i < sel.posCount(); ++i)
210 TestReferenceChecker poscompound(compound.checkCompound("Position", NULL));
211 const gmx::SelectionPosition &p = sel.position(i);
212 if (flags.test(efTestPositionAtoms))
214 gmx::ConstArrayRef<int> atoms = p.atomIndices();
215 poscompound.checkSequence(atoms.begin(), atoms.end(), "Atoms");
217 if (flags.test(efTestPositionCoordinates))
219 poscompound.checkVector(p.x(), "Coordinates");
221 if (flags.test(efTestPositionMapping))
223 poscompound.checkInteger(p.refId(), "RefId");
224 poscompound.checkInteger(p.mappedId(), "MappedId");
226 if (flags.test(efTestPositionMasses))
228 poscompound.checkReal(p.mass(), "Mass");
230 if (flags.test(efTestPositionCharges))
232 poscompound.checkReal(p.charge(), "Charge");
240 SelectionCollectionDataTest::runParser(const char *const *selections,
243 using gmx::test::TestReferenceChecker;
245 TestReferenceChecker compound(checker_.checkCompound("ParsedSelections", "Parsed"));
248 for (size_t i = 0; i < count; ++i)
250 SCOPED_TRACE(std::string("Parsing selection \"")
251 + selections[i] + "\"");
252 gmx::SelectionList result;
253 ASSERT_NO_THROW_GMX(result = sc_.parseFromString(selections[i]));
254 sel_.insert(sel_.end(), result.begin(), result.end());
255 if (sel_.size() == count_)
257 std::string id = gmx::formatString("Variable%d", static_cast<int>(varcount + 1));
258 TestReferenceChecker varcompound(
259 compound.checkCompound("ParsedVariable", id.c_str()));
260 varcompound.checkString(selections[i], "Input");
265 std::string id = gmx::formatString("Selection%d", static_cast<int>(count_ + 1));
266 TestReferenceChecker selcompound(
267 compound.checkCompound("ParsedSelection", id.c_str()));
268 selcompound.checkString(selections[i], "Input");
269 selcompound.checkString(sel_[count_].name(), "Name");
270 selcompound.checkString(sel_[count_].selectionText(), "Text");
271 selcompound.checkBoolean(sel_[count_].isDynamic(), "Dynamic");
279 SelectionCollectionDataTest::runCompiler()
281 ASSERT_NO_THROW_GMX(sc_.compile());
282 ASSERT_EQ(count_, sel_.size());
288 SelectionCollectionDataTest::checkCompiled()
290 using gmx::test::TestReferenceChecker;
291 const TestFlags mask = ~TestFlags(efTestPositionCoordinates);
293 TestReferenceChecker compound(checker_.checkCompound("CompiledSelections", "Compiled"));
294 for (size_t i = 0; i < count_; ++i)
296 SCOPED_TRACE(std::string("Checking selection \"") +
297 sel_[i].selectionText() + "\"");
298 std::string id = gmx::formatString("Selection%d", static_cast<int>(i + 1));
299 TestReferenceChecker selcompound(
300 compound.checkCompound("Selection", id.c_str()));
301 if (!flags_.test(efDontTestCompiledAtoms))
303 checkSelection(&selcompound, sel_[i], flags_ & mask);
310 SelectionCollectionDataTest::runEvaluate()
312 using gmx::test::TestReferenceChecker;
315 ASSERT_NO_THROW_GMX(sc_.evaluate(frame_, NULL));
316 std::string frame = gmx::formatString("Frame%d", framenr_);
317 TestReferenceChecker compound(
318 checker_.checkCompound("EvaluatedSelections", frame.c_str()));
319 for (size_t i = 0; i < count_; ++i)
321 SCOPED_TRACE(std::string("Checking selection \"") +
322 sel_[i].selectionText() + "\"");
323 std::string id = gmx::formatString("Selection%d", static_cast<int>(i + 1));
324 TestReferenceChecker selcompound(
325 compound.checkCompound("Selection", id.c_str()));
326 checkSelection(&selcompound, sel_[i], flags_);
332 SelectionCollectionDataTest::runEvaluateFinal()
334 ASSERT_NO_THROW_GMX(sc_.evaluateFinal(framenr_));
340 SelectionCollectionDataTest::runTest(int natoms, const char * const *selections,
343 ASSERT_NO_FATAL_FAILURE(runParser(selections, count));
344 ASSERT_NO_FATAL_FAILURE(setAtomCount(natoms));
345 ASSERT_NO_FATAL_FAILURE(runCompiler());
350 SelectionCollectionDataTest::runTest(const char *filename,
351 const char * const *selections,
354 ASSERT_NO_FATAL_FAILURE(runParser(selections, count));
355 ASSERT_NO_FATAL_FAILURE(loadTopology(filename));
356 ASSERT_NO_FATAL_FAILURE(runCompiler());
357 if (flags_.test(efTestEvaluation))
359 ASSERT_NO_FATAL_FAILURE(runEvaluate());
360 ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
365 /********************************************************************
366 * Tests for SelectionCollection functionality without reference data
369 TEST_F(SelectionCollectionTest, HandlesNoSelections)
371 EXPECT_FALSE(sc_.requiresTopology());
372 EXPECT_NO_THROW_GMX(sc_.compile());
375 TEST_F(SelectionCollectionTest, HandlesVelocityAndForceRequests)
377 ASSERT_NO_THROW_GMX(sel_ = sc_.parseFromString("atomnr 1 to 10; none"));
378 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
379 ASSERT_EQ(2U, sel_.size());
380 ASSERT_NO_THROW_GMX(sel_[0].setEvaluateVelocities(true));
381 ASSERT_NO_THROW_GMX(sel_[1].setEvaluateVelocities(true));
382 ASSERT_NO_THROW_GMX(sel_[0].setEvaluateForces(true));
383 ASSERT_NO_THROW_GMX(sel_[1].setEvaluateForces(true));
384 ASSERT_NO_THROW_GMX(sc_.compile());
385 EXPECT_TRUE(sel_[0].hasVelocities());
386 EXPECT_TRUE(sel_[1].hasVelocities());
387 EXPECT_TRUE(sel_[0].hasForces());
388 EXPECT_TRUE(sel_[1].hasForces());
391 TEST_F(SelectionCollectionTest, ParsesSelectionsFromFile)
393 ASSERT_NO_THROW_GMX(sel_ = sc_.parseFromFile(
394 gmx::test::TestFileManager::getInputFilePath("selfile.dat")));
395 // These should match the contents of selfile.dat
396 ASSERT_EQ(2U, sel_.size());
397 EXPECT_STREQ("resname RA RB", sel_[0].selectionText());
398 EXPECT_STREQ("resname RB RC", sel_[1].selectionText());
401 TEST_F(SelectionCollectionTest, HandlesInvalidRegularExpressions)
403 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
405 sc_.parseFromString("resname ~ \"R[A\"");
407 }, gmx::InvalidInputError);
410 TEST_F(SelectionCollectionTest, HandlesUnsupportedRegularExpressions)
412 if (!gmx::Regex::isSupported())
414 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
416 sc_.parseFromString("resname \"R[AD]\"");
418 }, gmx::InvalidInputError);
422 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue)
424 EXPECT_THROW_GMX(sc_.parseFromString("mindist from atomnr 1 cutoff"),
425 gmx::InvalidInputError);
428 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue2)
430 EXPECT_THROW_GMX(sc_.parseFromString("within 1 of"),
431 gmx::InvalidInputError);
434 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue3)
436 EXPECT_THROW_GMX(sc_.parseFromString("within of atomnr 1"),
437 gmx::InvalidInputError);
440 TEST_F(SelectionCollectionTest, HandlesHelpKeywordInInvalidContext)
442 EXPECT_THROW_GMX(sc_.parseFromString("resname help"),
443 gmx::InvalidInputError);
446 // TODO: Tests for more parser errors
448 TEST_F(SelectionCollectionTest, RecoversFromUnknownGroupReference)
450 ASSERT_NO_THROW_GMX(sc_.parseFromString("group \"foo\""));
451 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
452 EXPECT_THROW_GMX(sc_.setIndexGroups(NULL), gmx::InvalidInputError);
453 EXPECT_THROW_GMX(sc_.compile(), gmx::APIError);
456 TEST_F(SelectionCollectionTest, RecoversFromMissingMoleculeInfo)
458 ASSERT_NO_THROW_GMX(sc_.parseFromString("molindex 1 to 5"));
459 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
460 EXPECT_THROW_GMX(sc_.compile(), gmx::InconsistentInputError);
463 TEST_F(SelectionCollectionTest, RecoversFromMissingAtomTypes)
465 ASSERT_NO_THROW_GMX(sc_.parseFromString("type CA"));
466 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
467 EXPECT_THROW_GMX(sc_.compile(), gmx::InconsistentInputError);
470 TEST_F(SelectionCollectionTest, RecoversFromMissingPDBInfo)
472 ASSERT_NO_THROW_GMX(sc_.parseFromString("altloc A"));
473 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
474 EXPECT_THROW_GMX(sc_.compile(), gmx::InconsistentInputError);
477 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation)
479 ASSERT_NO_THROW_GMX(sc_.parseFromString("all permute 1 1"));
480 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
481 EXPECT_THROW_GMX(sc_.compile(), gmx::InvalidInputError);
484 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation2)
486 ASSERT_NO_THROW_GMX(sc_.parseFromString("all permute 3 2 1"));
487 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
488 EXPECT_THROW_GMX(sc_.compile(), gmx::InconsistentInputError);
491 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation3)
493 ASSERT_NO_THROW_GMX(sc_.parseFromString("x < 1.5 permute 3 2 1"));
494 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
495 ASSERT_NO_THROW_GMX(sc_.compile());
496 EXPECT_THROW_GMX(sc_.evaluate(frame_, NULL), gmx::InconsistentInputError);
499 // TODO: Tests for evaluation errors
502 /********************************************************************
503 * Tests for selection keywords
506 TEST_F(SelectionCollectionDataTest, HandlesAllNone)
508 static const char * const selections[] = {
512 runTest(10, selections);
515 TEST_F(SelectionCollectionDataTest, HandlesAtomnr)
517 static const char * const selections[] = {
518 "atomnr 1 to 3 6 to 8",
522 runTest(10, selections);
525 TEST_F(SelectionCollectionDataTest, HandlesResnr)
527 static const char * const selections[] = {
531 runTest("simple.gro", selections);
534 TEST_F(SelectionCollectionDataTest, HandlesResIndex)
536 static const char * const selections[] = {
540 runTest("simple.pdb", selections);
543 TEST_F(SelectionCollectionDataTest, HandlesMolIndex)
545 static const char * const selections[] = {
549 ASSERT_NO_FATAL_FAILURE(runParser(selections));
550 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
551 topManager_.initUniformMolecules(3);
552 ASSERT_NO_FATAL_FAILURE(runCompiler());
555 TEST_F(SelectionCollectionDataTest, HandlesAtomname)
557 static const char * const selections[] = {
561 runTest("simple.gro", selections);
564 TEST_F(SelectionCollectionDataTest, HandlesPdbAtomname)
566 static const char * const selections[] = {
572 runTest("simple.pdb", selections);
576 TEST_F(SelectionCollectionDataTest, HandlesAtomtype)
578 static const char * const selections[] = {
581 ASSERT_NO_FATAL_FAILURE(runParser(selections));
582 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
583 const char *const types[] = { "CA", "SA", "SB" };
584 topManager_.initAtomTypes(types);
585 ASSERT_NO_FATAL_FAILURE(runCompiler());
588 TEST_F(SelectionCollectionDataTest, HandlesChain)
590 static const char * const selections[] = {
594 runTest("simple.pdb", selections);
597 TEST_F(SelectionCollectionDataTest, HandlesMass)
599 static const char * const selections[] = {
602 ASSERT_NO_FATAL_FAILURE(runParser(selections));
603 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
604 for (int i = 0; i < top_->atoms.nr; ++i)
606 top_->atoms.atom[i].m = 1.0 + i;
608 ASSERT_NO_FATAL_FAILURE(runCompiler());
611 TEST_F(SelectionCollectionDataTest, HandlesCharge)
613 static const char * const selections[] = {
616 ASSERT_NO_FATAL_FAILURE(runParser(selections));
617 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
618 for (int i = 0; i < top_->atoms.nr; ++i)
620 top_->atoms.atom[i].q = i / 10.0;
622 ASSERT_NO_FATAL_FAILURE(runCompiler());
625 TEST_F(SelectionCollectionDataTest, HandlesAltLoc)
627 static const char * const selections[] = {
631 runTest("simple.pdb", selections);
634 TEST_F(SelectionCollectionDataTest, HandlesInsertCode)
636 static const char * const selections[] = {
640 runTest("simple.pdb", selections);
643 TEST_F(SelectionCollectionDataTest, HandlesOccupancy)
645 static const char * const selections[] = {
649 runTest("simple.pdb", selections);
652 TEST_F(SelectionCollectionDataTest, HandlesBeta)
654 static const char * const selections[] = {
658 runTest("simple.pdb", selections);
661 TEST_F(SelectionCollectionDataTest, HandlesResname)
663 static const char * const selections[] = {
667 runTest("simple.gro", selections);
670 TEST_F(SelectionCollectionDataTest, HandlesCoordinateKeywords)
672 static const char * const selections[] = {
677 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
678 runTest("simple.gro", selections);
682 TEST_F(SelectionCollectionDataTest, HandlesSameResidue)
684 static const char * const selections[] = {
685 "same residue as atomnr 1 4 12"
687 runTest("simple.gro", selections);
691 TEST_F(SelectionCollectionDataTest, HandlesSameResidueName)
693 static const char * const selections[] = {
694 "same resname as atomnr 1 14"
696 runTest("simple.gro", selections);
700 TEST_F(SelectionCollectionDataTest, HandlesPositionKeywords)
702 static const char * const selections[] = {
704 "res_cog of name CB and resnr 1 3",
705 "whole_res_cog of name CB and resnr 1 3",
706 "part_res_cog of x < 3",
707 "dyn_res_cog of x < 3"
709 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
710 | efTestPositionAtoms);
711 runTest("simple.gro", selections);
715 TEST_F(SelectionCollectionDataTest, HandlesDistanceKeyword)
717 static const char * const selections[] = {
718 "distance from cog of resnr 1 < 2"
720 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
721 runTest("simple.gro", selections);
725 TEST_F(SelectionCollectionDataTest, HandlesMinDistanceKeyword)
727 static const char * const selections[] = {
728 "mindistance from resnr 1 < 2"
730 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
731 runTest("simple.gro", selections);
735 TEST_F(SelectionCollectionDataTest, HandlesWithinKeyword)
737 static const char * const selections[] = {
738 "within 1 of resnr 2"
740 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
741 runTest("simple.gro", selections);
745 TEST_F(SelectionCollectionDataTest, HandlesInSolidAngleKeyword)
747 // Both of these should evaluate to empty on a correct implementation.
748 static const char * const selections[] = {
749 "resname TP and not insolidangle center cog of resname C span resname R cutoff 20",
750 "resname TN and insolidangle center cog of resname C span resname R cutoff 20"
752 setFlags(TestFlags() | efDontTestCompiledAtoms | efTestEvaluation);
753 runTest("sphere.gro", selections);
757 TEST_F(SelectionCollectionDataTest, HandlesPermuteModifier)
759 static const char * const selections[] = {
761 "res_cog of resnr 1 to 4 permute 2 1",
762 "name CB S1 and res_cog x < 3 permute 2 1"
764 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
765 | efTestPositionAtoms | efTestPositionMapping);
766 runTest("simple.gro", selections);
770 TEST_F(SelectionCollectionDataTest, HandlesPlusModifier)
772 static const char * const selections[] = {
773 "name S2 plus name S1",
774 "res_cog of resnr 2 plus res_cog of resnr 1 plus res_cog of resnr 3",
775 "name S1 and y < 3 plus res_cog of x < 2.5"
777 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
778 | efTestPositionAtoms | efTestPositionMapping);
779 runTest("simple.gro", selections);
783 TEST_F(SelectionCollectionDataTest, HandlesMergeModifier)
785 static const char * const selections[] = {
786 "name S2 merge name S1",
787 "resnr 1 2 and name S2 merge resnr 1 2 and name S1 merge res_cog of resnr 1 2",
788 "name S1 and x < 2.5 merge res_cog of x < 2.5"
790 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
791 | efTestPositionAtoms | efTestPositionMapping);
792 runTest("simple.gro", selections);
796 /********************************************************************
797 * Tests for generic selection evaluation
800 TEST_F(SelectionCollectionDataTest, ComputesMassesAndCharges)
802 static const char * const selections[] = {
807 setFlags(TestFlags() | efTestEvaluation | efTestPositionAtoms
808 | efTestPositionMasses | efTestPositionCharges);
809 ASSERT_NO_FATAL_FAILURE(runParser(selections));
810 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
811 for (int i = 0; i < top_->atoms.nr; ++i)
813 top_->atoms.atom[i].m = 1.0 + i / 100.0;
814 top_->atoms.atom[i].q = -(1.0 + i / 100.0);
816 ASSERT_NO_FATAL_FAILURE(runCompiler());
817 ASSERT_NO_FATAL_FAILURE(runEvaluate());
818 ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
821 TEST_F(SelectionCollectionDataTest, ComputesMassesAndChargesWithoutTopology)
823 static const char * const selections[] = {
824 "atomnr 1 to 3 8 to 9",
828 setFlags(TestFlags() | efTestPositionAtoms
829 | efTestPositionMasses | efTestPositionCharges);
830 runTest(10, selections);
834 /********************************************************************
835 * Tests for selection syntactic constructs
838 TEST_F(SelectionCollectionDataTest, HandlesConstantPositions)
840 static const char * const selections[] = {
843 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
844 runTest("simple.gro", selections);
848 TEST_F(SelectionCollectionDataTest, HandlesWithinConstantPositions)
850 static const char * const selections[] = {
851 "within 1 of [2, 1, 0]"
853 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
854 runTest("simple.gro", selections);
858 TEST_F(SelectionCollectionDataTest, HandlesForcedStringMatchingMode)
860 static const char * const selections[] = {
864 runTest("simple.gro", selections);
868 TEST_F(SelectionCollectionDataTest, HandlesWildcardMatching)
870 static const char * const selections[] = {
874 runTest("simple.gro", selections);
878 TEST_F(SelectionCollectionDataTest, HandlesRegexMatching)
880 static const char * const selections[] = {
882 "resname ~ \"R[BD]\""
884 if (gmx::Regex::isSupported())
886 runTest("simple.gro", selections);
891 TEST_F(SelectionCollectionDataTest, HandlesBasicBoolean)
893 static const char * const selections[] = {
894 "atomnr 1 to 5 and atomnr 2 to 7",
895 "atomnr 1 to 5 or not atomnr 3 to 8",
896 "not not atomnr 1 to 5 and atomnr 2 to 6 and not not atomnr 3 to 7",
897 "atomnr 1 to 5 and (atomnr 2 to 7 and atomnr 3 to 6)",
898 "x < 5 and atomnr 1 to 5 and y < 3 and atomnr 2 to 4"
900 runTest(10, selections);
904 TEST_F(SelectionCollectionDataTest, HandlesDynamicAtomValuedParameters)
906 static const char * const selections[] = {
907 "same residue as (atomnr 3 5 13 or y > 5)",
908 "(resnr 1 3 5 or x > 10) and same residue as (atomnr 3 5 13 or z > 5)"
910 setFlags(TestFlags() | efTestEvaluation);
911 runTest("simple.gro", selections);
915 TEST_F(SelectionCollectionDataTest, HandlesNumericComparisons)
917 static const char * const selections[] = {
924 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
925 runTest("simple.gro", selections);
929 TEST_F(SelectionCollectionDataTest, HandlesArithmeticExpressions)
931 static const char * const selections[] = {
937 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
938 runTest("simple.gro", selections);
942 TEST_F(SelectionCollectionDataTest, HandlesNumericVariables)
944 static const char * const selections[] = {
950 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
951 runTest("simple.gro", selections);
955 TEST_F(SelectionCollectionDataTest, HandlesComplexNumericVariables)
957 static const char * const selections[] = {
959 "resname RA and value <= 4",
960 "resname RA RB and x < 3 and value <= 4",
962 "resname RA and index < 3",
963 "resname RB and y < 3 and index < 6"
965 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
966 runTest("simple.gro", selections);
970 TEST_F(SelectionCollectionDataTest, HandlesPositionVariables)
972 static const char * const selections[] = {
973 "foo = res_cog of resname RA",
976 "bar = cog of resname RA",
980 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
981 runTest("simple.gro", selections);
985 TEST_F(SelectionCollectionDataTest, HandlesConstantPositionInVariable)
987 static const char * const selections[] = {
988 "constpos = [1.0, 2.5, 0.5]",
990 "within 2 of constpos"
992 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
993 | efTestPositionAtoms);
994 runTest("simple.gro", selections);
998 TEST_F(SelectionCollectionDataTest, HandlesNumericConstantsInVariables)
1000 static const char * const selections[] = {
1005 "x + constreal1 < constreal2"
1007 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
1008 runTest("simple.gro", selections);
1012 /********************************************************************
1013 * Tests for complex boolean syntax
1016 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysis)
1018 static const char * const selections[] = {
1019 "atomnr 1 to 5 and atomnr 2 to 7 and x < 2",
1020 "atomnr 1 to 5 and (atomnr 4 to 7 or x < 2)",
1021 "atomnr 1 to 5 and y < 3 and (atomnr 4 to 7 or x < 2)",
1022 "atomnr 1 to 5 and not (atomnr 4 to 7 or x < 2)",
1023 "atomnr 1 to 5 or (atomnr 4 to 6 and (atomnr 5 to 7 or x < 2))"
1025 runTest(10, selections);
1029 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithVariables)
1031 static const char * const selections[] = {
1032 "foo = atomnr 4 to 7 or x < 2",
1033 "atomnr 1 to 4 and foo",
1034 "atomnr 2 to 6 and y < 3 and foo",
1035 "atomnr 6 to 10 and not foo"
1037 runTest(10, selections);
1041 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithMoreVariables)
1043 static const char * const selections[] = {
1044 "foo = atomnr 4 to 7",
1045 "bar = foo and x < 2",
1046 "bar2 = foo and y < 2",
1047 "atomnr 1 to 4 and bar",
1048 "atomnr 2 to 6 and y < 3 and bar2",
1049 "atomnr 6 to 10 and not foo"
1051 runTest(10, selections);
1055 /********************************************************************
1056 * Tests for complex subexpression cases
1058 * These tests use some knowledge of the implementation to trigger different
1059 * paths in the code.
1062 TEST_F(SelectionCollectionDataTest, HandlesUnusedVariables)
1064 static const char * const selections[] = {
1065 "unused1 = atomnr 1 to 3",
1066 "foo = atomnr 4 to 7",
1067 "atomnr 1 to 6 and foo",
1068 "unused2 = atomnr 3 to 5"
1070 runTest(10, selections);
1074 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithStaticEvaluationGroups)
1076 static const char * const selections[] = {
1077 "foo = atomnr 4 to 7 and x < 2",
1078 "atomnr 1 to 5 and foo",
1079 "atomnr 3 to 7 and foo"
1081 runTest(10, selections);
1085 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithMixedEvaluationGroups)
1087 static const char * const selections[] = {
1088 "foo = atomnr 4 to 7 and x < 2",
1089 "atomnr 1 to 6 and foo",
1093 runTest(10, selections);
1097 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithMixedEvaluationGroups2)
1099 static const char * const selections[] = {
1100 "foo = atomnr 1 to 8 and x < 10",
1101 "atomnr 1 to 5 and y < 10 and foo",
1104 setFlags(TestFlags() | efTestEvaluation);
1105 runTest("simple.gro", selections);