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, ParsesSelectionsFromFile)
407 ASSERT_NO_THROW(sel_ = sc_.parseFromFile(
408 gmx::test::TestFileManager::getInputFilePath("selfile.dat")));
409 // These should match the contents of selfile.dat
410 ASSERT_EQ(2U, sel_.size());
411 EXPECT_STREQ("resname RA RB", sel_[0].selectionText());
412 EXPECT_STREQ("resname RB RC", sel_[1].selectionText());
415 TEST_F(SelectionCollectionTest, HandlesInvalidRegularExpressions)
417 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
419 sc_.parseFromString("resname ~ \"R[A\"");
421 }, gmx::InvalidInputError);
424 TEST_F(SelectionCollectionTest, HandlesUnsupportedRegularExpressions)
426 if (!gmx::Regex::isSupported())
428 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
430 sc_.parseFromString("resname \"R[AD]\"");
432 }, gmx::InvalidInputError);
436 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue)
438 EXPECT_THROW(sc_.parseFromString("mindist from atomnr 1 cutoff"),
439 gmx::InvalidInputError);
442 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue2)
444 EXPECT_THROW(sc_.parseFromString("within 1 of"),
445 gmx::InvalidInputError);
448 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue3)
450 EXPECT_THROW(sc_.parseFromString("within of atomnr 1"),
451 gmx::InvalidInputError);
454 TEST_F(SelectionCollectionTest, HandlesHelpKeywordInInvalidContext)
456 EXPECT_THROW(sc_.parseFromString("resname help"),
457 gmx::InvalidInputError);
460 // TODO: Tests for more parser errors
462 TEST_F(SelectionCollectionTest, RecoversFromUnknownGroupReference)
464 ASSERT_NO_THROW(sc_.parseFromString("group \"foo\""));
465 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
466 EXPECT_THROW(sc_.setIndexGroups(NULL), gmx::InvalidInputError);
467 EXPECT_THROW(sc_.compile(), gmx::APIError);
470 TEST_F(SelectionCollectionTest, RecoversFromMissingMoleculeInfo)
472 ASSERT_NO_THROW(sc_.parseFromString("molindex 1 to 5"));
473 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
474 EXPECT_THROW(sc_.compile(), gmx::InconsistentInputError);
477 TEST_F(SelectionCollectionTest, RecoversFromMissingAtomTypes)
479 ASSERT_NO_THROW(sc_.parseFromString("type CA"));
480 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
481 EXPECT_THROW(sc_.compile(), gmx::InconsistentInputError);
484 TEST_F(SelectionCollectionTest, RecoversFromMissingPDBInfo)
486 ASSERT_NO_THROW(sc_.parseFromString("altloc A"));
487 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
488 EXPECT_THROW(sc_.compile(), gmx::InconsistentInputError);
491 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation)
493 ASSERT_NO_THROW(sc_.parseFromString("all permute 1 1"));
494 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
495 EXPECT_THROW(sc_.compile(), gmx::InvalidInputError);
498 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation2)
500 ASSERT_NO_THROW(sc_.parseFromString("all permute 3 2 1"));
501 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
502 EXPECT_THROW(sc_.compile(), gmx::InconsistentInputError);
505 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation3)
507 ASSERT_NO_THROW(sc_.parseFromString("x < 1.5 permute 3 2 1"));
508 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
509 ASSERT_NO_THROW(sc_.compile());
510 EXPECT_THROW(sc_.evaluate(frame_, NULL), gmx::InconsistentInputError);
513 // TODO: Tests for evaluation errors
516 /********************************************************************
517 * Tests for selection keywords
520 TEST_F(SelectionCollectionDataTest, HandlesAllNone)
522 static const char * const selections[] = {
526 runTest(10, selections);
529 TEST_F(SelectionCollectionDataTest, HandlesAtomnr)
531 static const char * const selections[] = {
532 "atomnr 1 to 3 6 to 8",
536 runTest(10, selections);
539 TEST_F(SelectionCollectionDataTest, HandlesResnr)
541 static const char * const selections[] = {
545 runTest("simple.gro", selections);
548 TEST_F(SelectionCollectionDataTest, HandlesResIndex)
550 static const char * const selections[] = {
554 runTest("simple.pdb", selections);
557 // TODO: Add test for "molindex"
559 TEST_F(SelectionCollectionDataTest, HandlesAtomname)
561 static const char * const selections[] = {
565 runTest("simple.gro", selections);
568 TEST_F(SelectionCollectionDataTest, HandlesPdbAtomname)
570 static const char * const selections[] = {
576 runTest("simple.pdb", selections);
579 // TODO: Add test for atomtype
581 TEST_F(SelectionCollectionDataTest, HandlesChain)
583 static const char * const selections[] = {
587 runTest("simple.pdb", selections);
590 TEST_F(SelectionCollectionDataTest, HandlesMass)
592 static const char * const selections[] = {
595 ASSERT_NO_FATAL_FAILURE(runParser(selections));
596 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
597 for (int i = 0; i < top_->atoms.nr; ++i)
599 top_->atoms.atom[i].m = 1.0 + i;
601 ASSERT_NO_FATAL_FAILURE(runCompiler());
604 TEST_F(SelectionCollectionDataTest, HandlesCharge)
606 static const char * const selections[] = {
609 ASSERT_NO_FATAL_FAILURE(runParser(selections));
610 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
611 for (int i = 0; i < top_->atoms.nr; ++i)
613 top_->atoms.atom[i].q = i / 10.0;
615 ASSERT_NO_FATAL_FAILURE(runCompiler());
618 TEST_F(SelectionCollectionDataTest, HandlesAltLoc)
620 static const char * const selections[] = {
624 runTest("simple.pdb", selections);
627 TEST_F(SelectionCollectionDataTest, HandlesInsertCode)
629 static const char * const selections[] = {
633 runTest("simple.pdb", selections);
636 TEST_F(SelectionCollectionDataTest, HandlesOccupancy)
638 static const char * const selections[] = {
642 runTest("simple.pdb", selections);
645 TEST_F(SelectionCollectionDataTest, HandlesBeta)
647 static const char * const selections[] = {
651 runTest("simple.pdb", selections);
654 TEST_F(SelectionCollectionDataTest, HandlesResname)
656 static const char * const selections[] = {
660 runTest("simple.gro", selections);
663 TEST_F(SelectionCollectionDataTest, HandlesCoordinateKeywords)
665 static const char * const selections[] = {
670 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
671 runTest("simple.gro", selections);
675 TEST_F(SelectionCollectionDataTest, HandlesSameResidue)
677 static const char * const selections[] = {
678 "same residue as atomnr 1 4 12"
680 runTest("simple.gro", selections);
684 TEST_F(SelectionCollectionDataTest, HandlesSameResidueName)
686 static const char * const selections[] = {
687 "same resname as atomnr 1 14"
689 runTest("simple.gro", selections);
693 TEST_F(SelectionCollectionDataTest, HandlesPositionKeywords)
695 static const char * const selections[] = {
697 "res_cog of name CB and resnr 1 3",
698 "whole_res_cog of name CB and resnr 1 3",
699 "part_res_cog of x < 3",
700 "dyn_res_cog of x < 3"
702 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
703 | efTestPositionAtoms);
704 runTest("simple.gro", selections);
708 TEST_F(SelectionCollectionDataTest, HandlesDistanceKeyword)
710 static const char * const selections[] = {
711 "distance from cog of resnr 1 < 2"
713 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
714 runTest("simple.gro", selections);
718 TEST_F(SelectionCollectionDataTest, HandlesMinDistanceKeyword)
720 static const char * const selections[] = {
721 "mindistance from resnr 1 < 2"
723 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
724 runTest("simple.gro", selections);
728 TEST_F(SelectionCollectionDataTest, HandlesWithinKeyword)
730 static const char * const selections[] = {
731 "within 1 of resnr 2"
733 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
734 runTest("simple.gro", selections);
738 TEST_F(SelectionCollectionDataTest, HandlesInSolidAngleKeyword)
740 // Both of these should evaluate to empty on a correct implementation.
741 static const char * const selections[] = {
742 "resname TP and not insolidangle center cog of resname C span resname R cutoff 20",
743 "resname TN and insolidangle center cog of resname C span resname R cutoff 20"
745 setFlags(TestFlags() | efDontTestCompiledAtoms | efTestEvaluation);
746 runTest("sphere.gro", selections);
750 TEST_F(SelectionCollectionDataTest, HandlesPermuteModifier)
752 static const char * const selections[] = {
754 "res_cog of resnr 1 to 4 permute 2 1",
755 "name CB S1 and res_cog x < 3 permute 2 1"
757 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
758 | efTestPositionAtoms | efTestPositionMapping);
759 runTest("simple.gro", selections);
763 TEST_F(SelectionCollectionDataTest, HandlesPlusModifier)
765 static const char * const selections[] = {
766 "name S2 plus name S1",
767 "res_cog of resnr 2 plus res_cog of resnr 1 plus res_cog of resnr 3",
768 "name S1 and y < 3 plus res_cog of x < 2.5"
770 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
771 | efTestPositionAtoms | efTestPositionMapping);
772 runTest("simple.gro", selections);
776 TEST_F(SelectionCollectionDataTest, HandlesMergeModifier)
778 static const char * const selections[] = {
779 "name S2 merge name S1",
780 "resnr 1 2 and name S2 merge resnr 1 2 and name S1 merge res_cog of resnr 1 2",
781 "name S1 and x < 2.5 merge res_cog of x < 2.5"
783 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
784 | efTestPositionAtoms | efTestPositionMapping);
785 runTest("simple.gro", selections);
789 /********************************************************************
790 * Tests for generic selection evaluation
793 TEST_F(SelectionCollectionDataTest, ComputesMassesAndCharges)
795 static const char * const selections[] = {
800 setFlags(TestFlags() | efTestEvaluation | efTestPositionAtoms
801 | efTestPositionMasses | efTestPositionCharges);
802 ASSERT_NO_FATAL_FAILURE(runParser(selections));
803 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
804 for (int i = 0; i < top_->atoms.nr; ++i)
806 top_->atoms.atom[i].m = 1.0 + i / 100.0;
807 top_->atoms.atom[i].q = -(1.0 + i / 100.0);
809 ASSERT_NO_FATAL_FAILURE(runCompiler());
810 ASSERT_NO_FATAL_FAILURE(runEvaluate());
811 ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
814 TEST_F(SelectionCollectionDataTest, ComputesMassesAndChargesWithoutTopology)
816 static const char * const selections[] = {
817 "atomnr 1 to 3 8 to 9",
821 setFlags(TestFlags() | efTestPositionAtoms
822 | efTestPositionMasses | efTestPositionCharges);
823 runTest(10, selections);
827 /********************************************************************
828 * Tests for selection syntactic constructs
831 TEST_F(SelectionCollectionDataTest, HandlesConstantPositions)
833 static const char * const selections[] = {
836 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
837 runTest("simple.gro", selections);
841 TEST_F(SelectionCollectionDataTest, HandlesWithinConstantPositions)
843 static const char * const selections[] = {
844 "within 1 of [2, 1, 0]"
846 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
847 runTest("simple.gro", selections);
851 TEST_F(SelectionCollectionDataTest, HandlesForcedStringMatchingMode)
853 static const char * const selections[] = {
857 runTest("simple.gro", selections);
861 TEST_F(SelectionCollectionDataTest, HandlesWildcardMatching)
863 static const char * const selections[] = {
867 runTest("simple.gro", selections);
871 TEST_F(SelectionCollectionDataTest, HandlesRegexMatching)
873 static const char * const selections[] = {
875 "resname ~ \"R[BD]\""
877 if (gmx::Regex::isSupported())
879 runTest("simple.gro", selections);
884 TEST_F(SelectionCollectionDataTest, HandlesBasicBoolean)
886 static const char * const selections[] = {
887 "atomnr 1 to 5 and atomnr 2 to 7",
888 "atomnr 1 to 5 or not atomnr 3 to 8",
889 "not not atomnr 1 to 5 and atomnr 2 to 6 and not not atomnr 3 to 7",
890 "atomnr 1 to 5 and (atomnr 2 to 7 and atomnr 3 to 6)",
891 "x < 5 and atomnr 1 to 5 and y < 3 and atomnr 2 to 4"
893 runTest(10, selections);
897 TEST_F(SelectionCollectionDataTest, HandlesNumericComparisons)
899 static const char * const selections[] = {
906 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
907 runTest("simple.gro", selections);
911 TEST_F(SelectionCollectionDataTest, HandlesArithmeticExpressions)
913 static const char * const selections[] = {
919 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
920 runTest("simple.gro", selections);
924 TEST_F(SelectionCollectionDataTest, HandlesNumericVariables)
926 static const char * const selections[] = {
932 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
933 runTest("simple.gro", selections);
937 TEST_F(SelectionCollectionDataTest, HandlesComplexNumericVariables)
939 static const char * const selections[] = {
941 "resname RA and value <= 4",
942 "resname RA RB and x < 3 and value <= 4",
944 "resname RA and index < 3",
945 "resname RB and y < 3 and index < 6"
947 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
948 runTest("simple.gro", selections);
952 TEST_F(SelectionCollectionDataTest, HandlesPositionVariables)
954 static const char * const selections[] = {
955 "foo = res_cog of resname RA",
958 "bar = cog of resname RA",
962 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
963 runTest("simple.gro", selections);
967 TEST_F(SelectionCollectionDataTest, HandlesConstantPositionInVariable)
969 static const char * const selections[] = {
970 "constpos = [1.0, 2.5, 0.5]",
972 "within 2 of constpos"
974 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
975 | efTestPositionAtoms);
976 runTest("simple.gro", selections);
980 TEST_F(SelectionCollectionDataTest, HandlesNumericConstantsInVariables)
982 static const char * const selections[] = {
987 "x + constreal1 < constreal2"
989 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
990 runTest("simple.gro", selections);
994 /********************************************************************
995 * Tests for complex boolean syntax
998 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysis)
1000 static const char * const selections[] = {
1001 "atomnr 1 to 5 and atomnr 2 to 7 and x < 2",
1002 "atomnr 1 to 5 and (atomnr 4 to 7 or x < 2)",
1003 "atomnr 1 to 5 and y < 3 and (atomnr 4 to 7 or x < 2)",
1004 "atomnr 1 to 5 and not (atomnr 4 to 7 or x < 2)",
1005 "atomnr 1 to 5 or (atomnr 4 to 6 and (atomnr 5 to 7 or x < 2))"
1007 runTest(10, selections);
1011 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithVariables)
1013 static const char * const selections[] = {
1014 "foo = atomnr 4 to 7 or x < 2",
1015 "atomnr 1 to 4 and foo",
1016 "atomnr 2 to 6 and y < 3 and foo",
1017 "atomnr 6 to 10 and not foo"
1019 runTest(10, selections);
1023 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithMoreVariables)
1025 static const char * const selections[] = {
1026 "foo = atomnr 4 to 7",
1027 "bar = foo and x < 2",
1028 "bar2 = foo and y < 2",
1029 "atomnr 1 to 4 and bar",
1030 "atomnr 2 to 6 and y < 3 and bar2",
1031 "atomnr 6 to 10 and not foo"
1033 runTest(10, selections);
1037 /********************************************************************
1038 * Tests for complex subexpression cases
1040 * These tests use some knowledge of the implementation to trigger different
1041 * paths in the code.
1044 TEST_F(SelectionCollectionDataTest, HandlesUnusedVariables)
1046 static const char * const selections[] = {
1047 "unused1 = atomnr 1 to 3",
1048 "foo = atomnr 4 to 7",
1049 "atomnr 1 to 6 and foo",
1050 "unused2 = atomnr 3 to 5"
1052 runTest(10, selections);
1056 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithStaticEvaluationGroups)
1058 static const char * const selections[] = {
1059 "foo = atomnr 4 to 7 and x < 2",
1060 "atomnr 1 to 5 and foo",
1061 "atomnr 3 to 7 and foo"
1063 runTest(10, selections);
1067 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithMixedEvaluationGroups)
1069 static const char * const selections[] = {
1070 "foo = atomnr 4 to 7 and x < 2",
1071 "atomnr 1 to 6 and foo",
1075 runTest(10, selections);