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/testasserts.h"
60 #include "testutils/testfilemanager.h"
61 #include "testutils/testoptions.h"
66 /********************************************************************
67 * Test fixture for selection testing
70 class SelectionCollectionTest : public ::testing::Test
73 static void SetUpTestCase();
75 static int s_debugLevel;
77 SelectionCollectionTest();
78 ~SelectionCollectionTest();
80 void setAtomCount(int natoms)
82 ASSERT_NO_THROW_GMX(sc_.setTopology(NULL, natoms));
84 void loadTopology(const char *filename);
86 gmx::SelectionCollection sc_;
87 gmx::SelectionList sel_;
92 int SelectionCollectionTest::s_debugLevel = 0;
94 void SelectionCollectionTest::SetUpTestCase()
96 gmx::Options options(NULL, NULL);
97 options.addOption(gmx::IntegerOption("seldebug").store(&s_debugLevel));
98 gmx::test::parseTestOptions(&options);
102 SelectionCollectionTest::SelectionCollectionTest()
103 : top_(NULL), frame_(NULL)
105 sc_.setDebugLevel(s_debugLevel);
106 sc_.setReferencePosType("atom");
107 sc_.setOutputPosType("atom");
111 SelectionCollectionTest::~SelectionCollectionTest()
115 free_t_atoms(&top_->atoms, TRUE);
129 SelectionCollectionTest::loadTopology(const char *filename)
137 read_tps_conf(gmx::test::TestFileManager::getInputFilePath(filename).c_str(),
138 title, top_, &ePBC, &xtop, NULL, box, FALSE);
141 frame_->flags = TRX_NEED_X;
142 frame_->natoms = top_->atoms.nr;
144 snew(frame_->x, frame_->natoms);
145 memcpy(frame_->x, xtop, sizeof(*frame_->x) * frame_->natoms);
147 copy_mat(box, frame_->box);
151 ASSERT_NO_THROW_GMX(sc_.setTopology(top_, -1));
155 /********************************************************************
156 * Test fixture for selection testing with reference data
159 class SelectionCollectionDataTest : public SelectionCollectionTest
164 efTestEvaluation = 1<<0,
165 efTestPositionAtoms = 1<<1,
166 efTestPositionCoordinates = 1<<2,
167 efTestPositionMapping = 1<<3,
168 efTestPositionMasses = 1<<4,
169 efTestPositionCharges = 1<<5,
170 efDontTestCompiledAtoms = 1<<8
172 typedef gmx::FlagsTemplate<TestFlag> TestFlags;
174 SelectionCollectionDataTest()
175 : checker_(data_.rootChecker()), count_(0), framenr_(0)
179 void setFlags(TestFlags flags) { flags_ = flags; }
181 template <size_t count>
182 void runTest(int natoms, const char *const (&selections)[count])
184 runTest(natoms, selections, count);
186 template <size_t count>
187 void runTest(const char *filename, const char *const (&selections)[count])
189 runTest(filename, selections, count);
192 template <size_t count>
193 void runParser(const char *const (&selections)[count])
195 runParser(selections, count);
200 void runEvaluateFinal();
203 static void checkSelection(gmx::test::TestReferenceChecker *checker,
204 const gmx::Selection &sel, TestFlags flags);
206 void runTest(int natoms, const char *const *selections, size_t count);
207 void runTest(const char *filename, const char *const *selections,
209 void runParser(const char *const *selections, size_t count);
211 void checkCompiled();
213 gmx::test::TestReferenceData data_;
214 gmx::test::TestReferenceChecker checker_;
222 SelectionCollectionDataTest::checkSelection(
223 gmx::test::TestReferenceChecker *checker,
224 const gmx::Selection &sel, TestFlags flags)
226 using gmx::test::TestReferenceChecker;
229 gmx::ConstArrayRef<int> atoms = sel.atomIndices();
230 checker->checkSequence(atoms.begin(), atoms.end(), "Atoms");
232 if (flags.test(efTestPositionAtoms)
233 || flags.test(efTestPositionCoordinates)
234 || flags.test(efTestPositionMapping)
235 || flags.test(efTestPositionMasses)
236 || flags.test(efTestPositionCharges))
238 TestReferenceChecker compound(
239 checker->checkSequenceCompound("Positions", sel.posCount()));
240 for (int i = 0; i < sel.posCount(); ++i)
242 TestReferenceChecker poscompound(compound.checkCompound("Position", NULL));
243 const gmx::SelectionPosition &p = sel.position(i);
244 if (flags.test(efTestPositionAtoms))
246 gmx::ConstArrayRef<int> atoms = p.atomIndices();
247 poscompound.checkSequence(atoms.begin(), atoms.end(), "Atoms");
249 if (flags.test(efTestPositionCoordinates))
251 poscompound.checkVector(p.x(), "Coordinates");
253 if (flags.test(efTestPositionMapping))
255 poscompound.checkInteger(p.refId(), "RefId");
256 poscompound.checkInteger(p.mappedId(), "MappedId");
258 if (flags.test(efTestPositionMasses))
260 poscompound.checkReal(p.mass(), "Mass");
262 if (flags.test(efTestPositionCharges))
264 poscompound.checkReal(p.charge(), "Charge");
272 SelectionCollectionDataTest::runParser(const char *const *selections,
275 using gmx::test::TestReferenceChecker;
277 TestReferenceChecker compound(checker_.checkCompound("ParsedSelections", "Parsed"));
280 for (size_t i = 0; i < count; ++i)
282 SCOPED_TRACE(std::string("Parsing selection \"")
283 + selections[i] + "\"");
284 gmx::SelectionList result;
285 ASSERT_NO_THROW_GMX(result = sc_.parseFromString(selections[i]));
286 sel_.insert(sel_.end(), result.begin(), result.end());
287 if (sel_.size() == count_)
289 std::string id = gmx::formatString("Variable%d", static_cast<int>(varcount + 1));
290 TestReferenceChecker varcompound(
291 compound.checkCompound("ParsedVariable", id.c_str()));
292 varcompound.checkString(selections[i], "Input");
297 std::string id = gmx::formatString("Selection%d", static_cast<int>(count_ + 1));
298 TestReferenceChecker selcompound(
299 compound.checkCompound("ParsedSelection", id.c_str()));
300 selcompound.checkString(selections[i], "Input");
301 selcompound.checkString(sel_[count_].name(), "Name");
302 selcompound.checkString(sel_[count_].selectionText(), "Text");
303 selcompound.checkBoolean(sel_[count_].isDynamic(), "Dynamic");
311 SelectionCollectionDataTest::runCompiler()
313 ASSERT_NO_THROW_GMX(sc_.compile());
314 ASSERT_EQ(count_, sel_.size());
320 SelectionCollectionDataTest::checkCompiled()
322 using gmx::test::TestReferenceChecker;
323 const TestFlags mask = ~TestFlags(efTestPositionCoordinates);
325 TestReferenceChecker compound(checker_.checkCompound("CompiledSelections", "Compiled"));
326 for (size_t i = 0; i < count_; ++i)
328 SCOPED_TRACE(std::string("Checking selection \"") +
329 sel_[i].selectionText() + "\"");
330 std::string id = gmx::formatString("Selection%d", static_cast<int>(i + 1));
331 TestReferenceChecker selcompound(
332 compound.checkCompound("Selection", id.c_str()));
333 if (!flags_.test(efDontTestCompiledAtoms))
335 checkSelection(&selcompound, sel_[i], flags_ & mask);
342 SelectionCollectionDataTest::runEvaluate()
344 using gmx::test::TestReferenceChecker;
347 ASSERT_NO_THROW_GMX(sc_.evaluate(frame_, NULL));
348 std::string frame = gmx::formatString("Frame%d", framenr_);
349 TestReferenceChecker compound(
350 checker_.checkCompound("EvaluatedSelections", frame.c_str()));
351 for (size_t i = 0; i < count_; ++i)
353 SCOPED_TRACE(std::string("Checking selection \"") +
354 sel_[i].selectionText() + "\"");
355 std::string id = gmx::formatString("Selection%d", static_cast<int>(i + 1));
356 TestReferenceChecker selcompound(
357 compound.checkCompound("Selection", id.c_str()));
358 checkSelection(&selcompound, sel_[i], flags_);
364 SelectionCollectionDataTest::runEvaluateFinal()
366 ASSERT_NO_THROW_GMX(sc_.evaluateFinal(framenr_));
372 SelectionCollectionDataTest::runTest(int natoms, const char * const *selections,
375 ASSERT_NO_FATAL_FAILURE(runParser(selections, count));
376 ASSERT_NO_FATAL_FAILURE(setAtomCount(natoms));
377 ASSERT_NO_FATAL_FAILURE(runCompiler());
382 SelectionCollectionDataTest::runTest(const char *filename,
383 const char * const *selections,
386 ASSERT_NO_FATAL_FAILURE(runParser(selections, count));
387 ASSERT_NO_FATAL_FAILURE(loadTopology(filename));
388 ASSERT_NO_FATAL_FAILURE(runCompiler());
389 if (flags_.test(efTestEvaluation))
391 ASSERT_NO_FATAL_FAILURE(runEvaluate());
392 ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
397 /********************************************************************
398 * Tests for SelectionCollection functionality without reference data
401 TEST_F(SelectionCollectionTest, HandlesNoSelections)
403 EXPECT_FALSE(sc_.requiresTopology());
404 EXPECT_NO_THROW_GMX(sc_.compile());
407 TEST_F(SelectionCollectionTest, HandlesVelocityAndForceRequests)
409 ASSERT_NO_THROW_GMX(sel_ = sc_.parseFromString("atomnr 1 to 10; none"));
410 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
411 ASSERT_EQ(2U, sel_.size());
412 ASSERT_NO_THROW_GMX(sel_[0].setEvaluateVelocities(true));
413 ASSERT_NO_THROW_GMX(sel_[1].setEvaluateVelocities(true));
414 ASSERT_NO_THROW_GMX(sel_[0].setEvaluateForces(true));
415 ASSERT_NO_THROW_GMX(sel_[1].setEvaluateForces(true));
416 ASSERT_NO_THROW_GMX(sc_.compile());
417 EXPECT_TRUE(sel_[0].hasVelocities());
418 EXPECT_TRUE(sel_[1].hasVelocities());
419 EXPECT_TRUE(sel_[0].hasForces());
420 EXPECT_TRUE(sel_[1].hasForces());
423 TEST_F(SelectionCollectionTest, ParsesSelectionsFromFile)
425 ASSERT_NO_THROW_GMX(sel_ = sc_.parseFromFile(
426 gmx::test::TestFileManager::getInputFilePath("selfile.dat")));
427 // These should match the contents of selfile.dat
428 ASSERT_EQ(2U, sel_.size());
429 EXPECT_STREQ("resname RA RB", sel_[0].selectionText());
430 EXPECT_STREQ("resname RB RC", sel_[1].selectionText());
433 TEST_F(SelectionCollectionTest, HandlesInvalidRegularExpressions)
435 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
437 sc_.parseFromString("resname ~ \"R[A\"");
439 }, gmx::InvalidInputError);
442 TEST_F(SelectionCollectionTest, HandlesUnsupportedRegularExpressions)
444 if (!gmx::Regex::isSupported())
446 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
448 sc_.parseFromString("resname \"R[AD]\"");
450 }, gmx::InvalidInputError);
454 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue)
456 EXPECT_THROW_GMX(sc_.parseFromString("mindist from atomnr 1 cutoff"),
457 gmx::InvalidInputError);
460 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue2)
462 EXPECT_THROW_GMX(sc_.parseFromString("within 1 of"),
463 gmx::InvalidInputError);
466 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue3)
468 EXPECT_THROW_GMX(sc_.parseFromString("within of atomnr 1"),
469 gmx::InvalidInputError);
472 TEST_F(SelectionCollectionTest, HandlesHelpKeywordInInvalidContext)
474 EXPECT_THROW_GMX(sc_.parseFromString("resname help"),
475 gmx::InvalidInputError);
478 // TODO: Tests for more parser errors
480 TEST_F(SelectionCollectionTest, RecoversFromUnknownGroupReference)
482 ASSERT_NO_THROW_GMX(sc_.parseFromString("group \"foo\""));
483 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
484 EXPECT_THROW_GMX(sc_.setIndexGroups(NULL), gmx::InvalidInputError);
485 EXPECT_THROW_GMX(sc_.compile(), gmx::APIError);
488 TEST_F(SelectionCollectionTest, RecoversFromMissingMoleculeInfo)
490 ASSERT_NO_THROW_GMX(sc_.parseFromString("molindex 1 to 5"));
491 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
492 EXPECT_THROW_GMX(sc_.compile(), gmx::InconsistentInputError);
495 TEST_F(SelectionCollectionTest, RecoversFromMissingAtomTypes)
497 ASSERT_NO_THROW_GMX(sc_.parseFromString("type CA"));
498 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
499 EXPECT_THROW_GMX(sc_.compile(), gmx::InconsistentInputError);
502 TEST_F(SelectionCollectionTest, RecoversFromMissingPDBInfo)
504 ASSERT_NO_THROW_GMX(sc_.parseFromString("altloc A"));
505 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
506 EXPECT_THROW_GMX(sc_.compile(), gmx::InconsistentInputError);
509 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation)
511 ASSERT_NO_THROW_GMX(sc_.parseFromString("all permute 1 1"));
512 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
513 EXPECT_THROW_GMX(sc_.compile(), gmx::InvalidInputError);
516 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation2)
518 ASSERT_NO_THROW_GMX(sc_.parseFromString("all permute 3 2 1"));
519 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
520 EXPECT_THROW_GMX(sc_.compile(), gmx::InconsistentInputError);
523 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation3)
525 ASSERT_NO_THROW_GMX(sc_.parseFromString("x < 1.5 permute 3 2 1"));
526 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
527 ASSERT_NO_THROW_GMX(sc_.compile());
528 EXPECT_THROW_GMX(sc_.evaluate(frame_, NULL), gmx::InconsistentInputError);
531 // TODO: Tests for evaluation errors
534 /********************************************************************
535 * Tests for selection keywords
538 TEST_F(SelectionCollectionDataTest, HandlesAllNone)
540 static const char * const selections[] = {
544 runTest(10, selections);
547 TEST_F(SelectionCollectionDataTest, HandlesAtomnr)
549 static const char * const selections[] = {
550 "atomnr 1 to 3 6 to 8",
554 runTest(10, selections);
557 TEST_F(SelectionCollectionDataTest, HandlesResnr)
559 static const char * const selections[] = {
563 runTest("simple.gro", selections);
566 TEST_F(SelectionCollectionDataTest, HandlesResIndex)
568 static const char * const selections[] = {
572 runTest("simple.pdb", selections);
575 // TODO: Add test for "molindex"
577 TEST_F(SelectionCollectionDataTest, HandlesAtomname)
579 static const char * const selections[] = {
583 runTest("simple.gro", selections);
586 TEST_F(SelectionCollectionDataTest, HandlesPdbAtomname)
588 static const char * const selections[] = {
594 runTest("simple.pdb", selections);
597 // TODO: Add test for atomtype
599 TEST_F(SelectionCollectionDataTest, HandlesChain)
601 static const char * const selections[] = {
605 runTest("simple.pdb", selections);
608 TEST_F(SelectionCollectionDataTest, HandlesMass)
610 static const char * const selections[] = {
613 ASSERT_NO_FATAL_FAILURE(runParser(selections));
614 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
615 for (int i = 0; i < top_->atoms.nr; ++i)
617 top_->atoms.atom[i].m = 1.0 + i;
619 ASSERT_NO_FATAL_FAILURE(runCompiler());
622 TEST_F(SelectionCollectionDataTest, HandlesCharge)
624 static const char * const selections[] = {
627 ASSERT_NO_FATAL_FAILURE(runParser(selections));
628 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
629 for (int i = 0; i < top_->atoms.nr; ++i)
631 top_->atoms.atom[i].q = i / 10.0;
633 ASSERT_NO_FATAL_FAILURE(runCompiler());
636 TEST_F(SelectionCollectionDataTest, HandlesAltLoc)
638 static const char * const selections[] = {
642 runTest("simple.pdb", selections);
645 TEST_F(SelectionCollectionDataTest, HandlesInsertCode)
647 static const char * const selections[] = {
651 runTest("simple.pdb", selections);
654 TEST_F(SelectionCollectionDataTest, HandlesOccupancy)
656 static const char * const selections[] = {
660 runTest("simple.pdb", selections);
663 TEST_F(SelectionCollectionDataTest, HandlesBeta)
665 static const char * const selections[] = {
669 runTest("simple.pdb", selections);
672 TEST_F(SelectionCollectionDataTest, HandlesResname)
674 static const char * const selections[] = {
678 runTest("simple.gro", selections);
681 TEST_F(SelectionCollectionDataTest, HandlesCoordinateKeywords)
683 static const char * const selections[] = {
688 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
689 runTest("simple.gro", selections);
693 TEST_F(SelectionCollectionDataTest, HandlesSameResidue)
695 static const char * const selections[] = {
696 "same residue as atomnr 1 4 12"
698 runTest("simple.gro", selections);
702 TEST_F(SelectionCollectionDataTest, HandlesSameResidueName)
704 static const char * const selections[] = {
705 "same resname as atomnr 1 14"
707 runTest("simple.gro", selections);
711 TEST_F(SelectionCollectionDataTest, HandlesPositionKeywords)
713 static const char * const selections[] = {
715 "res_cog of name CB and resnr 1 3",
716 "whole_res_cog of name CB and resnr 1 3",
717 "part_res_cog of x < 3",
718 "dyn_res_cog of x < 3"
720 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
721 | efTestPositionAtoms);
722 runTest("simple.gro", selections);
726 TEST_F(SelectionCollectionDataTest, HandlesDistanceKeyword)
728 static const char * const selections[] = {
729 "distance from cog of resnr 1 < 2"
731 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
732 runTest("simple.gro", selections);
736 TEST_F(SelectionCollectionDataTest, HandlesMinDistanceKeyword)
738 static const char * const selections[] = {
739 "mindistance from resnr 1 < 2"
741 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
742 runTest("simple.gro", selections);
746 TEST_F(SelectionCollectionDataTest, HandlesWithinKeyword)
748 static const char * const selections[] = {
749 "within 1 of resnr 2"
751 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
752 runTest("simple.gro", selections);
756 TEST_F(SelectionCollectionDataTest, HandlesInSolidAngleKeyword)
758 // Both of these should evaluate to empty on a correct implementation.
759 static const char * const selections[] = {
760 "resname TP and not insolidangle center cog of resname C span resname R cutoff 20",
761 "resname TN and insolidangle center cog of resname C span resname R cutoff 20"
763 setFlags(TestFlags() | efDontTestCompiledAtoms | efTestEvaluation);
764 runTest("sphere.gro", selections);
768 TEST_F(SelectionCollectionDataTest, HandlesPermuteModifier)
770 static const char * const selections[] = {
772 "res_cog of resnr 1 to 4 permute 2 1",
773 "name CB S1 and res_cog x < 3 permute 2 1"
775 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
776 | efTestPositionAtoms | efTestPositionMapping);
777 runTest("simple.gro", selections);
781 TEST_F(SelectionCollectionDataTest, HandlesPlusModifier)
783 static const char * const selections[] = {
784 "name S2 plus name S1",
785 "res_cog of resnr 2 plus res_cog of resnr 1 plus res_cog of resnr 3",
786 "name S1 and y < 3 plus res_cog of x < 2.5"
788 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
789 | efTestPositionAtoms | efTestPositionMapping);
790 runTest("simple.gro", selections);
794 TEST_F(SelectionCollectionDataTest, HandlesMergeModifier)
796 static const char * const selections[] = {
797 "name S2 merge name S1",
798 "resnr 1 2 and name S2 merge resnr 1 2 and name S1 merge res_cog of resnr 1 2",
799 "name S1 and x < 2.5 merge res_cog of x < 2.5"
801 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
802 | efTestPositionAtoms | efTestPositionMapping);
803 runTest("simple.gro", selections);
807 /********************************************************************
808 * Tests for generic selection evaluation
811 TEST_F(SelectionCollectionDataTest, ComputesMassesAndCharges)
813 static const char * const selections[] = {
818 setFlags(TestFlags() | efTestEvaluation | efTestPositionAtoms
819 | efTestPositionMasses | efTestPositionCharges);
820 ASSERT_NO_FATAL_FAILURE(runParser(selections));
821 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
822 for (int i = 0; i < top_->atoms.nr; ++i)
824 top_->atoms.atom[i].m = 1.0 + i / 100.0;
825 top_->atoms.atom[i].q = -(1.0 + i / 100.0);
827 ASSERT_NO_FATAL_FAILURE(runCompiler());
828 ASSERT_NO_FATAL_FAILURE(runEvaluate());
829 ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
832 TEST_F(SelectionCollectionDataTest, ComputesMassesAndChargesWithoutTopology)
834 static const char * const selections[] = {
835 "atomnr 1 to 3 8 to 9",
839 setFlags(TestFlags() | efTestPositionAtoms
840 | efTestPositionMasses | efTestPositionCharges);
841 runTest(10, selections);
845 /********************************************************************
846 * Tests for selection syntactic constructs
849 TEST_F(SelectionCollectionDataTest, HandlesConstantPositions)
851 static const char * const selections[] = {
854 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
855 runTest("simple.gro", selections);
859 TEST_F(SelectionCollectionDataTest, HandlesWithinConstantPositions)
861 static const char * const selections[] = {
862 "within 1 of [2, 1, 0]"
864 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
865 runTest("simple.gro", selections);
869 TEST_F(SelectionCollectionDataTest, HandlesForcedStringMatchingMode)
871 static const char * const selections[] = {
875 runTest("simple.gro", selections);
879 TEST_F(SelectionCollectionDataTest, HandlesWildcardMatching)
881 static const char * const selections[] = {
885 runTest("simple.gro", selections);
889 TEST_F(SelectionCollectionDataTest, HandlesRegexMatching)
891 static const char * const selections[] = {
893 "resname ~ \"R[BD]\""
895 if (gmx::Regex::isSupported())
897 runTest("simple.gro", selections);
902 TEST_F(SelectionCollectionDataTest, HandlesBasicBoolean)
904 static const char * const selections[] = {
905 "atomnr 1 to 5 and atomnr 2 to 7",
906 "atomnr 1 to 5 or not atomnr 3 to 8",
907 "not not atomnr 1 to 5 and atomnr 2 to 6 and not not atomnr 3 to 7",
908 "atomnr 1 to 5 and (atomnr 2 to 7 and atomnr 3 to 6)",
909 "x < 5 and atomnr 1 to 5 and y < 3 and atomnr 2 to 4"
911 runTest(10, selections);
915 TEST_F(SelectionCollectionDataTest, HandlesDynamicAtomValuedParameters)
917 static const char * const selections[] = {
918 "same residue as (atomnr 3 5 13 or y > 5)",
919 "(resnr 1 3 5 or x > 10) and same residue as (atomnr 3 5 13 or y > 5)"
921 setFlags(TestFlags() | efTestEvaluation);
922 runTest("simple.gro", selections);
926 TEST_F(SelectionCollectionDataTest, HandlesNumericComparisons)
928 static const char * const selections[] = {
935 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
936 runTest("simple.gro", selections);
940 TEST_F(SelectionCollectionDataTest, HandlesArithmeticExpressions)
942 static const char * const selections[] = {
948 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
949 runTest("simple.gro", selections);
953 TEST_F(SelectionCollectionDataTest, HandlesNumericVariables)
955 static const char * const selections[] = {
961 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
962 runTest("simple.gro", selections);
966 TEST_F(SelectionCollectionDataTest, HandlesComplexNumericVariables)
968 static const char * const selections[] = {
970 "resname RA and value <= 4",
971 "resname RA RB and x < 3 and value <= 4",
973 "resname RA and index < 3",
974 "resname RB and y < 3 and index < 6"
976 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
977 runTest("simple.gro", selections);
981 TEST_F(SelectionCollectionDataTest, HandlesPositionVariables)
983 static const char * const selections[] = {
984 "foo = res_cog of resname RA",
987 "bar = cog of resname RA",
991 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
992 runTest("simple.gro", selections);
996 TEST_F(SelectionCollectionDataTest, HandlesConstantPositionInVariable)
998 static const char * const selections[] = {
999 "constpos = [1.0, 2.5, 0.5]",
1001 "within 2 of constpos"
1003 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
1004 | efTestPositionAtoms);
1005 runTest("simple.gro", selections);
1009 TEST_F(SelectionCollectionDataTest, HandlesNumericConstantsInVariables)
1011 static const char * const selections[] = {
1016 "x + constreal1 < constreal2"
1018 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
1019 runTest("simple.gro", selections);
1023 /********************************************************************
1024 * Tests for complex boolean syntax
1027 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysis)
1029 static const char * const selections[] = {
1030 "atomnr 1 to 5 and atomnr 2 to 7 and x < 2",
1031 "atomnr 1 to 5 and (atomnr 4 to 7 or x < 2)",
1032 "atomnr 1 to 5 and y < 3 and (atomnr 4 to 7 or x < 2)",
1033 "atomnr 1 to 5 and not (atomnr 4 to 7 or x < 2)",
1034 "atomnr 1 to 5 or (atomnr 4 to 6 and (atomnr 5 to 7 or x < 2))"
1036 runTest(10, selections);
1040 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithVariables)
1042 static const char * const selections[] = {
1043 "foo = atomnr 4 to 7 or x < 2",
1044 "atomnr 1 to 4 and foo",
1045 "atomnr 2 to 6 and y < 3 and foo",
1046 "atomnr 6 to 10 and not foo"
1048 runTest(10, selections);
1052 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithMoreVariables)
1054 static const char * const selections[] = {
1055 "foo = atomnr 4 to 7",
1056 "bar = foo and x < 2",
1057 "bar2 = foo and y < 2",
1058 "atomnr 1 to 4 and bar",
1059 "atomnr 2 to 6 and y < 3 and bar2",
1060 "atomnr 6 to 10 and not foo"
1062 runTest(10, selections);
1066 /********************************************************************
1067 * Tests for complex subexpression cases
1069 * These tests use some knowledge of the implementation to trigger different
1070 * paths in the code.
1073 TEST_F(SelectionCollectionDataTest, HandlesUnusedVariables)
1075 static const char * const selections[] = {
1076 "unused1 = atomnr 1 to 3",
1077 "foo = atomnr 4 to 7",
1078 "atomnr 1 to 6 and foo",
1079 "unused2 = atomnr 3 to 5"
1081 runTest(10, selections);
1085 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithStaticEvaluationGroups)
1087 static const char * const selections[] = {
1088 "foo = atomnr 4 to 7 and x < 2",
1089 "atomnr 1 to 5 and foo",
1090 "atomnr 3 to 7 and foo"
1092 runTest(10, selections);
1096 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithMixedEvaluationGroups)
1098 static const char * const selections[] = {
1099 "foo = atomnr 4 to 7 and x < 2",
1100 "atomnr 1 to 6 and foo",
1104 runTest(10, selections);
1108 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithMixedEvaluationGroups2)
1110 static const char * const selections[] = {
1111 "foo = atomnr 1 to 8 and x < 10",
1112 "atomnr 1 to 5 and y < 10 and foo",
1115 setFlags(TestFlags() | efTestEvaluation);
1116 runTest("simple.gro", selections);