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