Merge release-5-0 into master
[alexxy/gromacs.git] / src / gromacs / selection / tests / selectionoption.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2010,2011,2012,2013,2014, 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.
8  *
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.
13  *
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.
18  *
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.
23  *
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.
31  *
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.
34  */
35 /*! \internal \file
36  * \brief
37  * Tests handling of selection options.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \ingroup module_selection
41  */
42 #include <gtest/gtest.h>
43
44 #include "gromacs/options/options.h"
45 #include "gromacs/options/optionsassigner.h"
46 #include "gromacs/selection/selection.h"
47 #include "gromacs/selection/selectioncollection.h"
48 #include "gromacs/selection/selectionfileoption.h"
49 #include "gromacs/selection/selectionoption.h"
50 #include "gromacs/selection/selectionoptionmanager.h"
51 #include "gromacs/utility/exceptions.h"
52
53 #include "testutils/testasserts.h"
54 #include "testutils/testfilemanager.h"
55
56 #include "toputils.h"
57
58 using gmx::test::TestFileManager;
59
60 namespace
61 {
62
63 /********************************************************************
64  * Base fixture for tests in this file.
65  */
66
67 class SelectionOptionTestBase : public ::testing::Test
68 {
69     public:
70         SelectionOptionTestBase();
71
72         void loadTopology(const char *filename);
73
74         gmx::SelectionCollection    sc_;
75         gmx::SelectionOptionManager manager_;
76         gmx::Options                options_;
77
78     private:
79         gmx::test::TopologyManager  topManager_;
80 };
81
82 SelectionOptionTestBase::SelectionOptionTestBase()
83     : manager_(&sc_), options_(NULL, NULL)
84 {
85     options_.addManager(&manager_);
86     sc_.setReferencePosType("atom");
87     sc_.setOutputPosType("atom");
88 }
89
90 void SelectionOptionTestBase::loadTopology(const char *filename)
91 {
92     topManager_.loadTopology(filename);
93
94     ASSERT_NO_THROW_GMX(sc_.setTopology(topManager_.topology(), -1));
95 }
96
97
98 /********************************************************************
99  * Tests for SelectionOption
100  */
101
102 //! Test fixture for gmx::SelectionOption.
103 typedef SelectionOptionTestBase SelectionOptionTest;
104
105 TEST_F(SelectionOptionTest, ParsesSimpleSelection)
106 {
107     gmx::Selection sel;
108     using gmx::SelectionOption;
109     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel").store(&sel)));
110
111     gmx::OptionsAssigner assigner(&options_);
112     EXPECT_NO_THROW_GMX(assigner.start());
113     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
114     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RA RB"));
115     EXPECT_NO_THROW_GMX(assigner.finishOption());
116     EXPECT_NO_THROW_GMX(assigner.finish());
117     EXPECT_NO_THROW_GMX(options_.finish());
118
119     ASSERT_TRUE(sel.isValid());
120 }
121
122
123 TEST_F(SelectionOptionTest, HandlesDynamicSelectionWhenStaticRequired)
124 {
125     gmx::Selection sel;
126     using gmx::SelectionOption;
127     ASSERT_NO_THROW_GMX(options_.addOption(
128                                 SelectionOption("sel").store(&sel).onlyStatic()));
129
130     gmx::OptionsAssigner assigner(&options_);
131     EXPECT_NO_THROW_GMX(assigner.start());
132     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
133     EXPECT_THROW_GMX(assigner.appendValue("resname RA RB and x < 5"), gmx::InvalidInputError);
134     EXPECT_NO_THROW_GMX(assigner.finishOption());
135     EXPECT_NO_THROW_GMX(assigner.finish());
136     EXPECT_NO_THROW_GMX(options_.finish());
137 }
138
139
140 TEST_F(SelectionOptionTest, HandlesNonAtomicSelectionWhenAtomsRequired)
141 {
142     gmx::Selection sel;
143     using gmx::SelectionOption;
144     ASSERT_NO_THROW_GMX(options_.addOption(
145                                 SelectionOption("sel").store(&sel).onlyAtoms()));
146
147     gmx::OptionsAssigner assigner(&options_);
148     EXPECT_NO_THROW_GMX(assigner.start());
149     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
150     EXPECT_NO_THROW_GMX(assigner.appendValue("res_cog of resname RA RB"));
151     EXPECT_NO_THROW_GMX(assigner.finishOption());
152     EXPECT_NO_THROW_GMX(assigner.finish());
153     EXPECT_NO_THROW_GMX(options_.finish());
154
155     ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
156     EXPECT_THROW_GMX(sc_.compile(), gmx::InvalidInputError);
157 }
158
159
160 TEST_F(SelectionOptionTest, ChecksEmptySelections)
161 {
162     gmx::Selection sel;
163     using gmx::SelectionOption;
164     ASSERT_NO_THROW_GMX(options_.addOption(
165                                 SelectionOption("sel").store(&sel)));
166
167     gmx::OptionsAssigner assigner(&options_);
168     EXPECT_NO_THROW_GMX(assigner.start());
169     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
170     EXPECT_NO_THROW_GMX(assigner.appendValue("none"));
171     EXPECT_NO_THROW_GMX(assigner.finishOption());
172     EXPECT_NO_THROW_GMX(assigner.finish());
173     EXPECT_NO_THROW_GMX(options_.finish());
174
175     EXPECT_THROW_GMX(sc_.compile(), gmx::InvalidInputError);
176 }
177
178
179 TEST_F(SelectionOptionTest, ChecksEmptyDelayedSelections)
180 {
181     gmx::Selection sel;
182     using gmx::SelectionOption;
183     ASSERT_NO_THROW_GMX(options_.addOption(
184                                 SelectionOption("sel").store(&sel)));
185
186     gmx::OptionsAssigner assigner(&options_);
187     EXPECT_NO_THROW_GMX(assigner.start());
188     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
189     EXPECT_NO_THROW_GMX(assigner.finishOption());
190     EXPECT_NO_THROW_GMX(assigner.finish());
191     EXPECT_NO_THROW_GMX(options_.finish());
192     ASSERT_NO_THROW_GMX(manager_.parseRequestedFromString("none"));
193
194     EXPECT_THROW_GMX(sc_.compile(), gmx::InvalidInputError);
195 }
196
197
198 TEST_F(SelectionOptionTest, HandlesTooManySelections)
199 {
200     gmx::Selection sel;
201     using gmx::SelectionOption;
202     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel").store(&sel)));
203
204     gmx::OptionsAssigner assigner(&options_);
205     EXPECT_NO_THROW_GMX(assigner.start());
206     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
207     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RA RB"));
208     EXPECT_THROW_GMX(assigner.appendValue("resname RB RC"), gmx::InvalidInputError);
209     EXPECT_NO_THROW_GMX(assigner.finishOption());
210     EXPECT_NO_THROW_GMX(assigner.finish());
211     EXPECT_NO_THROW_GMX(options_.finish());
212 }
213
214
215 TEST_F(SelectionOptionTest, HandlesTooFewSelections)
216 {
217     gmx::Selection sel[2];
218     using gmx::SelectionOption;
219     ASSERT_NO_THROW_GMX(options_.addOption(
220                                 SelectionOption("sel").store(sel).valueCount(2)));
221
222     gmx::OptionsAssigner assigner(&options_);
223     EXPECT_NO_THROW_GMX(assigner.start());
224     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
225     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RA RB"));
226     EXPECT_THROW_GMX(assigner.finishOption(), gmx::InvalidInputError);
227     EXPECT_NO_THROW_GMX(assigner.finish());
228     EXPECT_NO_THROW_GMX(options_.finish());
229 }
230
231
232 TEST_F(SelectionOptionTest, HandlesDefaultSelectionText)
233 {
234     gmx::Selection sel;
235     using gmx::SelectionOption;
236     options_.addOption(SelectionOption("sel").store(&sel)
237                            .defaultSelectionText("all"));
238
239     EXPECT_NO_THROW_GMX(options_.finish());
240
241     ASSERT_TRUE(sel.isValid());
242
243     EXPECT_NO_THROW_GMX(sc_.setTopology(NULL, 10));
244     EXPECT_NO_THROW_GMX(sc_.compile());
245
246     EXPECT_STREQ("all", sel.selectionText());
247 }
248
249
250 TEST_F(SelectionOptionTest, HandlesAdjuster)
251 {
252     gmx::SelectionList        sel;
253     using gmx::SelectionOption;
254     gmx::SelectionOptionInfo *info = options_.addOption(
255                 SelectionOption("sel").storeVector(&sel).multiValue());
256
257     gmx::OptionsAssigner assigner(&options_);
258     EXPECT_NO_THROW_GMX(assigner.start());
259     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
260     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RA RB"));
261     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RB RC"));
262     EXPECT_NO_THROW_GMX(assigner.finishOption());
263     EXPECT_NO_THROW_GMX(assigner.finish());
264     EXPECT_NO_THROW_GMX(options_.finish());
265     EXPECT_NO_THROW_GMX(info->setValueCount(2));
266 }
267
268
269 TEST_F(SelectionOptionTest, HandlesDynamicWhenStaticRequiredWithAdjuster)
270 {
271     gmx::Selection            sel;
272     using gmx::SelectionOption;
273     gmx::SelectionOptionInfo *info = options_.addOption(
274                 SelectionOption("sel").store(&sel));
275
276     gmx::OptionsAssigner assigner(&options_);
277     EXPECT_NO_THROW_GMX(assigner.start());
278     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
279     EXPECT_NO_THROW_GMX(assigner.appendValue("x < 5"));
280     EXPECT_NO_THROW_GMX(assigner.finishOption());
281     EXPECT_NO_THROW_GMX(assigner.finish());
282     EXPECT_NO_THROW_GMX(options_.finish());
283     EXPECT_THROW_GMX(info->setOnlyStatic(true), gmx::InvalidInputError);
284 }
285
286
287 TEST_F(SelectionOptionTest, HandlesTooManySelectionsWithAdjuster)
288 {
289     gmx::SelectionList        sel;
290     using gmx::SelectionOption;
291     gmx::SelectionOptionInfo *info = options_.addOption(
292                 SelectionOption("sel").storeVector(&sel).multiValue());
293
294     gmx::OptionsAssigner assigner(&options_);
295     EXPECT_NO_THROW_GMX(assigner.start());
296     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
297     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RA RB"));
298     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RB RC"));
299     EXPECT_NO_THROW_GMX(assigner.finishOption());
300     EXPECT_NO_THROW_GMX(assigner.finish());
301     EXPECT_NO_THROW_GMX(options_.finish());
302     EXPECT_THROW_GMX(info->setValueCount(1), gmx::InvalidInputError);
303 }
304
305
306 TEST_F(SelectionOptionTest, HandlesTooFewSelectionsWithAdjuster)
307 {
308     gmx::SelectionList        sel;
309     using gmx::SelectionOption;
310     gmx::SelectionOptionInfo *info = options_.addOption(
311                 SelectionOption("sel").storeVector(&sel).multiValue());
312
313     gmx::OptionsAssigner assigner(&options_);
314     EXPECT_NO_THROW_GMX(assigner.start());
315     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
316     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RA RB"));
317     EXPECT_NO_THROW_GMX(assigner.finishOption());
318     EXPECT_NO_THROW_GMX(assigner.finish());
319     EXPECT_NO_THROW_GMX(options_.finish());
320     EXPECT_THROW_GMX(info->setValueCount(2), gmx::InvalidInputError);
321 }
322
323
324 TEST_F(SelectionOptionTest, HandlesDelayedRequiredSelection)
325 {
326     gmx::Selection sel;
327     using gmx::SelectionOption;
328     ASSERT_NO_THROW_GMX(options_.addOption(
329                                 SelectionOption("sel").store(&sel).required()));
330
331     gmx::OptionsAssigner assigner(&options_);
332     EXPECT_NO_THROW_GMX(assigner.start());
333     EXPECT_NO_THROW_GMX(assigner.finish());
334     EXPECT_NO_THROW_GMX(options_.finish());
335     ASSERT_NO_THROW_GMX(manager_.parseRequestedFromString("resname RA RB"));
336     ASSERT_STREQ("resname RA RB", sel.selectionText());
337 }
338
339
340 TEST_F(SelectionOptionTest, HandlesTooFewDelayedRequiredSelections)
341 {
342     gmx::Selection sel[2];
343     using gmx::SelectionOption;
344     ASSERT_NO_THROW_GMX(options_.addOption(
345                                 SelectionOption("sel").store(sel).required()
346                                     .valueCount(2)));
347
348     gmx::OptionsAssigner assigner(&options_);
349     EXPECT_NO_THROW_GMX(assigner.start());
350     EXPECT_NO_THROW_GMX(assigner.finish());
351     EXPECT_NO_THROW_GMX(options_.finish());
352     EXPECT_THROW_GMX(manager_.parseRequestedFromString("resname RA RB"), gmx::InvalidInputError);
353 }
354
355
356 TEST_F(SelectionOptionTest, HandlesDelayedOptionalSelection)
357 {
358     gmx::Selection sel;
359     using gmx::SelectionOption;
360     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel").store(&sel)));
361
362     gmx::OptionsAssigner assigner(&options_);
363     EXPECT_NO_THROW_GMX(assigner.start());
364     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
365     EXPECT_NO_THROW_GMX(assigner.finishOption());
366     EXPECT_NO_THROW_GMX(assigner.finish());
367     EXPECT_NO_THROW_GMX(options_.finish());
368     ASSERT_NO_THROW_GMX(manager_.parseRequestedFromString("resname RA RB"));
369     ASSERT_STREQ("resname RA RB", sel.selectionText());
370 }
371
372
373 TEST_F(SelectionOptionTest, HandlesDelayedSelectionWithAdjuster)
374 {
375     gmx::SelectionList        sel;
376     using gmx::SelectionOption;
377     gmx::SelectionOptionInfo *info = options_.addOption(
378                 SelectionOption("sel").storeVector(&sel).valueCount(3));
379
380     gmx::OptionsAssigner assigner(&options_);
381     EXPECT_NO_THROW_GMX(assigner.start());
382     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
383     EXPECT_NO_THROW_GMX(assigner.finishOption());
384     EXPECT_NO_THROW_GMX(assigner.finish());
385     EXPECT_NO_THROW_GMX(options_.finish());
386     EXPECT_NO_THROW_GMX(info->setValueCount(2));
387     EXPECT_NO_THROW_GMX(manager_.parseRequestedFromString("resname RA RB; resname RB RC"));
388 }
389
390
391 /********************************************************************
392  * Tests for SelectionFileOption
393  */
394
395 class SelectionFileOptionTest : public SelectionOptionTestBase
396 {
397     public:
398         SelectionFileOptionTest();
399 };
400
401 SelectionFileOptionTest::SelectionFileOptionTest()
402 {
403     options_.addOption(gmx::SelectionFileOption("sf"));
404 }
405
406
407 TEST_F(SelectionFileOptionTest, HandlesSingleSelectionOptionFromFile)
408 {
409     gmx::SelectionList sel;
410     gmx::SelectionList reqsel;
411     using gmx::SelectionOption;
412     ASSERT_NO_THROW_GMX(options_.addOption(
413                                 SelectionOption("sel").storeVector(&sel).multiValue()));
414     ASSERT_NO_THROW_GMX(options_.addOption(
415                                 SelectionOption("reqsel").storeVector(&reqsel)
416                                     .multiValue().required()));
417
418     gmx::OptionsAssigner assigner(&options_);
419     EXPECT_NO_THROW_GMX(assigner.start());
420     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
421     EXPECT_NO_THROW_GMX(assigner.finishOption());
422     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
423     EXPECT_NO_THROW_GMX(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
424     EXPECT_NO_THROW_GMX(assigner.finishOption());
425     EXPECT_NO_THROW_GMX(assigner.finish());
426     EXPECT_NO_THROW_GMX(options_.finish());
427
428     // These should match the contents of selfile.dat
429     ASSERT_EQ(2U, sel.size());
430     EXPECT_STREQ("resname RA RB", sel[0].selectionText());
431     EXPECT_STREQ("resname RB RC", sel[1].selectionText());
432     ASSERT_EQ(0U, reqsel.size());
433 }
434
435
436 TEST_F(SelectionFileOptionTest, HandlesTwoSeparateSelectionOptions)
437 {
438     gmx::SelectionList sel1;
439     gmx::SelectionList sel2;
440     using gmx::SelectionOption;
441     ASSERT_NO_THROW_GMX(options_.addOption(
442                                 SelectionOption("sel1").storeVector(&sel1).multiValue()));
443     ASSERT_NO_THROW_GMX(options_.addOption(
444                                 SelectionOption("sel2").storeVector(&sel2).multiValue()));
445
446     gmx::OptionsAssigner assigner(&options_);
447     std::string          value(TestFileManager::getInputFilePath("selfile.dat"));
448     EXPECT_NO_THROW_GMX(assigner.start());
449     ASSERT_NO_THROW_GMX(assigner.startOption("sel1"));
450     EXPECT_NO_THROW_GMX(assigner.finishOption());
451     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
452     EXPECT_NO_THROW_GMX(assigner.appendValue(value));
453     EXPECT_NO_THROW_GMX(assigner.finishOption());
454     ASSERT_NO_THROW_GMX(assigner.startOption("sel2"));
455     EXPECT_NO_THROW_GMX(assigner.finishOption());
456     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
457     EXPECT_NO_THROW_GMX(assigner.appendValue(value));
458     EXPECT_NO_THROW_GMX(assigner.finishOption());
459     EXPECT_NO_THROW_GMX(assigner.finish());
460     EXPECT_NO_THROW_GMX(options_.finish());
461
462     // These should match the contents of selfile.dat
463     ASSERT_EQ(2U, sel1.size());
464     EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
465     EXPECT_STREQ("resname RB RC", sel1[1].selectionText());
466     ASSERT_EQ(2U, sel2.size());
467     EXPECT_STREQ("resname RA RB", sel2[0].selectionText());
468     EXPECT_STREQ("resname RB RC", sel2[1].selectionText());
469 }
470
471
472 TEST_F(SelectionFileOptionTest, HandlesTwoSelectionOptionsFromSingleFile)
473 {
474     gmx::SelectionList sel1;
475     gmx::SelectionList sel2;
476     using gmx::SelectionOption;
477     ASSERT_NO_THROW_GMX(options_.addOption(
478                                 SelectionOption("sel1").storeVector(&sel1)));
479     ASSERT_NO_THROW_GMX(options_.addOption(
480                                 SelectionOption("sel2").storeVector(&sel2)));
481
482     gmx::OptionsAssigner assigner(&options_);
483     std::string          value(TestFileManager::getInputFilePath("selfile.dat"));
484     EXPECT_NO_THROW_GMX(assigner.start());
485     ASSERT_NO_THROW_GMX(assigner.startOption("sel1"));
486     EXPECT_NO_THROW_GMX(assigner.finishOption());
487     ASSERT_NO_THROW_GMX(assigner.startOption("sel2"));
488     EXPECT_NO_THROW_GMX(assigner.finishOption());
489     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
490     EXPECT_NO_THROW_GMX(assigner.appendValue(value));
491     EXPECT_NO_THROW_GMX(assigner.finishOption());
492     EXPECT_NO_THROW_GMX(assigner.finish());
493     EXPECT_NO_THROW_GMX(options_.finish());
494
495     // These should match the contents of selfile.dat
496     ASSERT_EQ(1U, sel1.size());
497     EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
498     ASSERT_EQ(1U, sel2.size());
499     EXPECT_STREQ("resname RB RC", sel2[0].selectionText());
500 }
501
502
503 TEST_F(SelectionFileOptionTest, HandlesRequiredOptionFromFile)
504 {
505     gmx::SelectionList sel;
506     gmx::SelectionList optsel;
507     using gmx::SelectionOption;
508     ASSERT_NO_THROW_GMX(options_.addOption(
509                                 SelectionOption("sel").storeVector(&sel)
510                                     .multiValue().required()));
511     ASSERT_NO_THROW_GMX(options_.addOption(
512                                 SelectionOption("optsel").storeVector(&optsel)
513                                     .multiValue()));
514
515     gmx::OptionsAssigner assigner(&options_);
516     EXPECT_NO_THROW_GMX(assigner.start());
517     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
518     EXPECT_NO_THROW_GMX(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
519     EXPECT_NO_THROW_GMX(assigner.finishOption());
520     EXPECT_NO_THROW_GMX(assigner.startOption("optsel"));
521     EXPECT_NO_THROW_GMX(assigner.finishOption());
522     EXPECT_NO_THROW_GMX(assigner.finish());
523     EXPECT_NO_THROW_GMX(options_.finish());
524     EXPECT_NO_THROW_GMX(manager_.parseRequestedFromString("resname RC RD"));
525
526     // These should match the contents of selfile.dat
527     ASSERT_EQ(2U, sel.size());
528     EXPECT_STREQ("resname RA RB", sel[0].selectionText());
529     EXPECT_STREQ("resname RB RC", sel[1].selectionText());
530     ASSERT_EQ(1U, optsel.size());
531     EXPECT_STREQ("resname RC RD", optsel[0].selectionText());
532 }
533
534
535 // TODO: Is this the best possible behavior, or should it error out?
536 TEST_F(SelectionFileOptionTest, HandlesRequiredOptionFromFileWithOtherOptionSet)
537 {
538     gmx::SelectionList sel1;
539     gmx::SelectionList sel2;
540     using gmx::SelectionOption;
541     ASSERT_NO_THROW_GMX(options_.addOption(
542                                 SelectionOption("sel1").storeVector(&sel1)
543                                     .multiValue().required()));
544     ASSERT_NO_THROW_GMX(options_.addOption(
545                                 SelectionOption("sel2").storeVector(&sel2)
546                                     .multiValue().required()));
547
548     gmx::OptionsAssigner assigner(&options_);
549     EXPECT_NO_THROW_GMX(assigner.start());
550     EXPECT_NO_THROW_GMX(assigner.startOption("sel1"));
551     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RC RD"));
552     EXPECT_NO_THROW_GMX(assigner.finishOption());
553     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
554     EXPECT_NO_THROW_GMX(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
555     EXPECT_NO_THROW_GMX(assigner.finishOption());
556     EXPECT_NO_THROW_GMX(assigner.finish());
557     EXPECT_NO_THROW_GMX(options_.finish());
558
559     // These should match the contents of selfile.dat
560     ASSERT_EQ(2U, sel2.size());
561     EXPECT_STREQ("resname RA RB", sel2[0].selectionText());
562     EXPECT_STREQ("resname RB RC", sel2[1].selectionText());
563     ASSERT_EQ(1U, sel1.size());
564     EXPECT_STREQ("resname RC RD", sel1[0].selectionText());
565 }
566
567
568 TEST_F(SelectionFileOptionTest, HandlesTwoRequiredOptionsFromSingleFile)
569 {
570     gmx::SelectionList sel1;
571     gmx::SelectionList sel2;
572     using gmx::SelectionOption;
573     ASSERT_NO_THROW_GMX(options_.addOption(
574                                 SelectionOption("sel1").storeVector(&sel1).required()));
575     ASSERT_NO_THROW_GMX(options_.addOption(
576                                 SelectionOption("sel2").storeVector(&sel2).required()));
577
578     gmx::OptionsAssigner assigner(&options_);
579     std::string          value(TestFileManager::getInputFilePath("selfile.dat"));
580     EXPECT_NO_THROW_GMX(assigner.start());
581     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
582     EXPECT_NO_THROW_GMX(assigner.appendValue(value));
583     EXPECT_NO_THROW_GMX(assigner.finishOption());
584     EXPECT_NO_THROW_GMX(assigner.finish());
585     EXPECT_NO_THROW_GMX(options_.finish());
586
587     // These should match the contents of selfile.dat
588     ASSERT_EQ(1U, sel1.size());
589     EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
590     ASSERT_EQ(1U, sel2.size());
591     EXPECT_STREQ("resname RB RC", sel2[0].selectionText());
592 }
593
594
595 TEST_F(SelectionFileOptionTest, GivesErrorWithNoFile)
596 {
597     gmx::SelectionList sel;
598     using gmx::SelectionOption;
599     ASSERT_NO_THROW_GMX(options_.addOption(
600                                 SelectionOption("sel").storeVector(&sel).multiValue()));
601
602     gmx::OptionsAssigner assigner(&options_);
603     EXPECT_NO_THROW_GMX(assigner.start());
604     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
605     EXPECT_NO_THROW_GMX(assigner.finishOption());
606     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
607     EXPECT_THROW_GMX(assigner.finishOption(), gmx::InvalidInputError);
608     EXPECT_NO_THROW_GMX(assigner.finish());
609     EXPECT_NO_THROW_GMX(options_.finish());
610 }
611
612
613 TEST_F(SelectionFileOptionTest, GivesErrorWithNonExistentFile)
614 {
615     gmx::SelectionList sel;
616     using gmx::SelectionOption;
617     ASSERT_NO_THROW_GMX(options_.addOption(
618                                 SelectionOption("sel").storeVector(&sel).multiValue()));
619
620     gmx::OptionsAssigner assigner(&options_);
621     EXPECT_NO_THROW_GMX(assigner.start());
622     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
623     EXPECT_NO_THROW_GMX(assigner.finishOption());
624     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
625     // TODO: Should this be changed to an InvalidInputError?
626     EXPECT_THROW_GMX(assigner.appendValue("nonexistentfile"), gmx::FileIOError);
627     EXPECT_THROW_GMX(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")),
628                      gmx::InvalidInputError);
629     EXPECT_NO_THROW_GMX(assigner.finishOption());
630     EXPECT_NO_THROW_GMX(assigner.finish());
631     EXPECT_NO_THROW_GMX(options_.finish());
632 }
633
634
635 TEST_F(SelectionFileOptionTest, GivesErrorWithMultipleFiles)
636 {
637     gmx::SelectionList sel;
638     using gmx::SelectionOption;
639     ASSERT_NO_THROW_GMX(options_.addOption(
640                                 SelectionOption("sel").storeVector(&sel).multiValue()));
641
642     gmx::OptionsAssigner assigner(&options_);
643     EXPECT_NO_THROW_GMX(assigner.start());
644     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
645     EXPECT_NO_THROW_GMX(assigner.finishOption());
646     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
647     EXPECT_NO_THROW_GMX(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
648     EXPECT_THROW_GMX(assigner.appendValue("nonexistentfile"), gmx::InvalidInputError);
649     EXPECT_NO_THROW_GMX(assigner.finishOption());
650     EXPECT_NO_THROW_GMX(assigner.finish());
651     EXPECT_NO_THROW_GMX(options_.finish());
652 }
653
654 } // namespace