3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
9 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11 * Copyright (c) 2001-2009, The GROMACS development team,
12 * check out http://www.gromacs.org for more information.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * If you want to redistribute modifications, please consider that
20 * scientific software is very special. Version control is crucial -
21 * bugs must be traceable. We will be happy to consider code for
22 * inclusion in the official distribution, but derived work must not
23 * be called official GROMACS. Details are found in the README & COPYING
24 * files - if they are missing, get the official version at www.gromacs.org.
26 * To help us fund GROMACS development, we humbly ask that you cite
27 * the papers on the package - you can find them in the top README file.
29 * For more info, check our website at http://www.gromacs.org
33 * Tests selection parsing and compilation.
35 * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36 * \ingroup module_selection
38 #include <gtest/gtest.h>
40 #include "gromacs/legacyheaders/smalloc.h"
41 #include "gromacs/legacyheaders/statutil.h"
42 #include "gromacs/legacyheaders/tpxio.h"
43 #include "gromacs/legacyheaders/vec.h"
45 #include "gromacs/options/basicoptions.h"
46 #include "gromacs/options/options.h"
47 #include "gromacs/selection/selectioncollection.h"
48 #include "gromacs/selection/selection.h"
49 #include "gromacs/utility/exceptions.h"
50 #include "gromacs/utility/flags.h"
51 #include "gromacs/utility/gmxregex.h"
52 #include "gromacs/utility/stringutil.h"
54 #include "testutils/refdata.h"
55 #include "testutils/testfilemanager.h"
56 #include "testutils/testoptions.h"
61 /********************************************************************
62 * Test fixture for selection testing
65 class SelectionCollectionTest : public ::testing::Test
68 static void SetUpTestCase();
70 static int s_debugLevel;
72 SelectionCollectionTest();
73 ~SelectionCollectionTest();
75 void setAtomCount(int natoms)
77 ASSERT_NO_THROW(sc_.setTopology(NULL, natoms));
79 void loadTopology(const char *filename);
81 gmx::SelectionCollection sc_;
82 gmx::SelectionList sel_;
87 int SelectionCollectionTest::s_debugLevel = 0;
89 void SelectionCollectionTest::SetUpTestCase()
91 gmx::Options options(NULL, NULL);
92 options.addOption(gmx::IntegerOption("seldebug").store(&s_debugLevel));
93 gmx::test::parseTestOptions(&options);
97 SelectionCollectionTest::SelectionCollectionTest()
98 : top_(NULL), frame_(NULL)
100 sc_.setDebugLevel(s_debugLevel);
101 sc_.setReferencePosType("atom");
102 sc_.setOutputPosType("atom");
106 SelectionCollectionTest::~SelectionCollectionTest()
110 free_t_atoms(&top_->atoms, TRUE);
124 SelectionCollectionTest::loadTopology(const char *filename)
132 read_tps_conf(gmx::test::TestFileManager::getInputFilePath(filename).c_str(),
133 title, top_, &ePBC, &xtop, NULL, box, FALSE);
136 frame_->flags = TRX_NEED_X;
137 frame_->natoms = top_->atoms.nr;
139 snew(frame_->x, frame_->natoms);
140 memcpy(frame_->x, xtop, sizeof(*frame_->x) * frame_->natoms);
142 copy_mat(box, frame_->box);
146 ASSERT_NO_THROW(sc_.setTopology(top_, -1));
150 /********************************************************************
151 * Test fixture for selection testing with reference data
154 class SelectionCollectionDataTest : public SelectionCollectionTest
159 efTestEvaluation = 1<<0,
160 efTestPositionAtoms = 1<<1,
161 efTestPositionCoordinates = 1<<2,
162 efTestPositionMapping = 1<<3,
163 efTestPositionMasses = 1<<4,
164 efTestPositionCharges = 1<<5,
165 efDontTestCompiledAtoms = 1<<8
167 typedef gmx::FlagsTemplate<TestFlag> TestFlags;
169 SelectionCollectionDataTest()
170 : checker_(data_.rootChecker()), count_(0), framenr_(0)
174 void setFlags(TestFlags flags) { flags_ = flags; }
176 template <size_t count>
177 void runTest(int natoms, const char *const (&selections)[count])
179 runTest(natoms, selections, count);
181 template <size_t count>
182 void runTest(const char *filename, const char *const (&selections)[count])
184 runTest(filename, selections, count);
187 template <size_t count>
188 void runParser(const char *const (&selections)[count])
190 runParser(selections, count);
195 void runEvaluateFinal();
198 static void checkSelection(gmx::test::TestReferenceChecker *checker,
199 const gmx::Selection &sel, TestFlags flags);
201 void runTest(int natoms, const char *const *selections, size_t count);
202 void runTest(const char *filename, const char *const *selections,
204 void runParser(const char *const *selections, size_t count);
206 void checkCompiled();
208 gmx::test::TestReferenceData data_;
209 gmx::test::TestReferenceChecker checker_;
217 SelectionCollectionDataTest::checkSelection(
218 gmx::test::TestReferenceChecker *checker,
219 const gmx::Selection &sel, TestFlags flags)
221 using gmx::test::TestReferenceChecker;
224 gmx::ConstArrayRef<int> atoms = sel.atomIndices();
225 checker->checkSequence(atoms.begin(), atoms.end(), "Atoms");
227 if (flags.test(efTestPositionAtoms)
228 || flags.test(efTestPositionCoordinates)
229 || flags.test(efTestPositionMapping)
230 || flags.test(efTestPositionMasses)
231 || flags.test(efTestPositionCharges))
233 TestReferenceChecker compound(
234 checker->checkSequenceCompound("Positions", sel.posCount()));
235 for (int i = 0; i < sel.posCount(); ++i)
237 TestReferenceChecker poscompound(compound.checkCompound("Position", NULL));
238 const gmx::SelectionPosition &p = sel.position(i);
239 if (flags.test(efTestPositionAtoms))
241 gmx::ConstArrayRef<int> atoms = p.atomIndices();
242 poscompound.checkSequence(atoms.begin(), atoms.end(), "Atoms");
244 if (flags.test(efTestPositionCoordinates))
246 poscompound.checkVector(p.x(), "Coordinates");
248 if (flags.test(efTestPositionMapping))
250 poscompound.checkInteger(p.refId(), "RefId");
251 poscompound.checkInteger(p.mappedId(), "MappedId");
253 if (flags.test(efTestPositionMasses))
255 poscompound.checkReal(p.mass(), "Mass");
257 if (flags.test(efTestPositionCharges))
259 poscompound.checkReal(p.charge(), "Charge");
267 SelectionCollectionDataTest::runParser(const char *const *selections,
270 using gmx::test::TestReferenceChecker;
272 TestReferenceChecker compound(checker_.checkCompound("ParsedSelections", "Parsed"));
275 for (size_t i = 0; i < count; ++i)
277 SCOPED_TRACE(std::string("Parsing selection \"")
278 + selections[i] + "\"");
279 gmx::SelectionList result;
280 ASSERT_NO_THROW(result = sc_.parseFromString(selections[i]));
281 sel_.insert(sel_.end(), result.begin(), result.end());
282 if (sel_.size() == count_)
284 std::string id = gmx::formatString("Variable%d", static_cast<int>(varcount + 1));
285 TestReferenceChecker varcompound(
286 compound.checkCompound("ParsedVariable", id.c_str()));
287 varcompound.checkString(selections[i], "Input");
292 std::string id = gmx::formatString("Selection%d", static_cast<int>(count_ + 1));
293 TestReferenceChecker selcompound(
294 compound.checkCompound("ParsedSelection", id.c_str()));
295 selcompound.checkString(selections[i], "Input");
296 selcompound.checkString(sel_[count_].name(), "Name");
297 selcompound.checkString(sel_[count_].selectionText(), "Text");
298 selcompound.checkBoolean(sel_[count_].isDynamic(), "Dynamic");
306 SelectionCollectionDataTest::runCompiler()
308 ASSERT_NO_THROW(sc_.compile());
309 ASSERT_EQ(count_, sel_.size());
315 SelectionCollectionDataTest::checkCompiled()
317 using gmx::test::TestReferenceChecker;
318 const TestFlags mask = ~TestFlags(efTestPositionCoordinates);
320 TestReferenceChecker compound(checker_.checkCompound("CompiledSelections", "Compiled"));
321 for (size_t i = 0; i < count_; ++i)
323 SCOPED_TRACE(std::string("Checking selection \"") +
324 sel_[i].selectionText() + "\"");
325 std::string id = gmx::formatString("Selection%d", static_cast<int>(i + 1));
326 TestReferenceChecker selcompound(
327 compound.checkCompound("Selection", id.c_str()));
328 if (!flags_.test(efDontTestCompiledAtoms))
330 checkSelection(&selcompound, sel_[i], flags_ & mask);
337 SelectionCollectionDataTest::runEvaluate()
339 using gmx::test::TestReferenceChecker;
342 ASSERT_NO_THROW(sc_.evaluate(frame_, NULL));
343 std::string frame = gmx::formatString("Frame%d", framenr_);
344 TestReferenceChecker compound(
345 checker_.checkCompound("EvaluatedSelections", frame.c_str()));
346 for (size_t i = 0; i < count_; ++i)
348 SCOPED_TRACE(std::string("Checking selection \"") +
349 sel_[i].selectionText() + "\"");
350 std::string id = gmx::formatString("Selection%d", static_cast<int>(i + 1));
351 TestReferenceChecker selcompound(
352 compound.checkCompound("Selection", id.c_str()));
353 checkSelection(&selcompound, sel_[i], flags_);
359 SelectionCollectionDataTest::runEvaluateFinal()
361 ASSERT_NO_THROW(sc_.evaluateFinal(framenr_));
362 if (!checker_.isWriteMode())
370 SelectionCollectionDataTest::runTest(int natoms, const char * const *selections,
373 ASSERT_NO_FATAL_FAILURE(runParser(selections, count));
374 ASSERT_NO_FATAL_FAILURE(setAtomCount(natoms));
375 ASSERT_NO_FATAL_FAILURE(runCompiler());
380 SelectionCollectionDataTest::runTest(const char *filename,
381 const char * const *selections,
384 ASSERT_NO_FATAL_FAILURE(runParser(selections, count));
385 ASSERT_NO_FATAL_FAILURE(loadTopology(filename));
386 ASSERT_NO_FATAL_FAILURE(runCompiler());
387 if (flags_.test(efTestEvaluation))
389 ASSERT_NO_FATAL_FAILURE(runEvaluate());
390 ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
395 /********************************************************************
396 * Tests for SelectionCollection functionality without reference data
399 TEST_F(SelectionCollectionTest, HandlesNoSelections)
401 EXPECT_FALSE(sc_.requiresTopology());
402 EXPECT_NO_THROW(sc_.compile());
405 TEST_F(SelectionCollectionTest, HandlesVelocityAndForceRequests)
407 ASSERT_NO_THROW(sel_ = sc_.parseFromString("atomnr 1 to 10; none"));
408 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
409 ASSERT_EQ(2U, sel_.size());
410 ASSERT_NO_THROW(sel_[0].setEvaluateVelocities(true));
411 ASSERT_NO_THROW(sel_[1].setEvaluateVelocities(true));
412 ASSERT_NO_THROW(sel_[0].setEvaluateForces(true));
413 ASSERT_NO_THROW(sel_[1].setEvaluateForces(true));
414 ASSERT_NO_THROW(sc_.compile());
415 EXPECT_TRUE(sel_[0].hasVelocities());
416 EXPECT_TRUE(sel_[1].hasVelocities());
417 EXPECT_TRUE(sel_[0].hasForces());
418 EXPECT_TRUE(sel_[1].hasForces());
421 TEST_F(SelectionCollectionTest, ParsesSelectionsFromFile)
423 ASSERT_NO_THROW(sel_ = sc_.parseFromFile(
424 gmx::test::TestFileManager::getInputFilePath("selfile.dat")));
425 // These should match the contents of selfile.dat
426 ASSERT_EQ(2U, sel_.size());
427 EXPECT_STREQ("resname RA RB", sel_[0].selectionText());
428 EXPECT_STREQ("resname RB RC", sel_[1].selectionText());
431 TEST_F(SelectionCollectionTest, HandlesInvalidRegularExpressions)
433 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
435 sc_.parseFromString("resname ~ \"R[A\"");
437 }, gmx::InvalidInputError);
440 TEST_F(SelectionCollectionTest, HandlesUnsupportedRegularExpressions)
442 if (!gmx::Regex::isSupported())
444 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
446 sc_.parseFromString("resname \"R[AD]\"");
448 }, gmx::InvalidInputError);
452 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue)
454 EXPECT_THROW(sc_.parseFromString("mindist from atomnr 1 cutoff"),
455 gmx::InvalidInputError);
458 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue2)
460 EXPECT_THROW(sc_.parseFromString("within 1 of"),
461 gmx::InvalidInputError);
464 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue3)
466 EXPECT_THROW(sc_.parseFromString("within of atomnr 1"),
467 gmx::InvalidInputError);
470 TEST_F(SelectionCollectionTest, HandlesHelpKeywordInInvalidContext)
472 EXPECT_THROW(sc_.parseFromString("resname help"),
473 gmx::InvalidInputError);
476 // TODO: Tests for more parser errors
478 TEST_F(SelectionCollectionTest, RecoversFromUnknownGroupReference)
480 ASSERT_NO_THROW(sc_.parseFromString("group \"foo\""));
481 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
482 EXPECT_THROW(sc_.setIndexGroups(NULL), gmx::InvalidInputError);
483 EXPECT_THROW(sc_.compile(), gmx::APIError);
486 TEST_F(SelectionCollectionTest, RecoversFromMissingMoleculeInfo)
488 ASSERT_NO_THROW(sc_.parseFromString("molindex 1 to 5"));
489 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
490 EXPECT_THROW(sc_.compile(), gmx::InconsistentInputError);
493 TEST_F(SelectionCollectionTest, RecoversFromMissingAtomTypes)
495 ASSERT_NO_THROW(sc_.parseFromString("type CA"));
496 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
497 EXPECT_THROW(sc_.compile(), gmx::InconsistentInputError);
500 TEST_F(SelectionCollectionTest, RecoversFromMissingPDBInfo)
502 ASSERT_NO_THROW(sc_.parseFromString("altloc A"));
503 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
504 EXPECT_THROW(sc_.compile(), gmx::InconsistentInputError);
507 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation)
509 ASSERT_NO_THROW(sc_.parseFromString("all permute 1 1"));
510 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
511 EXPECT_THROW(sc_.compile(), gmx::InvalidInputError);
514 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation2)
516 ASSERT_NO_THROW(sc_.parseFromString("all permute 3 2 1"));
517 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
518 EXPECT_THROW(sc_.compile(), gmx::InconsistentInputError);
521 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation3)
523 ASSERT_NO_THROW(sc_.parseFromString("x < 1.5 permute 3 2 1"));
524 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
525 ASSERT_NO_THROW(sc_.compile());
526 EXPECT_THROW(sc_.evaluate(frame_, NULL), gmx::InconsistentInputError);
529 // TODO: Tests for evaluation errors
532 /********************************************************************
533 * Tests for selection keywords
536 TEST_F(SelectionCollectionDataTest, HandlesAllNone)
538 static const char * const selections[] = {
542 runTest(10, selections);
545 TEST_F(SelectionCollectionDataTest, HandlesAtomnr)
547 static const char * const selections[] = {
548 "atomnr 1 to 3 6 to 8",
552 runTest(10, selections);
555 TEST_F(SelectionCollectionDataTest, HandlesResnr)
557 static const char * const selections[] = {
561 runTest("simple.gro", selections);
564 TEST_F(SelectionCollectionDataTest, HandlesResIndex)
566 static const char * const selections[] = {
570 runTest("simple.pdb", selections);
573 // TODO: Add test for "molindex"
575 TEST_F(SelectionCollectionDataTest, HandlesAtomname)
577 static const char * const selections[] = {
581 runTest("simple.gro", selections);
584 TEST_F(SelectionCollectionDataTest, HandlesPdbAtomname)
586 static const char * const selections[] = {
592 runTest("simple.pdb", selections);
595 // TODO: Add test for atomtype
597 TEST_F(SelectionCollectionDataTest, HandlesChain)
599 static const char * const selections[] = {
603 runTest("simple.pdb", selections);
606 TEST_F(SelectionCollectionDataTest, HandlesMass)
608 static const char * const selections[] = {
611 ASSERT_NO_FATAL_FAILURE(runParser(selections));
612 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
613 for (int i = 0; i < top_->atoms.nr; ++i)
615 top_->atoms.atom[i].m = 1.0 + i;
617 ASSERT_NO_FATAL_FAILURE(runCompiler());
620 TEST_F(SelectionCollectionDataTest, HandlesCharge)
622 static const char * const selections[] = {
625 ASSERT_NO_FATAL_FAILURE(runParser(selections));
626 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
627 for (int i = 0; i < top_->atoms.nr; ++i)
629 top_->atoms.atom[i].q = i / 10.0;
631 ASSERT_NO_FATAL_FAILURE(runCompiler());
634 TEST_F(SelectionCollectionDataTest, HandlesAltLoc)
636 static const char * const selections[] = {
640 runTest("simple.pdb", selections);
643 TEST_F(SelectionCollectionDataTest, HandlesInsertCode)
645 static const char * const selections[] = {
649 runTest("simple.pdb", selections);
652 TEST_F(SelectionCollectionDataTest, HandlesOccupancy)
654 static const char * const selections[] = {
658 runTest("simple.pdb", selections);
661 TEST_F(SelectionCollectionDataTest, HandlesBeta)
663 static const char * const selections[] = {
667 runTest("simple.pdb", selections);
670 TEST_F(SelectionCollectionDataTest, HandlesResname)
672 static const char * const selections[] = {
676 runTest("simple.gro", selections);
679 TEST_F(SelectionCollectionDataTest, HandlesCoordinateKeywords)
681 static const char * const selections[] = {
686 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
687 runTest("simple.gro", selections);
691 TEST_F(SelectionCollectionDataTest, HandlesSameResidue)
693 static const char * const selections[] = {
694 "same residue as atomnr 1 4 12"
696 runTest("simple.gro", selections);
700 TEST_F(SelectionCollectionDataTest, HandlesSameResidueName)
702 static const char * const selections[] = {
703 "same resname as atomnr 1 14"
705 runTest("simple.gro", selections);
709 TEST_F(SelectionCollectionDataTest, HandlesPositionKeywords)
711 static const char * const selections[] = {
713 "res_cog of name CB and resnr 1 3",
714 "whole_res_cog of name CB and resnr 1 3",
715 "part_res_cog of x < 3",
716 "dyn_res_cog of x < 3"
718 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
719 | efTestPositionAtoms);
720 runTest("simple.gro", selections);
724 TEST_F(SelectionCollectionDataTest, HandlesDistanceKeyword)
726 static const char * const selections[] = {
727 "distance from cog of resnr 1 < 2"
729 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
730 runTest("simple.gro", selections);
734 TEST_F(SelectionCollectionDataTest, HandlesMinDistanceKeyword)
736 static const char * const selections[] = {
737 "mindistance from resnr 1 < 2"
739 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
740 runTest("simple.gro", selections);
744 TEST_F(SelectionCollectionDataTest, HandlesWithinKeyword)
746 static const char * const selections[] = {
747 "within 1 of resnr 2"
749 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
750 runTest("simple.gro", selections);
754 TEST_F(SelectionCollectionDataTest, HandlesInSolidAngleKeyword)
756 // Both of these should evaluate to empty on a correct implementation.
757 static const char * const selections[] = {
758 "resname TP and not insolidangle center cog of resname C span resname R cutoff 20",
759 "resname TN and insolidangle center cog of resname C span resname R cutoff 20"
761 setFlags(TestFlags() | efDontTestCompiledAtoms | efTestEvaluation);
762 runTest("sphere.gro", selections);
766 TEST_F(SelectionCollectionDataTest, HandlesPermuteModifier)
768 static const char * const selections[] = {
770 "res_cog of resnr 1 to 4 permute 2 1",
771 "name CB S1 and res_cog x < 3 permute 2 1"
773 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
774 | efTestPositionAtoms | efTestPositionMapping);
775 runTest("simple.gro", selections);
779 TEST_F(SelectionCollectionDataTest, HandlesPlusModifier)
781 static const char * const selections[] = {
782 "name S2 plus name S1",
783 "res_cog of resnr 2 plus res_cog of resnr 1 plus res_cog of resnr 3",
784 "name S1 and y < 3 plus res_cog of x < 2.5"
786 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
787 | efTestPositionAtoms | efTestPositionMapping);
788 runTest("simple.gro", selections);
792 TEST_F(SelectionCollectionDataTest, HandlesMergeModifier)
794 static const char * const selections[] = {
795 "name S2 merge name S1",
796 "resnr 1 2 and name S2 merge resnr 1 2 and name S1 merge res_cog of resnr 1 2",
797 "name S1 and x < 2.5 merge res_cog of x < 2.5"
799 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
800 | efTestPositionAtoms | efTestPositionMapping);
801 runTest("simple.gro", selections);
805 /********************************************************************
806 * Tests for generic selection evaluation
809 TEST_F(SelectionCollectionDataTest, ComputesMassesAndCharges)
811 static const char * const selections[] = {
816 setFlags(TestFlags() | efTestEvaluation | efTestPositionAtoms
817 | efTestPositionMasses | efTestPositionCharges);
818 ASSERT_NO_FATAL_FAILURE(runParser(selections));
819 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
820 for (int i = 0; i < top_->atoms.nr; ++i)
822 top_->atoms.atom[i].m = 1.0 + i / 100.0;
823 top_->atoms.atom[i].q = -(1.0 + i / 100.0);
825 ASSERT_NO_FATAL_FAILURE(runCompiler());
826 ASSERT_NO_FATAL_FAILURE(runEvaluate());
827 ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
830 TEST_F(SelectionCollectionDataTest, ComputesMassesAndChargesWithoutTopology)
832 static const char * const selections[] = {
833 "atomnr 1 to 3 8 to 9",
837 setFlags(TestFlags() | efTestPositionAtoms
838 | efTestPositionMasses | efTestPositionCharges);
839 runTest(10, selections);
843 /********************************************************************
844 * Tests for selection syntactic constructs
847 TEST_F(SelectionCollectionDataTest, HandlesConstantPositions)
849 static const char * const selections[] = {
852 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
853 runTest("simple.gro", selections);
857 TEST_F(SelectionCollectionDataTest, HandlesWithinConstantPositions)
859 static const char * const selections[] = {
860 "within 1 of [2, 1, 0]"
862 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
863 runTest("simple.gro", selections);
867 TEST_F(SelectionCollectionDataTest, HandlesForcedStringMatchingMode)
869 static const char * const selections[] = {
873 runTest("simple.gro", selections);
877 TEST_F(SelectionCollectionDataTest, HandlesWildcardMatching)
879 static const char * const selections[] = {
883 runTest("simple.gro", selections);
887 TEST_F(SelectionCollectionDataTest, HandlesRegexMatching)
889 static const char * const selections[] = {
891 "resname ~ \"R[BD]\""
893 if (gmx::Regex::isSupported())
895 runTest("simple.gro", selections);
900 TEST_F(SelectionCollectionDataTest, HandlesBasicBoolean)
902 static const char * const selections[] = {
903 "atomnr 1 to 5 and atomnr 2 to 7",
904 "atomnr 1 to 5 or not atomnr 3 to 8",
905 "not not atomnr 1 to 5 and atomnr 2 to 6 and not not atomnr 3 to 7",
906 "atomnr 1 to 5 and (atomnr 2 to 7 and atomnr 3 to 6)",
907 "x < 5 and atomnr 1 to 5 and y < 3 and atomnr 2 to 4"
909 runTest(10, selections);
913 TEST_F(SelectionCollectionDataTest, HandlesNumericComparisons)
915 static const char * const selections[] = {
922 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
923 runTest("simple.gro", selections);
927 TEST_F(SelectionCollectionDataTest, HandlesArithmeticExpressions)
929 static const char * const selections[] = {
935 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
936 runTest("simple.gro", selections);
940 TEST_F(SelectionCollectionDataTest, HandlesNumericVariables)
942 static const char * const selections[] = {
948 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
949 runTest("simple.gro", selections);
953 TEST_F(SelectionCollectionDataTest, HandlesComplexNumericVariables)
955 static const char * const selections[] = {
957 "resname RA and value <= 4",
958 "resname RA RB and x < 3 and value <= 4",
960 "resname RA and index < 3",
961 "resname RB and y < 3 and index < 6"
963 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
964 runTest("simple.gro", selections);
968 TEST_F(SelectionCollectionDataTest, HandlesPositionVariables)
970 static const char * const selections[] = {
971 "foo = res_cog of resname RA",
974 "bar = cog of resname RA",
978 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
979 runTest("simple.gro", selections);
983 TEST_F(SelectionCollectionDataTest, HandlesConstantPositionInVariable)
985 static const char * const selections[] = {
986 "constpos = [1.0, 2.5, 0.5]",
988 "within 2 of constpos"
990 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
991 | efTestPositionAtoms);
992 runTest("simple.gro", selections);
996 TEST_F(SelectionCollectionDataTest, HandlesNumericConstantsInVariables)
998 static const char * const selections[] = {
1003 "x + constreal1 < constreal2"
1005 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
1006 runTest("simple.gro", selections);
1010 /********************************************************************
1011 * Tests for complex boolean syntax
1014 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysis)
1016 static const char * const selections[] = {
1017 "atomnr 1 to 5 and atomnr 2 to 7 and x < 2",
1018 "atomnr 1 to 5 and (atomnr 4 to 7 or x < 2)",
1019 "atomnr 1 to 5 and y < 3 and (atomnr 4 to 7 or x < 2)",
1020 "atomnr 1 to 5 and not (atomnr 4 to 7 or x < 2)",
1021 "atomnr 1 to 5 or (atomnr 4 to 6 and (atomnr 5 to 7 or x < 2))"
1023 runTest(10, selections);
1027 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithVariables)
1029 static const char * const selections[] = {
1030 "foo = atomnr 4 to 7 or x < 2",
1031 "atomnr 1 to 4 and foo",
1032 "atomnr 2 to 6 and y < 3 and foo",
1033 "atomnr 6 to 10 and not foo"
1035 runTest(10, selections);
1039 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithMoreVariables)
1041 static const char * const selections[] = {
1042 "foo = atomnr 4 to 7",
1043 "bar = foo and x < 2",
1044 "bar2 = foo and y < 2",
1045 "atomnr 1 to 4 and bar",
1046 "atomnr 2 to 6 and y < 3 and bar2",
1047 "atomnr 6 to 10 and not foo"
1049 runTest(10, selections);
1053 /********************************************************************
1054 * Tests for complex subexpression cases
1056 * These tests use some knowledge of the implementation to trigger different
1057 * paths in the code.
1060 TEST_F(SelectionCollectionDataTest, HandlesUnusedVariables)
1062 static const char * const selections[] = {
1063 "unused1 = atomnr 1 to 3",
1064 "foo = atomnr 4 to 7",
1065 "atomnr 1 to 6 and foo",
1066 "unused2 = atomnr 3 to 5"
1068 runTest(10, selections);
1072 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithStaticEvaluationGroups)
1074 static const char * const selections[] = {
1075 "foo = atomnr 4 to 7 and x < 2",
1076 "atomnr 1 to 5 and foo",
1077 "atomnr 3 to 7 and foo"
1079 runTest(10, selections);
1083 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithMixedEvaluationGroups)
1085 static const char * const selections[] = {
1086 "foo = atomnr 4 to 7 and x < 2",
1087 "atomnr 1 to 6 and foo",
1091 runTest(10, selections);