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 handling of selection options.
35 * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36 * \ingroup module_selection
38 #include <gtest/gtest.h>
40 #include "gromacs/options/options.h"
41 #include "gromacs/options/optionsassigner.h"
42 #include "gromacs/selection/selection.h"
43 #include "gromacs/selection/selectioncollection.h"
44 #include "gromacs/selection/selectionfileoption.h"
45 #include "gromacs/selection/selectionoption.h"
46 #include "gromacs/selection/selectionoptioninfo.h"
47 #include "gromacs/selection/selectionoptionmanager.h"
48 #include "gromacs/utility/exceptions.h"
50 #include "testutils/datapath.h"
55 /********************************************************************
56 * Base fixture for tests in this file.
59 class SelectionOptionTestBase : public ::testing::Test
62 SelectionOptionTestBase();
66 gmx::SelectionCollection sc_;
67 gmx::SelectionOptionManager manager_;
68 gmx::Options options_;
71 SelectionOptionTestBase::SelectionOptionTestBase()
72 : manager_(&sc_), options_(NULL, NULL)
74 sc_.setReferencePosType("atom");
75 sc_.setOutputPosType("atom");
78 void SelectionOptionTestBase::setManager()
80 setManagerForSelectionOptions(&options_, &manager_);
84 /********************************************************************
85 * Tests for SelectionOption
88 typedef SelectionOptionTestBase SelectionOptionTest;
90 TEST_F(SelectionOptionTest, ParsesSimpleSelection)
93 using gmx::SelectionOption;
94 ASSERT_NO_THROW(options_.addOption(SelectionOption("sel").store(&sel)));
97 gmx::OptionsAssigner assigner(&options_);
98 EXPECT_NO_THROW(assigner.start());
99 ASSERT_NO_THROW(assigner.startOption("sel"));
100 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
101 EXPECT_NO_THROW(assigner.finishOption());
102 EXPECT_NO_THROW(assigner.finish());
103 EXPECT_NO_THROW(options_.finish());
105 ASSERT_FALSE(sel.isDynamic());
109 TEST_F(SelectionOptionTest, HandlesDynamicSelectionWhenStaticRequired)
112 using gmx::SelectionOption;
113 ASSERT_NO_THROW(options_.addOption(
114 SelectionOption("sel").store(&sel).onlyStatic()));
117 gmx::OptionsAssigner assigner(&options_);
118 EXPECT_NO_THROW(assigner.start());
119 ASSERT_NO_THROW(assigner.startOption("sel"));
120 EXPECT_THROW(assigner.appendValue("resname RA RB and x < 5"), gmx::InvalidInputError);
121 EXPECT_NO_THROW(assigner.finishOption());
122 EXPECT_NO_THROW(assigner.finish());
123 EXPECT_NO_THROW(options_.finish());
127 TEST_F(SelectionOptionTest, HandlesTooManySelections)
130 using gmx::SelectionOption;
131 ASSERT_NO_THROW(options_.addOption(SelectionOption("sel").store(&sel)));
134 gmx::OptionsAssigner assigner(&options_);
135 EXPECT_NO_THROW(assigner.start());
136 ASSERT_NO_THROW(assigner.startOption("sel"));
137 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
138 EXPECT_THROW(assigner.appendValue("resname RB RC"), gmx::InvalidInputError);
139 EXPECT_NO_THROW(assigner.finishOption());
140 EXPECT_NO_THROW(assigner.finish());
141 EXPECT_NO_THROW(options_.finish());
142 ASSERT_STREQ("resname RA RB", sel.selectionText());
146 TEST_F(SelectionOptionTest, HandlesTooFewSelections)
148 gmx::Selection sel[2];
149 using gmx::SelectionOption;
150 ASSERT_NO_THROW(options_.addOption(
151 SelectionOption("sel").store(sel).valueCount(2)));
154 gmx::OptionsAssigner assigner(&options_);
155 EXPECT_NO_THROW(assigner.start());
156 ASSERT_NO_THROW(assigner.startOption("sel"));
157 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
158 EXPECT_THROW(assigner.finishOption(), gmx::InvalidInputError);
159 EXPECT_NO_THROW(assigner.finish());
160 EXPECT_NO_THROW(options_.finish());
164 TEST_F(SelectionOptionTest, HandlesAdjuster)
166 gmx::SelectionList sel;
167 gmx::SelectionOptionInfo *info;
168 using gmx::SelectionOption;
169 ASSERT_NO_THROW(options_.addOption(
170 SelectionOption("sel").storeVector(&sel).multiValue()
171 .getAdjuster(&info)));
174 gmx::OptionsAssigner assigner(&options_);
175 EXPECT_NO_THROW(assigner.start());
176 ASSERT_NO_THROW(assigner.startOption("sel"));
177 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
178 EXPECT_NO_THROW(assigner.appendValue("resname RB RC"));
179 EXPECT_NO_THROW(assigner.finishOption());
180 EXPECT_NO_THROW(assigner.finish());
181 EXPECT_NO_THROW(options_.finish());
182 EXPECT_NO_THROW(info->setValueCount(2));
186 TEST_F(SelectionOptionTest, HandlesDynamicWhenStaticRequiredWithAdjuster)
189 gmx::SelectionOptionInfo *info;
190 using gmx::SelectionOption;
191 ASSERT_NO_THROW(options_.addOption(
192 SelectionOption("sel").store(&sel)
193 .getAdjuster(&info)));
196 gmx::OptionsAssigner assigner(&options_);
197 EXPECT_NO_THROW(assigner.start());
198 ASSERT_NO_THROW(assigner.startOption("sel"));
199 EXPECT_NO_THROW(assigner.appendValue("x < 5"));
200 EXPECT_NO_THROW(assigner.finishOption());
201 EXPECT_NO_THROW(assigner.finish());
202 EXPECT_NO_THROW(options_.finish());
203 EXPECT_THROW(info->setOnlyStatic(true), gmx::InvalidInputError);
207 TEST_F(SelectionOptionTest, HandlesTooManySelectionsWithAdjuster)
209 gmx::SelectionList sel;
210 gmx::SelectionOptionInfo *info;
211 using gmx::SelectionOption;
212 ASSERT_NO_THROW(options_.addOption(
213 SelectionOption("sel").storeVector(&sel).multiValue()
214 .getAdjuster(&info)));
217 gmx::OptionsAssigner assigner(&options_);
218 EXPECT_NO_THROW(assigner.start());
219 ASSERT_NO_THROW(assigner.startOption("sel"));
220 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
221 EXPECT_NO_THROW(assigner.appendValue("resname RB RC"));
222 EXPECT_NO_THROW(assigner.finishOption());
223 EXPECT_NO_THROW(assigner.finish());
224 EXPECT_NO_THROW(options_.finish());
225 EXPECT_THROW(info->setValueCount(1), gmx::InvalidInputError);
229 TEST_F(SelectionOptionTest, HandlesTooFewSelectionsWithAdjuster)
231 gmx::SelectionList sel;
232 gmx::SelectionOptionInfo *info;
233 using gmx::SelectionOption;
234 ASSERT_NO_THROW(options_.addOption(
235 SelectionOption("sel").storeVector(&sel).multiValue()
236 .getAdjuster(&info)));
239 gmx::OptionsAssigner assigner(&options_);
240 EXPECT_NO_THROW(assigner.start());
241 ASSERT_NO_THROW(assigner.startOption("sel"));
242 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
243 EXPECT_NO_THROW(assigner.finishOption());
244 EXPECT_NO_THROW(assigner.finish());
245 EXPECT_NO_THROW(options_.finish());
246 EXPECT_THROW(info->setValueCount(2), gmx::InvalidInputError);
250 TEST_F(SelectionOptionTest, HandlesDelayedRequiredSelection)
253 using gmx::SelectionOption;
254 ASSERT_NO_THROW(options_.addOption(
255 SelectionOption("sel").store(&sel).required()));
258 gmx::OptionsAssigner assigner(&options_);
259 EXPECT_NO_THROW(assigner.start());
260 EXPECT_NO_THROW(assigner.finish());
261 EXPECT_NO_THROW(options_.finish());
262 EXPECT_NO_THROW(manager_.parseRequestedFromString("resname RA RB"));
263 ASSERT_STREQ("resname RA RB", sel.selectionText());
267 TEST_F(SelectionOptionTest, HandlesTooFewDelayedRequiredSelections)
269 gmx::Selection sel[2];
270 using gmx::SelectionOption;
271 ASSERT_NO_THROW(options_.addOption(
272 SelectionOption("sel").store(sel).required()
276 gmx::OptionsAssigner assigner(&options_);
277 EXPECT_NO_THROW(assigner.start());
278 EXPECT_NO_THROW(assigner.finish());
279 EXPECT_NO_THROW(options_.finish());
280 EXPECT_THROW(manager_.parseRequestedFromString("resname RA RB"), gmx::InvalidInputError);
284 TEST_F(SelectionOptionTest, HandlesDelayedOptionalSelection)
287 using gmx::SelectionOption;
288 ASSERT_NO_THROW(options_.addOption(SelectionOption("sel").store(&sel)));
291 gmx::OptionsAssigner assigner(&options_);
292 EXPECT_NO_THROW(assigner.start());
293 ASSERT_NO_THROW(assigner.startOption("sel"));
294 EXPECT_NO_THROW(assigner.finishOption());
295 EXPECT_NO_THROW(assigner.finish());
296 EXPECT_NO_THROW(options_.finish());
297 EXPECT_NO_THROW(manager_.parseRequestedFromString("resname RA RB"));
298 ASSERT_STREQ("resname RA RB", sel.selectionText());
302 TEST_F(SelectionOptionTest, HandlesDelayedSelectionWithAdjuster)
304 gmx::SelectionList sel;
305 gmx::SelectionOptionInfo *info;
306 using gmx::SelectionOption;
307 ASSERT_NO_THROW(options_.addOption(
308 SelectionOption("sel").storeVector(&sel).valueCount(3)
309 .getAdjuster(&info)));
312 gmx::OptionsAssigner assigner(&options_);
313 EXPECT_NO_THROW(assigner.start());
314 ASSERT_NO_THROW(assigner.startOption("sel"));
315 EXPECT_NO_THROW(assigner.finishOption());
316 EXPECT_NO_THROW(assigner.finish());
317 EXPECT_NO_THROW(options_.finish());
318 EXPECT_NO_THROW(info->setValueCount(2));
319 EXPECT_NO_THROW(manager_.parseRequestedFromString("resname RA RB; resname RB RC"));
323 /********************************************************************
324 * Tests for SelectionFileOption
327 class SelectionFileOptionTest : public SelectionOptionTestBase
330 SelectionFileOptionTest();
333 SelectionFileOptionTest::SelectionFileOptionTest()
335 options_.addOption(gmx::SelectionFileOption("sf"));
339 TEST_F(SelectionFileOptionTest, HandlesSingleSelectionOptionFromFile)
341 gmx::SelectionList sel;
342 gmx::SelectionList reqsel;
343 using gmx::SelectionOption;
344 ASSERT_NO_THROW(options_.addOption(
345 SelectionOption("sel").storeVector(&sel).multiValue()));
346 ASSERT_NO_THROW(options_.addOption(
347 SelectionOption("reqsel").storeVector(&reqsel)
348 .multiValue().required()));
351 gmx::OptionsAssigner assigner(&options_);
352 EXPECT_NO_THROW(assigner.start());
353 ASSERT_NO_THROW(assigner.startOption("sel"));
354 EXPECT_NO_THROW(assigner.finishOption());
355 ASSERT_NO_THROW(assigner.startOption("sf"));
356 EXPECT_NO_THROW(assigner.appendValue(gmx::test::TestFileManager::getTestFilePath("selfile.dat")));
357 EXPECT_NO_THROW(assigner.finishOption());
358 EXPECT_NO_THROW(assigner.finish());
359 EXPECT_NO_THROW(options_.finish());
361 // These should match the contents of selfile.dat
362 ASSERT_EQ(2U, sel.size());
363 EXPECT_STREQ("resname RA RB", sel[0].selectionText());
364 EXPECT_STREQ("resname RB RC", sel[1].selectionText());
365 ASSERT_EQ(0U, reqsel.size());
369 TEST_F(SelectionFileOptionTest, HandlesTwoSeparateSelectionOptions)
371 gmx::SelectionList sel1;
372 gmx::SelectionList sel2;
373 using gmx::SelectionOption;
374 ASSERT_NO_THROW(options_.addOption(
375 SelectionOption("sel1").storeVector(&sel1).multiValue()));
376 ASSERT_NO_THROW(options_.addOption(
377 SelectionOption("sel2").storeVector(&sel2).multiValue()));
380 gmx::OptionsAssigner assigner(&options_);
381 std::string value(gmx::test::TestFileManager::getTestFilePath("selfile.dat"));
382 EXPECT_NO_THROW(assigner.start());
383 ASSERT_NO_THROW(assigner.startOption("sel1"));
384 EXPECT_NO_THROW(assigner.finishOption());
385 ASSERT_NO_THROW(assigner.startOption("sf"));
386 EXPECT_NO_THROW(assigner.appendValue(value));
387 EXPECT_NO_THROW(assigner.finishOption());
388 ASSERT_NO_THROW(assigner.startOption("sel2"));
389 EXPECT_NO_THROW(assigner.finishOption());
390 ASSERT_NO_THROW(assigner.startOption("sf"));
391 EXPECT_NO_THROW(assigner.appendValue(value));
392 EXPECT_NO_THROW(assigner.finishOption());
393 EXPECT_NO_THROW(assigner.finish());
394 EXPECT_NO_THROW(options_.finish());
396 // These should match the contents of selfile.dat
397 ASSERT_EQ(2U, sel1.size());
398 EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
399 EXPECT_STREQ("resname RB RC", sel1[1].selectionText());
400 ASSERT_EQ(2U, sel2.size());
401 EXPECT_STREQ("resname RA RB", sel2[0].selectionText());
402 EXPECT_STREQ("resname RB RC", sel2[1].selectionText());
406 TEST_F(SelectionFileOptionTest, HandlesTwoSelectionOptionsFromSingleFile)
408 gmx::SelectionList sel1;
409 gmx::SelectionList sel2;
410 using gmx::SelectionOption;
411 ASSERT_NO_THROW(options_.addOption(
412 SelectionOption("sel1").storeVector(&sel1)));
413 ASSERT_NO_THROW(options_.addOption(
414 SelectionOption("sel2").storeVector(&sel2)));
417 gmx::OptionsAssigner assigner(&options_);
418 std::string value(gmx::test::TestFileManager::getTestFilePath("selfile.dat"));
419 EXPECT_NO_THROW(assigner.start());
420 ASSERT_NO_THROW(assigner.startOption("sel1"));
421 EXPECT_NO_THROW(assigner.finishOption());
422 ASSERT_NO_THROW(assigner.startOption("sel2"));
423 EXPECT_NO_THROW(assigner.finishOption());
424 ASSERT_NO_THROW(assigner.startOption("sf"));
425 EXPECT_NO_THROW(assigner.appendValue(value));
426 EXPECT_NO_THROW(assigner.finishOption());
427 EXPECT_NO_THROW(assigner.finish());
428 EXPECT_NO_THROW(options_.finish());
430 // These should match the contents of selfile.dat
431 ASSERT_EQ(1U, sel1.size());
432 EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
433 ASSERT_EQ(1U, sel2.size());
434 EXPECT_STREQ("resname RB RC", sel2[0].selectionText());
438 TEST_F(SelectionFileOptionTest, HandlesRequiredOptionFromFile)
440 gmx::SelectionList sel;
441 gmx::SelectionList optsel;
442 using gmx::SelectionOption;
443 ASSERT_NO_THROW(options_.addOption(
444 SelectionOption("sel").storeVector(&sel)
445 .multiValue().required()));
446 ASSERT_NO_THROW(options_.addOption(
447 SelectionOption("optsel").storeVector(&optsel)
451 gmx::OptionsAssigner assigner(&options_);
452 EXPECT_NO_THROW(assigner.start());
453 ASSERT_NO_THROW(assigner.startOption("sf"));
454 EXPECT_NO_THROW(assigner.appendValue(gmx::test::TestFileManager::getTestFilePath("selfile.dat")));
455 EXPECT_NO_THROW(assigner.finishOption());
456 EXPECT_NO_THROW(assigner.startOption("optsel"));
457 EXPECT_NO_THROW(assigner.finishOption());
458 EXPECT_NO_THROW(assigner.finish());
459 EXPECT_NO_THROW(options_.finish());
460 EXPECT_NO_THROW(manager_.parseRequestedFromString("resname RC RD"));
462 // These should match the contents of selfile.dat
463 ASSERT_EQ(2U, sel.size());
464 EXPECT_STREQ("resname RA RB", sel[0].selectionText());
465 EXPECT_STREQ("resname RB RC", sel[1].selectionText());
466 ASSERT_EQ(1U, optsel.size());
467 EXPECT_STREQ("resname RC RD", optsel[0].selectionText());
471 // TODO: Is this the best possible behavior, or should it error out?
472 TEST_F(SelectionFileOptionTest, HandlesRequiredOptionFromFileWithOtherOptionSet)
474 gmx::SelectionList sel1;
475 gmx::SelectionList sel2;
476 using gmx::SelectionOption;
477 ASSERT_NO_THROW(options_.addOption(
478 SelectionOption("sel1").storeVector(&sel1)
479 .multiValue().required()));
480 ASSERT_NO_THROW(options_.addOption(
481 SelectionOption("sel2").storeVector(&sel2)
482 .multiValue().required()));
485 gmx::OptionsAssigner assigner(&options_);
486 EXPECT_NO_THROW(assigner.start());
487 EXPECT_NO_THROW(assigner.startOption("sel1"));
488 EXPECT_NO_THROW(assigner.appendValue("resname RC RD"));
489 EXPECT_NO_THROW(assigner.finishOption());
490 ASSERT_NO_THROW(assigner.startOption("sf"));
491 EXPECT_NO_THROW(assigner.appendValue(gmx::test::TestFileManager::getTestFilePath("selfile.dat")));
492 EXPECT_NO_THROW(assigner.finishOption());
493 EXPECT_NO_THROW(assigner.finish());
494 EXPECT_NO_THROW(options_.finish());
496 // These should match the contents of selfile.dat
497 ASSERT_EQ(2U, sel2.size());
498 EXPECT_STREQ("resname RA RB", sel2[0].selectionText());
499 EXPECT_STREQ("resname RB RC", sel2[1].selectionText());
500 ASSERT_EQ(1U, sel1.size());
501 EXPECT_STREQ("resname RC RD", sel1[0].selectionText());
505 TEST_F(SelectionFileOptionTest, HandlesTwoRequiredOptionsFromSingleFile)
507 gmx::SelectionList sel1;
508 gmx::SelectionList sel2;
509 using gmx::SelectionOption;
510 ASSERT_NO_THROW(options_.addOption(
511 SelectionOption("sel1").storeVector(&sel1).required()));
512 ASSERT_NO_THROW(options_.addOption(
513 SelectionOption("sel2").storeVector(&sel2).required()));
516 gmx::OptionsAssigner assigner(&options_);
517 std::string value(gmx::test::TestFileManager::getTestFilePath("selfile.dat"));
518 EXPECT_NO_THROW(assigner.start());
519 ASSERT_NO_THROW(assigner.startOption("sf"));
520 EXPECT_NO_THROW(assigner.appendValue(value));
521 EXPECT_NO_THROW(assigner.finishOption());
522 EXPECT_NO_THROW(assigner.finish());
523 EXPECT_NO_THROW(options_.finish());
525 // These should match the contents of selfile.dat
526 ASSERT_EQ(1U, sel1.size());
527 EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
528 ASSERT_EQ(1U, sel2.size());
529 EXPECT_STREQ("resname RB RC", sel2[0].selectionText());
533 TEST_F(SelectionFileOptionTest, GivesErrorWithNoFile)
535 gmx::SelectionList sel;
536 using gmx::SelectionOption;
537 ASSERT_NO_THROW(options_.addOption(
538 SelectionOption("sel").storeVector(&sel).multiValue()));
541 gmx::OptionsAssigner assigner(&options_);
542 EXPECT_NO_THROW(assigner.start());
543 ASSERT_NO_THROW(assigner.startOption("sel"));
544 EXPECT_NO_THROW(assigner.finishOption());
545 ASSERT_NO_THROW(assigner.startOption("sf"));
546 EXPECT_THROW(assigner.finishOption(), gmx::InvalidInputError);
547 EXPECT_NO_THROW(assigner.finish());
548 EXPECT_NO_THROW(options_.finish());
552 TEST_F(SelectionFileOptionTest, GivesErrorWithNonExistentFile)
554 gmx::SelectionList sel;
555 using gmx::SelectionOption;
556 ASSERT_NO_THROW(options_.addOption(
557 SelectionOption("sel").storeVector(&sel).multiValue()));
560 gmx::OptionsAssigner assigner(&options_);
561 EXPECT_NO_THROW(assigner.start());
562 ASSERT_NO_THROW(assigner.startOption("sel"));
563 EXPECT_NO_THROW(assigner.finishOption());
564 ASSERT_NO_THROW(assigner.startOption("sf"));
565 // TODO: Should this be changed to an InvalidInputError?
566 EXPECT_THROW(assigner.appendValue("nonexistentfile"), gmx::FileIOError);
567 EXPECT_THROW(assigner.appendValue(gmx::test::TestFileManager::getTestFilePath("selfile.dat")),
568 gmx::InvalidInputError);
569 EXPECT_NO_THROW(assigner.finishOption());
570 EXPECT_NO_THROW(assigner.finish());
571 EXPECT_NO_THROW(options_.finish());
575 TEST_F(SelectionFileOptionTest, GivesErrorWithMultipleFiles)
577 gmx::SelectionList sel;
578 using gmx::SelectionOption;
579 ASSERT_NO_THROW(options_.addOption(
580 SelectionOption("sel").storeVector(&sel).multiValue()));
583 gmx::OptionsAssigner assigner(&options_);
584 EXPECT_NO_THROW(assigner.start());
585 ASSERT_NO_THROW(assigner.startOption("sel"));
586 EXPECT_NO_THROW(assigner.finishOption());
587 ASSERT_NO_THROW(assigner.startOption("sf"));
588 EXPECT_NO_THROW(assigner.appendValue(gmx::test::TestFileManager::getTestFilePath("selfile.dat")));
589 EXPECT_THROW(assigner.appendValue("nonexistentfile"), gmx::InvalidInputError);
590 EXPECT_NO_THROW(assigner.finishOption());
591 EXPECT_NO_THROW(assigner.finish());
592 EXPECT_NO_THROW(options_.finish());