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 efDontTestCompiledAtoms = 1<<8
165 typedef gmx::FlagsTemplate<TestFlag> TestFlags;
167 SelectionCollectionDataTest()
168 : checker_(data_.rootChecker()), count_(0), framenr_(0)
172 void setFlags(TestFlags flags) { flags_ = flags; }
174 void runTest(int natoms, const char *const *selections, size_t count);
175 void runTest(const char *filename, const char *const *selections,
177 template <size_t count>
178 void runTest(int natoms, const char *const (&selections)[count])
180 runTest(natoms, selections, count);
182 template <size_t count>
183 void runTest(const char *filename, const char *const (&selections)[count])
185 runTest(filename, selections, count);
189 static void checkSelection(gmx::test::TestReferenceChecker *checker,
190 const gmx::Selection &sel, TestFlags flags);
192 void runParser(const char *const *selections, size_t count);
194 void checkCompiled();
196 void runEvaluateFinal();
198 gmx::test::TestReferenceData data_;
199 gmx::test::TestReferenceChecker checker_;
207 SelectionCollectionDataTest::checkSelection(
208 gmx::test::TestReferenceChecker *checker,
209 const gmx::Selection &sel, TestFlags flags)
211 using gmx::test::TestReferenceChecker;
214 gmx::ConstArrayRef<int> atoms = sel.atomIndices();
215 checker->checkSequence(atoms.begin(), atoms.end(), "Atoms");
217 if (flags.test(efTestPositionAtoms)
218 || flags.test(efTestPositionCoordinates)
219 || flags.test(efTestPositionMapping))
221 TestReferenceChecker compound(
222 checker->checkSequenceCompound("Positions", sel.posCount()));
223 for (int i = 0; i < sel.posCount(); ++i)
225 TestReferenceChecker poscompound(compound.checkCompound("Position", NULL));
226 const gmx::SelectionPosition &p = sel.position(i);
227 if (flags.test(efTestPositionAtoms))
229 gmx::ConstArrayRef<int> atoms = p.atomIndices();
230 poscompound.checkSequence(atoms.begin(), atoms.end(), "Atoms");
232 if (flags.test(efTestPositionCoordinates))
234 poscompound.checkVector(p.x(), "Coordinates");
236 if (flags.test(efTestPositionMapping))
238 poscompound.checkInteger(p.refId(), "RefId");
239 poscompound.checkInteger(p.mappedId(), "MappedId");
247 SelectionCollectionDataTest::runParser(const char *const *selections,
250 using gmx::test::TestReferenceChecker;
252 TestReferenceChecker compound(checker_.checkCompound("ParsedSelections", "Parsed"));
255 for (size_t i = 0; i < count; ++i)
257 SCOPED_TRACE(std::string("Parsing selection \"")
258 + selections[i] + "\"");
259 gmx::SelectionList result;
260 ASSERT_NO_THROW(result = sc_.parseFromString(selections[i]));
261 sel_.insert(sel_.end(), result.begin(), result.end());
262 if (sel_.size() == count_)
264 std::string id = gmx::formatString("Variable%d", static_cast<int>(varcount + 1));
265 TestReferenceChecker varcompound(
266 compound.checkCompound("ParsedVariable", id.c_str()));
267 varcompound.checkString(selections[i], "Input");
272 std::string id = gmx::formatString("Selection%d", static_cast<int>(count_ + 1));
273 TestReferenceChecker selcompound(
274 compound.checkCompound("ParsedSelection", id.c_str()));
275 selcompound.checkString(selections[i], "Input");
276 selcompound.checkString(sel_[count_].name(), "Name");
277 selcompound.checkString(sel_[count_].selectionText(), "Text");
278 selcompound.checkBoolean(sel_[count_].isDynamic(), "Dynamic");
286 SelectionCollectionDataTest::runCompiler()
288 ASSERT_NO_THROW(sc_.compile());
289 ASSERT_EQ(count_, sel_.size());
295 SelectionCollectionDataTest::checkCompiled()
297 using gmx::test::TestReferenceChecker;
298 const TestFlags mask = ~TestFlags(efTestPositionCoordinates);
300 TestReferenceChecker compound(checker_.checkCompound("CompiledSelections", "Compiled"));
301 for (size_t i = 0; i < count_; ++i)
303 SCOPED_TRACE(std::string("Checking selection \"") +
304 sel_[i].selectionText() + "\"");
305 std::string id = gmx::formatString("Selection%d", static_cast<int>(i + 1));
306 TestReferenceChecker selcompound(
307 compound.checkCompound("Selection", id.c_str()));
308 if (!flags_.test(efDontTestCompiledAtoms))
310 checkSelection(&selcompound, sel_[i], flags_ & mask);
317 SelectionCollectionDataTest::runEvaluate()
319 using gmx::test::TestReferenceChecker;
322 ASSERT_NO_THROW(sc_.evaluate(frame_, NULL));
323 std::string frame = gmx::formatString("Frame%d", framenr_);
324 TestReferenceChecker compound(
325 checker_.checkCompound("EvaluatedSelections", frame.c_str()));
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 checkSelection(&selcompound, sel_[i], flags_);
339 SelectionCollectionDataTest::runEvaluateFinal()
341 ASSERT_NO_THROW(sc_.evaluateFinal(framenr_));
342 if (!checker_.isWriteMode())
350 SelectionCollectionDataTest::runTest(int natoms, const char * const *selections,
353 ASSERT_NO_FATAL_FAILURE(runParser(selections, count));
354 ASSERT_NO_FATAL_FAILURE(setAtomCount(natoms));
355 ASSERT_NO_FATAL_FAILURE(runCompiler());
360 SelectionCollectionDataTest::runTest(const char *filename,
361 const char * const *selections,
364 ASSERT_NO_FATAL_FAILURE(runParser(selections, count));
365 ASSERT_NO_FATAL_FAILURE(loadTopology(filename));
366 ASSERT_NO_FATAL_FAILURE(runCompiler());
367 if (flags_.test(efTestEvaluation))
369 ASSERT_NO_FATAL_FAILURE(runEvaluate());
370 ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
375 /********************************************************************
376 * Tests for SelectionCollection functionality without reference data
379 TEST_F(SelectionCollectionTest, HandlesNoSelections)
381 EXPECT_FALSE(sc_.requiresTopology());
382 EXPECT_NO_THROW(sc_.compile());
385 TEST_F(SelectionCollectionTest, ParsesSelectionsFromFile)
387 ASSERT_NO_THROW(sel_ = sc_.parseFromFile(
388 gmx::test::TestFileManager::getInputFilePath("selfile.dat")));
389 // These should match the contents of selfile.dat
390 ASSERT_EQ(2U, sel_.size());
391 EXPECT_STREQ("resname RA RB", sel_[0].selectionText());
392 EXPECT_STREQ("resname RB RC", sel_[1].selectionText());
395 TEST_F(SelectionCollectionTest, HandlesInvalidRegularExpressions)
397 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
399 sc_.parseFromString("resname ~ \"R[A\"");
401 }, gmx::InvalidInputError);
404 TEST_F(SelectionCollectionTest, HandlesUnsupportedRegularExpressions)
406 if (!gmx::Regex::isSupported())
408 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
410 sc_.parseFromString("resname \"R[AD]\"");
412 }, gmx::InvalidInputError);
416 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue)
418 EXPECT_THROW(sc_.parseFromString("mindist from atomnr 1 cutoff"),
419 gmx::InvalidInputError);
422 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue2)
424 EXPECT_THROW(sc_.parseFromString("within 1 of"),
425 gmx::InvalidInputError);
428 TEST_F(SelectionCollectionTest, HandlesMissingMethodParamValue3)
430 EXPECT_THROW(sc_.parseFromString("within of atomnr 1"),
431 gmx::InvalidInputError);
434 TEST_F(SelectionCollectionTest, HandlesHelpKeywordInInvalidContext)
436 EXPECT_THROW(sc_.parseFromString("resname help"),
437 gmx::InvalidInputError);
440 // TODO: Tests for more parser errors
442 TEST_F(SelectionCollectionTest, RecoversFromUnknownGroupReference)
444 ASSERT_NO_THROW(sc_.parseFromString("group \"foo\""));
445 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
446 EXPECT_THROW(sc_.setIndexGroups(NULL), gmx::InvalidInputError);
447 EXPECT_THROW(sc_.compile(), gmx::APIError);
450 TEST_F(SelectionCollectionTest, RecoversFromMissingMoleculeInfo)
452 ASSERT_NO_THROW(sc_.parseFromString("molindex 1 to 5"));
453 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
454 EXPECT_THROW(sc_.compile(), gmx::InconsistentInputError);
457 TEST_F(SelectionCollectionTest, RecoversFromMissingAtomTypes)
459 ASSERT_NO_THROW(sc_.parseFromString("type CA"));
460 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
461 EXPECT_THROW(sc_.compile(), gmx::InconsistentInputError);
464 TEST_F(SelectionCollectionTest, RecoversFromMissingPDBInfo)
466 ASSERT_NO_THROW(sc_.parseFromString("altloc A"));
467 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
468 EXPECT_THROW(sc_.compile(), gmx::InconsistentInputError);
471 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation)
473 ASSERT_NO_THROW(sc_.parseFromString("all permute 1 1"));
474 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
475 EXPECT_THROW(sc_.compile(), gmx::InvalidInputError);
478 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation2)
480 ASSERT_NO_THROW(sc_.parseFromString("all permute 3 2 1"));
481 ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
482 EXPECT_THROW(sc_.compile(), gmx::InconsistentInputError);
485 TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation3)
487 ASSERT_NO_THROW(sc_.parseFromString("x < 1.5 permute 3 2 1"));
488 ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
489 ASSERT_NO_THROW(sc_.compile());
490 EXPECT_THROW(sc_.evaluate(frame_, NULL), gmx::InconsistentInputError);
493 // TODO: Tests for evaluation errors
496 /********************************************************************
497 * Tests for selection keywords
500 TEST_F(SelectionCollectionDataTest, HandlesAllNone)
502 static const char * const selections[] = {
506 runTest(10, selections);
509 TEST_F(SelectionCollectionDataTest, HandlesAtomnr)
511 static const char * const selections[] = {
512 "atomnr 1 to 3 6 to 8",
516 runTest(10, selections);
519 TEST_F(SelectionCollectionDataTest, HandlesResnr)
521 static const char * const selections[] = {
525 runTest("simple.gro", selections);
528 TEST_F(SelectionCollectionDataTest, HandlesResIndex)
530 static const char * const selections[] = {
534 runTest("simple.pdb", selections);
537 // TODO: Add test for "molindex"
539 TEST_F(SelectionCollectionDataTest, HandlesAtomname)
541 static const char * const selections[] = {
545 runTest("simple.gro", selections);
548 TEST_F(SelectionCollectionDataTest, HandlesPdbAtomname)
550 static const char * const selections[] = {
556 runTest("simple.pdb", selections);
559 // TODO: Add test for atomtype
561 TEST_F(SelectionCollectionDataTest, HandlesChain)
563 static const char * const selections[] = {
567 runTest("simple.pdb", selections);
570 // TODO: Add test for mass
571 // TODO: Add test for charge
573 TEST_F(SelectionCollectionDataTest, HandlesAltLoc)
575 static const char * const selections[] = {
579 runTest("simple.pdb", selections);
582 TEST_F(SelectionCollectionDataTest, HandlesInsertCode)
584 static const char * const selections[] = {
588 runTest("simple.pdb", selections);
591 TEST_F(SelectionCollectionDataTest, HandlesOccupancy)
593 static const char * const selections[] = {
597 runTest("simple.pdb", selections);
600 TEST_F(SelectionCollectionDataTest, HandlesBeta)
602 static const char * const selections[] = {
606 runTest("simple.pdb", selections);
609 TEST_F(SelectionCollectionDataTest, HandlesResname)
611 static const char * const selections[] = {
615 runTest("simple.gro", selections);
618 TEST_F(SelectionCollectionDataTest, HandlesCoordinateKeywords)
620 static const char * const selections[] = {
625 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
626 runTest("simple.gro", selections);
630 TEST_F(SelectionCollectionDataTest, HandlesSameResidue)
632 static const char * const selections[] = {
633 "same residue as atomnr 1 4 12"
635 runTest("simple.gro", selections);
639 TEST_F(SelectionCollectionDataTest, HandlesSameResidueName)
641 static const char * const selections[] = {
642 "same resname as atomnr 1 14"
644 runTest("simple.gro", selections);
648 TEST_F(SelectionCollectionDataTest, HandlesPositionKeywords)
650 static const char * const selections[] = {
652 "res_cog of name CB and resnr 1 3",
653 "whole_res_cog of name CB and resnr 1 3",
654 "part_res_cog of x < 3",
655 "dyn_res_cog of x < 3"
657 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
658 | efTestPositionAtoms);
659 runTest("simple.gro", selections);
663 TEST_F(SelectionCollectionDataTest, HandlesDistanceKeyword)
665 static const char * const selections[] = {
666 "distance from cog of resnr 1 < 2"
668 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
669 runTest("simple.gro", selections);
673 TEST_F(SelectionCollectionDataTest, HandlesMinDistanceKeyword)
675 static const char * const selections[] = {
676 "mindistance from resnr 1 < 2"
678 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
679 runTest("simple.gro", selections);
683 TEST_F(SelectionCollectionDataTest, HandlesWithinKeyword)
685 static const char * const selections[] = {
686 "within 1 of resnr 2"
688 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
689 runTest("simple.gro", selections);
693 TEST_F(SelectionCollectionDataTest, HandlesInSolidAngleKeyword)
695 // Both of these should evaluate to empty on a correct implementation.
696 static const char * const selections[] = {
697 "resname TP and not insolidangle center cog of resname C span resname R cutoff 20",
698 "resname TN and insolidangle center cog of resname C span resname R cutoff 20"
700 setFlags(TestFlags() | efDontTestCompiledAtoms | efTestEvaluation);
701 runTest("sphere.gro", selections);
705 TEST_F(SelectionCollectionDataTest, HandlesPermuteModifier)
707 static const char * const selections[] = {
709 "res_cog of resnr 1 to 4 permute 2 1",
710 "name CB S1 and res_cog x < 3 permute 2 1"
712 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
713 | efTestPositionAtoms | efTestPositionMapping);
714 runTest("simple.gro", selections);
718 TEST_F(SelectionCollectionDataTest, HandlesPlusModifier)
720 static const char * const selections[] = {
721 "name S2 plus name S1",
722 "res_cog of resnr 2 plus res_cog of resnr 1 plus res_cog of resnr 3",
723 "name S1 and y < 3 plus res_cog of x < 2.5"
725 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
726 | efTestPositionAtoms | efTestPositionMapping);
727 runTest("simple.gro", selections);
731 TEST_F(SelectionCollectionDataTest, HandlesMergeModifier)
733 static const char * const selections[] = {
734 "name S2 merge name S1",
735 "resnr 1 2 and name S2 merge resnr 1 2 and name S1 merge res_cog of resnr 1 2",
736 "name S1 and x < 2.5 merge res_cog of x < 2.5"
738 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
739 | efTestPositionAtoms | efTestPositionMapping);
740 runTest("simple.gro", selections);
744 /********************************************************************
745 * Tests for selection syntactic constructs
748 TEST_F(SelectionCollectionDataTest, HandlesConstantPositions)
750 static const char * const selections[] = {
753 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
754 runTest("simple.gro", selections);
758 TEST_F(SelectionCollectionDataTest, HandlesWithinConstantPositions)
760 static const char * const selections[] = {
761 "within 1 of [2, 1, 0]"
763 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
764 runTest("simple.gro", selections);
768 TEST_F(SelectionCollectionDataTest, HandlesForcedStringMatchingMode)
770 static const char * const selections[] = {
774 runTest("simple.gro", selections);
778 TEST_F(SelectionCollectionDataTest, HandlesWildcardMatching)
780 static const char * const selections[] = {
784 runTest("simple.gro", selections);
788 TEST_F(SelectionCollectionDataTest, HandlesRegexMatching)
790 static const char * const selections[] = {
792 "resname ~ \"R[BD]\""
794 if (gmx::Regex::isSupported())
796 runTest("simple.gro", selections);
801 TEST_F(SelectionCollectionDataTest, HandlesBasicBoolean)
803 static const char * const selections[] = {
804 "atomnr 1 to 5 and atomnr 2 to 7",
805 "atomnr 1 to 5 or not atomnr 3 to 8",
806 "not not atomnr 1 to 5 and atomnr 2 to 6 and not not atomnr 3 to 7",
807 "atomnr 1 to 5 and (atomnr 2 to 7 and atomnr 3 to 6)",
808 "x < 5 and atomnr 1 to 5 and y < 3 and atomnr 2 to 4"
810 runTest(10, selections);
814 TEST_F(SelectionCollectionDataTest, HandlesNumericComparisons)
816 static const char * const selections[] = {
823 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
824 runTest("simple.gro", selections);
828 TEST_F(SelectionCollectionDataTest, HandlesArithmeticExpressions)
830 static const char * const selections[] = {
836 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
837 runTest("simple.gro", selections);
841 TEST_F(SelectionCollectionDataTest, HandlesNumericVariables)
843 static const char * const selections[] = {
849 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
850 runTest("simple.gro", selections);
854 TEST_F(SelectionCollectionDataTest, HandlesComplexNumericVariables)
856 static const char * const selections[] = {
858 "resname RA and value <= 4",
859 "resname RA RB and x < 3 and value <= 4",
861 "resname RA and index < 3",
862 "resname RB and y < 3 and index < 6"
864 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
865 runTest("simple.gro", selections);
869 TEST_F(SelectionCollectionDataTest, HandlesPositionVariables)
871 static const char * const selections[] = {
872 "foo = res_cog of resname RA",
875 "bar = cog of resname RA",
879 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
880 runTest("simple.gro", selections);
884 TEST_F(SelectionCollectionDataTest, HandlesConstantPositionInVariable)
886 static const char * const selections[] = {
887 "constpos = [1.0, 2.5, 0.5]",
889 "within 2 of constpos"
891 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates
892 | efTestPositionAtoms);
893 runTest("simple.gro", selections);
897 TEST_F(SelectionCollectionDataTest, HandlesNumericConstantsInVariables)
899 static const char * const selections[] = {
904 "x + constreal1 < constreal2"
906 setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
907 runTest("simple.gro", selections);
911 /********************************************************************
912 * Tests for complex boolean syntax
915 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysis)
917 static const char * const selections[] = {
918 "atomnr 1 to 5 and atomnr 2 to 7 and x < 2",
919 "atomnr 1 to 5 and (atomnr 4 to 7 or x < 2)",
920 "atomnr 1 to 5 and y < 3 and (atomnr 4 to 7 or x < 2)",
921 "atomnr 1 to 5 and not (atomnr 4 to 7 or x < 2)",
922 "atomnr 1 to 5 or (atomnr 4 to 6 and (atomnr 5 to 7 or x < 2))"
924 runTest(10, selections);
928 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithVariables)
930 static const char * const selections[] = {
931 "foo = atomnr 4 to 7 or x < 2",
932 "atomnr 1 to 4 and foo",
933 "atomnr 2 to 6 and y < 3 and foo",
934 "atomnr 6 to 10 and not foo"
936 runTest(10, selections);
940 TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithMoreVariables)
942 static const char * const selections[] = {
943 "foo = atomnr 4 to 7",
944 "bar = foo and x < 2",
945 "bar2 = foo and y < 2",
946 "atomnr 1 to 4 and bar",
947 "atomnr 2 to 6 and y < 3 and bar2",
948 "atomnr 6 to 10 and not foo"
950 runTest(10, selections);
954 /********************************************************************
955 * Tests for complex subexpression cases
957 * These tests use some knowledge of the implementation to trigger different
961 TEST_F(SelectionCollectionDataTest, HandlesUnusedVariables)
963 static const char * const selections[] = {
964 "unused1 = atomnr 1 to 3",
965 "foo = atomnr 4 to 7",
966 "atomnr 1 to 6 and foo",
967 "unused2 = atomnr 3 to 5"
969 runTest(10, selections);
973 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithStaticEvaluationGroups)
975 static const char * const selections[] = {
976 "foo = atomnr 4 to 7 and x < 2",
977 "atomnr 1 to 5 and foo",
978 "atomnr 3 to 7 and foo"
980 runTest(10, selections);
984 TEST_F(SelectionCollectionDataTest, HandlesVariablesWithMixedEvaluationGroups)
986 static const char * const selections[] = {
987 "foo = atomnr 4 to 7 and x < 2",
988 "atomnr 1 to 6 and foo",
992 runTest(10, selections);