2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2010-2017, The GROMACS development team.
5 * Copyright (c) 2019,2020, 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.
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.
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.
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.
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.
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.
38 * Tests option assignment.
40 * In addition to testing gmx::OptionsAssigner, these are the main
41 * tests for the classes from basicoptions.h and basicoptionstorage.h (and
42 * their base classes) that actually implement the behavior, as well as for the
43 * internal implementation of the gmx::Options and gmx::AbstractOptionStorage
46 * \author Teemu Murtola <teemu.murtola@gmail.com>
47 * \ingroup module_options
51 #include "gromacs/options/optionsassigner.h"
56 #include <gtest/gtest.h>
58 #include "gromacs/options/basicoptions.h"
59 #include "gromacs/options/options.h"
60 #include "gromacs/options/optionsection.h"
61 #include "gromacs/utility/any.h"
62 #include "gromacs/utility/exceptions.h"
63 #include "gromacs/utility/stringutil.h"
65 #include "testutils/testasserts.h"
70 /********************************************************************
71 * General assignment tests
74 TEST(OptionsAssignerTest
, HandlesMissingRequiredParameter
)
78 using gmx::IntegerOption
;
79 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(&value
).required()));
81 EXPECT_THROW(options
.finish(), gmx::InvalidInputError
);
84 TEST(OptionsAssignerTest
, HandlesRequiredParameterWithDefaultValue
)
88 using gmx::IntegerOption
;
89 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(&value
).required().defaultValue(1)));
91 EXPECT_NO_THROW(options
.finish());
95 TEST(OptionsAssignerTest
, HandlesInvalidMultipleParameter
)
98 std::vector
<int> values
;
100 using gmx::IntegerOption
;
101 ASSERT_NO_THROW(options
.addOption(
102 IntegerOption("p").storeVector(&values
).storeIsSet(&bIsSet
).multiValue()));
104 gmx::OptionsAssigner
assigner(&options
);
105 EXPECT_NO_THROW(assigner
.start());
106 ASSERT_NO_THROW(assigner
.startOption("p"));
107 ASSERT_NO_THROW(assigner
.appendValue("1"));
108 ASSERT_NO_THROW(assigner
.finishOption());
109 EXPECT_THROW(assigner
.startOption("p"), gmx::InvalidInputError
);
110 EXPECT_NO_THROW(assigner
.finish());
111 EXPECT_NO_THROW(options
.finish());
114 ASSERT_EQ(1U, values
.size());
115 EXPECT_EQ(1, values
[0]);
118 TEST(OptionsAssignerTest
, HandlesMultipleParameter
)
120 gmx::Options options
;
121 std::vector
<int> values
;
123 using gmx::IntegerOption
;
124 ASSERT_NO_THROW(options
.addOption(
125 IntegerOption("p").storeVector(&values
).storeIsSet(&bIsSet
).allowMultiple()));
127 gmx::OptionsAssigner
assigner(&options
);
128 EXPECT_NO_THROW_GMX(assigner
.start());
129 ASSERT_NO_THROW_GMX(assigner
.startOption("p"));
130 ASSERT_NO_THROW_GMX(assigner
.appendValue("1"));
131 EXPECT_NO_THROW_GMX(assigner
.finishOption());
132 ASSERT_NO_THROW_GMX(assigner
.startOption("p"));
133 ASSERT_NO_THROW_GMX(assigner
.appendValue("2"));
134 EXPECT_NO_THROW_GMX(assigner
.finishOption());
135 EXPECT_NO_THROW_GMX(assigner
.finish());
136 EXPECT_NO_THROW_GMX(options
.finish());
139 ASSERT_EQ(2U, values
.size());
140 EXPECT_EQ(1, values
[0]);
141 EXPECT_EQ(2, values
[1]);
144 TEST(OptionsAssignerTest
, HandlesMissingValue
)
146 gmx::Options options
;
147 int value1
= 0, value2
= 0;
148 using gmx::IntegerOption
;
149 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(&value1
)));
150 ASSERT_NO_THROW(options
.addOption(IntegerOption("q").store(&value2
)));
152 gmx::OptionsAssigner
assigner(&options
);
153 EXPECT_NO_THROW(assigner
.start());
154 ASSERT_NO_THROW(assigner
.startOption("p"));
155 EXPECT_THROW(assigner
.finishOption(), gmx::InvalidInputError
);
156 ASSERT_NO_THROW(assigner
.startOption("q"));
157 ASSERT_NO_THROW(assigner
.appendValue("2"));
158 EXPECT_NO_THROW(assigner
.finishOption());
159 EXPECT_NO_THROW(assigner
.finish());
160 EXPECT_NO_THROW(options
.finish());
162 EXPECT_EQ(2, value2
);
165 TEST(OptionsAssignerTest
, HandlesExtraValue
)
167 gmx::Options options
;
169 using gmx::IntegerOption
;
170 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(&value1
)));
172 gmx::OptionsAssigner
assigner(&options
);
173 EXPECT_NO_THROW(assigner
.start());
174 ASSERT_NO_THROW(assigner
.startOption("p"));
175 ASSERT_NO_THROW(assigner
.appendValue("2"));
176 EXPECT_THROW(assigner
.appendValue("3"), gmx::InvalidInputError
);
177 EXPECT_NO_THROW(assigner
.finishOption());
178 EXPECT_NO_THROW(assigner
.finish());
179 EXPECT_NO_THROW(options
.finish());
181 EXPECT_EQ(0, value1
);
184 TEST(OptionsAssignerTest
, HandlesGroups
)
186 gmx::Options options
;
187 gmx::IOptionsContainer
& group1
= options
.addGroup();
188 gmx::IOptionsContainer
& group2
= options
.addGroup();
192 using gmx::IntegerOption
;
193 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(&value
)));
194 ASSERT_NO_THROW(group1
.addOption(IntegerOption("q").store(&value1
)));
195 ASSERT_NO_THROW(group2
.addOption(IntegerOption("r").store(&value2
)));
197 gmx::OptionsAssigner
assigner(&options
);
198 EXPECT_NO_THROW(assigner
.start());
199 ASSERT_NO_THROW(assigner
.startOption("p"));
200 EXPECT_NO_THROW(assigner
.appendValue("5"));
201 EXPECT_NO_THROW(assigner
.finishOption());
202 ASSERT_NO_THROW(assigner
.startOption("q"));
203 EXPECT_NO_THROW(assigner
.appendValue("4"));
204 EXPECT_NO_THROW(assigner
.finishOption());
205 ASSERT_NO_THROW(assigner
.startOption("r"));
206 EXPECT_NO_THROW(assigner
.appendValue("6"));
207 EXPECT_NO_THROW(assigner
.finishOption());
208 EXPECT_NO_THROW(assigner
.finish());
209 EXPECT_NO_THROW(options
.finish());
212 EXPECT_EQ(4, value1
);
213 EXPECT_EQ(6, value2
);
216 TEST(OptionsAssignerTest
, HandlesSections
)
218 using gmx::OptionSection
;
219 gmx::Options options
;
220 auto sub1
= options
.addSection(OptionSection("section1"));
221 auto sub2
= options
.addSection(OptionSection("section2"));
225 using gmx::IntegerOption
;
226 ASSERT_NO_THROW_GMX(options
.addOption(IntegerOption("p").store(&value
)));
227 ASSERT_NO_THROW_GMX(sub1
.addOption(IntegerOption("p").store(&value1
)));
228 ASSERT_NO_THROW_GMX(sub2
.addOption(IntegerOption("p").store(&value2
)));
230 gmx::OptionsAssigner
assigner(&options
);
231 EXPECT_NO_THROW(assigner
.start());
232 ASSERT_NO_THROW(assigner
.startSection("section1"));
233 ASSERT_NO_THROW(assigner
.startOption("p"));
234 EXPECT_NO_THROW(assigner
.appendValue("5"));
235 EXPECT_NO_THROW(assigner
.finishOption());
236 EXPECT_NO_THROW(assigner
.finishSection());
237 ASSERT_NO_THROW(assigner
.startOption("p"));
238 EXPECT_NO_THROW(assigner
.appendValue("4"));
239 EXPECT_NO_THROW(assigner
.finishOption());
240 ASSERT_NO_THROW(assigner
.startSection("section2"));
241 ASSERT_NO_THROW(assigner
.startOption("p"));
242 EXPECT_NO_THROW(assigner
.appendValue("6"));
243 EXPECT_NO_THROW(assigner
.finishOption());
244 EXPECT_NO_THROW(assigner
.finishSection());
245 EXPECT_NO_THROW(assigner
.finish());
246 EXPECT_NO_THROW(options
.finish());
249 EXPECT_EQ(5, value1
);
250 EXPECT_EQ(6, value2
);
253 TEST(OptionsAssignerTest
, HandlesMultipleSources
)
255 gmx::Options options
;
257 using gmx::IntegerOption
;
258 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(&value
)));
261 gmx::OptionsAssigner
assigner(&options
);
262 EXPECT_NO_THROW(assigner
.start());
263 ASSERT_NO_THROW(assigner
.startOption("p"));
264 EXPECT_NO_THROW(assigner
.appendValue("1"));
265 EXPECT_NO_THROW(assigner
.finishOption());
266 EXPECT_NO_THROW(assigner
.finish());
269 gmx::OptionsAssigner
assigner2(&options
);
270 EXPECT_NO_THROW(assigner2
.start());
271 ASSERT_NO_THROW(assigner2
.startOption("p"));
272 EXPECT_NO_THROW(assigner2
.appendValue("2"));
273 EXPECT_NO_THROW(assigner2
.finishOption());
274 EXPECT_NO_THROW(assigner2
.finish());
276 EXPECT_NO_THROW(options
.finish());
282 /********************************************************************
283 * Tests for boolean assignment
286 TEST(OptionsAssignerBooleanTest
, StoresYesValue
)
288 gmx::Options options
;
290 using gmx::BooleanOption
;
291 ASSERT_NO_THROW(options
.addOption(BooleanOption("p").store(&value
)));
293 gmx::OptionsAssigner
assigner(&options
);
294 EXPECT_NO_THROW(assigner
.start());
295 ASSERT_NO_THROW(assigner
.startOption("p"));
296 EXPECT_NO_THROW(assigner
.appendValue("yes"));
297 EXPECT_NO_THROW(assigner
.finishOption());
298 EXPECT_NO_THROW(assigner
.finish());
299 EXPECT_NO_THROW(options
.finish());
304 TEST(OptionsAssignerBooleanTest
, SetsBooleanWithoutExplicitValue
)
306 gmx::Options options
;
308 using gmx::BooleanOption
;
309 ASSERT_NO_THROW(options
.addOption(BooleanOption("p").store(&value
)));
311 gmx::OptionsAssigner
assigner(&options
);
312 EXPECT_NO_THROW(assigner
.start());
313 ASSERT_NO_THROW(assigner
.startOption("p"));
314 EXPECT_NO_THROW(assigner
.finishOption());
315 EXPECT_NO_THROW(assigner
.finish());
316 EXPECT_NO_THROW(options
.finish());
321 TEST(OptionsAssignerBooleanTest
, ClearsBooleanWithPrefixNo
)
323 gmx::Options options
;
325 using gmx::BooleanOption
;
326 ASSERT_NO_THROW(options
.addOption(BooleanOption("p").store(&value
)));
328 gmx::OptionsAssigner
assigner(&options
);
329 assigner
.setAcceptBooleanNoPrefix(true);
330 EXPECT_NO_THROW(assigner
.start());
331 ASSERT_NO_THROW(assigner
.startOption("nop"));
332 EXPECT_NO_THROW(assigner
.finishOption());
333 EXPECT_NO_THROW(assigner
.finish());
334 EXPECT_NO_THROW(options
.finish());
339 TEST(OptionsAssignerBooleanTest
, HandlesBooleanWithPrefixAndValue
)
341 gmx::Options options
;
343 using gmx::BooleanOption
;
344 ASSERT_NO_THROW(options
.addOption(BooleanOption("p").store(&value
)));
346 gmx::OptionsAssigner
assigner(&options
);
347 assigner
.setAcceptBooleanNoPrefix(true);
348 EXPECT_NO_THROW(assigner
.start());
349 ASSERT_NO_THROW(assigner
.startOption("nop"));
350 // It's OK to fail, but if it doesn't, it should work.
353 assigner
.appendValue("no");
354 assigner
.finishOption();
355 EXPECT_NO_THROW(assigner
.finish());
358 catch (const gmx::InvalidInputError
&)
364 /********************************************************************
365 * Tests for integer assignment
367 * These tests also contain tests for general default value handling.
370 TEST(OptionsAssignerIntegerTest
, StoresSingleValue
)
372 gmx::Options options
;
374 using gmx::IntegerOption
;
375 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(&value
)));
377 gmx::OptionsAssigner
assigner(&options
);
378 EXPECT_NO_THROW(assigner
.start());
379 ASSERT_NO_THROW(assigner
.startOption("p"));
380 ASSERT_NO_THROW(assigner
.appendValue("3"));
381 EXPECT_NO_THROW(assigner
.finishOption());
382 EXPECT_NO_THROW(assigner
.finish());
383 EXPECT_NO_THROW(options
.finish());
388 TEST(OptionsAssignerIntegerTest
, HandlesEmptyValue
)
390 gmx::Options options
;
392 using gmx::IntegerOption
;
393 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(&value
)));
395 gmx::OptionsAssigner
assigner(&options
);
396 EXPECT_NO_THROW(assigner
.start());
397 ASSERT_NO_THROW(assigner
.startOption("p"));
398 EXPECT_THROW(assigner
.appendValue(""), gmx::InvalidInputError
);
399 EXPECT_NO_THROW(assigner
.finishOption());
400 EXPECT_NO_THROW(assigner
.finish());
401 EXPECT_NO_THROW(options
.finish());
406 TEST(OptionsAssignerIntegerTest
, HandlesInvalidValue
)
408 gmx::Options options
;
410 using gmx::IntegerOption
;
411 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(&value
)));
413 gmx::OptionsAssigner
assigner(&options
);
414 EXPECT_NO_THROW(assigner
.start());
415 ASSERT_NO_THROW(assigner
.startOption("p"));
416 EXPECT_THROW(assigner
.appendValue("2abc"), gmx::InvalidInputError
);
417 EXPECT_NO_THROW(assigner
.finishOption());
418 EXPECT_NO_THROW(assigner
.finish());
419 EXPECT_NO_THROW(options
.finish());
424 TEST(OptionsAssignerIntegerTest
, HandlesOverflow
)
426 gmx::Options options
;
428 using gmx::IntegerOption
;
429 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(&value
)));
431 gmx::OptionsAssigner
assigner(&options
);
432 EXPECT_NO_THROW(assigner
.start());
433 ASSERT_NO_THROW(assigner
.startOption("p"));
434 std::string
overflowValue(gmx::formatString("%d0000", std::numeric_limits
<int>::max()));
435 EXPECT_THROW(assigner
.appendValue(overflowValue
), gmx::InvalidInputError
);
436 EXPECT_NO_THROW(assigner
.finishOption());
437 EXPECT_NO_THROW(assigner
.finish());
438 EXPECT_NO_THROW(options
.finish());
443 TEST(OptionsAssignerIntegerTest
, StoresDefaultValue
)
445 gmx::Options options
;
447 using gmx::IntegerOption
;
448 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(&value
).defaultValue(2)));
451 gmx::OptionsAssigner
assigner(&options
);
452 EXPECT_NO_THROW(assigner
.start());
453 EXPECT_NO_THROW(assigner
.finish());
454 EXPECT_NO_THROW(options
.finish());
459 TEST(OptionsAssignerIntegerTest
, StoresDefaultValueIfSet
)
461 gmx::Options options
;
463 using gmx::IntegerOption
;
464 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(&value
).defaultValueIfSet(2)));
465 EXPECT_EQ(-1, value
);
467 gmx::OptionsAssigner
assigner(&options
);
468 EXPECT_NO_THROW(assigner
.start());
469 ASSERT_NO_THROW(assigner
.startOption("p"));
470 EXPECT_NO_THROW(assigner
.finishOption());
471 EXPECT_NO_THROW(assigner
.finish());
472 EXPECT_NO_THROW(options
.finish());
477 TEST(OptionsAssignerIntegerTest
, HandlesDefaultValueIfSetWhenNotSet
)
479 gmx::Options options
;
481 using gmx::IntegerOption
;
482 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(&value
).defaultValueIfSet(2)));
483 EXPECT_EQ(-1, value
);
485 gmx::OptionsAssigner
assigner(&options
);
486 EXPECT_NO_THROW(assigner
.start());
487 EXPECT_NO_THROW(assigner
.finish());
488 EXPECT_NO_THROW(options
.finish());
490 EXPECT_EQ(-1, value
);
493 TEST(OptionsAssignerIntegerTest
, HandlesBothDefaultValues
)
495 gmx::Options options
;
497 using gmx::IntegerOption
;
499 options
.addOption(IntegerOption("p").store(&value
).defaultValue(1).defaultValueIfSet(2)));
502 gmx::OptionsAssigner
assigner(&options
);
503 EXPECT_NO_THROW(assigner
.start());
504 ASSERT_NO_THROW(assigner
.startOption("p"));
505 EXPECT_NO_THROW(assigner
.finishOption());
506 EXPECT_NO_THROW(assigner
.finish());
507 EXPECT_NO_THROW(options
.finish());
512 TEST(OptionsAssignerIntegerTest
, StoresToVector
)
514 gmx::Options options
;
515 std::vector
<int> values
;
516 using gmx::IntegerOption
;
517 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").storeVector(&values
).multiValue()));
519 gmx::OptionsAssigner
assigner(&options
);
520 EXPECT_NO_THROW(assigner
.start());
521 ASSERT_NO_THROW(assigner
.startOption("p"));
522 ASSERT_NO_THROW(assigner
.appendValue("-2"));
523 ASSERT_NO_THROW(assigner
.appendValue("1"));
524 ASSERT_NO_THROW(assigner
.appendValue("4"));
525 EXPECT_NO_THROW(assigner
.finishOption());
526 EXPECT_NO_THROW(assigner
.finish());
527 EXPECT_NO_THROW(options
.finish());
529 EXPECT_EQ(3U, values
.size());
530 EXPECT_EQ(-2, values
[0]);
531 EXPECT_EQ(1, values
[1]);
532 EXPECT_EQ(4, values
[2]);
535 TEST(OptionsAssignerIntegerTest
, HandlesVectors
)
537 gmx::Options options
;
538 int vec
[3] = { 0, 0, 0 };
539 using gmx::IntegerOption
;
540 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(vec
).vector()));
542 gmx::OptionsAssigner
assigner(&options
);
543 EXPECT_NO_THROW(assigner
.start());
544 ASSERT_NO_THROW(assigner
.startOption("p"));
545 ASSERT_NO_THROW(assigner
.appendValue("-2"));
546 ASSERT_NO_THROW(assigner
.appendValue("1"));
547 ASSERT_NO_THROW(assigner
.appendValue("4"));
548 EXPECT_NO_THROW(assigner
.finishOption());
549 EXPECT_NO_THROW(assigner
.finish());
550 EXPECT_NO_THROW(options
.finish());
552 EXPECT_EQ(-2, vec
[0]);
553 EXPECT_EQ(1, vec
[1]);
554 EXPECT_EQ(4, vec
[2]);
557 TEST(OptionsAssignerIntegerTest
, HandlesVectorFromSingleValue
)
559 gmx::Options options
;
560 int vec
[3] = { 0, 0, 0 };
561 using gmx::IntegerOption
;
562 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(vec
).vector()));
564 gmx::OptionsAssigner
assigner(&options
);
565 EXPECT_NO_THROW(assigner
.start());
566 ASSERT_NO_THROW(assigner
.startOption("p"));
567 ASSERT_NO_THROW(assigner
.appendValue("2"));
568 EXPECT_NO_THROW(assigner
.finishOption());
569 EXPECT_NO_THROW(assigner
.finish());
570 EXPECT_NO_THROW(options
.finish());
572 EXPECT_EQ(2, vec
[0]);
573 EXPECT_EQ(2, vec
[1]);
574 EXPECT_EQ(2, vec
[2]);
577 TEST(OptionsAssignerIntegerTest
, HandlesVectorsWithDefaultValue
)
579 gmx::Options options
;
580 int vec
[3] = { 3, 2, 1 };
581 using gmx::IntegerOption
;
582 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(vec
).vector()));
584 EXPECT_NO_THROW(options
.finish());
586 EXPECT_EQ(3, vec
[0]);
587 EXPECT_EQ(2, vec
[1]);
588 EXPECT_EQ(1, vec
[2]);
591 TEST(OptionsAssignerIntegerTest
, HandlesVectorsWithDefaultValueWithInvalidAssignment
)
593 gmx::Options options
;
594 int vec
[3] = { 3, 2, 1 };
595 using gmx::IntegerOption
;
596 ASSERT_NO_THROW(options
.addOption(IntegerOption("p").store(vec
).vector()));
598 gmx::OptionsAssigner
assigner(&options
);
599 EXPECT_NO_THROW(assigner
.start());
600 ASSERT_NO_THROW(assigner
.startOption("p"));
601 EXPECT_NO_THROW(assigner
.appendValue("1"));
602 EXPECT_NO_THROW(assigner
.appendValue("3"));
603 EXPECT_THROW(assigner
.finishOption(), gmx::InvalidInputError
);
604 EXPECT_NO_THROW(assigner
.finish());
605 EXPECT_NO_THROW(options
.finish());
607 EXPECT_EQ(3, vec
[0]);
608 EXPECT_EQ(2, vec
[1]);
609 EXPECT_EQ(1, vec
[2]);
613 /********************************************************************
614 * Tests for double assignment
617 TEST(OptionsAssignerDoubleTest
, StoresSingleValue
)
619 gmx::Options options
;
621 using gmx::DoubleOption
;
622 ASSERT_NO_THROW(options
.addOption(DoubleOption("p").store(&value
)));
624 gmx::OptionsAssigner
assigner(&options
);
625 EXPECT_NO_THROW(assigner
.start());
626 ASSERT_NO_THROW(assigner
.startOption("p"));
627 ASSERT_NO_THROW(assigner
.appendValue("2.7"));
628 EXPECT_NO_THROW(assigner
.finishOption());
629 EXPECT_NO_THROW(assigner
.finish());
630 EXPECT_NO_THROW(options
.finish());
632 EXPECT_DOUBLE_EQ(2.7, value
);
635 TEST(OptionsAssignerDoubleTest
, StoresValueFromFloat
)
637 gmx::Options options
;
639 using gmx::DoubleOption
;
640 ASSERT_NO_THROW(options
.addOption(DoubleOption("p").store(&value
)));
642 gmx::OptionsAssigner
assigner(&options
);
643 EXPECT_NO_THROW(assigner
.start());
644 ASSERT_NO_THROW(assigner
.startOption("p"));
645 ASSERT_NO_THROW(assigner
.appendValue(gmx::Any::create
<float>(2.7)));
646 EXPECT_NO_THROW(assigner
.finishOption());
647 EXPECT_NO_THROW(assigner
.finish());
648 EXPECT_NO_THROW(options
.finish());
650 EXPECT_FLOAT_EQ(2.7, value
);
653 TEST(OptionsAssignerDoubleTest
, HandlesEmptyValue
)
655 gmx::Options options
;
657 using gmx::DoubleOption
;
658 ASSERT_NO_THROW(options
.addOption(DoubleOption("p").store(&value
)));
660 gmx::OptionsAssigner
assigner(&options
);
661 EXPECT_NO_THROW(assigner
.start());
662 ASSERT_NO_THROW(assigner
.startOption("p"));
663 EXPECT_THROW(assigner
.appendValue(""), gmx::InvalidInputError
);
664 EXPECT_NO_THROW(assigner
.finishOption());
665 EXPECT_NO_THROW(assigner
.finish());
666 EXPECT_NO_THROW(options
.finish());
668 EXPECT_DOUBLE_EQ(1.0, value
);
671 TEST(OptionsAssignerDoubleTest
, HandlesPreSetScaleValue
)
673 gmx::Options options
;
675 using gmx::DoubleOption
;
676 gmx::DoubleOptionInfo
* info
= options
.addOption(DoubleOption("p").store(&value
));
677 EXPECT_NO_THROW(info
->setScaleFactor(10));
679 gmx::OptionsAssigner
assigner(&options
);
680 EXPECT_NO_THROW(assigner
.start());
681 ASSERT_NO_THROW(assigner
.startOption("p"));
682 ASSERT_NO_THROW(assigner
.appendValue("2.7"));
683 EXPECT_NO_THROW(assigner
.finishOption());
684 EXPECT_NO_THROW(assigner
.finish());
685 EXPECT_NO_THROW(options
.finish());
687 EXPECT_DOUBLE_EQ(27, value
);
690 TEST(OptionsAssignerDoubleTest
, HandlesPostSetScaleValue
)
692 gmx::Options options
;
694 using gmx::DoubleOption
;
695 gmx::DoubleOptionInfo
* info
= options
.addOption(DoubleOption("p").store(&value
));
697 gmx::OptionsAssigner
assigner(&options
);
698 EXPECT_NO_THROW(assigner
.start());
699 ASSERT_NO_THROW(assigner
.startOption("p"));
700 ASSERT_NO_THROW(assigner
.appendValue("2.7"));
701 EXPECT_NO_THROW(assigner
.finishOption());
702 EXPECT_NO_THROW(assigner
.finish());
703 EXPECT_NO_THROW(info
->setScaleFactor(10));
704 EXPECT_NO_THROW(options
.finish());
706 EXPECT_DOUBLE_EQ(27, value
);
710 /********************************************************************
711 * Tests for string assignment
714 //! Set of allowed values for enum option tests.
715 const char* const c_allowed
[] = { "none", "test", "value" };
717 TEST(OptionsAssignerStringTest
, StoresSingleValue
)
719 gmx::Options options
;
721 using gmx::StringOption
;
722 ASSERT_NO_THROW(options
.addOption(StringOption("p").store(&value
)));
724 gmx::OptionsAssigner
assigner(&options
);
725 EXPECT_NO_THROW(assigner
.start());
726 ASSERT_NO_THROW(assigner
.startOption("p"));
727 ASSERT_NO_THROW(assigner
.appendValue("value"));
728 EXPECT_NO_THROW(assigner
.finishOption());
729 EXPECT_NO_THROW(assigner
.finish());
730 EXPECT_NO_THROW(options
.finish());
732 EXPECT_EQ("value", value
);
735 TEST(OptionsAssignerStringTest
, HandlesEnumValue
)
737 gmx::Options options
;
739 using gmx::StringOption
;
740 ASSERT_NO_THROW(options
.addOption(StringOption("p").store(&value
).enumValue(c_allowed
)));
742 gmx::OptionsAssigner
assigner(&options
);
743 EXPECT_NO_THROW(assigner
.start());
744 ASSERT_NO_THROW(assigner
.startOption("p"));
745 ASSERT_NO_THROW(assigner
.appendValue("test"));
746 EXPECT_NO_THROW(assigner
.finishOption());
747 EXPECT_NO_THROW(assigner
.finish());
748 EXPECT_NO_THROW(options
.finish());
750 EXPECT_EQ("test", value
);
753 TEST(OptionsAssignerStringTest
, HandlesEnumValueFromNullTerminatedArray
)
755 gmx::Options options
;
757 const char* const allowed
[] = { "none", "test", "value", nullptr };
758 using gmx::StringOption
;
759 ASSERT_NO_THROW(options
.addOption(
760 StringOption("p").store(&value
).enumValueFromNullTerminatedArray(allowed
)));
762 gmx::OptionsAssigner
assigner(&options
);
763 EXPECT_NO_THROW(assigner
.start());
764 ASSERT_NO_THROW(assigner
.startOption("p"));
765 ASSERT_NO_THROW(assigner
.appendValue("value"));
766 EXPECT_NO_THROW(assigner
.finishOption());
767 EXPECT_NO_THROW(assigner
.finish());
768 EXPECT_NO_THROW(options
.finish());
770 EXPECT_EQ("value", value
);
773 TEST(OptionsAssignerStringTest
, HandlesIncorrectEnumValue
)
775 gmx::Options options
;
777 using gmx::StringOption
;
778 ASSERT_NO_THROW(options
.addOption(StringOption("p").store(&value
).enumValue(c_allowed
)));
780 gmx::OptionsAssigner
assigner(&options
);
781 EXPECT_NO_THROW(assigner
.start());
782 ASSERT_NO_THROW(assigner
.startOption("p"));
783 ASSERT_THROW(assigner
.appendValue("unknown"), gmx::InvalidInputError
);
786 TEST(OptionsAssignerStringTest
, CompletesEnumValue
)
788 gmx::Options options
;
790 using gmx::StringOption
;
791 ASSERT_NO_THROW(options
.addOption(StringOption("p").store(&value
).enumValue(c_allowed
)));
793 gmx::OptionsAssigner
assigner(&options
);
794 EXPECT_NO_THROW(assigner
.start());
795 ASSERT_NO_THROW(assigner
.startOption("p"));
796 ASSERT_NO_THROW(assigner
.appendValue("te"));
797 EXPECT_NO_THROW(assigner
.finishOption());
798 EXPECT_NO_THROW(assigner
.finish());
799 EXPECT_NO_THROW(options
.finish());
801 EXPECT_EQ("test", value
);
804 TEST(OptionsAssignerStringTest
, HandlesEnumWithNoValue
)
806 gmx::Options options
;
808 using gmx::StringOption
;
809 ASSERT_NO_THROW(options
.addOption(StringOption("p").store(&value
).enumValue(c_allowed
)));
810 EXPECT_TRUE(value
.empty());
812 ASSERT_NO_THROW(options
.finish());
814 EXPECT_TRUE(value
.empty());
817 TEST(OptionsAssignerStringTest
, HandlesEnumDefaultValue
)
819 gmx::Options options
;
821 using gmx::StringOption
;
822 ASSERT_NO_THROW(options
.addOption(
823 StringOption("p").store(&value
).enumValue(c_allowed
).defaultValue("test")));
824 EXPECT_EQ("test", value
);
826 gmx::OptionsAssigner
assigner(&options
);
827 EXPECT_NO_THROW(assigner
.start());
828 EXPECT_NO_THROW(assigner
.finish());
829 EXPECT_NO_THROW(options
.finish());
831 EXPECT_EQ("test", value
);
834 TEST(OptionsAssignerStringTest
, HandlesEnumDefaultValueFromVariable
)
836 gmx::Options options
;
837 std::string
value("test");
838 using gmx::StringOption
;
839 ASSERT_NO_THROW(options
.addOption(StringOption("p").store(&value
).enumValue(c_allowed
)));
840 EXPECT_EQ("test", value
);
842 gmx::OptionsAssigner
assigner(&options
);
843 EXPECT_NO_THROW(assigner
.start());
844 EXPECT_NO_THROW(assigner
.finish());
845 EXPECT_NO_THROW(options
.finish());
847 EXPECT_EQ("test", value
);
850 TEST(OptionsAssignerStringTest
, HandlesEnumDefaultValueFromVector
)
852 gmx::Options options
;
853 std::vector
<std::string
> value
;
854 value
.emplace_back("test");
855 value
.emplace_back("value");
856 using gmx::StringOption
;
857 ASSERT_NO_THROW(options
.addOption(
858 StringOption("p").storeVector(&value
).valueCount(2).enumValue(c_allowed
)));
859 ASSERT_EQ(2U, value
.size());
860 EXPECT_EQ("test", value
[0]);
861 EXPECT_EQ("value", value
[1]);
863 gmx::OptionsAssigner
assigner(&options
);
864 EXPECT_NO_THROW(assigner
.start());
865 EXPECT_NO_THROW(assigner
.finish());
866 EXPECT_NO_THROW(options
.finish());
868 ASSERT_EQ(2U, value
.size());
869 EXPECT_EQ("test", value
[0]);
870 EXPECT_EQ("value", value
[1]);
874 /********************************************************************
875 * Tests for enum options
878 //! Enum type for EnumOption tests.
879 enum class TestEnum
: int
886 //! Set of allowed values for enum option tests.
887 const gmx::EnumerationArray
<TestEnum
, const char*> c_testEnumNames
= { { "none", "test", "value" } };
889 TEST(OptionsAssignerEnumTest
, StoresSingleValue
)
891 gmx::Options options
;
892 TestEnum value
= TestEnum::None
;
893 using gmx::EnumOption
;
894 ASSERT_NO_THROW(options
.addOption(EnumOption
<TestEnum
>("p").store(&value
).enumValue(c_testEnumNames
)));
895 EXPECT_EQ(TestEnum::None
, value
);
897 gmx::OptionsAssigner
assigner(&options
);
898 EXPECT_NO_THROW(assigner
.start());
899 ASSERT_NO_THROW(assigner
.startOption("p"));
900 ASSERT_NO_THROW(assigner
.appendValue("test"));
901 EXPECT_NO_THROW(assigner
.finishOption());
902 EXPECT_NO_THROW(assigner
.finish());
903 EXPECT_NO_THROW(options
.finish());
905 EXPECT_EQ(TestEnum::Test
, value
);
908 TEST(OptionsAssignerEnumTest
, StoresVectorValues
)
910 gmx::Options options
;
911 std::vector
<TestEnum
> values
;
912 using gmx::EnumOption
;
913 ASSERT_NO_THROW(options
.addOption(
914 EnumOption
<TestEnum
>("p").storeVector(&values
).multiValue().enumValue(c_testEnumNames
)));
915 EXPECT_TRUE(values
.empty());
917 gmx::OptionsAssigner
assigner(&options
);
918 EXPECT_NO_THROW(assigner
.start());
919 ASSERT_NO_THROW(assigner
.startOption("p"));
920 ASSERT_NO_THROW(assigner
.appendValue("test"));
921 ASSERT_NO_THROW(assigner
.appendValue("value"));
922 EXPECT_NO_THROW(assigner
.finishOption());
923 EXPECT_NO_THROW(assigner
.finish());
924 EXPECT_NO_THROW(options
.finish());
926 ASSERT_EQ(2U, values
.size());
927 EXPECT_EQ(TestEnum::Test
, values
[0]);
928 EXPECT_EQ(TestEnum::Value
, values
[1]);
931 TEST(OptionsAssignerEnumTest
, HandlesInitialValueOutOfRange
)
933 gmx::Options options
;
934 TestEnum value
= TestEnum::Count
;
935 using gmx::EnumOption
;
936 ASSERT_NO_THROW(options
.addOption(EnumOption
<TestEnum
>("p").store(&value
).enumValue(c_testEnumNames
)));
937 EXPECT_EQ(TestEnum::Count
, value
);
939 gmx::OptionsAssigner
assigner(&options
);
940 EXPECT_NO_THROW(assigner
.start());
941 EXPECT_NO_THROW(assigner
.finish());
942 EXPECT_NO_THROW(options
.finish());
944 EXPECT_EQ(TestEnum::Count
, value
);
947 TEST(OptionsAssignerEnumTest
, HandlesEnumDefaultValue
)
949 gmx::Options options
;
950 TestEnum value
= TestEnum::None
;
951 using gmx::EnumOption
;
952 ASSERT_NO_THROW(options
.addOption(
953 EnumOption
<TestEnum
>("p").store(&value
).enumValue(c_testEnumNames
).defaultValue(TestEnum::Test
)));
954 EXPECT_EQ(TestEnum::Test
, value
);
956 gmx::OptionsAssigner
assigner(&options
);
957 EXPECT_NO_THROW(assigner
.start());
958 EXPECT_NO_THROW(assigner
.finish());
959 EXPECT_NO_THROW(options
.finish());
961 EXPECT_EQ(TestEnum::Test
, value
);
964 TEST(OptionsAssignerEnumTest
, HandlesEnumDefaultValueFromVariable
)
966 gmx::Options options
;
967 TestEnum value
= TestEnum::Test
;
968 using gmx::EnumOption
;
969 ASSERT_NO_THROW(options
.addOption(EnumOption
<TestEnum
>("p").store(&value
).enumValue(c_testEnumNames
)));
970 EXPECT_EQ(TestEnum::Test
, value
);
972 gmx::OptionsAssigner
assigner(&options
);
973 EXPECT_NO_THROW(assigner
.start());
974 EXPECT_NO_THROW(assigner
.finish());
975 EXPECT_NO_THROW(options
.finish());
977 EXPECT_EQ(TestEnum::Test
, value
);
980 TEST(OptionsAssignerEnumTest
, HandlesEnumDefaultValueFromVector
)
982 gmx::Options options
;
983 std::vector
<TestEnum
> value
;
984 value
.push_back(TestEnum::None
);
985 value
.push_back(TestEnum::Test
);
986 using gmx::EnumOption
;
987 ASSERT_NO_THROW(options
.addOption(
988 EnumOption
<TestEnum
>("p").storeVector(&value
).valueCount(2).enumValue(c_testEnumNames
)));
989 ASSERT_EQ(2U, value
.size());
990 EXPECT_EQ(TestEnum::None
, value
[0]);
991 EXPECT_EQ(TestEnum::Test
, value
[1]);
993 gmx::OptionsAssigner
assigner(&options
);
994 EXPECT_NO_THROW(assigner
.start());
995 EXPECT_NO_THROW(assigner
.finish());
996 EXPECT_NO_THROW(options
.finish());
998 ASSERT_EQ(2U, value
.size());
999 EXPECT_EQ(TestEnum::None
, value
[0]);
1000 EXPECT_EQ(TestEnum::Test
, value
[1]);