2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source 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
44 #include "gromacs/selection/selectioncollection.h"
46 #include <gtest/gtest.h>
48 #include "gromacs/fileio/trx.h"
49 #include "gromacs/options/basicoptions.h"
50 #include "gromacs/options/options.h"
51 #include "gromacs/selection/indexutil.h"
52 #include "gromacs/selection/selection.h"
53 #include "gromacs/topology/topology.h"
54 #include "gromacs/utility/arrayref.h"
55 #include "gromacs/utility/exceptions.h"
56 #include "gromacs/utility/flags.h"
57 #include "gromacs/utility/gmxregex.h"
58 #include "gromacs/utility/stringutil.h"
60 #include "testutils/interactivetest.h"
61 #include "testutils/refdata.h"
62 #include "testutils/testasserts.h"
63 #include "testutils/testfilemanager.h"
64 #include "testutils/testoptions.h"
71 /********************************************************************
72 * Test fixture for selection testing
75 class SelectionCollectionTest : public ::testing::Test
78 static int s_debugLevel;
80 SelectionCollectionTest();
81 ~SelectionCollectionTest();
83 void setAtomCount(int natoms)
85 ASSERT_NO_THROW_GMX(sc_.setTopology(NULL, natoms));
87 void loadTopology(const char *filename);
89 void loadIndexGroups(const char *filename);
91 gmx::test::TopologyManager topManager_;
92 gmx::SelectionCollection sc_;
93 gmx::SelectionList sel_;
96 gmx_ana_indexgrps_t *grps_;
99 int SelectionCollectionTest::s_debugLevel = 0;
101 // \cond/\endcond do not seem to work here with Doxygen 1.8.5 parser.
103 GMX_TEST_OPTIONS(SelectionCollectionTestOptions, options)
105 options->addOption(gmx::IntegerOption("seldebug")
106 .store(&SelectionCollectionTest::s_debugLevel)
107 .description("Set selection debug level"));
111 SelectionCollectionTest::SelectionCollectionTest()
112 : top_(NULL), frame_(NULL), grps_(NULL)
114 topManager_.requestFrame();
115 sc_.setDebugLevel(s_debugLevel);
116 sc_.setReferencePosType("atom");
117 sc_.setOutputPosType("atom");
120 SelectionCollectionTest::~SelectionCollectionTest()
124 gmx_ana_indexgrps_free(grps_);
129 SelectionCollectionTest::loadTopology(const char *filename)
131 topManager_.loadTopology(filename);
136 SelectionCollectionTest::setTopology()
138 top_ = topManager_.topology();
139 frame_ = topManager_.frame();
141 ASSERT_NO_THROW_GMX(sc_.setTopology(top_, -1));
145 SelectionCollectionTest::loadIndexGroups(const char *filename)
147 GMX_RELEASE_ASSERT(grps_ == NULL,
148 "External groups can only be loaded once");
149 std::string fullpath =
150 gmx::test::TestFileManager::getInputFilePath(filename);
151 gmx_ana_indexgrps_init(&grps_, NULL, fullpath.c_str());
152 sc_.setIndexGroups(grps_);
156 /********************************************************************
157 * Test fixture for interactive SelectionCollection tests
160 class SelectionCollectionInteractiveTest : public SelectionCollectionTest
163 SelectionCollectionInteractiveTest()
164 : helper_(data_.rootChecker())
168 void runTest(int count, bool bInteractive,
169 const gmx::ConstArrayRef<const char *> &input);
171 gmx::test::TestReferenceData data_;
172 gmx::test::InteractiveTestHelper helper_;
175 void SelectionCollectionInteractiveTest::runTest(
176 int count, bool bInteractive,
177 const gmx::ConstArrayRef<const char *> &inputLines)
179 helper_.setInputLines(inputLines);
180 // TODO: Check something about the returned selections as well.
181 ASSERT_NO_THROW_GMX(sc_.parseInteractive(
182 count, &helper_.inputStream(),
183 bInteractive ? &helper_.outputStream() : NULL,
184 "for test context"));
185 helper_.checkSession();
189 /********************************************************************
190 * Test fixture for selection testing with reference data
193 class SelectionCollectionDataTest : public SelectionCollectionTest
198 efTestEvaluation = 1<<0,
199 efTestPositionAtoms = 1<<1,
200 efTestPositionCoordinates = 1<<2,
201 efTestPositionMapping = 1<<3,
202 efTestPositionMasses = 1<<4,
203 efTestPositionCharges = 1<<5,
204 efTestSelectionNames = 1<<6,
205 efDontTestCompiledAtoms = 1<<8
207 typedef gmx::FlagsTemplate<TestFlag> TestFlags;
209 SelectionCollectionDataTest()
210 : checker_(data_.rootChecker()), count_(0), framenr_(0)
214 void setFlags(TestFlags flags) { flags_ = flags; }
216 void runParser(const gmx::ConstArrayRef<const char *> &selections);
219 void runEvaluateFinal();
221 void runTest(int natoms,
222 const gmx::ConstArrayRef<const char *> &selections);
223 void runTest(const char *filename,
224 const gmx::ConstArrayRef<const char *> &selections);
227 static void checkSelection(gmx::test::TestReferenceChecker *checker,
228 const gmx::Selection &sel, TestFlags flags);
230 void checkCompiled();
232 gmx::test::TestReferenceData data_;
233 gmx::test::TestReferenceChecker checker_;
241 SelectionCollectionDataTest::checkSelection(
242 gmx::test::TestReferenceChecker *checker,
243 const gmx::Selection &sel, TestFlags flags)
245 using gmx::test::TestReferenceChecker;
248 gmx::ConstArrayRef<int> atoms = sel.atomIndices();
249 checker->checkSequence(atoms.begin(), atoms.end(), "Atoms");
251 if (flags.test(efTestPositionAtoms)
252 || flags.test(efTestPositionCoordinates)
253 || flags.test(efTestPositionMapping)
254 || flags.test(efTestPositionMasses)
255 || flags.test(efTestPositionCharges))
257 TestReferenceChecker compound(
258 checker->checkSequenceCompound("Positions", sel.posCount()));
259 for (int i = 0; i < sel.posCount(); ++i)
261 TestReferenceChecker poscompound(compound.checkCompound("Position", NULL));
262 const gmx::SelectionPosition &p = sel.position(i);
263 if (flags.test(efTestPositionAtoms))
265 gmx::ConstArrayRef<int> atoms = p.atomIndices();
266 poscompound.checkSequence(atoms.begin(), atoms.end(), "Atoms");
268 if (flags.test(efTestPositionCoordinates))
270 poscompound.checkVector(p.x(), "Coordinates");
272 if (flags.test(efTestPositionMapping))
274 poscompound.checkInteger(p.refId(), "RefId");
275 poscompound.checkInteger(p.mappedId(), "MappedId");
277 if (flags.test(efTestPositionMasses))
279 poscompound.checkReal(p.mass(), "Mass");
281 if (flags.test(efTestPositionCharges))
283 poscompound.checkReal(p.charge(), "Charge");
291 SelectionCollectionDataTest::runParser(
292 const gmx::ConstArrayRef<const char *> &selections)
294 using gmx::test::TestReferenceChecker;
296 TestReferenceChecker compound(checker_.checkCompound("ParsedSelections", "Parsed"));
299 for (size_t i = 0; i < selections.size(); ++i)
301 SCOPED_TRACE(std::string("Parsing selection \"")
302 + selections[i] + "\"");
303 gmx::SelectionList result;
304 ASSERT_NO_THROW_GMX(result = sc_.parseFromString(selections[i]));
305 sel_.insert(sel_.end(), result.begin(), result.end());
306 if (sel_.size() == count_)
308 std::string id = gmx::formatString("Variable%d", static_cast<int>(varcount + 1));
309 TestReferenceChecker varcompound(
310 compound.checkCompound("ParsedVariable", id.c_str()));
311 varcompound.checkString(selections[i], "Input");
316 std::string id = gmx::formatString("Selection%d", static_cast<int>(count_ + 1));
317 TestReferenceChecker selcompound(
318 compound.checkCompound("ParsedSelection", id.c_str()));
319 selcompound.checkString(selections[i], "Input");
320 if (flags_.test(efTestSelectionNames))
322 selcompound.checkString(sel_[count_].name(), "Name");
324 selcompound.checkString(sel_[count_].selectionText(), "Text");
325 selcompound.checkBoolean(sel_[count_].isDynamic(), "Dynamic");
333 SelectionCollectionDataTest::runCompiler()
335 ASSERT_NO_THROW_GMX(sc_.compile());
336 ASSERT_EQ(count_, sel_.size());
342 SelectionCollectionDataTest::checkCompiled()
344 using gmx::test::TestReferenceChecker;
345 const TestFlags mask = ~TestFlags(efTestPositionCoordinates);
347 TestReferenceChecker compound(checker_.checkCompound("CompiledSelections", "Compiled"));
348 for (size_t i = 0; i < count_; ++i)
350 SCOPED_TRACE(std::string("Checking selection \"") +
351 sel_[i].selectionText() + "\"");
352 std::string id = gmx::formatString("Selection%d", static_cast<int>(i + 1));
353 TestReferenceChecker selcompound(
354 compound.checkCompound("Selection", id.c_str()));
355 if (flags_.test(efTestSelectionNames))
357 selcompound.checkString(sel_[i].name(), "Name");
359 if (!flags_.test(efDontTestCompiledAtoms))
361 checkSelection(&selcompound, sel_[i], flags_ & mask);
368 SelectionCollectionDataTest::runEvaluate()
370 using gmx::test::TestReferenceChecker;
373 ASSERT_NO_THROW_GMX(sc_.evaluate(frame_, NULL));
374 std::string frame = gmx::formatString("Frame%d", framenr_);
375 TestReferenceChecker compound(
376 checker_.checkCompound("EvaluatedSelections", frame.c_str()));
377 for (size_t i = 0; i < count_; ++i)
379 SCOPED_TRACE(std::string("Checking selection \"") +
380 sel_[i].selectionText() + "\"");
381 std::string id = gmx::formatString("Selection%d", static_cast<int>(i + 1));
382 TestReferenceChecker selcompound(
383 compound.checkCompound("Selection", id.c_str()));
384 checkSelection(&selcompound, sel_[i], flags_);
390 SelectionCollectionDataTest::runEvaluateFinal()
392 ASSERT_NO_THROW_GMX(sc_.evaluateFinal(framenr_));
398 SelectionCollectionDataTest::runTest(
399 int natoms, const gmx::ConstArrayRef<const char *> &selections)
401 ASSERT_NO_FATAL_FAILURE(runParser(selections));
402 ASSERT_NO_FATAL_FAILURE(setAtomCount(natoms));
403 ASSERT_NO_FATAL_FAILURE(runCompiler());
408 SelectionCollectionDataTest::runTest(
409 const char *filename, const gmx::ConstArrayRef<const char *> &selections)
411 ASSERT_NO_FATAL_FAILURE(runParser(selections));
412 ASSERT_NO_FATAL_FAILURE(loadTopology(filename));
413 ASSERT_NO_FATAL_FAILURE(runCompiler());
414 if (flags_.test(efTestEvaluation))
416 ASSERT_NO_FATAL_FAILURE(runEvaluate());
417 ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
422 /********************************************************************
423 * Tests for SelectionCollection functionality without reference data
426 TEST_F(SelectionCollectionTest, HandlesNoSelections)
428 EXPECT_FALSE(sc_.requiresTopology());
429 EXPECT_NO_THROW_GMX(sc_.compile());
432 TEST_F(SelectionCollectionTest, HandlesVelocityAndForceRequests)
434 ASSERT_NO_THROW_GMX(sel_ = sc_.parseFromString("atomnr 1 to 10; none"));
435 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
436 ASSERT_EQ(2U, sel_.size());
437 ASSERT_NO_THROW_GMX(sel_[0].setEvaluateVelocities(true));
438 ASSERT_NO_THROW_GMX(sel_[1].setEvaluateVelocities(true));
439 ASSERT_NO_THROW_GMX(sel_[0].setEvaluateForces(true));
440 ASSERT_NO_THROW_GMX(sel_[1].setEvaluateForces(true));
441 ASSERT_NO_THROW_GMX(sc_.compile());
442 EXPECT_TRUE(sel_[0].hasVelocities());
443 EXPECT_TRUE(sel_[1].hasVelocities());
444 EXPECT_TRUE(sel_[0].hasForces());
445 EXPECT_TRUE(sel_[1].hasForces());
448 TEST_F(SelectionCollectionTest, ParsesSelectionsFromFile)
450 ASSERT_NO_THROW_GMX(sel_ = sc_.parseFromFile(
451 gmx::test::TestFileManager::getInputFilePath("selfile.dat")));
452 // These should match the contents of selfile.dat
453 ASSERT_EQ(2U, sel_.size());
454 EXPECT_STREQ("resname RA RB", sel_[0].selectionText());
455 EXPECT_STREQ("resname RB RC", sel_[1].selectionText());
458 TEST_F(SelectionCollectionTest, HandlesAtypicalWhitespace)
460 ASSERT_NO_THROW_GMX(sel_ = sc_.parseFromString("atomnr\n1\r\nto\t10;\vatomnr 3\f to 14\r"));
461 ASSERT_EQ(2U, sel_.size());
462 EXPECT_STREQ("atomnr 1 to 10", sel_[0].selectionText());
463 // TODO: Get rid of the trailing whitespace.
464 EXPECT_STREQ("atomnr 3 to 14 ", sel_[1].selectionText());
467 TEST_F(SelectionCollectionTest, HandlesInvalidRegularExpressions)
469 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
471 sc_.parseFromString("resname ~ \"R[A\"");
473 }, gmx::InvalidInputError);
476 TEST_F(SelectionCollectionTest, HandlesUnsupportedRegularExpressions)
478 if (!gmx::Regex::isSupported())
480 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
482 sc_.parseFromString("resname \"R[AD]\"");
484 }, gmx::InvalidInputError);
488 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue)
490 EXPECT_THROW_GMX(sc_.parseFromString("mindist from atomnr 1 cutoff"),
491 gmx::InvalidInputError);
494 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue2)
496 EXPECT_THROW_GMX(sc_.parseFromString("within 1 of"),
497 gmx::InvalidInputError);
500 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue3)
502 EXPECT_THROW_GMX(sc_.parseFromString("within of atomnr 1"),
503 gmx::InvalidInputError);
506 // TODO: Tests for more parser errors
508 TEST_F(SelectionCollectionTest, HandlesUnknownGroupReferenceParser1)
510 ASSERT_NO_THROW_GMX(sc_.setIndexGroups(NULL));
511 EXPECT_THROW_GMX(sc_.parseFromString("group \"foo\""), gmx::InconsistentInputError);
512 EXPECT_THROW_GMX(sc_.parseFromString("4"), gmx::InconsistentInputError);
515 TEST_F(SelectionCollectionTest, HandlesUnknownGroupReferenceParser2)
517 ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
518 EXPECT_THROW_GMX(sc_.parseFromString("group \"foo\""), gmx::InconsistentInputError);
519 EXPECT_THROW_GMX(sc_.parseFromString("4"), gmx::InconsistentInputError);
522 TEST_F(SelectionCollectionTest, HandlesUnknownGroupReferenceDelayed1)
524 ASSERT_NO_THROW_GMX(sc_.parseFromString("group \"foo\""));
525 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
526 EXPECT_THROW_GMX(sc_.setIndexGroups(NULL), gmx::InconsistentInputError);
527 EXPECT_THROW_GMX(sc_.compile(), gmx::APIError);
530 TEST_F(SelectionCollectionTest, HandlesUnknownGroupReferenceDelayed2)
532 ASSERT_NO_THROW_GMX(sc_.parseFromString("group 4; group \"foo\""));
533 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
534 EXPECT_THROW_GMX(loadIndexGroups("simple.ndx"), gmx::InconsistentInputError);
535 EXPECT_THROW_GMX(sc_.compile(), gmx::APIError);
538 TEST_F(SelectionCollectionTest, HandlesUnsortedGroupReference)
540 ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
541 EXPECT_THROW_GMX(sc_.parseFromString("atomnr 1 to 3 and group \"GrpUnsorted\""),
542 gmx::InconsistentInputError);
543 EXPECT_THROW_GMX(sc_.parseFromString("group 2 or atomnr 2 to 5"),
544 gmx::InconsistentInputError);
545 EXPECT_THROW_GMX(sc_.parseFromString("within 1 of group 2"),
546 gmx::InconsistentInputError);
549 TEST_F(SelectionCollectionTest, HandlesUnsortedGroupReferenceDelayed)
551 ASSERT_NO_THROW_GMX(sc_.parseFromString("atomnr 1 to 3 and group \"GrpUnsorted\""));
552 ASSERT_NO_THROW_GMX(sc_.parseFromString("atomnr 1 to 3 and group 2"));
553 EXPECT_THROW_GMX(loadIndexGroups("simple.ndx"), gmx::InconsistentInputError);
554 // TODO: Add a separate check in the selection compiler for a safer API
555 // (makes sense in the future if the compiler needs the information for
556 // other purposes as well).
557 // EXPECT_THROW_GMX(sc_.compile(), gmx::APIError);
560 TEST_F(SelectionCollectionTest, HandlesOutOfRangeAtomIndexInGroup)
562 ASSERT_NO_THROW_GMX(sc_.setTopology(NULL, 5));
563 ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
564 EXPECT_THROW_GMX(sc_.parseFromString("group \"GrpB\""), gmx::InconsistentInputError);
567 TEST_F(SelectionCollectionTest, HandlesOutOfRangeAtomIndexInGroupDelayed)
569 ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
570 ASSERT_NO_THROW_GMX(sc_.parseFromString("group \"GrpB\""));
571 EXPECT_THROW_GMX(sc_.setTopology(NULL, 5), gmx::InconsistentInputError);
574 TEST_F(SelectionCollectionTest, HandlesOutOfRangeAtomIndexInGroupDelayed2)
576 ASSERT_NO_THROW_GMX(sc_.setTopology(NULL, 5));
577 ASSERT_NO_THROW_GMX(sc_.parseFromString("group \"GrpB\""));
578 EXPECT_THROW_GMX(loadIndexGroups("simple.ndx"), gmx::InconsistentInputError);
581 TEST_F(SelectionCollectionTest, RecoversFromMissingMoleculeInfo)
583 ASSERT_NO_THROW_GMX(sc_.parseFromString("molindex 1 to 5"));
584 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
585 EXPECT_THROW_GMX(sc_.compile(), gmx::InconsistentInputError);
588 TEST_F(SelectionCollectionTest, RecoversFromMissingAtomTypes)
590 ASSERT_NO_THROW_GMX(sc_.parseFromString("type CA"));
591 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
592 EXPECT_THROW_GMX(sc_.compile(), gmx::InconsistentInputError);
595 TEST_F(SelectionCollectionTest, RecoversFromMissingPDBInfo)
597 ASSERT_NO_THROW_GMX(sc_.parseFromString("altloc A"));
598 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
599 EXPECT_THROW_GMX(sc_.compile(), gmx::InconsistentInputError);
602 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation)
604 ASSERT_NO_THROW_GMX(sc_.parseFromString("all permute 1 1"));
605 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
606 EXPECT_THROW_GMX(sc_.compile(), gmx::InvalidInputError);
609 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation2)
611 ASSERT_NO_THROW_GMX(sc_.parseFromString("all permute 3 2 1"));
612 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
613 EXPECT_THROW_GMX(sc_.compile(), gmx::InconsistentInputError);
616 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation3)
618 ASSERT_NO_THROW_GMX(sc_.parseFromString("x < 1.5 permute 3 2 1"));
619 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
620 ASSERT_NO_THROW_GMX(sc_.compile());
621 EXPECT_THROW_GMX(sc_.evaluate(frame_, NULL), gmx::InconsistentInputError);
624 TEST_F(SelectionCollectionTest, HandlesFramesWithTooSmallAtomSubsets)
626 ASSERT_NO_THROW_GMX(sc_.parseFromString("atomnr 3 to 10"));
627 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
628 ASSERT_NO_THROW_GMX(sc_.compile());
630 EXPECT_THROW_GMX(sc_.evaluate(frame_, NULL), gmx::InconsistentInputError);
633 TEST_F(SelectionCollectionTest, HandlesFramesWithTooSmallAtomSubsets2)
635 // Evaluating the positions will require atoms 1-9.
636 ASSERT_NO_THROW_GMX(sc_.parseFromString("whole_res_com of atomnr 2 5 7"));
637 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
638 ASSERT_NO_THROW_GMX(sc_.compile());
640 EXPECT_THROW_GMX(sc_.evaluate(frame_, NULL), gmx::InconsistentInputError);
643 TEST_F(SelectionCollectionTest, HandlesFramesWithTooSmallAtomSubsets3)
645 ASSERT_NO_THROW_GMX(sc_.parseFromString("mindistance from atomnr 1 to 5 < 2"));
646 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
647 ASSERT_NO_THROW_GMX(sc_.compile());
649 EXPECT_THROW_GMX(sc_.evaluate(frame_, NULL), gmx::InconsistentInputError);
652 // TODO: Tests for more evaluation errors
654 /********************************************************************
655 * Tests for interactive selection input
658 TEST_F(SelectionCollectionInteractiveTest, HandlesBasicInput)
660 const char *const input[] = {
663 "\"Name\" resname RC"
665 runTest(-1, true, input);
668 TEST_F(SelectionCollectionInteractiveTest, HandlesContinuation)
670 const char *const input[] = {
674 runTest(-1, true, input);
677 TEST_F(SelectionCollectionInteractiveTest, HandlesSingleSelectionInput)
679 const char *const input[] = {
683 runTest(1, true, input);
686 TEST_F(SelectionCollectionInteractiveTest, HandlesTwoSelectionInput)
688 const char *const input[] = {
692 runTest(2, true, input);
695 TEST_F(SelectionCollectionInteractiveTest, HandlesStatusWithGroups)
697 const char *const input[] = {
701 loadIndexGroups("simple.ndx");
702 runTest(-1, true, input);
705 TEST_F(SelectionCollectionInteractiveTest, HandlesStatusWithExistingSelections)
707 const char *const input[] = {
713 ASSERT_NO_THROW_GMX(sc_.parseFromString("foo = resname RA"));
714 ASSERT_NO_THROW_GMX(sc_.parseFromString("resname RB"));
715 runTest(-1, true, input);
718 TEST_F(SelectionCollectionInteractiveTest, HandlesSingleSelectionInputStatus)
720 const char *const input[] = {
725 runTest(1, true, input);
728 TEST_F(SelectionCollectionInteractiveTest, HandlesTwoSelectionInputStatus)
730 const char *const input[] = {
731 "\"Sel\" resname RA",
735 runTest(2, true, input);
738 TEST_F(SelectionCollectionInteractiveTest, HandlesMultiSelectionInputStatus)
740 const char *const input[] = {
741 "\"Sel\" resname RA",
742 "\"Sel2\" resname RB",
745 runTest(-1, true, input);
748 TEST_F(SelectionCollectionInteractiveTest, HandlesNoFinalNewline)
750 // TODO: There is an extra prompt printed after the input is finished; it
751 // would be cleaner not to have it, but it's only a cosmetic issue.
752 const char *const input[] = {
755 helper_.setLastNewline(false);
756 runTest(-1, true, input);
759 TEST_F(SelectionCollectionInteractiveTest, HandlesEmptySelections)
761 const char *const input[] = {
767 runTest(-1, true, input);
770 TEST_F(SelectionCollectionInteractiveTest, HandlesMultipleSelectionsOnLine)
772 const char *const input[] = {
773 "resname RA; resname RB and \\",
776 runTest(2, true, input);
779 TEST_F(SelectionCollectionInteractiveTest, HandlesNoninteractiveInput)
781 const char *const input[] = {
784 "\"Name\" resname RC"
786 runTest(-1, false, input);
789 TEST_F(SelectionCollectionInteractiveTest, HandlesSingleSelectionInputNoninteractively)
791 const char *const input[] = {
795 runTest(1, false, input);
799 /********************************************************************
800 * Tests for selection keywords
803 TEST_F(SelectionCollectionDataTest, HandlesAllNone)
805 static const char * const selections[] = {
809 runTest(10, selections);
812 TEST_F(SelectionCollectionDataTest, HandlesAtomnr)
814 static const char * const selections[] = {
815 "atomnr 1 to 3 6 to 8",
819 runTest(10, selections);
822 TEST_F(SelectionCollectionDataTest, HandlesResnr)
824 static const char * const selections[] = {
828 runTest("simple.gro", selections);
831 TEST_F(SelectionCollectionDataTest, HandlesResIndex)
833 static const char * const selections[] = {
837 runTest("simple.pdb", selections);
840 TEST_F(SelectionCollectionDataTest, HandlesMolIndex)
842 static const char * const selections[] = {
846 ASSERT_NO_FATAL_FAILURE(runParser(selections));
847 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
848 topManager_.initUniformMolecules(3);
849 ASSERT_NO_FATAL_FAILURE(runCompiler());
852 TEST_F(SelectionCollectionDataTest, HandlesAtomname)
854 static const char * const selections[] = {
858 runTest("simple.gro", selections);
861 TEST_F(SelectionCollectionDataTest, HandlesPdbAtomname)
863 static const char * const selections[] = {
869 runTest("simple.pdb", selections);
873 TEST_F(SelectionCollectionDataTest, HandlesAtomtype)
875 static const char * const selections[] = {
878 ASSERT_NO_FATAL_FAILURE(runParser(selections));
879 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
880 const char *const types[] = { "CA", "SA", "SB" };
881 topManager_.initAtomTypes(types);
882 ASSERT_NO_FATAL_FAILURE(runCompiler());
885 TEST_F(SelectionCollectionDataTest, HandlesChain)
887 static const char * const selections[] = {
891 runTest("simple.pdb", selections);
894 TEST_F(SelectionCollectionDataTest, HandlesMass)
896 static const char * const selections[] = {
899 ASSERT_NO_FATAL_FAILURE(runParser(selections));
900 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
901 for (int i = 0; i < top_->atoms.nr; ++i)
903 top_->atoms.atom[i].m = 1.0 + i;
905 ASSERT_NO_FATAL_FAILURE(runCompiler());
908 TEST_F(SelectionCollectionDataTest, HandlesCharge)
910 static const char * const selections[] = {
913 ASSERT_NO_FATAL_FAILURE(runParser(selections));
914 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
915 for (int i = 0; i < top_->atoms.nr; ++i)
917 top_->atoms.atom[i].q = i / 10.0;
919 ASSERT_NO_FATAL_FAILURE(runCompiler());
922 TEST_F(SelectionCollectionDataTest, HandlesAltLoc)
924 static const char * const selections[] = {
928 runTest("simple.pdb", selections);
931 TEST_F(SelectionCollectionDataTest, HandlesInsertCode)
933 static const char * const selections[] = {
937 runTest("simple.pdb", selections);
940 TEST_F(SelectionCollectionDataTest, HandlesOccupancy)
942 static const char * const selections[] = {
946 runTest("simple.pdb", selections);
949 TEST_F(SelectionCollectionDataTest, HandlesBeta)
951 static const char * const selections[] = {
955 runTest("simple.pdb", selections);
958 TEST_F(SelectionCollectionDataTest, HandlesResname)
960 static const char * const selections[] = {
964 runTest("simple.gro", selections);
967 TEST_F(SelectionCollectionDataTest, HandlesCoordinateKeywords)
969 static const char * const selections[] = {
974 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
975 runTest("simple.gro", selections);
979 TEST_F(SelectionCollectionDataTest, HandlesSameResidue)
981 static const char * const selections[] = {
982 "same residue as atomnr 1 4 12"
984 runTest("simple.gro", selections);
988 TEST_F(SelectionCollectionDataTest, HandlesSameResidueName)
990 static const char * const selections[] = {
991 "same resname as atomnr 1 14"
993 runTest("simple.gro", selections);
997 TEST_F(SelectionCollectionDataTest, HandlesPositionKeywords)
999 static const char * const selections[] = {
1001 "res_cog of name CB and resnr 1 3",
1002 "whole_res_cog of name CB and resnr 1 3",
1003 "part_res_cog of x < 3",
1004 "dyn_res_cog of x < 3"
1006 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
1007 | efTestPositionAtoms);
1008 runTest("simple.gro", selections);
1012 TEST_F(SelectionCollectionDataTest, HandlesDistanceKeyword)
1014 static const char * const selections[] = {
1015 "distance from cog of resnr 1 < 2"
1017 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
1018 runTest("simple.gro", selections);
1022 TEST_F(SelectionCollectionDataTest, HandlesMinDistanceKeyword)
1024 static const char * const selections[] = {
1025 "mindistance from resnr 1 < 2"
1027 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
1028 runTest("simple.gro", selections);
1032 TEST_F(SelectionCollectionDataTest, HandlesWithinKeyword)
1034 static const char * const selections[] = {
1035 "within 1 of resnr 2"
1037 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
1038 runTest("simple.gro", selections);
1042 TEST_F(SelectionCollectionDataTest, HandlesInSolidAngleKeyword)
1044 // Both of these should evaluate to empty on a correct implementation.
1045 static const char * const selections[] = {
1046 "resname TP and not insolidangle center cog of resname C span resname R cutoff 20",
1047 "resname TN and insolidangle center cog of resname C span resname R cutoff 20"
1049 setFlags(TestFlags() | efDontTestCompiledAtoms | efTestEvaluation);
1050 runTest("sphere.gro", selections);
1054 TEST_F(SelectionCollectionDataTest, HandlesPermuteModifier)
1056 static const char * const selections[] = {
1057 "all permute 3 1 2",
1058 "res_cog of resnr 1 to 4 permute 2 1",
1059 "name CB S1 and res_cog x < 3 permute 2 1"
1061 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
1062 | efTestPositionAtoms | efTestPositionMapping);
1063 runTest("simple.gro", selections);
1067 TEST_F(SelectionCollectionDataTest, HandlesPlusModifier)
1069 static const char * const selections[] = {
1070 "name S2 plus name S1",
1071 "res_cog of resnr 2 plus res_cog of resnr 1 plus res_cog of resnr 3",
1072 "name S1 and y < 3 plus res_cog of x < 2.5"
1074 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
1075 | efTestPositionAtoms | efTestPositionMapping);
1076 runTest("simple.gro", selections);
1080 TEST_F(SelectionCollectionDataTest, HandlesMergeModifier)
1082 static const char * const selections[] = {
1083 "name S2 merge name S1",
1084 "resnr 1 2 and name S2 merge resnr 1 2 and name S1 merge res_cog of resnr 1 2",
1085 "name S1 and x < 2.5 merge res_cog of x < 2.5"
1087 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
1088 | efTestPositionAtoms | efTestPositionMapping);
1089 runTest("simple.gro", selections);
1093 /********************************************************************
1094 * Tests for generic selection evaluation
1097 TEST_F(SelectionCollectionDataTest, ComputesMassesAndCharges)
1099 static const char * const selections[] = {
1104 setFlags(TestFlags() | efTestEvaluation | efTestPositionAtoms
1105 | efTestPositionMasses | efTestPositionCharges);
1106 ASSERT_NO_FATAL_FAILURE(runParser(selections));
1107 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
1108 for (int i = 0; i < top_->atoms.nr; ++i)
1110 top_->atoms.atom[i].m = 1.0 + i / 100.0;
1111 top_->atoms.atom[i].q = -(1.0 + i / 100.0);
1113 ASSERT_NO_FATAL_FAILURE(runCompiler());
1114 ASSERT_NO_FATAL_FAILURE(runEvaluate());
1115 ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
1118 TEST_F(SelectionCollectionDataTest, ComputesMassesAndChargesWithoutTopology)
1120 static const char * const selections[] = {
1121 "atomnr 1 to 3 8 to 9",
1125 setFlags(TestFlags() | efTestPositionAtoms
1126 | efTestPositionMasses | efTestPositionCharges);
1127 runTest(10, selections);
1131 /********************************************************************
1132 * Tests for selection syntactic constructs
1135 TEST_F(SelectionCollectionDataTest, HandlesSelectionNames)
1137 static const char * const selections[] = {
1138 "\"GroupSelection\" group \"GrpA\"",
1139 "\"DynamicSelection\" x < 5",
1142 setFlags(TestFlags() | efTestSelectionNames);
1143 ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
1144 runTest(10, selections);
1147 TEST_F(SelectionCollectionDataTest, HandlesIndexGroupsInSelections)
1149 static const char * const selections[] = {
1153 // These test that the name of the group is not too eagerly promoted to
1154 // the name of the selection.
1155 "group \"GrpB\" and resname RB",
1156 "group \"GrpA\" permute 5 3 2 1 4",
1157 "group \"GrpA\" plus group \"GrpB\"",
1158 "res_cog of group \"GrpA\""
1160 setFlags(TestFlags() | efTestSelectionNames);
1161 ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
1162 runTest("simple.gro", selections);
1165 TEST_F(SelectionCollectionDataTest, HandlesIndexGroupsInSelectionsDelayed)
1167 static const char * const selections[] = {
1171 "group \"GrpB\" and resname RB"
1173 setFlags(TestFlags() | efTestSelectionNames);
1174 ASSERT_NO_FATAL_FAILURE(runParser(selections));
1175 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
1176 ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
1177 ASSERT_NO_FATAL_FAILURE(runCompiler());
1180 TEST_F(SelectionCollectionDataTest, HandlesUnsortedIndexGroupsInSelections)
1182 static const char * const selections[] = {
1183 "foo = group \"GrpUnsorted\"",
1184 "group \"GrpUnsorted\"",
1187 "res_cog of group \"GrpUnsorted\"",
1188 "group \"GrpUnsorted\" permute 2 1",
1191 setFlags(TestFlags() | efTestPositionAtoms | efTestPositionMapping
1192 | efTestSelectionNames);
1193 ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
1194 runTest("simple.gro", selections);
1197 TEST_F(SelectionCollectionDataTest, HandlesUnsortedIndexGroupsInSelectionsDelayed)
1199 static const char * const selections[] = {
1200 "foo = group \"GrpUnsorted\"",
1201 "group \"GrpUnsorted\"",
1204 "res_cog of group \"GrpUnsorted\"",
1205 "group \"GrpUnsorted\" permute 2 1",
1208 ASSERT_NO_FATAL_FAILURE(runParser(selections));
1209 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
1210 ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
1211 ASSERT_NO_FATAL_FAILURE(runCompiler());
1215 TEST_F(SelectionCollectionDataTest, HandlesConstantPositions)
1217 static const char * const selections[] = {
1220 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
1221 | efTestPositionMapping);
1222 runTest("simple.gro", selections);
1226 TEST_F(SelectionCollectionDataTest, HandlesConstantPositionsWithModifiers)
1228 static const char * const selections[] = {
1229 "[0, 0, 0] plus [0, 1, 0]"
1231 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
1232 | efTestPositionMapping);
1233 runTest("simple.gro", selections);
1237 TEST_F(SelectionCollectionDataTest, HandlesWithinConstantPositions)
1239 static const char * const selections[] = {
1240 "within 1 of [2, 1, 0]"
1242 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
1243 runTest("simple.gro", selections);
1247 TEST_F(SelectionCollectionDataTest, HandlesOverlappingIntegerRanges)
1249 static const char * const selections[] = {
1250 "atomnr 2 to 4 5 to 8",
1251 "atomnr 2 to 5 4 to 7"
1253 ASSERT_NO_FATAL_FAILURE(runTest(10, selections));
1257 TEST_F(SelectionCollectionDataTest, HandlesOverlappingRealRanges)
1259 static const char * const selections[] = {
1260 "charge {-0.35 to -0.05 0.25 to 0.75}",
1261 "charge {0.05 to -0.3 -0.05 to 0.55}"
1263 ASSERT_NO_FATAL_FAILURE(runParser(selections));
1264 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
1265 for (int i = 0; i < top_->atoms.nr; ++i)
1267 top_->atoms.atom[i].q = i / 10.0 - 0.5;
1269 ASSERT_NO_FATAL_FAILURE(runCompiler());
1273 TEST_F(SelectionCollectionDataTest, HandlesForcedStringMatchingMode)
1275 static const char * const selections[] = {
1279 runTest("simple.gro", selections);
1283 TEST_F(SelectionCollectionDataTest, HandlesWildcardMatching)
1285 static const char * const selections[] = {
1289 runTest("simple.gro", selections);
1293 TEST_F(SelectionCollectionDataTest, HandlesRegexMatching)
1295 static const char * const selections[] = {
1296 "resname \"R[BD]\"",
1297 "resname ~ \"R[BD]\""
1299 if (gmx::Regex::isSupported())
1301 runTest("simple.gro", selections);
1306 TEST_F(SelectionCollectionDataTest, HandlesBasicBoolean)
1308 static const char * const selections[] = {
1309 "atomnr 1 to 5 and atomnr 2 to 7",
1310 "atomnr 1 to 5 or not atomnr 3 to 8",
1311 "not not atomnr 1 to 5 and atomnr 2 to 6 and not not atomnr 3 to 7",
1312 "atomnr 1 to 5 and (atomnr 2 to 7 and atomnr 3 to 6)",
1313 "x < 5 and atomnr 1 to 5 and y < 3 and atomnr 2 to 4"
1315 runTest(10, selections);
1319 TEST_F(SelectionCollectionDataTest, HandlesDynamicAtomValuedParameters)
1321 static const char * const selections[] = {
1322 "same residue as (atomnr 3 5 13 or y > 5)",
1323 "(resnr 1 3 5 or x > 10) and same residue as (atomnr 3 5 13 or z > 5)"
1325 setFlags(TestFlags() | efTestEvaluation);
1326 runTest("simple.gro", selections);
1330 TEST_F(SelectionCollectionDataTest, HandlesEmptySelectionWithUnevaluatedExpressions)
1332 static const char * const selections[] = {
1334 "none and same resname as resnr 2"
1336 runTest("simple.gro", selections);
1340 TEST_F(SelectionCollectionDataTest, HandlesEmptyReferenceForSame)
1342 static const char * const selections[] = {
1343 "same residue as none",
1344 "same resname as none"
1346 runTest("simple.gro", selections);
1350 TEST_F(SelectionCollectionDataTest, HandlesPositionModifiersForKeywords)
1352 static const char * const selections[] = {
1354 "name CB and res_cog y > 2.5"
1356 setFlags(TestFlags() | efTestEvaluation);
1357 runTest("simple.gro", selections);
1361 TEST_F(SelectionCollectionDataTest, HandlesPositionModifiersForMethods)
1363 static const char * const selections[] = {
1364 "res_cog distance from cog of resnr 1 < 2",
1365 "res_cog within 2 of cog of resnr 1"
1367 setFlags(TestFlags() | efTestEvaluation);
1368 runTest("simple.gro", selections);
1372 TEST_F(SelectionCollectionDataTest, HandlesKeywordOfPositions)
1374 static const char * const selections[] = {
1375 "x < y of cog of resnr 2"
1377 setFlags(TestFlags() | efTestEvaluation);
1378 runTest("simple.gro", selections);
1381 TEST_F(SelectionCollectionDataTest, HandlesKeywordOfPositionsInArithmetic)
1383 static const char * const selections[] = {
1384 "x - y of cog of resnr 2 < 0"
1386 setFlags(TestFlags() | efTestEvaluation);
1387 runTest("simple.gro", selections);
1391 TEST_F(SelectionCollectionDataTest, HandlesNumericComparisons)
1393 static const char * const selections[] = {
1400 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
1401 runTest("simple.gro", selections);
1405 TEST_F(SelectionCollectionDataTest, HandlesArithmeticExpressions)
1407 static const char * const selections[] = {
1413 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
1414 runTest("simple.gro", selections);
1418 TEST_F(SelectionCollectionDataTest, HandlesNumericVariables)
1420 static const char * const selections[] = {
1426 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
1427 runTest("simple.gro", selections);
1431 TEST_F(SelectionCollectionDataTest, HandlesComplexNumericVariables)
1433 static const char * const selections[] = {
1435 "resname RA and value <= 4",
1436 "resname RA RB and x < 3 and value <= 4",
1438 "resname RA and index < 3",
1439 "resname RB and y < 3 and index < 6"
1441 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
1442 runTest("simple.gro", selections);
1446 TEST_F(SelectionCollectionDataTest, HandlesPositionVariables)
1448 static const char * const selections[] = {
1449 "foo = res_cog of resname RA",
1452 "bar = cog of resname RA",
1456 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
1457 runTest("simple.gro", selections);
1461 TEST_F(SelectionCollectionDataTest, HandlesConstantPositionInVariable)
1463 static const char * const selections[] = {
1464 "constpos = [1.0, 2.5, 0.5]",
1466 "within 2 of constpos"
1468 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
1469 | efTestPositionAtoms);
1470 runTest("simple.gro", selections);
1474 TEST_F(SelectionCollectionDataTest, HandlesNumericConstantsInVariables)
1476 static const char * const selections[] = {
1481 "x + constreal1 < constreal2"
1483 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
1484 runTest("simple.gro", selections);
1488 /********************************************************************
1489 * Tests for complex boolean syntax
1492 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysis)
1494 static const char * const selections[] = {
1495 "atomnr 1 to 5 and atomnr 2 to 7 and x < 2",
1496 "atomnr 1 to 5 and (atomnr 4 to 7 or x < 2)",
1497 "atomnr 1 to 5 and y < 3 and (atomnr 4 to 7 or x < 2)",
1498 "atomnr 1 to 5 and not (atomnr 4 to 7 or x < 2)",
1499 "atomnr 1 to 5 or (atomnr 4 to 6 and (atomnr 5 to 7 or x < 2))"
1501 runTest(10, selections);
1505 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithVariables)
1507 static const char * const selections[] = {
1508 "foo = atomnr 4 to 7 or x < 2",
1509 "atomnr 1 to 4 and foo",
1510 "atomnr 2 to 6 and y < 3 and foo",
1511 "atomnr 6 to 10 and not foo"
1513 runTest(10, selections);
1517 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithMoreVariables)
1519 static const char * const selections[] = {
1520 "foo = atomnr 4 to 7",
1521 "bar = foo and x < 2",
1522 "bar2 = foo and y < 2",
1523 "atomnr 1 to 4 and bar",
1524 "atomnr 2 to 6 and y < 3 and bar2",
1525 "atomnr 6 to 10 and not foo"
1527 runTest(10, selections);
1531 /********************************************************************
1532 * Tests for complex subexpression cases
1534 * These tests use some knowledge of the implementation to trigger different
1535 * paths in the code.
1538 TEST_F(SelectionCollectionDataTest, HandlesUnusedVariables)
1540 static const char * const selections[] = {
1541 "unused1 = atomnr 1 to 3",
1542 "foo = atomnr 4 to 7",
1543 "atomnr 1 to 6 and foo",
1544 "unused2 = atomnr 3 to 5"
1546 runTest(10, selections);
1550 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithStaticEvaluationGroups)
1552 static const char * const selections[] = {
1553 "foo = atomnr 4 to 7 and x < 2",
1554 "atomnr 1 to 5 and foo",
1555 "atomnr 3 to 7 and foo"
1557 runTest(10, selections);
1561 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithMixedEvaluationGroups)
1563 static const char * const selections[] = {
1564 "foo = atomnr 4 to 7 and x < 2",
1565 "atomnr 1 to 6 and foo",
1569 runTest(10, selections);
1573 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithMixedEvaluationGroups2)
1575 static const char * const selections[] = {
1576 "foo = atomnr 1 to 8 and x < 10",
1577 "atomnr 1 to 5 and y < 10 and foo",
1580 setFlags(TestFlags() | efTestEvaluation);
1581 runTest("simple.gro", selections);