1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
3 * Copyright 2016 Couchbase, Inc
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include "configuration.h"
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
23 /* Like EXPECT_THROW except you can check the exception's `what()` */
24 # define CB_EXPECT_THROW_MSG(EXPR, ETYPE, MSG) \
25 EXPECT_THROW(EXPR, ETYPE); \
28 ADD_FAILURE() << "Expected: " #EXPR " throws an exception of type " \
29 #ETYPE ".\n Actual: it throws nothing."; \
30 } catch (const ETYPE& EXCEPTION) { \
31 EXPECT_STREQ(MSG, EXCEPTION.what()) << "Wrong exception message!" ; \
33 ADD_FAILURE() << "Expected: " #EXPR " throws an exception of type " \
34 #ETYPE ".\n Actual: it throws different type."; \
37 TEST(ValueChangedValidatorTest, AllMethodsThrow) {
38 ValueChangedValidator validator;
39 std::string key{"test_key"};
41 EXPECT_THROW(validator.validateBool(key, false), std::runtime_error);
42 EXPECT_THROW(validator.validateSize(key, 0), std::runtime_error);
43 EXPECT_THROW(validator.validateSSize(key, 0), std::runtime_error);
44 EXPECT_THROW(validator.validateFloat(key, 0.0), std::runtime_error);
45 EXPECT_THROW(validator.validateString(key, ""), std::runtime_error);
48 TEST(SizeRangeValidatorTest, UninitialisedIsOnlyZero) {
49 SizeRangeValidator validator;
50 std::string key{"test_key"};
52 EXPECT_NO_THROW(validator.validateSize(key, 0));
53 EXPECT_NO_THROW(validator.validateSSize(key, 0));
56 validator.validateSize(key, 1),
58 "Validation Error, test_key takes values between 0 and 0 (Got: 1)"
61 validator.validateSSize(key, 1),
63 "Validation Error, test_key takes values between 0 and 0 (Got: 1)"
66 validator.validateSSize(key, -1),
68 "Validation Error, test_key takes values between 0 and 0 (Got: -1)"
72 TEST(SizeRangeValidatorTest, UnsignedBoundsWorks) {
73 SizeRangeValidator validator;
74 std::string key{"test_key"};
76 (&validator)->min(100)->max(1000);
78 EXPECT_NO_THROW(validator.validateSize(key, 100));
79 EXPECT_NO_THROW(validator.validateSize(key, 1000));
80 EXPECT_NO_THROW(validator.validateSize(key, 101));
81 EXPECT_NO_THROW(validator.validateSize(key, 999));
84 validator.validateSize(key, 99),
86 "Validation Error, test_key takes values between 100 and 1000 (Got: 99)"
89 validator.validateSize(key, 1001),
91 "Validation Error, test_key takes values between 100 and 1000 (Got: 1001)"
95 TEST(SizeRangeValidatorTest, SignedBoundsWorks) {
96 SizeRangeValidator validator;
97 std::string key{"test_key"};
99 (&validator)->min(-100)->max(1000);
101 EXPECT_NO_THROW(validator.validateSSize(key, -100));
102 EXPECT_NO_THROW(validator.validateSSize(key, 1000));
103 EXPECT_NO_THROW(validator.validateSSize(key, -99));
104 EXPECT_NO_THROW(validator.validateSSize(key, 999));
107 validator.validateSSize(key, -101),
109 "Validation Error, test_key takes values between -100 and 1000 (Got: -101)"
112 validator.validateSSize(key, 1001),
114 "Validation Error, test_key takes values between -100 and 1000 (Got: 1001)"
118 TEST(SSizeRangeValidatorTest, UninitialisedIsOnlyZero) {
119 SizeRangeValidator validator;
120 std::string key{"test_key"};
122 EXPECT_NO_THROW(validator.validateSSize(key, 0));
125 validator.validateSSize(key, 1),
127 "Validation Error, test_key takes values between 0 and 0 (Got: 1)"
130 validator.validateSSize(key, -1),
132 "Validation Error, test_key takes values between 0 and 0 (Got: -1)"
136 TEST(SSizeRangeValidatorTest, SignedBoundsWork) {
137 SSizeRangeValidator validator;
138 std::string key{"test_key"};
140 (&validator)->min(-100)->max(1000);
142 EXPECT_NO_THROW(validator.validateSSize(key, -100));
143 EXPECT_NO_THROW(validator.validateSSize(key, 1000));
144 EXPECT_NO_THROW(validator.validateSSize(key, -99));
145 EXPECT_NO_THROW(validator.validateSSize(key, 999));
148 validator.validateSSize(key, -101),
150 "Validation Error, test_key takes values between -100 and 1000 (Got: -101)"
153 validator.validateSSize(key, 1001),
155 "Validation Error, test_key takes values between -100 and 1000 (Got: 1001)"
159 TEST(FloatRangeValidatorTest, UninitialisedIsZero) {
160 FloatRangeValidator validator;
161 std::string key{"test_key"};
163 validator.validateFloat(key, 0.0);
165 validator.validateFloat(key, 1.0),
167 "Validation Error, test_key takes values between 0.000000 and 0.000000 (Got: 1.000000)"
172 TEST(FloatRangeValidatorTest, FloatBoundsWork) {
173 FloatRangeValidator validator;
174 std::string key{"test_key"};
176 (&validator)->min(-100.1)->max(1000.1);
179 EXPECT_NO_THROW(validator.validateFloat(key, -100.1));
180 EXPECT_NO_THROW(validator.validateFloat(key, 100.00));
181 EXPECT_NO_THROW(validator.validateFloat(key, 101.0));
182 EXPECT_NO_THROW(validator.validateFloat(key, 999.0));
186 validator.validateFloat(key, -100.2),
188 ("Validation Error, test_key takes values between "
189 + std::to_string(-100.1f)
190 + " and " + std::to_string(1000.1f)
191 + " (Got: " + std::to_string(-100.2f) + ")").c_str()
194 validator.validateFloat(key, 1000.2),
196 ("Validation Error, test_key takes values between "
197 + std::to_string(-100.1f)
198 + " and " + std::to_string(1000.1f)
199 + " (Got: " + std::to_string(1000.2f) + ")").c_str()
203 TEST(EnumValidatorTest, EmptyWorks) {
204 EnumValidator validator;
205 std::string key{"test_key"};
209 validator.validateString(key, "my_enum"),
211 "Validation Error, test_key takes one of [] (Got: my_enum)"
215 TEST(EnumValidatorTest, AddOneWorks) {
216 EnumValidator validator;
217 std::string key{"test_key"};
219 /* Single test, in-bounds */
220 validator.add("enum_one");
221 EXPECT_NO_THROW(validator.validateString(key, "enum_one"));
223 /* Single test, out of bounds */
225 validator.validateString(key, "my_enum"),
227 "Validation Error, test_key takes one of [enum_one] (Got: my_enum)"
231 TEST(EnumValidatorTest, OverwriteWorks) {
232 EnumValidator validator;
233 std::string key{"test_key"};
235 validator.add("enum_one");
236 validator.add("enum_one");
237 EXPECT_NO_THROW(validator.validateString(key, "enum_one"));
240 TEST(EnumValidatorTest, MultipleWorks) {
241 EnumValidator validator;
242 std::string key{"test_key"};
244 validator.add("enum_1");
245 validator.add("enum_2");
246 validator.add("enum_3");
247 EXPECT_NO_THROW(validator.validateString(key, "enum_1"));
248 EXPECT_NO_THROW(validator.validateString(key, "enum_2"));
249 EXPECT_NO_THROW(validator.validateString(key, "enum_3"));
251 /* Multi, out of bounds */
253 validator.validateString(key, "my_enum"),
255 "Validation Error, test_key takes one of [enum_1, enum_2, enum_3] (Got: my_enum)"
259 TEST(EnumValidatorTest, EnMassWorks) {
260 EnumValidator validator;
261 std::string key{"test_key"};
264 std::vector<std::string> mass;
265 for(auto i = 0; i < 100000; i++) {
266 mass.push_back(std::to_string(i));
270 validator.add(i.c_str());
273 EXPECT_NO_THROW(validator.validateString(key, i.c_str()));
278 class ConfigurationShim : public Configuration {
280 * Shim class to allow testing the protected methods which are usually
281 * exposed through the generated configuration.
285 using Configuration::setParameter;
286 using Configuration::getParameter;
289 TEST(ConfigurationTest, SetGetWorks) {
290 ConfigurationShim configuration;
292 configuration.setParameter("bool", false);
293 EXPECT_EQ(configuration.getParameter<bool>("bool"), false);
295 configuration.setParameter("size", (size_t)100);
296 EXPECT_EQ(configuration.getParameter<size_t>("size"), 100);
298 configuration.setParameter("ssize", (ssize_t)-100);
299 EXPECT_EQ(configuration.getParameter<ssize_t>("ssize"), -100);
301 configuration.setParameter("float", (float)123.5);
302 EXPECT_EQ(configuration.getParameter<float>("float"), 123.5);
304 configuration.setParameter("char*", "hello");
305 EXPECT_EQ(configuration.getParameter<std::string>("char*"), "hello");
307 configuration.setParameter("string", std::string("hello"));
308 EXPECT_EQ(configuration.getParameter<std::string>("string"), "hello");
311 TEST(ConfigurationTest, ValidatorWorks) {
312 ConfigurationShim configuration;
313 std::string key{"test_key"};
315 configuration.setParameter(key, (size_t)110);
316 EXPECT_NO_THROW(configuration.setValueValidator(key, (new SizeRangeValidator())->min(10)->max(100)));
317 EXPECT_NO_THROW(configuration.setParameter(key, (size_t)10));
318 EXPECT_NO_THROW(configuration.setParameter(key, (size_t)100));
319 EXPECT_THROW(configuration.setParameter(key, (size_t)9), std::range_error);
321 CB_EXPECT_THROW_MSG(configuration.setParameter(key, (size_t)9),
323 "Validation Error, test_key takes values between 10 "
327 class MockValueChangedListener : public ValueChangedListener {
329 MOCK_METHOD2(booleanValueChanged, void(const std::string&, bool));
330 MOCK_METHOD2(sizeValueChanged, void(const std::string&, size_t));
331 MOCK_METHOD2(ssizeValueChanged, void(const std::string&, ssize_t));
332 MOCK_METHOD2(floatValueChanged, void(const std::string&, float));
333 MOCK_METHOD2(stringValueChanged, void(const std::string&, const char*));
338 TEST(ChangeListenerTest, ChangeListenerSSizeRegression) {
340 * Confirming that setting a config parameter of type ssize_t
341 * correctly calls ssizeValueChanged on Changelisteners. Previously, it
342 * instead called sizeValueChanged - and some code had become dependent on
345 ConfigurationShim configuration;
346 std::string key{"test_key"};
349 auto mvcl = new MockValueChangedListener;
350 // set parameter once so entry in attributes is present to add a listener
351 configuration.setParameter(key, (ssize_t)1);
353 EXPECT_CALL(*mvcl, ssizeValueChanged("test_key", 2)).Times(1);
354 EXPECT_CALL(*mvcl, sizeValueChanged(_, _)).Times(0);
357 configuration.addValueChangedListener(key, mvcl);
360 configuration.setParameter(key, (ssize_t)2);