Add check for empty selections.
[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, ChecksEmptySelections)
184 {
185     gmx::Selection sel;
186     using gmx::SelectionOption;
187     ASSERT_NO_THROW_GMX(options_.addOption(
188                                 SelectionOption("sel").store(&sel)));
189     setManager();
190
191     gmx::OptionsAssigner assigner(&options_);
192     EXPECT_NO_THROW_GMX(assigner.start());
193     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
194     EXPECT_NO_THROW_GMX(assigner.appendValue("none"));
195     EXPECT_NO_THROW_GMX(assigner.finishOption());
196     EXPECT_NO_THROW_GMX(assigner.finish());
197     EXPECT_NO_THROW_GMX(options_.finish());
198
199     EXPECT_THROW_GMX(sc_.compile(), gmx::InvalidInputError);
200 }
201
202
203 TEST_F(SelectionOptionTest, HandlesTooManySelections)
204 {
205     gmx::Selection sel;
206     using gmx::SelectionOption;
207     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel").store(&sel)));
208     setManager();
209
210     gmx::OptionsAssigner assigner(&options_);
211     EXPECT_NO_THROW_GMX(assigner.start());
212     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
213     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RA RB"));
214     EXPECT_THROW_GMX(assigner.appendValue("resname RB RC"), gmx::InvalidInputError);
215     EXPECT_NO_THROW_GMX(assigner.finishOption());
216     EXPECT_NO_THROW_GMX(assigner.finish());
217     EXPECT_NO_THROW_GMX(options_.finish());
218 }
219
220
221 TEST_F(SelectionOptionTest, HandlesTooFewSelections)
222 {
223     gmx::Selection sel[2];
224     using gmx::SelectionOption;
225     ASSERT_NO_THROW_GMX(options_.addOption(
226                                 SelectionOption("sel").store(sel).valueCount(2)));
227     setManager();
228
229     gmx::OptionsAssigner assigner(&options_);
230     EXPECT_NO_THROW_GMX(assigner.start());
231     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
232     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RA RB"));
233     EXPECT_THROW_GMX(assigner.finishOption(), gmx::InvalidInputError);
234     EXPECT_NO_THROW_GMX(assigner.finish());
235     EXPECT_NO_THROW_GMX(options_.finish());
236 }
237
238
239 TEST_F(SelectionOptionTest, HandlesAdjuster)
240 {
241     gmx::SelectionList        sel;
242     using gmx::SelectionOption;
243     gmx::SelectionOptionInfo *info = options_.addOption(
244                 SelectionOption("sel").storeVector(&sel).multiValue());
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("resname RA RB"));
251     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RB RC"));
252     EXPECT_NO_THROW_GMX(assigner.finishOption());
253     EXPECT_NO_THROW_GMX(assigner.finish());
254     EXPECT_NO_THROW_GMX(options_.finish());
255     EXPECT_NO_THROW_GMX(info->setValueCount(2));
256 }
257
258
259 TEST_F(SelectionOptionTest, HandlesDynamicWhenStaticRequiredWithAdjuster)
260 {
261     gmx::Selection            sel;
262     using gmx::SelectionOption;
263     gmx::SelectionOptionInfo *info = options_.addOption(
264                 SelectionOption("sel").store(&sel));
265     setManager();
266
267     gmx::OptionsAssigner assigner(&options_);
268     EXPECT_NO_THROW_GMX(assigner.start());
269     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
270     EXPECT_NO_THROW_GMX(assigner.appendValue("x < 5"));
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->setOnlyStatic(true), gmx::InvalidInputError);
275 }
276
277
278 TEST_F(SelectionOptionTest, HandlesTooManySelectionsWithAdjuster)
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.appendValue("resname RB RC"));
291     EXPECT_NO_THROW_GMX(assigner.finishOption());
292     EXPECT_NO_THROW_GMX(assigner.finish());
293     EXPECT_NO_THROW_GMX(options_.finish());
294     EXPECT_THROW_GMX(info->setValueCount(1), gmx::InvalidInputError);
295 }
296
297
298 TEST_F(SelectionOptionTest, HandlesTooFewSelectionsWithAdjuster)
299 {
300     gmx::SelectionList        sel;
301     using gmx::SelectionOption;
302     gmx::SelectionOptionInfo *info = options_.addOption(
303                 SelectionOption("sel").storeVector(&sel).multiValue());
304     setManager();
305
306     gmx::OptionsAssigner assigner(&options_);
307     EXPECT_NO_THROW_GMX(assigner.start());
308     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
309     EXPECT_NO_THROW_GMX(assigner.appendValue("resname RA RB"));
310     EXPECT_NO_THROW_GMX(assigner.finishOption());
311     EXPECT_NO_THROW_GMX(assigner.finish());
312     EXPECT_NO_THROW_GMX(options_.finish());
313     EXPECT_THROW_GMX(info->setValueCount(2), gmx::InvalidInputError);
314 }
315
316
317 TEST_F(SelectionOptionTest, HandlesDelayedRequiredSelection)
318 {
319     gmx::Selection sel;
320     using gmx::SelectionOption;
321     ASSERT_NO_THROW_GMX(options_.addOption(
322                                 SelectionOption("sel").store(&sel).required()));
323     setManager();
324
325     gmx::OptionsAssigner assigner(&options_);
326     EXPECT_NO_THROW_GMX(assigner.start());
327     EXPECT_NO_THROW_GMX(assigner.finish());
328     EXPECT_NO_THROW_GMX(options_.finish());
329     ASSERT_NO_THROW_GMX(manager_.parseRequestedFromString("resname RA RB"));
330     ASSERT_STREQ("resname RA RB", sel.selectionText());
331 }
332
333
334 TEST_F(SelectionOptionTest, HandlesTooFewDelayedRequiredSelections)
335 {
336     gmx::Selection sel[2];
337     using gmx::SelectionOption;
338     ASSERT_NO_THROW_GMX(options_.addOption(
339                                 SelectionOption("sel").store(sel).required()
340                                     .valueCount(2)));
341     setManager();
342
343     gmx::OptionsAssigner assigner(&options_);
344     EXPECT_NO_THROW_GMX(assigner.start());
345     EXPECT_NO_THROW_GMX(assigner.finish());
346     EXPECT_NO_THROW_GMX(options_.finish());
347     EXPECT_THROW_GMX(manager_.parseRequestedFromString("resname RA RB"), gmx::InvalidInputError);
348 }
349
350
351 TEST_F(SelectionOptionTest, HandlesDelayedOptionalSelection)
352 {
353     gmx::Selection sel;
354     using gmx::SelectionOption;
355     ASSERT_NO_THROW_GMX(options_.addOption(SelectionOption("sel").store(&sel)));
356     setManager();
357
358     gmx::OptionsAssigner assigner(&options_);
359     EXPECT_NO_THROW_GMX(assigner.start());
360     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
361     EXPECT_NO_THROW_GMX(assigner.finishOption());
362     EXPECT_NO_THROW_GMX(assigner.finish());
363     EXPECT_NO_THROW_GMX(options_.finish());
364     ASSERT_NO_THROW_GMX(manager_.parseRequestedFromString("resname RA RB"));
365     ASSERT_STREQ("resname RA RB", sel.selectionText());
366 }
367
368
369 TEST_F(SelectionOptionTest, HandlesDelayedSelectionWithAdjuster)
370 {
371     gmx::SelectionList        sel;
372     using gmx::SelectionOption;
373     gmx::SelectionOptionInfo *info = options_.addOption(
374                 SelectionOption("sel").storeVector(&sel).valueCount(3));
375     setManager();
376
377     gmx::OptionsAssigner assigner(&options_);
378     EXPECT_NO_THROW_GMX(assigner.start());
379     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
380     EXPECT_NO_THROW_GMX(assigner.finishOption());
381     EXPECT_NO_THROW_GMX(assigner.finish());
382     EXPECT_NO_THROW_GMX(options_.finish());
383     EXPECT_NO_THROW_GMX(info->setValueCount(2));
384     EXPECT_NO_THROW_GMX(manager_.parseRequestedFromString("resname RA RB; resname RB RC"));
385 }
386
387
388 /********************************************************************
389  * Tests for SelectionFileOption
390  */
391
392 class SelectionFileOptionTest : public SelectionOptionTestBase
393 {
394     public:
395         SelectionFileOptionTest();
396 };
397
398 SelectionFileOptionTest::SelectionFileOptionTest()
399 {
400     options_.addOption(gmx::SelectionFileOption("sf"));
401 }
402
403
404 TEST_F(SelectionFileOptionTest, HandlesSingleSelectionOptionFromFile)
405 {
406     gmx::SelectionList sel;
407     gmx::SelectionList reqsel;
408     using gmx::SelectionOption;
409     ASSERT_NO_THROW_GMX(options_.addOption(
410                                 SelectionOption("sel").storeVector(&sel).multiValue()));
411     ASSERT_NO_THROW_GMX(options_.addOption(
412                                 SelectionOption("reqsel").storeVector(&reqsel)
413                                     .multiValue().required()));
414     setManager();
415
416     gmx::OptionsAssigner assigner(&options_);
417     EXPECT_NO_THROW_GMX(assigner.start());
418     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
419     EXPECT_NO_THROW_GMX(assigner.finishOption());
420     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
421     EXPECT_NO_THROW_GMX(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
422     EXPECT_NO_THROW_GMX(assigner.finishOption());
423     EXPECT_NO_THROW_GMX(assigner.finish());
424     EXPECT_NO_THROW_GMX(options_.finish());
425
426     // These should match the contents of selfile.dat
427     ASSERT_EQ(2U, sel.size());
428     EXPECT_STREQ("resname RA RB", sel[0].selectionText());
429     EXPECT_STREQ("resname RB RC", sel[1].selectionText());
430     ASSERT_EQ(0U, reqsel.size());
431 }
432
433
434 TEST_F(SelectionFileOptionTest, HandlesTwoSeparateSelectionOptions)
435 {
436     gmx::SelectionList sel1;
437     gmx::SelectionList sel2;
438     using gmx::SelectionOption;
439     ASSERT_NO_THROW_GMX(options_.addOption(
440                                 SelectionOption("sel1").storeVector(&sel1).multiValue()));
441     ASSERT_NO_THROW_GMX(options_.addOption(
442                                 SelectionOption("sel2").storeVector(&sel2).multiValue()));
443     setManager();
444
445     gmx::OptionsAssigner assigner(&options_);
446     std::string          value(TestFileManager::getInputFilePath("selfile.dat"));
447     EXPECT_NO_THROW_GMX(assigner.start());
448     ASSERT_NO_THROW_GMX(assigner.startOption("sel1"));
449     EXPECT_NO_THROW_GMX(assigner.finishOption());
450     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
451     EXPECT_NO_THROW_GMX(assigner.appendValue(value));
452     EXPECT_NO_THROW_GMX(assigner.finishOption());
453     ASSERT_NO_THROW_GMX(assigner.startOption("sel2"));
454     EXPECT_NO_THROW_GMX(assigner.finishOption());
455     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
456     EXPECT_NO_THROW_GMX(assigner.appendValue(value));
457     EXPECT_NO_THROW_GMX(assigner.finishOption());
458     EXPECT_NO_THROW_GMX(assigner.finish());
459     EXPECT_NO_THROW_GMX(options_.finish());
460
461     // These should match the contents of selfile.dat
462     ASSERT_EQ(2U, sel1.size());
463     EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
464     EXPECT_STREQ("resname RB RC", sel1[1].selectionText());
465     ASSERT_EQ(2U, sel2.size());
466     EXPECT_STREQ("resname RA RB", sel2[0].selectionText());
467     EXPECT_STREQ("resname RB RC", sel2[1].selectionText());
468 }
469
470
471 TEST_F(SelectionFileOptionTest, HandlesTwoSelectionOptionsFromSingleFile)
472 {
473     gmx::SelectionList sel1;
474     gmx::SelectionList sel2;
475     using gmx::SelectionOption;
476     ASSERT_NO_THROW_GMX(options_.addOption(
477                                 SelectionOption("sel1").storeVector(&sel1)));
478     ASSERT_NO_THROW_GMX(options_.addOption(
479                                 SelectionOption("sel2").storeVector(&sel2)));
480     setManager();
481
482     gmx::OptionsAssigner assigner(&options_);
483     std::string          value(TestFileManager::getInputFilePath("selfile.dat"));
484     EXPECT_NO_THROW_GMX(assigner.start());
485     ASSERT_NO_THROW_GMX(assigner.startOption("sel1"));
486     EXPECT_NO_THROW_GMX(assigner.finishOption());
487     ASSERT_NO_THROW_GMX(assigner.startOption("sel2"));
488     EXPECT_NO_THROW_GMX(assigner.finishOption());
489     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
490     EXPECT_NO_THROW_GMX(assigner.appendValue(value));
491     EXPECT_NO_THROW_GMX(assigner.finishOption());
492     EXPECT_NO_THROW_GMX(assigner.finish());
493     EXPECT_NO_THROW_GMX(options_.finish());
494
495     // These should match the contents of selfile.dat
496     ASSERT_EQ(1U, sel1.size());
497     EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
498     ASSERT_EQ(1U, sel2.size());
499     EXPECT_STREQ("resname RB RC", sel2[0].selectionText());
500 }
501
502
503 TEST_F(SelectionFileOptionTest, HandlesRequiredOptionFromFile)
504 {
505     gmx::SelectionList sel;
506     gmx::SelectionList optsel;
507     using gmx::SelectionOption;
508     ASSERT_NO_THROW_GMX(options_.addOption(
509                                 SelectionOption("sel").storeVector(&sel)
510                                     .multiValue().required()));
511     ASSERT_NO_THROW_GMX(options_.addOption(
512                                 SelectionOption("optsel").storeVector(&optsel)
513                                     .multiValue()));
514     setManager();
515
516     gmx::OptionsAssigner assigner(&options_);
517     EXPECT_NO_THROW_GMX(assigner.start());
518     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
519     EXPECT_NO_THROW_GMX(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
520     EXPECT_NO_THROW_GMX(assigner.finishOption());
521     EXPECT_NO_THROW_GMX(assigner.startOption("optsel"));
522     EXPECT_NO_THROW_GMX(assigner.finishOption());
523     EXPECT_NO_THROW_GMX(assigner.finish());
524     EXPECT_NO_THROW_GMX(options_.finish());
525     EXPECT_NO_THROW_GMX(manager_.parseRequestedFromString("resname RC RD"));
526
527     // These should match the contents of selfile.dat
528     ASSERT_EQ(2U, sel.size());
529     EXPECT_STREQ("resname RA RB", sel[0].selectionText());
530     EXPECT_STREQ("resname RB RC", sel[1].selectionText());
531     ASSERT_EQ(1U, optsel.size());
532     EXPECT_STREQ("resname RC RD", optsel[0].selectionText());
533 }
534
535
536 // TODO: Is this the best possible behavior, or should it error out?
537 TEST_F(SelectionFileOptionTest, HandlesRequiredOptionFromFileWithOtherOptionSet)
538 {
539     gmx::SelectionList sel1;
540     gmx::SelectionList sel2;
541     using gmx::SelectionOption;
542     ASSERT_NO_THROW_GMX(options_.addOption(
543                                 SelectionOption("sel1").storeVector(&sel1)
544                                     .multiValue().required()));
545     ASSERT_NO_THROW_GMX(options_.addOption(
546                                 SelectionOption("sel2").storeVector(&sel2)
547                                     .multiValue().required()));
548     setManager();
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     setManager();
580
581     gmx::OptionsAssigner assigner(&options_);
582     std::string          value(TestFileManager::getInputFilePath("selfile.dat"));
583     EXPECT_NO_THROW_GMX(assigner.start());
584     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
585     EXPECT_NO_THROW_GMX(assigner.appendValue(value));
586     EXPECT_NO_THROW_GMX(assigner.finishOption());
587     EXPECT_NO_THROW_GMX(assigner.finish());
588     EXPECT_NO_THROW_GMX(options_.finish());
589
590     // These should match the contents of selfile.dat
591     ASSERT_EQ(1U, sel1.size());
592     EXPECT_STREQ("resname RA RB", sel1[0].selectionText());
593     ASSERT_EQ(1U, sel2.size());
594     EXPECT_STREQ("resname RB RC", sel2[0].selectionText());
595 }
596
597
598 TEST_F(SelectionFileOptionTest, GivesErrorWithNoFile)
599 {
600     gmx::SelectionList sel;
601     using gmx::SelectionOption;
602     ASSERT_NO_THROW_GMX(options_.addOption(
603                                 SelectionOption("sel").storeVector(&sel).multiValue()));
604     setManager();
605
606     gmx::OptionsAssigner assigner(&options_);
607     EXPECT_NO_THROW_GMX(assigner.start());
608     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
609     EXPECT_NO_THROW_GMX(assigner.finishOption());
610     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
611     EXPECT_THROW_GMX(assigner.finishOption(), gmx::InvalidInputError);
612     EXPECT_NO_THROW_GMX(assigner.finish());
613     EXPECT_NO_THROW_GMX(options_.finish());
614 }
615
616
617 TEST_F(SelectionFileOptionTest, GivesErrorWithNonExistentFile)
618 {
619     gmx::SelectionList sel;
620     using gmx::SelectionOption;
621     ASSERT_NO_THROW_GMX(options_.addOption(
622                                 SelectionOption("sel").storeVector(&sel).multiValue()));
623     setManager();
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     // TODO: Should this be changed to an InvalidInputError?
631     EXPECT_THROW_GMX(assigner.appendValue("nonexistentfile"), gmx::FileIOError);
632     EXPECT_THROW_GMX(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")),
633                      gmx::InvalidInputError);
634     EXPECT_NO_THROW_GMX(assigner.finishOption());
635     EXPECT_NO_THROW_GMX(assigner.finish());
636     EXPECT_NO_THROW_GMX(options_.finish());
637 }
638
639
640 TEST_F(SelectionFileOptionTest, GivesErrorWithMultipleFiles)
641 {
642     gmx::SelectionList sel;
643     using gmx::SelectionOption;
644     ASSERT_NO_THROW_GMX(options_.addOption(
645                                 SelectionOption("sel").storeVector(&sel).multiValue()));
646     setManager();
647
648     gmx::OptionsAssigner assigner(&options_);
649     EXPECT_NO_THROW_GMX(assigner.start());
650     ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
651     EXPECT_NO_THROW_GMX(assigner.finishOption());
652     ASSERT_NO_THROW_GMX(assigner.startOption("sf"));
653     EXPECT_NO_THROW_GMX(assigner.appendValue(TestFileManager::getInputFilePath("selfile.dat")));
654     EXPECT_THROW_GMX(assigner.appendValue("nonexistentfile"), gmx::InvalidInputError);
655     EXPECT_NO_THROW_GMX(assigner.finishOption());
656     EXPECT_NO_THROW_GMX(assigner.finish());
657     EXPECT_NO_THROW_GMX(options_.finish());
658 }
659
660 } // namespace