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