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/legacyheaders/smalloc.h"
45 #include "gromacs/legacyheaders/statutil.h"
46 #include "gromacs/legacyheaders/tpxio.h"
47 #include "gromacs/legacyheaders/vec.h"
49 #include "gromacs/options/basicoptions.h"
50 #include "gromacs/options/options.h"
51 #include "gromacs/selection/selectioncollection.h"
52 #include "gromacs/selection/selection.h"
53 #include "gromacs/utility/exceptions.h"
54 #include "gromacs/utility/flags.h"
55 #include "gromacs/utility/gmxregex.h"
56 #include "gromacs/utility/stringutil.h"
58 #include "testutils/refdata.h"
59 #include "testutils/testfilemanager.h"
60 #include "testutils/testoptions.h"
65 /********************************************************************
66 * Test fixture for selection testing
69 class SelectionCollectionTest : public ::testing::Test
72 static void SetUpTestCase();
74 static int s_debugLevel;
76 SelectionCollectionTest();
77 ~SelectionCollectionTest();
79 void setAtomCount(int natoms)
81 ASSERT_NO_THROW(sc_.setTopology(NULL, natoms));
83 void loadTopology(const char *filename);
85 gmx::SelectionCollection sc_;
86 gmx::SelectionList sel_;
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);
101 SelectionCollectionTest::SelectionCollectionTest()
102 : top_(NULL), frame_(NULL)
104 sc_.setDebugLevel(s_debugLevel);
105 sc_.setReferencePosType("atom");
106 sc_.setOutputPosType("atom");
110 SelectionCollectionTest::~SelectionCollectionTest()
114 free_t_atoms(&top_->atoms, TRUE);
128 SelectionCollectionTest::loadTopology(const char *filename)
136 read_tps_conf(gmx::test::TestFileManager::getInputFilePath(filename).c_str(),
137 title, top_, &ePBC, &xtop, NULL, box, FALSE);
140 frame_->flags = TRX_NEED_X;
141 frame_->natoms = top_->atoms.nr;
143 snew(frame_->x, frame_->natoms);
144 memcpy(frame_->x, xtop, sizeof(*frame_->x) * frame_->natoms);
146 copy_mat(box, frame_->box);
150 ASSERT_NO_THROW(sc_.setTopology(top_, -1));
154 /********************************************************************
155 * Test fixture for selection testing with reference data
158 class SelectionCollectionDataTest : public SelectionCollectionTest
163 efTestEvaluation = 1<<0,
164 efTestPositionAtoms = 1<<1,
165 efTestPositionCoordinates = 1<<2,
166 efTestPositionMapping = 1<<3,
167 efTestPositionMasses = 1<<4,
168 efTestPositionCharges = 1<<5,
169 efDontTestCompiledAtoms = 1<<8
171 typedef gmx::FlagsTemplate<TestFlag> TestFlags;
173 SelectionCollectionDataTest()
174 : checker_(data_.rootChecker()), count_(0), framenr_(0)
178 void setFlags(TestFlags flags) { flags_ = flags; }
180 template <size_t count>
181 void runTest(int natoms, const char *const (&selections)[count])
183 runTest(natoms, selections, count);
185 template <size_t count>
186 void runTest(const char *filename, const char *const (&selections)[count])
188 runTest(filename, selections, count);
191 template <size_t count>
192 void runParser(const char *const (&selections)[count])
194 runParser(selections, count);
199 void runEvaluateFinal();
202 static void checkSelection(gmx::test::TestReferenceChecker *checker,
203 const gmx::Selection &sel, TestFlags flags);
205 void runTest(int natoms, const char *const *selections, size_t count);
206 void runTest(const char *filename, const char *const *selections,
208 void runParser(const char *const *selections, size_t count);
210 void checkCompiled();
212 gmx::test::TestReferenceData data_;
213 gmx::test::TestReferenceChecker checker_;
221 SelectionCollectionDataTest::checkSelection(
222 gmx::test::TestReferenceChecker *checker,
223 const gmx::Selection &sel, TestFlags flags)
225 using gmx::test::TestReferenceChecker;
228 gmx::ConstArrayRef<int> atoms = sel.atomIndices();
229 checker->checkSequence(atoms.begin(), atoms.end(), "Atoms");
231 if (flags.test(efTestPositionAtoms)
232 || flags.test(efTestPositionCoordinates)
233 || flags.test(efTestPositionMapping)
234 || flags.test(efTestPositionMasses)
235 || flags.test(efTestPositionCharges))
237 TestReferenceChecker compound(
238 checker->checkSequenceCompound("Positions", sel.posCount()));
239 for (int i = 0; i < sel.posCount(); ++i)
241 TestReferenceChecker poscompound(compound.checkCompound("Position", NULL));
242 const gmx::SelectionPosition &p = sel.position(i);
243 if (flags.test(efTestPositionAtoms))
245 gmx::ConstArrayRef<int> atoms = p.atomIndices();
246 poscompound.checkSequence(atoms.begin(), atoms.end(), "Atoms");
248 if (flags.test(efTestPositionCoordinates))
250 poscompound.checkVector(p.x(), "Coordinates");
252 if (flags.test(efTestPositionMapping))
254 poscompound.checkInteger(p.refId(), "RefId");
255 poscompound.checkInteger(p.mappedId(), "MappedId");
257 if (flags.test(efTestPositionMasses))
259 poscompound.checkReal(p.mass(), "Mass");
261 if (flags.test(efTestPositionCharges))
263 poscompound.checkReal(p.charge(), "Charge");
271 SelectionCollectionDataTest::runParser(const char *const *selections,
274 using gmx::test::TestReferenceChecker;
276 TestReferenceChecker compound(checker_.checkCompound("ParsedSelections", "Parsed"));
279 for (size_t i = 0; i < count; ++i)
281 SCOPED_TRACE(std::string("Parsing selection \"")
282 + selections[i] + "\"");
283 gmx::SelectionList result;
284 ASSERT_NO_THROW(result = sc_.parseFromString(selections[i]));
285 sel_.insert(sel_.end(), result.begin(), result.end());
286 if (sel_.size() == count_)
288 std::string id = gmx::formatString("Variable%d", static_cast<int>(varcount + 1));
289 TestReferenceChecker varcompound(
290 compound.checkCompound("ParsedVariable", id.c_str()));
291 varcompound.checkString(selections[i], "Input");
296 std::string id = gmx::formatString("Selection%d", static_cast<int>(count_ + 1));
297 TestReferenceChecker selcompound(
298 compound.checkCompound("ParsedSelection", id.c_str()));
299 selcompound.checkString(selections[i], "Input");
300 selcompound.checkString(sel_[count_].name(), "Name");
301 selcompound.checkString(sel_[count_].selectionText(), "Text");
302 selcompound.checkBoolean(sel_[count_].isDynamic(), "Dynamic");
310 SelectionCollectionDataTest::runCompiler()
312 ASSERT_NO_THROW(sc_.compile());
313 ASSERT_EQ(count_, sel_.size());
319 SelectionCollectionDataTest::checkCompiled()
321 using gmx::test::TestReferenceChecker;
322 const TestFlags mask = ~TestFlags(efTestPositionCoordinates);
324 TestReferenceChecker compound(checker_.checkCompound("CompiledSelections", "Compiled"));
325 for (size_t i = 0; i < count_; ++i)
327 SCOPED_TRACE(std::string("Checking selection \"") +
328 sel_[i].selectionText() + "\"");
329 std::string id = gmx::formatString("Selection%d", static_cast<int>(i + 1));
330 TestReferenceChecker selcompound(
331 compound.checkCompound("Selection", id.c_str()));
332 if (!flags_.test(efDontTestCompiledAtoms))
334 checkSelection(&selcompound, sel_[i], flags_ & mask);
341 SelectionCollectionDataTest::runEvaluate()
343 using gmx::test::TestReferenceChecker;
346 ASSERT_NO_THROW(sc_.evaluate(frame_, NULL));
347 std::string frame = gmx::formatString("Frame%d", framenr_);
348 TestReferenceChecker compound(
349 checker_.checkCompound("EvaluatedSelections", frame.c_str()));
350 for (size_t i = 0; i < count_; ++i)
352 SCOPED_TRACE(std::string("Checking selection \"") +
353 sel_[i].selectionText() + "\"");
354 std::string id = gmx::formatString("Selection%d", static_cast<int>(i + 1));
355 TestReferenceChecker selcompound(
356 compound.checkCompound("Selection", id.c_str()));
357 checkSelection(&selcompound, sel_[i], flags_);
363 SelectionCollectionDataTest::runEvaluateFinal()
365 ASSERT_NO_THROW(sc_.evaluateFinal(framenr_));
366 if (!checker_.isWriteMode())
374 SelectionCollectionDataTest::runTest(int natoms, const char * const *selections,
377 ASSERT_NO_FATAL_FAILURE(runParser(selections, count));
378 ASSERT_NO_FATAL_FAILURE(setAtomCount(natoms));
379 ASSERT_NO_FATAL_FAILURE(runCompiler());
384 SelectionCollectionDataTest::runTest(const char *filename,
385 const char * const *selections,
388 ASSERT_NO_FATAL_FAILURE(runParser(selections, count));
389 ASSERT_NO_FATAL_FAILURE(loadTopology(filename));
390 ASSERT_NO_FATAL_FAILURE(runCompiler());
391 if (flags_.test(efTestEvaluation))
393 ASSERT_NO_FATAL_FAILURE(runEvaluate());
394 ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
399 /********************************************************************
400 * Tests for SelectionCollection functionality without reference data
403 TEST_F(SelectionCollectionTest, HandlesNoSelections)
405 EXPECT_FALSE(sc_.requiresTopology());
406 EXPECT_NO_THROW(sc_.compile());
409 TEST_F(SelectionCollectionTest, HandlesVelocityAndForceRequests)
411 ASSERT_NO_THROW(sel_ = sc_.parseFromString("atomnr 1 to 10; none"));
412 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
413 ASSERT_EQ(2U, sel_.size());
414 ASSERT_NO_THROW(sel_[0].setEvaluateVelocities(true));
415 ASSERT_NO_THROW(sel_[1].setEvaluateVelocities(true));
416 ASSERT_NO_THROW(sel_[0].setEvaluateForces(true));
417 ASSERT_NO_THROW(sel_[1].setEvaluateForces(true));
418 ASSERT_NO_THROW(sc_.compile());
419 EXPECT_TRUE(sel_[0].hasVelocities());
420 EXPECT_TRUE(sel_[1].hasVelocities());
421 EXPECT_TRUE(sel_[0].hasForces());
422 EXPECT_TRUE(sel_[1].hasForces());
425 TEST_F(SelectionCollectionTest, ParsesSelectionsFromFile)
427 ASSERT_NO_THROW(sel_ = sc_.parseFromFile(
428 gmx::test::TestFileManager::getInputFilePath("selfile.dat")));
429 // These should match the contents of selfile.dat
430 ASSERT_EQ(2U, sel_.size());
431 EXPECT_STREQ("resname RA RB", sel_[0].selectionText());
432 EXPECT_STREQ("resname RB RC", sel_[1].selectionText());
435 TEST_F(SelectionCollectionTest, HandlesInvalidRegularExpressions)
437 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
439 sc_.parseFromString("resname ~ \"R[A\"");
441 }, gmx::InvalidInputError);
444 TEST_F(SelectionCollectionTest, HandlesUnsupportedRegularExpressions)
446 if (!gmx::Regex::isSupported())
448 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
450 sc_.parseFromString("resname \"R[AD]\"");
452 }, gmx::InvalidInputError);
456 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue)
458 EXPECT_THROW(sc_.parseFromString("mindist from atomnr 1 cutoff"),
459 gmx::InvalidInputError);
462 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue2)
464 EXPECT_THROW(sc_.parseFromString("within 1 of"),
465 gmx::InvalidInputError);
468 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue3)
470 EXPECT_THROW(sc_.parseFromString("within of atomnr 1"),
471 gmx::InvalidInputError);
474 TEST_F(SelectionCollectionTest, HandlesHelpKeywordInInvalidContext)
476 EXPECT_THROW(sc_.parseFromString("resname help"),
477 gmx::InvalidInputError);
480 // TODO: Tests for more parser errors
482 TEST_F(SelectionCollectionTest, RecoversFromUnknownGroupReference)
484 ASSERT_NO_THROW(sc_.parseFromString("group \"foo\""));
485 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
486 EXPECT_THROW(sc_.setIndexGroups(NULL), gmx::InvalidInputError);
487 EXPECT_THROW(sc_.compile(), gmx::APIError);
490 TEST_F(SelectionCollectionTest, RecoversFromMissingMoleculeInfo)
492 ASSERT_NO_THROW(sc_.parseFromString("molindex 1 to 5"));
493 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
494 EXPECT_THROW(sc_.compile(), gmx::InconsistentInputError);
497 TEST_F(SelectionCollectionTest, RecoversFromMissingAtomTypes)
499 ASSERT_NO_THROW(sc_.parseFromString("type CA"));
500 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
501 EXPECT_THROW(sc_.compile(), gmx::InconsistentInputError);
504 TEST_F(SelectionCollectionTest, RecoversFromMissingPDBInfo)
506 ASSERT_NO_THROW(sc_.parseFromString("altloc A"));
507 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
508 EXPECT_THROW(sc_.compile(), gmx::InconsistentInputError);
511 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation)
513 ASSERT_NO_THROW(sc_.parseFromString("all permute 1 1"));
514 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
515 EXPECT_THROW(sc_.compile(), gmx::InvalidInputError);
518 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation2)
520 ASSERT_NO_THROW(sc_.parseFromString("all permute 3 2 1"));
521 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
522 EXPECT_THROW(sc_.compile(), gmx::InconsistentInputError);
525 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation3)
527 ASSERT_NO_THROW(sc_.parseFromString("x < 1.5 permute 3 2 1"));
528 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
529 ASSERT_NO_THROW(sc_.compile());
530 EXPECT_THROW(sc_.evaluate(frame_, NULL), gmx::InconsistentInputError);
533 // TODO: Tests for evaluation errors
536 /********************************************************************
537 * Tests for selection keywords
540 TEST_F(SelectionCollectionDataTest, HandlesAllNone)
542 static const char * const selections[] = {
546 runTest(10, selections);
549 TEST_F(SelectionCollectionDataTest, HandlesAtomnr)
551 static const char * const selections[] = {
552 "atomnr 1 to 3 6 to 8",
556 runTest(10, selections);
559 TEST_F(SelectionCollectionDataTest, HandlesResnr)
561 static const char * const selections[] = {
565 runTest("simple.gro", selections);
568 TEST_F(SelectionCollectionDataTest, HandlesResIndex)
570 static const char * const selections[] = {
574 runTest("simple.pdb", selections);
577 // TODO: Add test for "molindex"
579 TEST_F(SelectionCollectionDataTest, HandlesAtomname)
581 static const char * const selections[] = {
585 runTest("simple.gro", selections);
588 TEST_F(SelectionCollectionDataTest, HandlesPdbAtomname)
590 static const char * const selections[] = {
596 runTest("simple.pdb", selections);
599 // TODO: Add test for atomtype
601 TEST_F(SelectionCollectionDataTest, HandlesChain)
603 static const char * const selections[] = {
607 runTest("simple.pdb", selections);
610 TEST_F(SelectionCollectionDataTest, HandlesMass)
612 static const char * const selections[] = {
615 ASSERT_NO_FATAL_FAILURE(runParser(selections));
616 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
617 for (int i = 0; i < top_->atoms.nr; ++i)
619 top_->atoms.atom[i].m = 1.0 + i;
621 ASSERT_NO_FATAL_FAILURE(runCompiler());
624 TEST_F(SelectionCollectionDataTest, HandlesCharge)
626 static const char * const selections[] = {
629 ASSERT_NO_FATAL_FAILURE(runParser(selections));
630 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
631 for (int i = 0; i < top_->atoms.nr; ++i)
633 top_->atoms.atom[i].q = i / 10.0;
635 ASSERT_NO_FATAL_FAILURE(runCompiler());
638 TEST_F(SelectionCollectionDataTest, HandlesAltLoc)
640 static const char * const selections[] = {
644 runTest("simple.pdb", selections);
647 TEST_F(SelectionCollectionDataTest, HandlesInsertCode)
649 static const char * const selections[] = {
653 runTest("simple.pdb", selections);
656 TEST_F(SelectionCollectionDataTest, HandlesOccupancy)
658 static const char * const selections[] = {
662 runTest("simple.pdb", selections);
665 TEST_F(SelectionCollectionDataTest, HandlesBeta)
667 static const char * const selections[] = {
671 runTest("simple.pdb", selections);
674 TEST_F(SelectionCollectionDataTest, HandlesResname)
676 static const char * const selections[] = {
680 runTest("simple.gro", selections);
683 TEST_F(SelectionCollectionDataTest, HandlesCoordinateKeywords)
685 static const char * const selections[] = {
690 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
691 runTest("simple.gro", selections);
695 TEST_F(SelectionCollectionDataTest, HandlesSameResidue)
697 static const char * const selections[] = {
698 "same residue as atomnr 1 4 12"
700 runTest("simple.gro", selections);
704 TEST_F(SelectionCollectionDataTest, HandlesSameResidueName)
706 static const char * const selections[] = {
707 "same resname as atomnr 1 14"
709 runTest("simple.gro", selections);
713 TEST_F(SelectionCollectionDataTest, HandlesPositionKeywords)
715 static const char * const selections[] = {
717 "res_cog of name CB and resnr 1 3",
718 "whole_res_cog of name CB and resnr 1 3",
719 "part_res_cog of x < 3",
720 "dyn_res_cog of x < 3"
722 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
723 | efTestPositionAtoms);
724 runTest("simple.gro", selections);
728 TEST_F(SelectionCollectionDataTest, HandlesDistanceKeyword)
730 static const char * const selections[] = {
731 "distance from cog of resnr 1 < 2"
733 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
734 runTest("simple.gro", selections);
738 TEST_F(SelectionCollectionDataTest, HandlesMinDistanceKeyword)
740 static const char * const selections[] = {
741 "mindistance from resnr 1 < 2"
743 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
744 runTest("simple.gro", selections);
748 TEST_F(SelectionCollectionDataTest, HandlesWithinKeyword)
750 static const char * const selections[] = {
751 "within 1 of resnr 2"
753 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
754 runTest("simple.gro", selections);
758 TEST_F(SelectionCollectionDataTest, HandlesInSolidAngleKeyword)
760 // Both of these should evaluate to empty on a correct implementation.
761 static const char * const selections[] = {
762 "resname TP and not insolidangle center cog of resname C span resname R cutoff 20",
763 "resname TN and insolidangle center cog of resname C span resname R cutoff 20"
765 setFlags(TestFlags() | efDontTestCompiledAtoms | efTestEvaluation);
766 runTest("sphere.gro", selections);
770 TEST_F(SelectionCollectionDataTest, HandlesPermuteModifier)
772 static const char * const selections[] = {
774 "res_cog of resnr 1 to 4 permute 2 1",
775 "name CB S1 and res_cog x < 3 permute 2 1"
777 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
778 | efTestPositionAtoms | efTestPositionMapping);
779 runTest("simple.gro", selections);
783 TEST_F(SelectionCollectionDataTest, HandlesPlusModifier)
785 static const char * const selections[] = {
786 "name S2 plus name S1",
787 "res_cog of resnr 2 plus res_cog of resnr 1 plus res_cog of resnr 3",
788 "name S1 and y < 3 plus res_cog of x < 2.5"
790 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
791 | efTestPositionAtoms | efTestPositionMapping);
792 runTest("simple.gro", selections);
796 TEST_F(SelectionCollectionDataTest, HandlesMergeModifier)
798 static const char * const selections[] = {
799 "name S2 merge name S1",
800 "resnr 1 2 and name S2 merge resnr 1 2 and name S1 merge res_cog of resnr 1 2",
801 "name S1 and x < 2.5 merge res_cog of x < 2.5"
803 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
804 | efTestPositionAtoms | efTestPositionMapping);
805 runTest("simple.gro", selections);
809 /********************************************************************
810 * Tests for generic selection evaluation
813 TEST_F(SelectionCollectionDataTest, ComputesMassesAndCharges)
815 static const char * const selections[] = {
820 setFlags(TestFlags() | efTestEvaluation | efTestPositionAtoms
821 | efTestPositionMasses | efTestPositionCharges);
822 ASSERT_NO_FATAL_FAILURE(runParser(selections));
823 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
824 for (int i = 0; i < top_->atoms.nr; ++i)
826 top_->atoms.atom[i].m = 1.0 + i / 100.0;
827 top_->atoms.atom[i].q = -(1.0 + i / 100.0);
829 ASSERT_NO_FATAL_FAILURE(runCompiler());
830 ASSERT_NO_FATAL_FAILURE(runEvaluate());
831 ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
834 TEST_F(SelectionCollectionDataTest, ComputesMassesAndChargesWithoutTopology)
836 static const char * const selections[] = {
837 "atomnr 1 to 3 8 to 9",
841 setFlags(TestFlags() | efTestPositionAtoms
842 | efTestPositionMasses | efTestPositionCharges);
843 runTest(10, selections);
847 /********************************************************************
848 * Tests for selection syntactic constructs
851 TEST_F(SelectionCollectionDataTest, HandlesConstantPositions)
853 static const char * const selections[] = {
856 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
857 runTest("simple.gro", selections);
861 TEST_F(SelectionCollectionDataTest, HandlesWithinConstantPositions)
863 static const char * const selections[] = {
864 "within 1 of [2, 1, 0]"
866 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
867 runTest("simple.gro", selections);
871 TEST_F(SelectionCollectionDataTest, HandlesForcedStringMatchingMode)
873 static const char * const selections[] = {
877 runTest("simple.gro", selections);
881 TEST_F(SelectionCollectionDataTest, HandlesWildcardMatching)
883 static const char * const selections[] = {
887 runTest("simple.gro", selections);
891 TEST_F(SelectionCollectionDataTest, HandlesRegexMatching)
893 static const char * const selections[] = {
895 "resname ~ \"R[BD]\""
897 if (gmx::Regex::isSupported())
899 runTest("simple.gro", selections);
904 TEST_F(SelectionCollectionDataTest, HandlesBasicBoolean)
906 static const char * const selections[] = {
907 "atomnr 1 to 5 and atomnr 2 to 7",
908 "atomnr 1 to 5 or not atomnr 3 to 8",
909 "not not atomnr 1 to 5 and atomnr 2 to 6 and not not atomnr 3 to 7",
910 "atomnr 1 to 5 and (atomnr 2 to 7 and atomnr 3 to 6)",
911 "x < 5 and atomnr 1 to 5 and y < 3 and atomnr 2 to 4"
913 runTest(10, selections);
917 TEST_F(SelectionCollectionDataTest, HandlesNumericComparisons)
919 static const char * const selections[] = {
926 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
927 runTest("simple.gro", selections);
931 TEST_F(SelectionCollectionDataTest, HandlesArithmeticExpressions)
933 static const char * const selections[] = {
939 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
940 runTest("simple.gro", selections);
944 TEST_F(SelectionCollectionDataTest, HandlesNumericVariables)
946 static const char * const selections[] = {
952 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
953 runTest("simple.gro", selections);
957 TEST_F(SelectionCollectionDataTest, HandlesComplexNumericVariables)
959 static const char * const selections[] = {
961 "resname RA and value <= 4",
962 "resname RA RB and x < 3 and value <= 4",
964 "resname RA and index < 3",
965 "resname RB and y < 3 and index < 6"
967 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
968 runTest("simple.gro", selections);
972 TEST_F(SelectionCollectionDataTest, HandlesPositionVariables)
974 static const char * const selections[] = {
975 "foo = res_cog of resname RA",
978 "bar = cog of resname RA",
982 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
983 runTest("simple.gro", selections);
987 TEST_F(SelectionCollectionDataTest, HandlesConstantPositionInVariable)
989 static const char * const selections[] = {
990 "constpos = [1.0, 2.5, 0.5]",
992 "within 2 of constpos"
994 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
995 | efTestPositionAtoms);
996 runTest("simple.gro", selections);
1000 TEST_F(SelectionCollectionDataTest, HandlesNumericConstantsInVariables)
1002 static const char * const selections[] = {
1007 "x + constreal1 < constreal2"
1009 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
1010 runTest("simple.gro", selections);
1014 /********************************************************************
1015 * Tests for complex boolean syntax
1018 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysis)
1020 static const char * const selections[] = {
1021 "atomnr 1 to 5 and atomnr 2 to 7 and x < 2",
1022 "atomnr 1 to 5 and (atomnr 4 to 7 or x < 2)",
1023 "atomnr 1 to 5 and y < 3 and (atomnr 4 to 7 or x < 2)",
1024 "atomnr 1 to 5 and not (atomnr 4 to 7 or x < 2)",
1025 "atomnr 1 to 5 or (atomnr 4 to 6 and (atomnr 5 to 7 or x < 2))"
1027 runTest(10, selections);
1031 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithVariables)
1033 static const char * const selections[] = {
1034 "foo = atomnr 4 to 7 or x < 2",
1035 "atomnr 1 to 4 and foo",
1036 "atomnr 2 to 6 and y < 3 and foo",
1037 "atomnr 6 to 10 and not foo"
1039 runTest(10, selections);
1043 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithMoreVariables)
1045 static const char * const selections[] = {
1046 "foo = atomnr 4 to 7",
1047 "bar = foo and x < 2",
1048 "bar2 = foo and y < 2",
1049 "atomnr 1 to 4 and bar",
1050 "atomnr 2 to 6 and y < 3 and bar2",
1051 "atomnr 6 to 10 and not foo"
1053 runTest(10, selections);
1057 /********************************************************************
1058 * Tests for complex subexpression cases
1060 * These tests use some knowledge of the implementation to trigger different
1061 * paths in the code.
1064 TEST_F(SelectionCollectionDataTest, HandlesUnusedVariables)
1066 static const char * const selections[] = {
1067 "unused1 = atomnr 1 to 3",
1068 "foo = atomnr 4 to 7",
1069 "atomnr 1 to 6 and foo",
1070 "unused2 = atomnr 3 to 5"
1072 runTest(10, selections);
1076 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithStaticEvaluationGroups)
1078 static const char * const selections[] = {
1079 "foo = atomnr 4 to 7 and x < 2",
1080 "atomnr 1 to 5 and foo",
1081 "atomnr 3 to 7 and foo"
1083 runTest(10, selections);
1087 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithMixedEvaluationGroups)
1089 static const char * const selections[] = {
1090 "foo = atomnr 4 to 7 and x < 2",
1091 "atomnr 1 to 6 and foo",
1095 runTest(10, selections);