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