2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 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.
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.
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.
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.
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.
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.
37 * Tests option support for operations on KeyValueTree.
39 * \author Teemu Murtola <teemu.murtola@gmail.com>
40 * \ingroup module_options
44 #include "gromacs/options/treesupport.h"
48 #include <gtest/gtest.h>
50 #include "gromacs/options/basicoptions.h"
51 #include "gromacs/options/options.h"
52 #include "gromacs/options/optionsection.h"
53 #include "gromacs/options/repeatingsection.h"
54 #include "gromacs/utility/exceptions.h"
55 #include "gromacs/utility/keyvaluetree.h"
56 #include "gromacs/utility/keyvaluetreebuilder.h"
58 #include "testutils/refdata.h"
59 #include "testutils/testasserts.h"
64 /********************************************************************
65 * Tests for assignOptionsFromKeyValueTree()
68 TEST(TreeValueSupportAssignTest, AssignsFromTree)
74 options.addOption(gmx::IntegerOption("a").store(&a0));
75 auto sec = options.addSection(gmx::OptionSection("s"));
76 sec.addOption(gmx::IntegerOption("a").store(&a1));
77 sec.addOption(gmx::StringOption("b").store(&b1));
79 gmx::KeyValueTreeBuilder builder;
80 builder.rootObject().addValue<int>("a", 2);
81 auto obj = builder.rootObject().addObject("s");
82 obj.addValue<int>("a", 1);
83 obj.addValue<std::string>("b", "foo");
84 gmx::KeyValueTreeObject tree = builder.build();
86 ASSERT_NO_THROW_GMX(gmx::assignOptionsFromKeyValueTree(&options, tree, nullptr));
87 EXPECT_NO_THROW_GMX(options.finish());
99 TEST(TreeValueSupportAssignTest, AssignsFromTreeWithArrays)
102 std::vector<SectionData> s;
104 gmx::Options options;
105 options.addOption(gmx::IntegerOption("a").storeVector(&a0).multiValue());
106 auto sec = options.addSection(gmx::RepeatingOptionSection<SectionData>("s").storeVector(&s));
107 sec.addOption(gmx::IntegerOption("a").store(&sec.bind().a));
109 gmx::KeyValueTreeBuilder builder;
110 auto array = builder.rootObject().addUniformArray<int>("a");
113 auto objArray = builder.rootObject().addObjectArray("s");
114 auto obj1 = objArray.addObject();
115 obj1.addValue<int>("a", 3);
116 auto obj2 = objArray.addObject();
117 obj2.addValue<int>("a", 4);
118 gmx::KeyValueTreeObject tree = builder.build();
120 ASSERT_NO_THROW_GMX(gmx::assignOptionsFromKeyValueTree(&options, tree, nullptr));
121 EXPECT_NO_THROW_GMX(options.finish());
123 ASSERT_EQ(2U, a0.size());
126 ASSERT_EQ(2U, s.size());
127 EXPECT_EQ(3, s[0].a);
128 EXPECT_EQ(4, s[1].a);
131 TEST(TreeValueSupportAssignErrorTest, HandlesInvalidValue)
135 gmx::Options options;
136 auto sec = options.addSection(gmx::OptionSection("s"));
137 sec.addOption(gmx::IntegerOption("a").store(&a1));
139 gmx::KeyValueTreeBuilder builder;
140 auto obj = builder.rootObject().addObject("s");
141 obj.addValue<std::string>("a", "foo");
142 gmx::KeyValueTreeObject tree = builder.build();
144 EXPECT_THROW_GMX(gmx::assignOptionsFromKeyValueTree(&options, tree, nullptr),
145 gmx::InvalidInputError);
148 /********************************************************************
149 * Tests for adjustKeyValueTreeFromOptions()
152 class TreeValueSupportAdjustTest : public ::testing::Test
157 gmx::test::TestReferenceData refdata;
158 gmx::test::TestReferenceChecker checker(refdata.rootChecker());
159 gmx::KeyValueTreeObject tree(builder_.build());
160 checker.checkKeyValueTreeObject(tree, "Input");
161 ASSERT_NO_THROW_GMX(tree = gmx::adjustKeyValueTreeFromOptions(tree, options_));
162 checker.checkKeyValueTreeObject(tree, "Output");
165 gmx::Options options_;
166 gmx::KeyValueTreeBuilder builder_;
169 TEST_F(TreeValueSupportAdjustTest, FillsDefaultValues)
171 options_.addOption(gmx::IntegerOption("a").defaultValue(2));
175 TEST_F(TreeValueSupportAdjustTest, FillsDefaultVectorValues)
177 int v[3] = {1, 2, 3};
178 options_.addOption(gmx::IntegerOption("a").store(v).vector());
182 TEST_F(TreeValueSupportAdjustTest, FillsDefaultObjectValues)
184 auto sec1 = options_.addSection(gmx::OptionSection("s"));
185 sec1.addOption(gmx::IntegerOption("a").defaultValue(1));
186 auto sec2 = options_.addSection(gmx::OptionSection("r"));
187 sec2.addOption(gmx::IntegerOption("a").defaultValue(2));
188 options_.addOption(gmx::IntegerOption("a").defaultValue(3));
192 TEST_F(TreeValueSupportAdjustTest, NormalizesValues)
194 options_.addOption(gmx::IntegerOption("a"));
195 builder_.rootObject().addValue<std::string>("a", "2");
199 TEST_F(TreeValueSupportAdjustTest, MergesDefaultValues)
201 builder_.rootObject().addValue<int>("b", 1);
202 options_.addOption(gmx::IntegerOption("a").defaultValue(2));
203 options_.addOption(gmx::IntegerOption("b").defaultValue(3));
207 TEST_F(TreeValueSupportAdjustTest, OrdersValues)
209 builder_.rootObject().addValue<int>("a", 1);
210 builder_.rootObject().addValue<int>("c", 1);
211 builder_.rootObject().addValue<int>("b", 1);
212 options_.addOption(gmx::IntegerOption("b").defaultValue(2));
213 options_.addOption(gmx::IntegerOption("a").defaultValue(1));
214 options_.addOption(gmx::IntegerOption("c").defaultValue(3));
215 // TODO: This does not actually test the correct ordering, since the
216 // reference data is not currently order-sensitive, but the order can be
217 // checked manually from the reference data.