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