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/selectionoptionmanager.h"
47 #include "gromacs/utility/exceptions.h"
49 #include "testutils/testfilemanager.h"
51 using gmx::test::TestFileManager;
56 /********************************************************************
57 * Base fixture for tests in this file.
60 class SelectionOptionTestBase : public ::testing::Test
63 SelectionOptionTestBase();
67 gmx::SelectionCollection sc_;
68 gmx::SelectionOptionManager manager_;
69 gmx::Options options_;
72 SelectionOptionTestBase::SelectionOptionTestBase()
73 : manager_(&sc_), options_(NULL, NULL)
75 sc_.setReferencePosType("atom");
76 sc_.setOutputPosType("atom");
79 void SelectionOptionTestBase::setManager()
81 setManagerForSelectionOptions(&options_, &manager_);
85 /********************************************************************
86 * Tests for SelectionOption
89 //! Test fixture for gmx::SelectionOption.
90 typedef SelectionOptionTestBase SelectionOptionTest;
92 TEST_F(SelectionOptionTest, ParsesSimpleSelection)
95 using gmx::SelectionOption;
96 ASSERT_NO_THROW(options_.addOption(SelectionOption("sel").store(&sel)));
99 gmx::OptionsAssigner assigner(&options_);
100 EXPECT_NO_THROW(assigner.start());
101 ASSERT_NO_THROW(assigner.startOption("sel"));
102 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
103 EXPECT_NO_THROW(assigner.finishOption());
104 EXPECT_NO_THROW(assigner.finish());
105 EXPECT_NO_THROW(options_.finish());
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());
145 TEST_F(SelectionOptionTest, HandlesTooFewSelections)
147 gmx::Selection sel[2];
148 using gmx::SelectionOption;
149 ASSERT_NO_THROW(options_.addOption(
150 SelectionOption("sel").store(sel).valueCount(2)));
153 gmx::OptionsAssigner assigner(&options_);
154 EXPECT_NO_THROW(assigner.start());
155 ASSERT_NO_THROW(assigner.startOption("sel"));
156 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
157 EXPECT_THROW(assigner.finishOption(), gmx::InvalidInputError);
158 EXPECT_NO_THROW(assigner.finish());
159 EXPECT_NO_THROW(options_.finish());
163 TEST_F(SelectionOptionTest, HandlesAdjuster)
165 gmx::SelectionList sel;
166 using gmx::SelectionOption;
167 gmx::SelectionOptionInfo *info = options_.addOption(
168 SelectionOption("sel").storeVector(&sel).multiValue());
171 gmx::OptionsAssigner assigner(&options_);
172 EXPECT_NO_THROW(assigner.start());
173 ASSERT_NO_THROW(assigner.startOption("sel"));
174 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
175 EXPECT_NO_THROW(assigner.appendValue("resname RB RC"));
176 EXPECT_NO_THROW(assigner.finishOption());
177 EXPECT_NO_THROW(assigner.finish());
178 EXPECT_NO_THROW(options_.finish());
179 EXPECT_NO_THROW(info->setValueCount(2));
183 TEST_F(SelectionOptionTest, HandlesDynamicWhenStaticRequiredWithAdjuster)
186 using gmx::SelectionOption;
187 gmx::SelectionOptionInfo *info = options_.addOption(
188 SelectionOption("sel").store(&sel));
191 gmx::OptionsAssigner assigner(&options_);
192 EXPECT_NO_THROW(assigner.start());
193 ASSERT_NO_THROW(assigner.startOption("sel"));
194 EXPECT_NO_THROW(assigner.appendValue("x < 5"));
195 EXPECT_NO_THROW(assigner.finishOption());
196 EXPECT_NO_THROW(assigner.finish());
197 EXPECT_NO_THROW(options_.finish());
198 EXPECT_THROW(info->setOnlyStatic(true), gmx::InvalidInputError);
202 TEST_F(SelectionOptionTest, HandlesTooManySelectionsWithAdjuster)
204 gmx::SelectionList sel;
205 using gmx::SelectionOption;
206 gmx::SelectionOptionInfo *info = options_.addOption(
207 SelectionOption("sel").storeVector(&sel).multiValue());
210 gmx::OptionsAssigner assigner(&options_);
211 EXPECT_NO_THROW(assigner.start());
212 ASSERT_NO_THROW(assigner.startOption("sel"));
213 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
214 EXPECT_NO_THROW(assigner.appendValue("resname RB RC"));
215 EXPECT_NO_THROW(assigner.finishOption());
216 EXPECT_NO_THROW(assigner.finish());
217 EXPECT_NO_THROW(options_.finish());
218 EXPECT_THROW(info->setValueCount(1), gmx::InvalidInputError);
222 TEST_F(SelectionOptionTest, HandlesTooFewSelectionsWithAdjuster)
224 gmx::SelectionList sel;
225 using gmx::SelectionOption;
226 gmx::SelectionOptionInfo *info = options_.addOption(
227 SelectionOption("sel").storeVector(&sel).multiValue());
230 gmx::OptionsAssigner assigner(&options_);
231 EXPECT_NO_THROW(assigner.start());
232 ASSERT_NO_THROW(assigner.startOption("sel"));
233 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
234 EXPECT_NO_THROW(assigner.finishOption());
235 EXPECT_NO_THROW(assigner.finish());
236 EXPECT_NO_THROW(options_.finish());
237 EXPECT_THROW(info->setValueCount(2), gmx::InvalidInputError);
241 TEST_F(SelectionOptionTest, HandlesDelayedRequiredSelection)
244 using gmx::SelectionOption;
245 ASSERT_NO_THROW(options_.addOption(
246 SelectionOption("sel").store(&sel).required()));
249 gmx::OptionsAssigner assigner(&options_);
250 EXPECT_NO_THROW(assigner.start());
251 EXPECT_NO_THROW(assigner.finish());
252 EXPECT_NO_THROW(options_.finish());
253 ASSERT_NO_THROW(manager_.parseRequestedFromString("resname RA RB"));
254 ASSERT_STREQ("resname RA RB", sel.selectionText());
258 TEST_F(SelectionOptionTest, HandlesTooFewDelayedRequiredSelections)
260 gmx::Selection sel[2];
261 using gmx::SelectionOption;
262 ASSERT_NO_THROW(options_.addOption(
263 SelectionOption("sel").store(sel).required()
267 gmx::OptionsAssigner assigner(&options_);
268 EXPECT_NO_THROW(assigner.start());
269 EXPECT_NO_THROW(assigner.finish());
270 EXPECT_NO_THROW(options_.finish());
271 EXPECT_THROW(manager_.parseRequestedFromString("resname RA RB"), gmx::InvalidInputError);
275 TEST_F(SelectionOptionTest, HandlesDelayedOptionalSelection)
278 using gmx::SelectionOption;
279 ASSERT_NO_THROW(options_.addOption(SelectionOption("sel").store(&sel)));
282 gmx::OptionsAssigner assigner(&options_);
283 EXPECT_NO_THROW(assigner.start());
284 ASSERT_NO_THROW(assigner.startOption("sel"));
285 EXPECT_NO_THROW(assigner.finishOption());
286 EXPECT_NO_THROW(assigner.finish());
287 EXPECT_NO_THROW(options_.finish());
288 ASSERT_NO_THROW(manager_.parseRequestedFromString("resname RA RB"));
289 ASSERT_STREQ("resname RA RB", sel.selectionText());
293 TEST_F(SelectionOptionTest, HandlesDelayedSelectionWithAdjuster)
295 gmx::SelectionList sel;
296 using gmx::SelectionOption;
297 gmx::SelectionOptionInfo *info = options_.addOption(
298 SelectionOption("sel").storeVector(&sel).valueCount(3));
301 gmx::OptionsAssigner assigner(&options_);
302 EXPECT_NO_THROW(assigner.start());
303 ASSERT_NO_THROW(assigner.startOption("sel"));
304 EXPECT_NO_THROW(assigner.finishOption());
305 EXPECT_NO_THROW(assigner.finish());
306 EXPECT_NO_THROW(options_.finish());
307 EXPECT_NO_THROW(info->setValueCount(2));
308 EXPECT_NO_THROW(manager_.parseRequestedFromString("resname RA RB; resname RB RC"));
312 /********************************************************************
313 * Tests for SelectionFileOption
316 class SelectionFileOptionTest : public SelectionOptionTestBase
319 SelectionFileOptionTest();
322 SelectionFileOptionTest::SelectionFileOptionTest()
324 options_.addOption(gmx::SelectionFileOption("sf"));
328 TEST_F(SelectionFileOptionTest, HandlesSingleSelectionOptionFromFile)
330 gmx::SelectionList sel;
331 gmx::SelectionList reqsel;
332 using gmx::SelectionOption;
333 ASSERT_NO_THROW(options_.addOption(
334 SelectionOption("sel").storeVector(&sel).multiValue()));
335 ASSERT_NO_THROW(options_.addOption(
336 SelectionOption("reqsel").storeVector(&reqsel)
337 .multiValue().required()));
340 gmx::OptionsAssigner assigner(&options_);
341 EXPECT_NO_THROW(assigner.start());
342 ASSERT_NO_THROW(assigner.startOption("sel"));
343 EXPECT_NO_THROW(assigner.finishOption());
344 ASSERT_NO_THROW(assigner.startOption("sf"));
345 EXPECT_NO_THROW(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
346 EXPECT_NO_THROW(assigner.finishOption());
347 EXPECT_NO_THROW(assigner.finish());
348 EXPECT_NO_THROW(options_.finish());
350 // These should match the contents of selfile.dat
351 ASSERT_EQ(2U, sel.size());
352 EXPECT_STREQ("resname RA RB", sel[0].selectionText());
353 EXPECT_STREQ("resname RB RC", sel[1].selectionText());
354 ASSERT_EQ(0U, reqsel.size());
358 TEST_F(SelectionFileOptionTest, HandlesTwoSeparateSelectionOptions)
360 gmx::SelectionList sel1;
361 gmx::SelectionList sel2;
362 using gmx::SelectionOption;
363 ASSERT_NO_THROW(options_.addOption(
364 SelectionOption("sel1").storeVector(&sel1).multiValue()));
365 ASSERT_NO_THROW(options_.addOption(
366 SelectionOption("sel2").storeVector(&sel2).multiValue()));
369 gmx::OptionsAssigner assigner(&options_);
370 std::string value(TestFileManager::getInputFilePath("selfile.dat"));
371 EXPECT_NO_THROW(assigner.start());
372 ASSERT_NO_THROW(assigner.startOption("sel1"));
373 EXPECT_NO_THROW(assigner.finishOption());
374 ASSERT_NO_THROW(assigner.startOption("sf"));
375 EXPECT_NO_THROW(assigner.appendValue(value));
376 EXPECT_NO_THROW(assigner.finishOption());
377 ASSERT_NO_THROW(assigner.startOption("sel2"));
378 EXPECT_NO_THROW(assigner.finishOption());
379 ASSERT_NO_THROW(assigner.startOption("sf"));
380 EXPECT_NO_THROW(assigner.appendValue(value));
381 EXPECT_NO_THROW(assigner.finishOption());
382 EXPECT_NO_THROW(assigner.finish());
383 EXPECT_NO_THROW(options_.finish());
385 // These should match the contents of selfile.dat
386 ASSERT_EQ(2U, sel1.size());
387 EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
388 EXPECT_STREQ("resname RB RC", sel1[1].selectionText());
389 ASSERT_EQ(2U, sel2.size());
390 EXPECT_STREQ("resname RA RB", sel2[0].selectionText());
391 EXPECT_STREQ("resname RB RC", sel2[1].selectionText());
395 TEST_F(SelectionFileOptionTest, HandlesTwoSelectionOptionsFromSingleFile)
397 gmx::SelectionList sel1;
398 gmx::SelectionList sel2;
399 using gmx::SelectionOption;
400 ASSERT_NO_THROW(options_.addOption(
401 SelectionOption("sel1").storeVector(&sel1)));
402 ASSERT_NO_THROW(options_.addOption(
403 SelectionOption("sel2").storeVector(&sel2)));
406 gmx::OptionsAssigner assigner(&options_);
407 std::string value(TestFileManager::getInputFilePath("selfile.dat"));
408 EXPECT_NO_THROW(assigner.start());
409 ASSERT_NO_THROW(assigner.startOption("sel1"));
410 EXPECT_NO_THROW(assigner.finishOption());
411 ASSERT_NO_THROW(assigner.startOption("sel2"));
412 EXPECT_NO_THROW(assigner.finishOption());
413 ASSERT_NO_THROW(assigner.startOption("sf"));
414 EXPECT_NO_THROW(assigner.appendValue(value));
415 EXPECT_NO_THROW(assigner.finishOption());
416 EXPECT_NO_THROW(assigner.finish());
417 EXPECT_NO_THROW(options_.finish());
419 // These should match the contents of selfile.dat
420 ASSERT_EQ(1U, sel1.size());
421 EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
422 ASSERT_EQ(1U, sel2.size());
423 EXPECT_STREQ("resname RB RC", sel2[0].selectionText());
427 TEST_F(SelectionFileOptionTest, HandlesRequiredOptionFromFile)
429 gmx::SelectionList sel;
430 gmx::SelectionList optsel;
431 using gmx::SelectionOption;
432 ASSERT_NO_THROW(options_.addOption(
433 SelectionOption("sel").storeVector(&sel)
434 .multiValue().required()));
435 ASSERT_NO_THROW(options_.addOption(
436 SelectionOption("optsel").storeVector(&optsel)
440 gmx::OptionsAssigner assigner(&options_);
441 EXPECT_NO_THROW(assigner.start());
442 ASSERT_NO_THROW(assigner.startOption("sf"));
443 EXPECT_NO_THROW(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
444 EXPECT_NO_THROW(assigner.finishOption());
445 EXPECT_NO_THROW(assigner.startOption("optsel"));
446 EXPECT_NO_THROW(assigner.finishOption());
447 EXPECT_NO_THROW(assigner.finish());
448 EXPECT_NO_THROW(options_.finish());
449 EXPECT_NO_THROW(manager_.parseRequestedFromString("resname RC RD"));
451 // These should match the contents of selfile.dat
452 ASSERT_EQ(2U, sel.size());
453 EXPECT_STREQ("resname RA RB", sel[0].selectionText());
454 EXPECT_STREQ("resname RB RC", sel[1].selectionText());
455 ASSERT_EQ(1U, optsel.size());
456 EXPECT_STREQ("resname RC RD", optsel[0].selectionText());
460 // TODO: Is this the best possible behavior, or should it error out?
461 TEST_F(SelectionFileOptionTest, HandlesRequiredOptionFromFileWithOtherOptionSet)
463 gmx::SelectionList sel1;
464 gmx::SelectionList sel2;
465 using gmx::SelectionOption;
466 ASSERT_NO_THROW(options_.addOption(
467 SelectionOption("sel1").storeVector(&sel1)
468 .multiValue().required()));
469 ASSERT_NO_THROW(options_.addOption(
470 SelectionOption("sel2").storeVector(&sel2)
471 .multiValue().required()));
474 gmx::OptionsAssigner assigner(&options_);
475 EXPECT_NO_THROW(assigner.start());
476 EXPECT_NO_THROW(assigner.startOption("sel1"));
477 EXPECT_NO_THROW(assigner.appendValue("resname RC RD"));
478 EXPECT_NO_THROW(assigner.finishOption());
479 ASSERT_NO_THROW(assigner.startOption("sf"));
480 EXPECT_NO_THROW(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
481 EXPECT_NO_THROW(assigner.finishOption());
482 EXPECT_NO_THROW(assigner.finish());
483 EXPECT_NO_THROW(options_.finish());
485 // These should match the contents of selfile.dat
486 ASSERT_EQ(2U, sel2.size());
487 EXPECT_STREQ("resname RA RB", sel2[0].selectionText());
488 EXPECT_STREQ("resname RB RC", sel2[1].selectionText());
489 ASSERT_EQ(1U, sel1.size());
490 EXPECT_STREQ("resname RC RD", sel1[0].selectionText());
494 TEST_F(SelectionFileOptionTest, HandlesTwoRequiredOptionsFromSingleFile)
496 gmx::SelectionList sel1;
497 gmx::SelectionList sel2;
498 using gmx::SelectionOption;
499 ASSERT_NO_THROW(options_.addOption(
500 SelectionOption("sel1").storeVector(&sel1).required()));
501 ASSERT_NO_THROW(options_.addOption(
502 SelectionOption("sel2").storeVector(&sel2).required()));
505 gmx::OptionsAssigner assigner(&options_);
506 std::string value(TestFileManager::getInputFilePath("selfile.dat"));
507 EXPECT_NO_THROW(assigner.start());
508 ASSERT_NO_THROW(assigner.startOption("sf"));
509 EXPECT_NO_THROW(assigner.appendValue(value));
510 EXPECT_NO_THROW(assigner.finishOption());
511 EXPECT_NO_THROW(assigner.finish());
512 EXPECT_NO_THROW(options_.finish());
514 // These should match the contents of selfile.dat
515 ASSERT_EQ(1U, sel1.size());
516 EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
517 ASSERT_EQ(1U, sel2.size());
518 EXPECT_STREQ("resname RB RC", sel2[0].selectionText());
522 TEST_F(SelectionFileOptionTest, GivesErrorWithNoFile)
524 gmx::SelectionList sel;
525 using gmx::SelectionOption;
526 ASSERT_NO_THROW(options_.addOption(
527 SelectionOption("sel").storeVector(&sel).multiValue()));
530 gmx::OptionsAssigner assigner(&options_);
531 EXPECT_NO_THROW(assigner.start());
532 ASSERT_NO_THROW(assigner.startOption("sel"));
533 EXPECT_NO_THROW(assigner.finishOption());
534 ASSERT_NO_THROW(assigner.startOption("sf"));
535 EXPECT_THROW(assigner.finishOption(), gmx::InvalidInputError);
536 EXPECT_NO_THROW(assigner.finish());
537 EXPECT_NO_THROW(options_.finish());
541 TEST_F(SelectionFileOptionTest, GivesErrorWithNonExistentFile)
543 gmx::SelectionList sel;
544 using gmx::SelectionOption;
545 ASSERT_NO_THROW(options_.addOption(
546 SelectionOption("sel").storeVector(&sel).multiValue()));
549 gmx::OptionsAssigner assigner(&options_);
550 EXPECT_NO_THROW(assigner.start());
551 ASSERT_NO_THROW(assigner.startOption("sel"));
552 EXPECT_NO_THROW(assigner.finishOption());
553 ASSERT_NO_THROW(assigner.startOption("sf"));
554 // TODO: Should this be changed to an InvalidInputError?
555 EXPECT_THROW(assigner.appendValue("nonexistentfile"), gmx::FileIOError);
556 EXPECT_THROW(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")),
557 gmx::InvalidInputError);
558 EXPECT_NO_THROW(assigner.finishOption());
559 EXPECT_NO_THROW(assigner.finish());
560 EXPECT_NO_THROW(options_.finish());
564 TEST_F(SelectionFileOptionTest, GivesErrorWithMultipleFiles)
566 gmx::SelectionList sel;
567 using gmx::SelectionOption;
568 ASSERT_NO_THROW(options_.addOption(
569 SelectionOption("sel").storeVector(&sel).multiValue()));
572 gmx::OptionsAssigner assigner(&options_);
573 EXPECT_NO_THROW(assigner.start());
574 ASSERT_NO_THROW(assigner.startOption("sel"));
575 EXPECT_NO_THROW(assigner.finishOption());
576 ASSERT_NO_THROW(assigner.startOption("sf"));
577 EXPECT_NO_THROW(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
578 EXPECT_THROW(assigner.appendValue("nonexistentfile"), gmx::InvalidInputError);
579 EXPECT_NO_THROW(assigner.finishOption());
580 EXPECT_NO_THROW(assigner.finish());
581 EXPECT_NO_THROW(options_.finish());