Apply clang-format to source tree
[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-2017, The GROMACS development team.
5  * Copyright (c) 2019, by the GROMACS development team, led by
6  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7  * and including many others, as listed in the AUTHORS file in the
8  * top-level source directory and at http://www.gromacs.org.
9  *
10  * GROMACS is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public License
12  * as published by the Free Software Foundation; either version 2.1
13  * of the License, or (at your option) any later version.
14  *
15  * GROMACS is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with GROMACS; if not, see
22  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
24  *
25  * If you want to redistribute modifications to GROMACS, please
26  * consider that scientific software is very special. Version
27  * control is crucial - bugs must be traceable. We will be happy to
28  * consider code for inclusion in the official distribution, but
29  * derived work must not be called official GROMACS. Details are found
30  * in the README & COPYING files - if they are missing, get the
31  * official version at http://www.gromacs.org.
32  *
33  * To help us fund GROMACS development, we humbly ask that you cite
34  * the research papers on the package. Check out http://www.gromacs.org.
35  */
36 /*! \internal \file
37  * \brief
38  * Tests handling of selection options.
39  *
40  * \author Teemu Murtola <teemu.murtola@gmail.com>
41  * \ingroup module_selection
42  */
43 #include "gmxpre.h"
44
45 #include "gromacs/selection/selectionoption.h"
46
47 #include <gtest/gtest.h>
48
49 #include "gromacs/options/options.h"
50 #include "gromacs/options/optionsassigner.h"
51 #include "gromacs/selection/selection.h"
52 #include "gromacs/selection/selectioncollection.h"
53 #include "gromacs/selection/selectionfileoption.h"
54 #include "gromacs/selection/selectionoptionmanager.h"
55 #include "gromacs/utility/exceptions.h"
56
57 #include "testutils/testasserts.h"
58 #include "testutils/testfilemanager.h"
59
60 #include "toputils.h"
61
62 using gmx::test::TestFileManager;
63
64 namespace
65 {
66
67 /********************************************************************
68  * Base fixture for tests in this file.
69  */
70
71 class SelectionOptionTestBase : public ::testing::Test
72 {
73 public:
74     SelectionOptionTestBase();
75
76     void loadTopology(const char* filename);
77
78     gmx::SelectionCollection    sc_;
79     gmx::SelectionOptionManager manager_;
80     gmx::Options                options_;
81
82 private:
83     gmx::test::TopologyManager topManager_;
84 };
85
86 SelectionOptionTestBase::SelectionOptionTestBase() : manager_(&sc_)
87 {
88     options_.addManager(&manager_);
89     sc_.setReferencePosType("atom");
90     sc_.setOutputPosType("atom");
91 }
92
93 void SelectionOptionTestBase::loadTopology(const char* filename)
94 {
95     topManager_.loadTopology(filename);
96
97     ASSERT_NO_THROW_GMX(sc_.setTopology(topManager_.topology(), -1));
98 }
99
100
101 /********************************************************************
102  * Tests for SelectionOption
103  */
104
105 //! Test fixture for gmx::SelectionOption.
106 typedef SelectionOptionTestBase SelectionOptionTest;
107
108 TEST_F(SelectionOptionTest, ParsesSimpleSelection)
109 {
110     gmx::Selection sel;
111     using gmx::SelectionOption;
112     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel").store(&sel)));
113
114     gmx::OptionsAssigner assigner(&options_);
115     EXPECT_NO_THROW_GMX(assigner.start());
116     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
117     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RA RB"));
118     EXPECT_NO_THROW_GMX(assigner.finishOption());
119     EXPECT_NO_THROW_GMX(assigner.finish());
120     EXPECT_NO_THROW_GMX(options_.finish());
121
122     ASSERT_TRUE(sel.isValid());
123 }
124
125
126 TEST_F(SelectionOptionTest, HandlesDynamicSelectionWhenStaticRequired)
127 {
128     gmx::Selection sel;
129     using gmx::SelectionOption;
130     ASSERT_NO_THROW_GMX(options_.addOption(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(SelectionOption("sel").store(&sel).onlyAtoms()));
147
148     gmx::OptionsAssigner assigner(&options_);
149     EXPECT_NO_THROW_GMX(assigner.start());
150     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
151     EXPECT_NO_THROW_GMX(assigner.appendValue("res_cog of resname RA RB"));
152     EXPECT_NO_THROW_GMX(assigner.finishOption());
153     EXPECT_NO_THROW_GMX(assigner.finish());
154     EXPECT_NO_THROW_GMX(options_.finish());
155
156     ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
157     EXPECT_THROW_GMX(sc_.compile(), gmx::InvalidInputError);
158 }
159
160
161 TEST_F(SelectionOptionTest, ChecksForSortedAtomsWhenRequired)
162 {
163     gmx::Selection sel;
164     using gmx::SelectionOption;
165     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel").store(&sel).onlySortedAtoms()));
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("resnr 1 2 permute 2 1"));
171     EXPECT_NO_THROW_GMX(assigner.finishOption());
172     EXPECT_NO_THROW_GMX(assigner.finish());
173     EXPECT_NO_THROW_GMX(options_.finish());
174
175     ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
176     EXPECT_THROW_GMX(sc_.compile(), gmx::InvalidInputError);
177 }
178
179
180 TEST_F(SelectionOptionTest, ChecksEmptySelections)
181 {
182     gmx::Selection sel;
183     using gmx::SelectionOption;
184     ASSERT_NO_THROW_GMX(options_.addOption(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.appendValue("none"));
190     EXPECT_NO_THROW_GMX(assigner.finishOption());
191     EXPECT_NO_THROW_GMX(assigner.finish());
192     EXPECT_NO_THROW_GMX(options_.finish());
193
194     EXPECT_THROW_GMX(sc_.compile(), gmx::InvalidInputError);
195 }
196
197
198 TEST_F(SelectionOptionTest, ChecksEmptyDelayedSelections)
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.finishOption());
208     EXPECT_NO_THROW_GMX(assigner.finish());
209     EXPECT_NO_THROW_GMX(options_.finish());
210     ASSERT_NO_THROW_GMX(manager_.parseRequestedFromString("none"));
211
212     EXPECT_THROW_GMX(sc_.compile(), gmx::InvalidInputError);
213 }
214
215
216 TEST_F(SelectionOptionTest, HandlesTooManySelections)
217 {
218     gmx::Selection sel;
219     using gmx::SelectionOption;
220     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel").store(&sel)));
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.appendValue("resname RB RC"), gmx::InvalidInputError);
227     EXPECT_NO_THROW_GMX(assigner.finishOption());
228     EXPECT_NO_THROW_GMX(assigner.finish());
229     EXPECT_NO_THROW_GMX(options_.finish());
230 }
231
232
233 TEST_F(SelectionOptionTest, HandlesTooFewSelections)
234 {
235     gmx::Selection sel[2];
236     using gmx::SelectionOption;
237     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel").store(sel).valueCount(2)));
238
239     gmx::OptionsAssigner assigner(&options_);
240     EXPECT_NO_THROW_GMX(assigner.start());
241     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
242     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RA RB"));
243     EXPECT_THROW_GMX(assigner.finishOption(), gmx::InvalidInputError);
244     EXPECT_NO_THROW_GMX(assigner.finish());
245     EXPECT_NO_THROW_GMX(options_.finish());
246 }
247
248
249 TEST_F(SelectionOptionTest, HandlesDefaultSelectionText)
250 {
251     gmx::Selection sel;
252     using gmx::SelectionOption;
253     options_.addOption(SelectionOption("sel").store(&sel).defaultSelectionText("all"));
254
255     EXPECT_NO_THROW_GMX(options_.finish());
256
257     ASSERT_TRUE(sel.isValid());
258
259     EXPECT_NO_THROW_GMX(sc_.setTopology(nullptr, 10));
260     EXPECT_NO_THROW_GMX(sc_.compile());
261
262     EXPECT_STREQ("all", sel.selectionText());
263 }
264
265
266 TEST_F(SelectionOptionTest, HandlesAdjuster)
267 {
268     gmx::SelectionList sel;
269     using gmx::SelectionOption;
270     gmx::SelectionOptionInfo* info =
271             options_.addOption(SelectionOption("sel").storeVector(&sel).multiValue());
272
273     gmx::OptionsAssigner assigner(&options_);
274     EXPECT_NO_THROW_GMX(assigner.start());
275     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
276     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RA RB"));
277     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RB RC"));
278     EXPECT_NO_THROW_GMX(assigner.finishOption());
279     EXPECT_NO_THROW_GMX(assigner.finish());
280     EXPECT_NO_THROW_GMX(options_.finish());
281     EXPECT_NO_THROW_GMX(info->setValueCount(2));
282 }
283
284
285 TEST_F(SelectionOptionTest, HandlesDynamicWhenStaticRequiredWithAdjuster)
286 {
287     gmx::Selection sel;
288     using gmx::SelectionOption;
289     gmx::SelectionOptionInfo* info = options_.addOption(SelectionOption("sel").store(&sel));
290
291     gmx::OptionsAssigner assigner(&options_);
292     EXPECT_NO_THROW_GMX(assigner.start());
293     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
294     EXPECT_NO_THROW_GMX(assigner.appendValue("x < 5"));
295     EXPECT_NO_THROW_GMX(assigner.finishOption());
296     EXPECT_NO_THROW_GMX(assigner.finish());
297     EXPECT_NO_THROW_GMX(options_.finish());
298     EXPECT_THROW_GMX(info->setOnlyStatic(true), gmx::InvalidInputError);
299 }
300
301
302 TEST_F(SelectionOptionTest, HandlesTooManySelectionsWithAdjuster)
303 {
304     gmx::SelectionList sel;
305     using gmx::SelectionOption;
306     gmx::SelectionOptionInfo* info =
307             options_.addOption(SelectionOption("sel").storeVector(&sel).multiValue());
308
309     gmx::OptionsAssigner assigner(&options_);
310     EXPECT_NO_THROW_GMX(assigner.start());
311     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
312     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RA RB"));
313     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RB RC"));
314     EXPECT_NO_THROW_GMX(assigner.finishOption());
315     EXPECT_NO_THROW_GMX(assigner.finish());
316     EXPECT_NO_THROW_GMX(options_.finish());
317     EXPECT_THROW_GMX(info->setValueCount(1), gmx::InvalidInputError);
318 }
319
320
321 TEST_F(SelectionOptionTest, HandlesTooFewSelectionsWithAdjuster)
322 {
323     gmx::SelectionList sel;
324     using gmx::SelectionOption;
325     gmx::SelectionOptionInfo* info =
326             options_.addOption(SelectionOption("sel").storeVector(&sel).multiValue());
327
328     gmx::OptionsAssigner assigner(&options_);
329     EXPECT_NO_THROW_GMX(assigner.start());
330     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
331     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RA RB"));
332     EXPECT_NO_THROW_GMX(assigner.finishOption());
333     EXPECT_NO_THROW_GMX(assigner.finish());
334     EXPECT_NO_THROW_GMX(options_.finish());
335     EXPECT_THROW_GMX(info->setValueCount(2), gmx::InvalidInputError);
336 }
337
338
339 TEST_F(SelectionOptionTest, HandlesDelayedRequiredSelection)
340 {
341     gmx::Selection sel;
342     using gmx::SelectionOption;
343     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel").store(&sel).required()));
344
345     gmx::OptionsAssigner assigner(&options_);
346     EXPECT_NO_THROW_GMX(assigner.start());
347     EXPECT_NO_THROW_GMX(assigner.finish());
348     EXPECT_NO_THROW_GMX(options_.finish());
349     ASSERT_NO_THROW_GMX(manager_.parseRequestedFromString("resname RA RB"));
350     ASSERT_STREQ("resname RA RB", sel.selectionText());
351 }
352
353
354 TEST_F(SelectionOptionTest, HandlesTooFewDelayedRequiredSelections)
355 {
356     gmx::Selection sel[2];
357     using gmx::SelectionOption;
358     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel").store(sel).required().valueCount(2)));
359
360     gmx::OptionsAssigner assigner(&options_);
361     EXPECT_NO_THROW_GMX(assigner.start());
362     EXPECT_NO_THROW_GMX(assigner.finish());
363     EXPECT_NO_THROW_GMX(options_.finish());
364     EXPECT_THROW_GMX(manager_.parseRequestedFromString("resname RA RB"), gmx::InvalidInputError);
365 }
366
367
368 TEST_F(SelectionOptionTest, HandlesDelayedOptionalSelection)
369 {
370     gmx::Selection sel;
371     using gmx::SelectionOption;
372     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel").store(&sel)));
373
374     gmx::OptionsAssigner assigner(&options_);
375     EXPECT_NO_THROW_GMX(assigner.start());
376     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
377     EXPECT_NO_THROW_GMX(assigner.finishOption());
378     EXPECT_NO_THROW_GMX(assigner.finish());
379     EXPECT_NO_THROW_GMX(options_.finish());
380     ASSERT_NO_THROW_GMX(manager_.parseRequestedFromString("resname RA RB"));
381     ASSERT_STREQ("resname RA RB", sel.selectionText());
382 }
383
384
385 TEST_F(SelectionOptionTest, HandlesDelayedSelectionWithAdjuster)
386 {
387     gmx::SelectionList sel;
388     using gmx::SelectionOption;
389     gmx::SelectionOptionInfo* info =
390             options_.addOption(SelectionOption("sel").storeVector(&sel).valueCount(3));
391
392     gmx::OptionsAssigner assigner(&options_);
393     EXPECT_NO_THROW_GMX(assigner.start());
394     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
395     EXPECT_NO_THROW_GMX(assigner.finishOption());
396     EXPECT_NO_THROW_GMX(assigner.finish());
397     EXPECT_NO_THROW_GMX(options_.finish());
398     EXPECT_NO_THROW_GMX(info->setValueCount(2));
399     EXPECT_NO_THROW_GMX(manager_.parseRequestedFromString("resname RA RB; resname RB RC"));
400 }
401
402
403 /********************************************************************
404  * Tests for SelectionFileOption
405  */
406
407 class SelectionFileOptionTest : public SelectionOptionTestBase
408 {
409 public:
410     SelectionFileOptionTest();
411 };
412
413 SelectionFileOptionTest::SelectionFileOptionTest()
414 {
415     options_.addOption(gmx::SelectionFileOption("sf"));
416 }
417
418
419 TEST_F(SelectionFileOptionTest, HandlesSingleSelectionOptionFromFile)
420 {
421     gmx::SelectionList sel;
422     gmx::SelectionList reqsel;
423     using gmx::SelectionOption;
424     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel").storeVector(&sel).multiValue()));
425     ASSERT_NO_THROW_GMX(
426             options_.addOption(SelectionOption("reqsel").storeVector(&reqsel).multiValue().required()));
427
428     gmx::OptionsAssigner assigner(&options_);
429     EXPECT_NO_THROW_GMX(assigner.start());
430     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
431     EXPECT_NO_THROW_GMX(assigner.finishOption());
432     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
433     EXPECT_NO_THROW_GMX(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
434     EXPECT_NO_THROW_GMX(assigner.finishOption());
435     EXPECT_NO_THROW_GMX(assigner.finish());
436     EXPECT_NO_THROW_GMX(options_.finish());
437
438     // These should match the contents of selfile.dat
439     ASSERT_EQ(2U, sel.size());
440     EXPECT_STREQ("resname RA RB", sel[0].selectionText());
441     EXPECT_STREQ("resname RB RC", sel[1].selectionText());
442     ASSERT_EQ(0U, reqsel.size());
443 }
444
445
446 TEST_F(SelectionFileOptionTest, HandlesTwoSeparateSelectionOptions)
447 {
448     gmx::SelectionList sel1;
449     gmx::SelectionList sel2;
450     using gmx::SelectionOption;
451     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel1").storeVector(&sel1).multiValue()));
452     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel2").storeVector(&sel2).multiValue()));
453
454     gmx::OptionsAssigner assigner(&options_);
455     std::string          value(TestFileManager::getInputFilePath("selfile.dat"));
456     EXPECT_NO_THROW_GMX(assigner.start());
457     ASSERT_NO_THROW_GMX(assigner.startOption("sel1"));
458     EXPECT_NO_THROW_GMX(assigner.finishOption());
459     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
460     EXPECT_NO_THROW_GMX(assigner.appendValue(value));
461     EXPECT_NO_THROW_GMX(assigner.finishOption());
462     ASSERT_NO_THROW_GMX(assigner.startOption("sel2"));
463     EXPECT_NO_THROW_GMX(assigner.finishOption());
464     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
465     EXPECT_NO_THROW_GMX(assigner.appendValue(value));
466     EXPECT_NO_THROW_GMX(assigner.finishOption());
467     EXPECT_NO_THROW_GMX(assigner.finish());
468     EXPECT_NO_THROW_GMX(options_.finish());
469
470     // These should match the contents of selfile.dat
471     ASSERT_EQ(2U, sel1.size());
472     EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
473     EXPECT_STREQ("resname RB RC", sel1[1].selectionText());
474     ASSERT_EQ(2U, sel2.size());
475     EXPECT_STREQ("resname RA RB", sel2[0].selectionText());
476     EXPECT_STREQ("resname RB RC", sel2[1].selectionText());
477 }
478
479
480 TEST_F(SelectionFileOptionTest, HandlesTwoSelectionOptionsFromSingleFile)
481 {
482     gmx::SelectionList sel1;
483     gmx::SelectionList sel2;
484     using gmx::SelectionOption;
485     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel1").storeVector(&sel1)));
486     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel2").storeVector(&sel2)));
487
488     gmx::OptionsAssigner assigner(&options_);
489     std::string          value(TestFileManager::getInputFilePath("selfile.dat"));
490     EXPECT_NO_THROW_GMX(assigner.start());
491     ASSERT_NO_THROW_GMX(assigner.startOption("sel1"));
492     EXPECT_NO_THROW_GMX(assigner.finishOption());
493     ASSERT_NO_THROW_GMX(assigner.startOption("sel2"));
494     EXPECT_NO_THROW_GMX(assigner.finishOption());
495     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
496     EXPECT_NO_THROW_GMX(assigner.appendValue(value));
497     EXPECT_NO_THROW_GMX(assigner.finishOption());
498     EXPECT_NO_THROW_GMX(assigner.finish());
499     EXPECT_NO_THROW_GMX(options_.finish());
500
501     // These should match the contents of selfile.dat
502     ASSERT_EQ(1U, sel1.size());
503     EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
504     ASSERT_EQ(1U, sel2.size());
505     EXPECT_STREQ("resname RB RC", sel2[0].selectionText());
506 }
507
508
509 TEST_F(SelectionFileOptionTest, HandlesRequiredOptionFromFile)
510 {
511     gmx::SelectionList sel;
512     gmx::SelectionList optsel;
513     using gmx::SelectionOption;
514     ASSERT_NO_THROW_GMX(
515             options_.addOption(SelectionOption("sel").storeVector(&sel).multiValue().required()));
516     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("optsel").storeVector(&optsel).multiValue()));
517
518     gmx::OptionsAssigner assigner(&options_);
519     EXPECT_NO_THROW_GMX(assigner.start());
520     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
521     EXPECT_NO_THROW_GMX(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
522     EXPECT_NO_THROW_GMX(assigner.finishOption());
523     EXPECT_NO_THROW_GMX(assigner.startOption("optsel"));
524     EXPECT_NO_THROW_GMX(assigner.finishOption());
525     EXPECT_NO_THROW_GMX(assigner.finish());
526     EXPECT_NO_THROW_GMX(options_.finish());
527     EXPECT_NO_THROW_GMX(manager_.parseRequestedFromString("resname RC RD"));
528
529     // These should match the contents of selfile.dat
530     ASSERT_EQ(2U, sel.size());
531     EXPECT_STREQ("resname RA RB", sel[0].selectionText());
532     EXPECT_STREQ("resname RB RC", sel[1].selectionText());
533     ASSERT_EQ(1U, optsel.size());
534     EXPECT_STREQ("resname RC RD", optsel[0].selectionText());
535 }
536
537
538 // TODO: Is this the best possible behavior, or should it error out?
539 TEST_F(SelectionFileOptionTest, HandlesRequiredOptionFromFileWithOtherOptionSet)
540 {
541     gmx::SelectionList sel1;
542     gmx::SelectionList sel2;
543     using gmx::SelectionOption;
544     ASSERT_NO_THROW_GMX(
545             options_.addOption(SelectionOption("sel1").storeVector(&sel1).multiValue().required()));
546     ASSERT_NO_THROW_GMX(
547             options_.addOption(SelectionOption("sel2").storeVector(&sel2).multiValue().required()));
548
549     gmx::OptionsAssigner assigner(&options_);
550     EXPECT_NO_THROW_GMX(assigner.start());
551     EXPECT_NO_THROW_GMX(assigner.startOption("sel1"));
552     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RC RD"));
553     EXPECT_NO_THROW_GMX(assigner.finishOption());
554     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
555     EXPECT_NO_THROW_GMX(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
556     EXPECT_NO_THROW_GMX(assigner.finishOption());
557     EXPECT_NO_THROW_GMX(assigner.finish());
558     EXPECT_NO_THROW_GMX(options_.finish());
559
560     // These should match the contents of selfile.dat
561     ASSERT_EQ(2U, sel2.size());
562     EXPECT_STREQ("resname RA RB", sel2[0].selectionText());
563     EXPECT_STREQ("resname RB RC", sel2[1].selectionText());
564     ASSERT_EQ(1U, sel1.size());
565     EXPECT_STREQ("resname RC RD", sel1[0].selectionText());
566 }
567
568
569 TEST_F(SelectionFileOptionTest, HandlesTwoRequiredOptionsFromSingleFile)
570 {
571     gmx::SelectionList sel1;
572     gmx::SelectionList sel2;
573     using gmx::SelectionOption;
574     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel1").storeVector(&sel1).required()));
575     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel2").storeVector(&sel2).required()));
576
577     gmx::OptionsAssigner assigner(&options_);
578     std::string          value(TestFileManager::getInputFilePath("selfile.dat"));
579     EXPECT_NO_THROW_GMX(assigner.start());
580     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
581     EXPECT_NO_THROW_GMX(assigner.appendValue(value));
582     EXPECT_NO_THROW_GMX(assigner.finishOption());
583     EXPECT_NO_THROW_GMX(assigner.finish());
584     EXPECT_NO_THROW_GMX(options_.finish());
585
586     // These should match the contents of selfile.dat
587     ASSERT_EQ(1U, sel1.size());
588     EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
589     ASSERT_EQ(1U, sel2.size());
590     EXPECT_STREQ("resname RB RC", sel2[0].selectionText());
591 }
592
593
594 TEST_F(SelectionFileOptionTest, GivesErrorWithNoFile)
595 {
596     gmx::SelectionList sel;
597     using gmx::SelectionOption;
598     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel").storeVector(&sel).multiValue()));
599
600     gmx::OptionsAssigner assigner(&options_);
601     EXPECT_NO_THROW_GMX(assigner.start());
602     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
603     EXPECT_NO_THROW_GMX(assigner.finishOption());
604     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
605     EXPECT_THROW_GMX(assigner.finishOption(), gmx::InvalidInputError);
606     EXPECT_NO_THROW_GMX(assigner.finish());
607     EXPECT_NO_THROW_GMX(options_.finish());
608 }
609
610
611 TEST_F(SelectionFileOptionTest, GivesErrorWithNonExistentFile)
612 {
613     gmx::SelectionList sel;
614     using gmx::SelectionOption;
615     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel").storeVector(&sel).multiValue()));
616
617     gmx::OptionsAssigner assigner(&options_);
618     EXPECT_NO_THROW_GMX(assigner.start());
619     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
620     EXPECT_NO_THROW_GMX(assigner.finishOption());
621     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
622     // TODO: Should this be changed to an InvalidInputError?
623     EXPECT_THROW_GMX(assigner.appendValue("nonexistentfile"), gmx::FileIOError);
624     EXPECT_THROW_GMX(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")),
625                      gmx::InvalidInputError);
626     EXPECT_NO_THROW_GMX(assigner.finishOption());
627     EXPECT_NO_THROW_GMX(assigner.finish());
628     EXPECT_NO_THROW_GMX(options_.finish());
629 }
630
631
632 TEST_F(SelectionFileOptionTest, GivesErrorWithMultipleFiles)
633 {
634     gmx::SelectionList sel;
635     using gmx::SelectionOption;
636     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel").storeVector(&sel).multiValue()));
637
638     gmx::OptionsAssigner assigner(&options_);
639     EXPECT_NO_THROW_GMX(assigner.start());
640     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
641     EXPECT_NO_THROW_GMX(assigner.finishOption());
642     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
643     EXPECT_NO_THROW_GMX(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
644     EXPECT_THROW_GMX(assigner.appendValue("nonexistentfile"), gmx::InvalidInputError);
645     EXPECT_NO_THROW_GMX(assigner.finishOption());
646     EXPECT_NO_THROW_GMX(assigner.finish());
647     EXPECT_NO_THROW_GMX(options_.finish());
648 }
649
650 } // namespace