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 typedef SelectionOptionTestBase SelectionOptionTest;
91 TEST_F(SelectionOptionTest, ParsesSimpleSelection)
94 using gmx::SelectionOption;
95 ASSERT_NO_THROW(options_.addOption(SelectionOption("sel").store(&sel)));
98 gmx::OptionsAssigner assigner(&options_);
99 EXPECT_NO_THROW(assigner.start());
100 ASSERT_NO_THROW(assigner.startOption("sel"));
101 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
102 EXPECT_NO_THROW(assigner.finishOption());
103 EXPECT_NO_THROW(assigner.finish());
104 EXPECT_NO_THROW(options_.finish());
108 TEST_F(SelectionOptionTest, HandlesDynamicSelectionWhenStaticRequired)
111 using gmx::SelectionOption;
112 ASSERT_NO_THROW(options_.addOption(
113 SelectionOption("sel").store(&sel).onlyStatic()));
116 gmx::OptionsAssigner assigner(&options_);
117 EXPECT_NO_THROW(assigner.start());
118 ASSERT_NO_THROW(assigner.startOption("sel"));
119 EXPECT_THROW(assigner.appendValue("resname RA RB and x < 5"), gmx::InvalidInputError);
120 EXPECT_NO_THROW(assigner.finishOption());
121 EXPECT_NO_THROW(assigner.finish());
122 EXPECT_NO_THROW(options_.finish());
126 TEST_F(SelectionOptionTest, HandlesTooManySelections)
129 using gmx::SelectionOption;
130 ASSERT_NO_THROW(options_.addOption(SelectionOption("sel").store(&sel)));
133 gmx::OptionsAssigner assigner(&options_);
134 EXPECT_NO_THROW(assigner.start());
135 ASSERT_NO_THROW(assigner.startOption("sel"));
136 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
137 EXPECT_THROW(assigner.appendValue("resname RB RC"), gmx::InvalidInputError);
138 EXPECT_NO_THROW(assigner.finishOption());
139 EXPECT_NO_THROW(assigner.finish());
140 EXPECT_NO_THROW(options_.finish());
144 TEST_F(SelectionOptionTest, HandlesTooFewSelections)
146 gmx::Selection sel[2];
147 using gmx::SelectionOption;
148 ASSERT_NO_THROW(options_.addOption(
149 SelectionOption("sel").store(sel).valueCount(2)));
152 gmx::OptionsAssigner assigner(&options_);
153 EXPECT_NO_THROW(assigner.start());
154 ASSERT_NO_THROW(assigner.startOption("sel"));
155 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
156 EXPECT_THROW(assigner.finishOption(), gmx::InvalidInputError);
157 EXPECT_NO_THROW(assigner.finish());
158 EXPECT_NO_THROW(options_.finish());
162 TEST_F(SelectionOptionTest, HandlesAdjuster)
164 gmx::SelectionList sel;
165 using gmx::SelectionOption;
166 gmx::SelectionOptionInfo *info = options_.addOption(
167 SelectionOption("sel").storeVector(&sel).multiValue());
170 gmx::OptionsAssigner assigner(&options_);
171 EXPECT_NO_THROW(assigner.start());
172 ASSERT_NO_THROW(assigner.startOption("sel"));
173 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
174 EXPECT_NO_THROW(assigner.appendValue("resname RB RC"));
175 EXPECT_NO_THROW(assigner.finishOption());
176 EXPECT_NO_THROW(assigner.finish());
177 EXPECT_NO_THROW(options_.finish());
178 EXPECT_NO_THROW(info->setValueCount(2));
182 TEST_F(SelectionOptionTest, HandlesDynamicWhenStaticRequiredWithAdjuster)
185 using gmx::SelectionOption;
186 gmx::SelectionOptionInfo *info = options_.addOption(
187 SelectionOption("sel").store(&sel));
190 gmx::OptionsAssigner assigner(&options_);
191 EXPECT_NO_THROW(assigner.start());
192 ASSERT_NO_THROW(assigner.startOption("sel"));
193 EXPECT_NO_THROW(assigner.appendValue("x < 5"));
194 EXPECT_NO_THROW(assigner.finishOption());
195 EXPECT_NO_THROW(assigner.finish());
196 EXPECT_NO_THROW(options_.finish());
197 EXPECT_THROW(info->setOnlyStatic(true), gmx::InvalidInputError);
201 TEST_F(SelectionOptionTest, HandlesTooManySelectionsWithAdjuster)
203 gmx::SelectionList sel;
204 using gmx::SelectionOption;
205 gmx::SelectionOptionInfo *info = options_.addOption(
206 SelectionOption("sel").storeVector(&sel).multiValue());
209 gmx::OptionsAssigner assigner(&options_);
210 EXPECT_NO_THROW(assigner.start());
211 ASSERT_NO_THROW(assigner.startOption("sel"));
212 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
213 EXPECT_NO_THROW(assigner.appendValue("resname RB RC"));
214 EXPECT_NO_THROW(assigner.finishOption());
215 EXPECT_NO_THROW(assigner.finish());
216 EXPECT_NO_THROW(options_.finish());
217 EXPECT_THROW(info->setValueCount(1), gmx::InvalidInputError);
221 TEST_F(SelectionOptionTest, HandlesTooFewSelectionsWithAdjuster)
223 gmx::SelectionList sel;
224 using gmx::SelectionOption;
225 gmx::SelectionOptionInfo *info = options_.addOption(
226 SelectionOption("sel").storeVector(&sel).multiValue());
229 gmx::OptionsAssigner assigner(&options_);
230 EXPECT_NO_THROW(assigner.start());
231 ASSERT_NO_THROW(assigner.startOption("sel"));
232 EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
233 EXPECT_NO_THROW(assigner.finishOption());
234 EXPECT_NO_THROW(assigner.finish());
235 EXPECT_NO_THROW(options_.finish());
236 EXPECT_THROW(info->setValueCount(2), gmx::InvalidInputError);
240 TEST_F(SelectionOptionTest, HandlesDelayedRequiredSelection)
243 using gmx::SelectionOption;
244 ASSERT_NO_THROW(options_.addOption(
245 SelectionOption("sel").store(&sel).required()));
248 gmx::OptionsAssigner assigner(&options_);
249 EXPECT_NO_THROW(assigner.start());
250 EXPECT_NO_THROW(assigner.finish());
251 EXPECT_NO_THROW(options_.finish());
252 ASSERT_NO_THROW(manager_.parseRequestedFromString("resname RA RB"));
253 ASSERT_STREQ("resname RA RB", sel.selectionText());
257 TEST_F(SelectionOptionTest, HandlesTooFewDelayedRequiredSelections)
259 gmx::Selection sel[2];
260 using gmx::SelectionOption;
261 ASSERT_NO_THROW(options_.addOption(
262 SelectionOption("sel").store(sel).required()
266 gmx::OptionsAssigner assigner(&options_);
267 EXPECT_NO_THROW(assigner.start());
268 EXPECT_NO_THROW(assigner.finish());
269 EXPECT_NO_THROW(options_.finish());
270 EXPECT_THROW(manager_.parseRequestedFromString("resname RA RB"), gmx::InvalidInputError);
274 TEST_F(SelectionOptionTest, HandlesDelayedOptionalSelection)
277 using gmx::SelectionOption;
278 ASSERT_NO_THROW(options_.addOption(SelectionOption("sel").store(&sel)));
281 gmx::OptionsAssigner assigner(&options_);
282 EXPECT_NO_THROW(assigner.start());
283 ASSERT_NO_THROW(assigner.startOption("sel"));
284 EXPECT_NO_THROW(assigner.finishOption());
285 EXPECT_NO_THROW(assigner.finish());
286 EXPECT_NO_THROW(options_.finish());
287 ASSERT_NO_THROW(manager_.parseRequestedFromString("resname RA RB"));
288 ASSERT_STREQ("resname RA RB", sel.selectionText());
292 TEST_F(SelectionOptionTest, HandlesDelayedSelectionWithAdjuster)
294 gmx::SelectionList sel;
295 using gmx::SelectionOption;
296 gmx::SelectionOptionInfo *info = options_.addOption(
297 SelectionOption("sel").storeVector(&sel).valueCount(3));
300 gmx::OptionsAssigner assigner(&options_);
301 EXPECT_NO_THROW(assigner.start());
302 ASSERT_NO_THROW(assigner.startOption("sel"));
303 EXPECT_NO_THROW(assigner.finishOption());
304 EXPECT_NO_THROW(assigner.finish());
305 EXPECT_NO_THROW(options_.finish());
306 EXPECT_NO_THROW(info->setValueCount(2));
307 EXPECT_NO_THROW(manager_.parseRequestedFromString("resname RA RB; resname RB RC"));
311 /********************************************************************
312 * Tests for SelectionFileOption
315 class SelectionFileOptionTest : public SelectionOptionTestBase
318 SelectionFileOptionTest();
321 SelectionFileOptionTest::SelectionFileOptionTest()
323 options_.addOption(gmx::SelectionFileOption("sf"));
327 TEST_F(SelectionFileOptionTest, HandlesSingleSelectionOptionFromFile)
329 gmx::SelectionList sel;
330 gmx::SelectionList reqsel;
331 using gmx::SelectionOption;
332 ASSERT_NO_THROW(options_.addOption(
333 SelectionOption("sel").storeVector(&sel).multiValue()));
334 ASSERT_NO_THROW(options_.addOption(
335 SelectionOption("reqsel").storeVector(&reqsel)
336 .multiValue().required()));
339 gmx::OptionsAssigner assigner(&options_);
340 EXPECT_NO_THROW(assigner.start());
341 ASSERT_NO_THROW(assigner.startOption("sel"));
342 EXPECT_NO_THROW(assigner.finishOption());
343 ASSERT_NO_THROW(assigner.startOption("sf"));
344 EXPECT_NO_THROW(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
345 EXPECT_NO_THROW(assigner.finishOption());
346 EXPECT_NO_THROW(assigner.finish());
347 EXPECT_NO_THROW(options_.finish());
349 // These should match the contents of selfile.dat
350 ASSERT_EQ(2U, sel.size());
351 EXPECT_STREQ("resname RA RB", sel[0].selectionText());
352 EXPECT_STREQ("resname RB RC", sel[1].selectionText());
353 ASSERT_EQ(0U, reqsel.size());
357 TEST_F(SelectionFileOptionTest, HandlesTwoSeparateSelectionOptions)
359 gmx::SelectionList sel1;
360 gmx::SelectionList sel2;
361 using gmx::SelectionOption;
362 ASSERT_NO_THROW(options_.addOption(
363 SelectionOption("sel1").storeVector(&sel1).multiValue()));
364 ASSERT_NO_THROW(options_.addOption(
365 SelectionOption("sel2").storeVector(&sel2).multiValue()));
368 gmx::OptionsAssigner assigner(&options_);
369 std::string value(TestFileManager::getInputFilePath("selfile.dat"));
370 EXPECT_NO_THROW(assigner.start());
371 ASSERT_NO_THROW(assigner.startOption("sel1"));
372 EXPECT_NO_THROW(assigner.finishOption());
373 ASSERT_NO_THROW(assigner.startOption("sf"));
374 EXPECT_NO_THROW(assigner.appendValue(value));
375 EXPECT_NO_THROW(assigner.finishOption());
376 ASSERT_NO_THROW(assigner.startOption("sel2"));
377 EXPECT_NO_THROW(assigner.finishOption());
378 ASSERT_NO_THROW(assigner.startOption("sf"));
379 EXPECT_NO_THROW(assigner.appendValue(value));
380 EXPECT_NO_THROW(assigner.finishOption());
381 EXPECT_NO_THROW(assigner.finish());
382 EXPECT_NO_THROW(options_.finish());
384 // These should match the contents of selfile.dat
385 ASSERT_EQ(2U, sel1.size());
386 EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
387 EXPECT_STREQ("resname RB RC", sel1[1].selectionText());
388 ASSERT_EQ(2U, sel2.size());
389 EXPECT_STREQ("resname RA RB", sel2[0].selectionText());
390 EXPECT_STREQ("resname RB RC", sel2[1].selectionText());
394 TEST_F(SelectionFileOptionTest, HandlesTwoSelectionOptionsFromSingleFile)
396 gmx::SelectionList sel1;
397 gmx::SelectionList sel2;
398 using gmx::SelectionOption;
399 ASSERT_NO_THROW(options_.addOption(
400 SelectionOption("sel1").storeVector(&sel1)));
401 ASSERT_NO_THROW(options_.addOption(
402 SelectionOption("sel2").storeVector(&sel2)));
405 gmx::OptionsAssigner assigner(&options_);
406 std::string value(TestFileManager::getInputFilePath("selfile.dat"));
407 EXPECT_NO_THROW(assigner.start());
408 ASSERT_NO_THROW(assigner.startOption("sel1"));
409 EXPECT_NO_THROW(assigner.finishOption());
410 ASSERT_NO_THROW(assigner.startOption("sel2"));
411 EXPECT_NO_THROW(assigner.finishOption());
412 ASSERT_NO_THROW(assigner.startOption("sf"));
413 EXPECT_NO_THROW(assigner.appendValue(value));
414 EXPECT_NO_THROW(assigner.finishOption());
415 EXPECT_NO_THROW(assigner.finish());
416 EXPECT_NO_THROW(options_.finish());
418 // These should match the contents of selfile.dat
419 ASSERT_EQ(1U, sel1.size());
420 EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
421 ASSERT_EQ(1U, sel2.size());
422 EXPECT_STREQ("resname RB RC", sel2[0].selectionText());
426 TEST_F(SelectionFileOptionTest, HandlesRequiredOptionFromFile)
428 gmx::SelectionList sel;
429 gmx::SelectionList optsel;
430 using gmx::SelectionOption;
431 ASSERT_NO_THROW(options_.addOption(
432 SelectionOption("sel").storeVector(&sel)
433 .multiValue().required()));
434 ASSERT_NO_THROW(options_.addOption(
435 SelectionOption("optsel").storeVector(&optsel)
439 gmx::OptionsAssigner assigner(&options_);
440 EXPECT_NO_THROW(assigner.start());
441 ASSERT_NO_THROW(assigner.startOption("sf"));
442 EXPECT_NO_THROW(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
443 EXPECT_NO_THROW(assigner.finishOption());
444 EXPECT_NO_THROW(assigner.startOption("optsel"));
445 EXPECT_NO_THROW(assigner.finishOption());
446 EXPECT_NO_THROW(assigner.finish());
447 EXPECT_NO_THROW(options_.finish());
448 EXPECT_NO_THROW(manager_.parseRequestedFromString("resname RC RD"));
450 // These should match the contents of selfile.dat
451 ASSERT_EQ(2U, sel.size());
452 EXPECT_STREQ("resname RA RB", sel[0].selectionText());
453 EXPECT_STREQ("resname RB RC", sel[1].selectionText());
454 ASSERT_EQ(1U, optsel.size());
455 EXPECT_STREQ("resname RC RD", optsel[0].selectionText());
459 // TODO: Is this the best possible behavior, or should it error out?
460 TEST_F(SelectionFileOptionTest, HandlesRequiredOptionFromFileWithOtherOptionSet)
462 gmx::SelectionList sel1;
463 gmx::SelectionList sel2;
464 using gmx::SelectionOption;
465 ASSERT_NO_THROW(options_.addOption(
466 SelectionOption("sel1").storeVector(&sel1)
467 .multiValue().required()));
468 ASSERT_NO_THROW(options_.addOption(
469 SelectionOption("sel2").storeVector(&sel2)
470 .multiValue().required()));
473 gmx::OptionsAssigner assigner(&options_);
474 EXPECT_NO_THROW(assigner.start());
475 EXPECT_NO_THROW(assigner.startOption("sel1"));
476 EXPECT_NO_THROW(assigner.appendValue("resname RC RD"));
477 EXPECT_NO_THROW(assigner.finishOption());
478 ASSERT_NO_THROW(assigner.startOption("sf"));
479 EXPECT_NO_THROW(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
480 EXPECT_NO_THROW(assigner.finishOption());
481 EXPECT_NO_THROW(assigner.finish());
482 EXPECT_NO_THROW(options_.finish());
484 // These should match the contents of selfile.dat
485 ASSERT_EQ(2U, sel2.size());
486 EXPECT_STREQ("resname RA RB", sel2[0].selectionText());
487 EXPECT_STREQ("resname RB RC", sel2[1].selectionText());
488 ASSERT_EQ(1U, sel1.size());
489 EXPECT_STREQ("resname RC RD", sel1[0].selectionText());
493 TEST_F(SelectionFileOptionTest, HandlesTwoRequiredOptionsFromSingleFile)
495 gmx::SelectionList sel1;
496 gmx::SelectionList sel2;
497 using gmx::SelectionOption;
498 ASSERT_NO_THROW(options_.addOption(
499 SelectionOption("sel1").storeVector(&sel1).required()));
500 ASSERT_NO_THROW(options_.addOption(
501 SelectionOption("sel2").storeVector(&sel2).required()));
504 gmx::OptionsAssigner assigner(&options_);
505 std::string value(TestFileManager::getInputFilePath("selfile.dat"));
506 EXPECT_NO_THROW(assigner.start());
507 ASSERT_NO_THROW(assigner.startOption("sf"));
508 EXPECT_NO_THROW(assigner.appendValue(value));
509 EXPECT_NO_THROW(assigner.finishOption());
510 EXPECT_NO_THROW(assigner.finish());
511 EXPECT_NO_THROW(options_.finish());
513 // These should match the contents of selfile.dat
514 ASSERT_EQ(1U, sel1.size());
515 EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
516 ASSERT_EQ(1U, sel2.size());
517 EXPECT_STREQ("resname RB RC", sel2[0].selectionText());
521 TEST_F(SelectionFileOptionTest, GivesErrorWithNoFile)
523 gmx::SelectionList sel;
524 using gmx::SelectionOption;
525 ASSERT_NO_THROW(options_.addOption(
526 SelectionOption("sel").storeVector(&sel).multiValue()));
529 gmx::OptionsAssigner assigner(&options_);
530 EXPECT_NO_THROW(assigner.start());
531 ASSERT_NO_THROW(assigner.startOption("sel"));
532 EXPECT_NO_THROW(assigner.finishOption());
533 ASSERT_NO_THROW(assigner.startOption("sf"));
534 EXPECT_THROW(assigner.finishOption(), gmx::InvalidInputError);
535 EXPECT_NO_THROW(assigner.finish());
536 EXPECT_NO_THROW(options_.finish());
540 TEST_F(SelectionFileOptionTest, GivesErrorWithNonExistentFile)
542 gmx::SelectionList sel;
543 using gmx::SelectionOption;
544 ASSERT_NO_THROW(options_.addOption(
545 SelectionOption("sel").storeVector(&sel).multiValue()));
548 gmx::OptionsAssigner assigner(&options_);
549 EXPECT_NO_THROW(assigner.start());
550 ASSERT_NO_THROW(assigner.startOption("sel"));
551 EXPECT_NO_THROW(assigner.finishOption());
552 ASSERT_NO_THROW(assigner.startOption("sf"));
553 // TODO: Should this be changed to an InvalidInputError?
554 EXPECT_THROW(assigner.appendValue("nonexistentfile"), gmx::FileIOError);
555 EXPECT_THROW(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")),
556 gmx::InvalidInputError);
557 EXPECT_NO_THROW(assigner.finishOption());
558 EXPECT_NO_THROW(assigner.finish());
559 EXPECT_NO_THROW(options_.finish());
563 TEST_F(SelectionFileOptionTest, GivesErrorWithMultipleFiles)
565 gmx::SelectionList sel;
566 using gmx::SelectionOption;
567 ASSERT_NO_THROW(options_.addOption(
568 SelectionOption("sel").storeVector(&sel).multiValue()));
571 gmx::OptionsAssigner assigner(&options_);
572 EXPECT_NO_THROW(assigner.start());
573 ASSERT_NO_THROW(assigner.startOption("sel"));
574 EXPECT_NO_THROW(assigner.finishOption());
575 ASSERT_NO_THROW(assigner.startOption("sf"));
576 EXPECT_NO_THROW(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
577 EXPECT_THROW(assigner.appendValue("nonexistentfile"), gmx::InvalidInputError);
578 EXPECT_NO_THROW(assigner.finishOption());
579 EXPECT_NO_THROW(assigner.finish());
580 EXPECT_NO_THROW(options_.finish());