]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/common/test_config.cc
update sources to v12.1.2
[ceph.git] / ceph / src / test / common / test_config.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2014 Cloudwatt <libre.licensing@cloudwatt.com>
7 *
8 * Author: Loic Dachary <loic@dachary.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Library Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * This program 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
18 * GNU Library Public License for more details.
19 *
20 *
21 */
22#include "common/config.h"
23#include "common/errno.h"
24#include "gtest/gtest.h"
25
26extern std::string exec(const char* cmd); // defined in test_hostname.cc
27
28class test_md_config_t : public md_config_t, public ::testing::Test {
29public:
c07f9fc5
FG
30
31 test_md_config_t()
32 : md_config_t(true), Test()
33 {}
34
7c673cae
FG
35 void test_expand_meta() {
36 Mutex::Locker l(lock);
37 // successfull meta expansion $run_dir and ${run_dir}
38 {
39 ostringstream oss;
40 std::string before = " BEFORE ";
41 std::string after = " AFTER ";
c07f9fc5 42
7c673cae
FG
43 std::string val(before + "$run_dir${run_dir}" + after);
44 EXPECT_TRUE(expand_meta(val, &oss));
45 EXPECT_EQ(before + "/var/run/ceph/var/run/ceph" + after, val);
46 EXPECT_EQ("", oss.str());
47 }
48 {
49 ostringstream oss;
50 std::string before = " BEFORE ";
51 std::string after = " AFTER ";
52 std::string val(before + "$host${host}" + after);
53 EXPECT_TRUE(expand_meta(val, &oss));
54 std::string hostname = exec("hostname -s");
55 EXPECT_EQ(before + hostname + hostname + after, val);
56 EXPECT_EQ("", oss.str());
57 }
58 // no meta expansion if variables are unknown
59 {
60 ostringstream oss;
61 std::string expected = "expect $foo and ${bar} to not expand";
62 std::string val = expected;
63 EXPECT_FALSE(expand_meta(val, &oss));
64 EXPECT_EQ(expected, val);
65 EXPECT_EQ("", oss.str());
66 }
67 // recursive variable expansion
68 {
69 std::string host = "localhost";
70 EXPECT_EQ(0, set_val("host", host.c_str(), false));
71
72 std::string mon_host = "$cluster_network";
73 EXPECT_EQ(0, set_val("mon_host", mon_host.c_str(), false));
74
75 std::string lockdep = "true";
76 EXPECT_EQ(0, set_val("lockdep", lockdep.c_str(), false));
77
78 std::string cluster_network = "$public_network $public_network $lockdep $host";
79 EXPECT_EQ(0, set_val("cluster_network", cluster_network.c_str(), false));
80
81 std::string public_network = "NETWORK";
82 EXPECT_EQ(0, set_val("public_network", public_network.c_str(), false));
83
84 ostringstream oss;
85 std::string val = "$mon_host";
86 EXPECT_TRUE(expand_meta(val, &oss));
87 EXPECT_EQ(public_network + " " +
88 public_network + " " +
89 lockdep + " " +
90 "localhost", val);
91 EXPECT_EQ("", oss.str());
92 }
93 // variable expansion loops are non fatal
94 {
95 std::string mon_host = "$cluster_network";
96 EXPECT_EQ(0, set_val("mon_host", mon_host.c_str(), false));
97
98 std::string cluster_network = "$public_network";
99 EXPECT_EQ(0, set_val("cluster_network", cluster_network.c_str(), false));
100
101 std::string public_network = "$mon_host";
102 EXPECT_EQ(0, set_val("public_network", public_network.c_str(), false));
103
104 ostringstream oss;
105 std::string val = "$mon_host";
106 EXPECT_TRUE(expand_meta(val, &oss));
107 EXPECT_EQ("$cluster_network", val);
108 const char *expected_oss =
109 "variable expansion loop at mon_host=$cluster_network\n"
110 "expansion stack: \n"
111 "public_network=$mon_host\n"
112 "cluster_network=$public_network\n"
113 "mon_host=$cluster_network\n";
114 EXPECT_EQ(expected_oss, oss.str());
115 }
116 }
117
118 void test_expand_all_meta() {
119 Mutex::Locker l(lock);
120 int before_count = 0, data_dir = 0;
c07f9fc5
FG
121 for (const auto &i : schema) {
122 const Option &opt = i.second;
123 if (opt.type == Option::TYPE_STR) {
124 const auto &str = boost::get<std::string>(opt.value);
125 if (str.find("$") != string::npos)
7c673cae 126 before_count++;
c07f9fc5 127 if (str.find("$data_dir") != string::npos)
7c673cae
FG
128 data_dir++;
129 }
130 }
c07f9fc5 131
7c673cae
FG
132 // if there are no meta variables in the default configuration,
133 // something must be done to check the expected side effect
134 // of expand_all_meta
135 ASSERT_LT(0, before_count);
136 expand_all_meta();
137 int after_count = 0;
c07f9fc5
FG
138 for (auto& i : values) {
139 const auto &opt = schema.at(i.first);
140 if (opt.type == Option::TYPE_STR) {
141 const std::string &str = boost::get<std::string>(i.second);
7c673cae 142 size_t pos = 0;
c07f9fc5
FG
143 while ((pos = str.find("$", pos)) != string::npos) {
144 if (str.substr(pos, 8) != "$channel") {
7c673cae 145 std::cout << "unexpected meta-variable found at pos " << pos
c07f9fc5 146 << " of '" << str << "'" << std::endl;
7c673cae
FG
147 after_count++;
148 }
149 pos++;
150 }
151 }
152 }
153 ASSERT_EQ(data_dir, after_count);
154 }
155};
156
157TEST_F(test_md_config_t, expand_meta)
158{
159 test_expand_meta();
160}
161
162TEST_F(test_md_config_t, expand_all_meta)
163{
164 test_expand_all_meta();
165}
166
167TEST(md_config_t, set_val)
168{
169 int buf_size = 1024;
170 md_config_t conf;
171 // disable meta variable expansion
172 {
173 char *buf = (char*)malloc(buf_size);
174 std::string expected = "$host";
175 EXPECT_EQ(0, conf.set_val("mon_host", expected.c_str(), false));
176 EXPECT_EQ(0, conf.get_val("mon_host", &buf, buf_size));
177 EXPECT_EQ(expected, buf);
178 free(buf);
179 }
180 // meta variable expansion is enabled by default
181 {
182 char *run_dir = (char*)malloc(buf_size);
183 EXPECT_EQ(0, conf.get_val("run_dir", &run_dir, buf_size));
184 EXPECT_EQ(0, conf.set_val("admin_socket", "$run_dir"));
185 char *admin_socket = (char*)malloc(buf_size);
186 EXPECT_EQ(0, conf.get_val("admin_socket", &admin_socket, buf_size));
187 EXPECT_EQ(std::string(run_dir), std::string(admin_socket));
188 free(run_dir);
189 free(admin_socket);
190 }
191}
192
c07f9fc5
FG
193TEST(Option, validation)
194{
195 Option opt_int("foo", Option::TYPE_INT, Option::LEVEL_BASIC);
196 opt_int.set_min_max(5, 10);
197
198 std::string msg;
199 EXPECT_EQ(-EINVAL, opt_int.validate(Option::value_t(int64_t(4)), &msg));
200 EXPECT_EQ(-EINVAL, opt_int.validate(Option::value_t(int64_t(11)), &msg));
201 EXPECT_EQ(0, opt_int.validate(Option::value_t(int64_t(7)), &msg));
202
203 Option opt_enum("foo", Option::TYPE_STR, Option::LEVEL_BASIC);
204 opt_enum.set_enum_allowed({"red", "blue"});
205 EXPECT_EQ(0, opt_enum.validate(Option::value_t(std::string("red")), &msg));
206 EXPECT_EQ(0, opt_enum.validate(Option::value_t(std::string("blue")), &msg));
207 EXPECT_EQ(-EINVAL, opt_enum.validate(Option::value_t(std::string("green")), &msg));
208
209 Option opt_validator("foo", Option::TYPE_INT, Option::LEVEL_BASIC);
210 opt_validator.set_validator([](std::string *value, std::string *error_message){
211 if (*value == std::string("one")) {
212 *value = "1";
213 return 0;
214 } else if (*value == std::string("666")) {
215 return -EINVAL;
216 } else {
217 return 0;
218 }
219 });
220
221 std::string input = "666"; // An explicitly forbidden value
222 EXPECT_EQ(-EINVAL, opt_validator.pre_validate(&input, &msg));
223 EXPECT_EQ(input, "666");
224
225 input = "123"; // A permitted value with no special behaviour
226 EXPECT_EQ(0, opt_validator.pre_validate(&input, &msg));
227 EXPECT_EQ(input, "123");
228
229 input = "one"; // A value that has a magic conversion
230 EXPECT_EQ(0, opt_validator.pre_validate(&input, &msg));
231 EXPECT_EQ(input, "1");
232}
233
7c673cae
FG
234/*
235 * Local Variables:
236 * compile-command: "cd ../.. ;
237 * make unittest_config &&
238 * valgrind \
239 * --max-stackframe=20000000 --tool=memcheck \
240 * ./unittest_config # --gtest_filter=md_config_t.set_val
241 * "
242 * End:
243 */