Update instructions in containers.rst
[gromacs.git] / src / gromacs / options / tests / optionsassigner.cpp
blob80f917b5a8c1cc11d357f775e1f69cf0fc30613e
1 /*
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.
36 /*! \internal \file
37 * \brief
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
44 * classes.
46 * \author Teemu Murtola <teemu.murtola@gmail.com>
47 * \ingroup module_options
49 #include "gmxpre.h"
51 #include "gromacs/options/optionsassigner.h"
53 #include <limits>
54 #include <vector>
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"
67 namespace
70 /********************************************************************
71 * General assignment tests
74 TEST(OptionsAssignerTest, HandlesMissingRequiredParameter)
76 gmx::Options options;
77 int value = 0;
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)
86 gmx::Options options;
87 int value = 0;
88 using gmx::IntegerOption;
89 ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value).required().defaultValue(1)));
91 EXPECT_NO_THROW(options.finish());
92 EXPECT_EQ(1, value);
95 TEST(OptionsAssignerTest, HandlesInvalidMultipleParameter)
97 gmx::Options options;
98 std::vector<int> values;
99 bool bIsSet = false;
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());
113 EXPECT_TRUE(bIsSet);
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;
122 bool bIsSet = false;
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());
138 EXPECT_TRUE(bIsSet);
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;
168 int value1 = 0;
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();
189 int value = 3;
190 int value1 = 1;
191 int value2 = 2;
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());
211 EXPECT_EQ(5, value);
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"));
222 int value = 3;
223 int value1 = 1;
224 int value2 = 2;
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());
248 EXPECT_EQ(4, value);
249 EXPECT_EQ(5, value1);
250 EXPECT_EQ(6, value2);
253 TEST(OptionsAssignerTest, HandlesMultipleSources)
255 gmx::Options options;
256 int value = -1;
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());
278 EXPECT_EQ(2, value);
282 /********************************************************************
283 * Tests for boolean assignment
286 TEST(OptionsAssignerBooleanTest, StoresYesValue)
288 gmx::Options options;
289 bool value = false;
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());
301 EXPECT_TRUE(value);
304 TEST(OptionsAssignerBooleanTest, SetsBooleanWithoutExplicitValue)
306 gmx::Options options;
307 bool value = false;
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());
318 EXPECT_TRUE(value);
321 TEST(OptionsAssignerBooleanTest, ClearsBooleanWithPrefixNo)
323 gmx::Options options;
324 bool value = true;
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());
336 EXPECT_FALSE(value);
339 TEST(OptionsAssignerBooleanTest, HandlesBooleanWithPrefixAndValue)
341 gmx::Options options;
342 bool value = false;
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());
356 EXPECT_TRUE(value);
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;
373 int value = 1;
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());
385 EXPECT_EQ(3, value);
388 TEST(OptionsAssignerIntegerTest, HandlesEmptyValue)
390 gmx::Options options;
391 int value = 1;
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());
403 EXPECT_EQ(1, value);
406 TEST(OptionsAssignerIntegerTest, HandlesInvalidValue)
408 gmx::Options options;
409 int value = 1;
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());
421 EXPECT_EQ(1, value);
424 TEST(OptionsAssignerIntegerTest, HandlesOverflow)
426 gmx::Options options;
427 int value = 1;
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());
440 EXPECT_EQ(1, value);
443 TEST(OptionsAssignerIntegerTest, StoresDefaultValue)
445 gmx::Options options;
446 int value = -1;
447 using gmx::IntegerOption;
448 ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value).defaultValue(2)));
449 EXPECT_EQ(2, value);
451 gmx::OptionsAssigner assigner(&options);
452 EXPECT_NO_THROW(assigner.start());
453 EXPECT_NO_THROW(assigner.finish());
454 EXPECT_NO_THROW(options.finish());
456 EXPECT_EQ(2, value);
459 TEST(OptionsAssignerIntegerTest, StoresDefaultValueIfSet)
461 gmx::Options options;
462 int value = -1;
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());
474 EXPECT_EQ(2, value);
477 TEST(OptionsAssignerIntegerTest, HandlesDefaultValueIfSetWhenNotSet)
479 gmx::Options options;
480 int value = -1;
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;
496 int value = -1;
497 using gmx::IntegerOption;
498 ASSERT_NO_THROW(
499 options.addOption(IntegerOption("p").store(&value).defaultValue(1).defaultValueIfSet(2)));
500 EXPECT_EQ(1, value);
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());
509 EXPECT_EQ(2, value);
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;
620 double value = 0.0;
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;
638 double value = 0.0;
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;
656 double value = 1.0;
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;
674 double value = 1.0;
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;
693 double value = 1.0;
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;
720 std::string value;
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;
738 std::string value;
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;
756 std::string value;
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;
776 std::string value;
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;
789 std::string value;
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;
807 std::string value;
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;
820 std::string value;
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
881 None,
882 Test,
883 Value,
884 Count
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]);
1003 } // namespace