]>
Commit | Line | Data |
---|---|---|
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) 2011 New Dream Network | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
15 | #include "gtest/gtest.h" | |
16 | #include "common/ceph_argparse.h" | |
17 | #include "common/config.h" | |
18 | #include "global/global_context.h" | |
19 | #include "include/cephfs/libcephfs.h" | |
20 | #include "include/rados/librados.h" | |
21 | ||
22 | #include <errno.h> | |
23 | #include <sstream> | |
24 | #include <string> | |
25 | #include <string.h> | |
26 | ||
27 | #include <boost/lexical_cast.hpp> | |
28 | ||
29 | ||
30 | using std::string; | |
31 | ||
32 | TEST(DaemonConfig, SimpleSet) { | |
33 | int ret; | |
c07f9fc5 | 34 | ret = g_ceph_context->_conf->set_val("log_graylog_port", "21"); |
7c673cae FG |
35 | ASSERT_EQ(ret, 0); |
36 | g_ceph_context->_conf->apply_changes(NULL); | |
37 | char buf[128]; | |
38 | memset(buf, 0, sizeof(buf)); | |
39 | char *tmp = buf; | |
c07f9fc5 | 40 | ret = g_ceph_context->_conf->get_val("log_graylog_port", &tmp, sizeof(buf)); |
7c673cae FG |
41 | ASSERT_EQ(ret, 0); |
42 | ASSERT_EQ(string("21"), string(buf)); | |
43 | } | |
44 | ||
45 | TEST(DaemonConfig, Substitution) { | |
46 | int ret; | |
47 | ret = g_ceph_context->_conf->set_val("internal_safe_to_start_threads", "false"); | |
48 | ASSERT_EQ(ret, 0); | |
49 | ret = g_ceph_context->_conf->set_val("host", "foo"); | |
50 | ASSERT_EQ(ret, 0); | |
51 | ret = g_ceph_context->_conf->set_val("public_network", "bar$host.baz", false); | |
52 | ASSERT_EQ(ret, 0); | |
53 | g_ceph_context->_conf->apply_changes(NULL); | |
54 | char buf[128]; | |
55 | memset(buf, 0, sizeof(buf)); | |
56 | char *tmp = buf; | |
57 | ret = g_ceph_context->_conf->get_val("public_network", &tmp, sizeof(buf)); | |
58 | ASSERT_EQ(ret, 0); | |
59 | ASSERT_EQ(string("barfoo.baz"), string(buf)); | |
60 | } | |
61 | ||
62 | TEST(DaemonConfig, SubstitutionTrailing) { | |
63 | int ret; | |
64 | ret = g_ceph_context->_conf->set_val("internal_safe_to_start_threads", "false"); | |
65 | ASSERT_EQ(ret, 0); | |
66 | ret = g_ceph_context->_conf->set_val("host", "foo"); | |
67 | ASSERT_EQ(ret, 0); | |
68 | ret = g_ceph_context->_conf->set_val("public_network", "bar$host", false); | |
69 | ASSERT_EQ(ret, 0); | |
70 | g_ceph_context->_conf->apply_changes(NULL); | |
71 | char buf[128]; | |
72 | memset(buf, 0, sizeof(buf)); | |
73 | char *tmp = buf; | |
74 | ret = g_ceph_context->_conf->get_val("public_network", &tmp, sizeof(buf)); | |
75 | ASSERT_EQ(ret, 0); | |
76 | ASSERT_EQ(string("barfoo"), string(buf)); | |
77 | } | |
78 | ||
79 | TEST(DaemonConfig, SubstitutionBraces) { | |
80 | int ret; | |
81 | ret = g_ceph_context->_conf->set_val("internal_safe_to_start_threads", "false"); | |
82 | ASSERT_EQ(ret, 0); | |
83 | ret = g_ceph_context->_conf->set_val("host", "foo"); | |
84 | ASSERT_EQ(ret, 0); | |
85 | ret = g_ceph_context->_conf->set_val("public_network", "bar${host}baz", false); | |
86 | ASSERT_EQ(ret, 0); | |
87 | g_ceph_context->_conf->apply_changes(NULL); | |
88 | char buf[128]; | |
89 | memset(buf, 0, sizeof(buf)); | |
90 | char *tmp = buf; | |
91 | ret = g_ceph_context->_conf->get_val("public_network", &tmp, sizeof(buf)); | |
92 | ASSERT_EQ(ret, 0); | |
93 | ASSERT_EQ(string("barfoobaz"), string(buf)); | |
94 | } | |
95 | TEST(DaemonConfig, SubstitutionBracesTrailing) { | |
96 | int ret; | |
97 | ret = g_ceph_context->_conf->set_val("internal_safe_to_start_threads", "false"); | |
98 | ASSERT_EQ(ret, 0); | |
99 | ret = g_ceph_context->_conf->set_val("host", "foo"); | |
100 | ASSERT_EQ(ret, 0); | |
101 | ret = g_ceph_context->_conf->set_val("public_network", "bar${host}", false); | |
102 | ASSERT_EQ(ret, 0); | |
103 | g_ceph_context->_conf->apply_changes(NULL); | |
104 | char buf[128]; | |
105 | memset(buf, 0, sizeof(buf)); | |
106 | char *tmp = buf; | |
107 | ret = g_ceph_context->_conf->get_val("public_network", &tmp, sizeof(buf)); | |
108 | ASSERT_EQ(ret, 0); | |
109 | ASSERT_EQ(string("barfoo"), string(buf)); | |
110 | } | |
111 | ||
112 | // config: variable substitution happen only once http://tracker.ceph.com/issues/7103 | |
113 | TEST(DaemonConfig, SubstitutionMultiple) { | |
114 | int ret; | |
115 | ret = g_ceph_context->_conf->set_val("mon_host", "localhost", false); | |
116 | ASSERT_EQ(ret, 0); | |
117 | ret = g_ceph_context->_conf->set_val("keyring", "$mon_host/$cluster.keyring,$mon_host/$cluster.mon.keyring", false); | |
118 | ASSERT_EQ(ret, 0); | |
119 | g_ceph_context->_conf->apply_changes(NULL); | |
120 | char buf[512]; | |
121 | memset(buf, 0, sizeof(buf)); | |
122 | char *tmp = buf; | |
123 | ret = g_ceph_context->_conf->get_val("keyring", &tmp, sizeof(buf)); | |
124 | ASSERT_EQ(ret, 0); | |
125 | ASSERT_EQ(string("localhost/ceph.keyring,localhost/ceph.mon.keyring"), tmp); | |
126 | ASSERT_TRUE(strchr(buf, '$') == NULL); | |
127 | } | |
128 | ||
129 | TEST(DaemonConfig, ArgV) { | |
130 | ASSERT_EQ(0, g_ceph_context->_conf->set_val("internal_safe_to_start_threads", | |
131 | "false")); | |
132 | ||
133 | int ret; | |
c07f9fc5 | 134 | const char *argv[] = { "foo", "--log-graylog-port", "22", |
7c673cae FG |
135 | "--keyfile", "/tmp/my-keyfile", NULL }; |
136 | size_t argc = (sizeof(argv) / sizeof(argv[0])) - 1; | |
137 | vector<const char*> args; | |
138 | argv_to_vec(argc, argv, args); | |
139 | g_ceph_context->_conf->parse_argv(args); | |
140 | g_ceph_context->_conf->apply_changes(NULL); | |
141 | ||
142 | char buf[128]; | |
143 | char *tmp = buf; | |
144 | memset(buf, 0, sizeof(buf)); | |
145 | ret = g_ceph_context->_conf->get_val("keyfile", &tmp, sizeof(buf)); | |
146 | ASSERT_EQ(ret, 0); | |
147 | ASSERT_EQ(string("/tmp/my-keyfile"), string(buf)); | |
148 | ||
149 | memset(buf, 0, sizeof(buf)); | |
c07f9fc5 | 150 | ret = g_ceph_context->_conf->get_val("log_graylog_port", &tmp, sizeof(buf)); |
7c673cae FG |
151 | ASSERT_EQ(ret, 0); |
152 | ASSERT_EQ(string("22"), string(buf)); | |
153 | ||
154 | ASSERT_EQ(0, g_ceph_context->_conf->set_val("internal_safe_to_start_threads", | |
155 | "true")); | |
156 | } | |
157 | ||
158 | TEST(DaemonConfig, InjectArgs) { | |
159 | int ret; | |
c07f9fc5 | 160 | std::string injection("--log-graylog-port 56 --leveldb-max-open-files 42"); |
7c673cae FG |
161 | ret = g_ceph_context->_conf->injectargs(injection, &cout); |
162 | ASSERT_EQ(ret, 0); | |
163 | ||
164 | char buf[128]; | |
165 | char *tmp = buf; | |
166 | memset(buf, 0, sizeof(buf)); | |
c07f9fc5 | 167 | ret = g_ceph_context->_conf->get_val("leveldb_max_open_files", &tmp, sizeof(buf)); |
7c673cae FG |
168 | ASSERT_EQ(ret, 0); |
169 | ASSERT_EQ(string("42"), string(buf)); | |
170 | ||
171 | memset(buf, 0, sizeof(buf)); | |
c07f9fc5 | 172 | ret = g_ceph_context->_conf->get_val("log_graylog_port", &tmp, sizeof(buf)); |
7c673cae FG |
173 | ASSERT_EQ(ret, 0); |
174 | ASSERT_EQ(string("56"), string(buf)); | |
175 | ||
c07f9fc5 | 176 | injection = "--log-graylog-port 57"; |
7c673cae FG |
177 | ret = g_ceph_context->_conf->injectargs(injection, &cout); |
178 | ASSERT_EQ(ret, 0); | |
c07f9fc5 | 179 | ret = g_ceph_context->_conf->get_val("log_graylog_port", &tmp, sizeof(buf)); |
7c673cae FG |
180 | ASSERT_EQ(ret, 0); |
181 | ASSERT_EQ(string("57"), string(buf)); | |
182 | } | |
183 | ||
184 | TEST(DaemonConfig, InjectArgsReject) { | |
185 | int ret; | |
186 | char buf[128]; | |
187 | char *tmp = buf; | |
188 | char buf2[128]; | |
189 | char *tmp2 = buf2; | |
190 | ||
191 | // We should complain about the garbage in the input | |
c07f9fc5 | 192 | std::string injection("--random-garbage-in-injectargs 26 --log-graylog-port 28"); |
7c673cae FG |
193 | ret = g_ceph_context->_conf->injectargs(injection, &cout); |
194 | ASSERT_EQ(ret, -EINVAL); | |
195 | ||
196 | // But, debug should still be set... | |
197 | memset(buf, 0, sizeof(buf)); | |
c07f9fc5 | 198 | ret = g_ceph_context->_conf->get_val("log_graylog_port", &tmp, sizeof(buf)); |
7c673cae FG |
199 | ASSERT_EQ(ret, 0); |
200 | ASSERT_EQ(string("28"), string(buf)); | |
201 | ||
202 | // What's the current value of osd_data? | |
203 | memset(buf, 0, sizeof(buf)); | |
204 | ret = g_ceph_context->_conf->get_val("osd_data", &tmp, sizeof(buf)); | |
205 | ASSERT_EQ(ret, 0); | |
206 | ||
207 | // Injectargs shouldn't let us change this, since it is a string-valued | |
208 | // variable and there isn't an observer for it. | |
c07f9fc5 | 209 | std::string injection2("--osd_data /tmp/some-other-directory --log-graylog-port 4"); |
7c673cae FG |
210 | ret = g_ceph_context->_conf->injectargs(injection2, &cout); |
211 | ASSERT_EQ(ret, -ENOSYS); | |
212 | ||
213 | // It should be unchanged. | |
214 | memset(buf2, 0, sizeof(buf2)); | |
215 | ret = g_ceph_context->_conf->get_val("osd_data", &tmp2, sizeof(buf2)); | |
216 | ASSERT_EQ(ret, 0); | |
217 | ASSERT_EQ(string(buf), string(buf2)); | |
218 | } | |
219 | ||
220 | TEST(DaemonConfig, InjectArgsBooleans) { | |
221 | int ret; | |
222 | char buf[128]; | |
223 | char *tmp = buf; | |
224 | ||
225 | // Change log_to_syslog | |
c07f9fc5 | 226 | std::string injection("--log_to_syslog --log-graylog-port 28"); |
7c673cae FG |
227 | ret = g_ceph_context->_conf->injectargs(injection, &cout); |
228 | ASSERT_EQ(ret, 0); | |
229 | ||
230 | // log_to_syslog should be set... | |
231 | memset(buf, 0, sizeof(buf)); | |
232 | ret = g_ceph_context->_conf->get_val("log_to_syslog", &tmp, sizeof(buf)); | |
233 | ASSERT_EQ(ret, 0); | |
234 | ASSERT_EQ(string("true"), string(buf)); | |
235 | ||
236 | // Turn off log_to_syslog | |
c07f9fc5 | 237 | injection = "--log_to_syslog=false --log-graylog-port 28"; |
7c673cae FG |
238 | ret = g_ceph_context->_conf->injectargs(injection, &cout); |
239 | ASSERT_EQ(ret, 0); | |
240 | ||
241 | // log_to_syslog should be cleared... | |
242 | memset(buf, 0, sizeof(buf)); | |
243 | ret = g_ceph_context->_conf->get_val("log_to_syslog", &tmp, sizeof(buf)); | |
244 | ASSERT_EQ(ret, 0); | |
245 | ASSERT_EQ(string("false"), string(buf)); | |
246 | ||
247 | // Turn on log_to_syslog | |
c07f9fc5 | 248 | injection = "--log-graylog-port=1 --log_to_syslog=true --leveldb-max-open-files 40"; |
7c673cae FG |
249 | ret = g_ceph_context->_conf->injectargs(injection, &cout); |
250 | ASSERT_EQ(ret, 0); | |
251 | ||
252 | // log_to_syslog should be set... | |
253 | memset(buf, 0, sizeof(buf)); | |
254 | ret = g_ceph_context->_conf->get_val("log_to_syslog", &tmp, sizeof(buf)); | |
255 | ASSERT_EQ(ret, 0); | |
256 | ASSERT_EQ(string("true"), string(buf)); | |
257 | ||
258 | // parse error | |
c07f9fc5 | 259 | injection = "--log-graylog-port 1 --log_to_syslog=falsey --leveldb-max-open-files 42"; |
7c673cae FG |
260 | ret = g_ceph_context->_conf->injectargs(injection, &cout); |
261 | ASSERT_EQ(ret, -EINVAL); | |
262 | ||
263 | // log_to_syslog should still be set... | |
264 | memset(buf, 0, sizeof(buf)); | |
265 | ret = g_ceph_context->_conf->get_val("log_to_syslog", &tmp, sizeof(buf)); | |
266 | ASSERT_EQ(ret, 0); | |
267 | ASSERT_EQ(string("true"), string(buf)); | |
268 | ||
269 | // debug-ms should still become 42... | |
270 | memset(buf, 0, sizeof(buf)); | |
c07f9fc5 | 271 | ret = g_ceph_context->_conf->get_val("leveldb_max_open_files", &tmp, sizeof(buf)); |
7c673cae FG |
272 | ASSERT_EQ(ret, 0); |
273 | ASSERT_EQ(string("42"), string(buf)); | |
274 | } | |
275 | ||
276 | TEST(DaemonConfig, InjectArgsLogfile) { | |
277 | int ret; | |
278 | char tmpfile[PATH_MAX]; | |
279 | const char *tmpdir = getenv("TMPDIR"); | |
280 | if (!tmpdir) | |
281 | tmpdir = "/tmp"; | |
282 | snprintf(tmpfile, sizeof(tmpfile), "%s/daemon_config_test.%d", | |
283 | tmpdir, getpid()); | |
284 | std::string injection("--log_file "); | |
285 | injection += tmpfile; | |
286 | // We're allowed to change log_file because there is an observer. | |
287 | ret = g_ceph_context->_conf->injectargs(injection, &cout); | |
288 | ASSERT_EQ(ret, 0); | |
289 | ||
290 | // It should have taken effect. | |
291 | char buf[128]; | |
292 | char *tmp = buf; | |
293 | memset(buf, 0, sizeof(buf)); | |
294 | ret = g_ceph_context->_conf->get_val("log_file", &tmp, sizeof(buf)); | |
295 | ASSERT_EQ(ret, 0); | |
296 | ASSERT_EQ(string(buf), string(tmpfile)); | |
297 | ||
298 | // The logfile should exist. | |
299 | ASSERT_EQ(access(tmpfile, R_OK), 0); | |
300 | ||
301 | // Let's turn off the logfile. | |
302 | ret = g_ceph_context->_conf->set_val("log_file", ""); | |
303 | ASSERT_EQ(ret, 0); | |
304 | g_ceph_context->_conf->apply_changes(NULL); | |
305 | ret = g_ceph_context->_conf->get_val("log_file", &tmp, sizeof(buf)); | |
306 | ASSERT_EQ(ret, 0); | |
307 | ASSERT_EQ(string(""), string(buf)); | |
308 | ||
309 | // Clean up the garbage | |
310 | unlink(tmpfile); | |
311 | } | |
312 | ||
313 | TEST(DaemonConfig, ThreadSafety1) { | |
314 | int ret; | |
315 | // Verify that we can't change this, since internal_safe_to_start_threads has | |
316 | // been set. | |
317 | ret = g_ceph_context->_conf->set_val("osd_data", ""); | |
318 | ASSERT_EQ(ret, -ENOSYS); | |
319 | ||
320 | ASSERT_EQ(0, g_ceph_context->_conf->set_val("internal_safe_to_start_threads", | |
321 | "false")); | |
322 | ||
323 | // Ok, now we can change this. Since this is just a test, and there are no | |
324 | // OSD threads running, we know changing osd_data won't actually blow up the | |
325 | // world. | |
326 | ret = g_ceph_context->_conf->set_val("osd_data", "/tmp/crazydata"); | |
327 | ASSERT_EQ(ret, 0); | |
328 | ||
329 | char buf[128]; | |
330 | char *tmp = buf; | |
331 | memset(buf, 0, sizeof(buf)); | |
332 | ret = g_ceph_context->_conf->get_val("osd_data", &tmp, sizeof(buf)); | |
333 | ASSERT_EQ(ret, 0); | |
334 | ASSERT_EQ(string("/tmp/crazydata"), string(buf)); | |
335 | ||
336 | ASSERT_EQ(0, g_ceph_context->_conf->set_val("internal_safe_to_start_threads", | |
337 | "false")); | |
338 | ASSERT_EQ(ret, 0); | |
339 | } | |
340 | ||
341 | TEST(DaemonConfig, InvalidIntegers) { | |
342 | { | |
c07f9fc5 | 343 | int ret = g_ceph_context->_conf->set_val("log_graylog_port", "rhubarb"); |
7c673cae FG |
344 | ASSERT_EQ(ret, -EINVAL); |
345 | } | |
c07f9fc5 | 346 | |
7c673cae | 347 | { |
c07f9fc5 FG |
348 | int64_t max = std::numeric_limits<int64_t>::max(); |
349 | string str = boost::lexical_cast<string>(max); | |
350 | str = str + "999"; // some extra digits to take us out of bounds | |
351 | int ret = g_ceph_context->_conf->set_val("log_graylog_port", str); | |
7c673cae FG |
352 | ASSERT_EQ(ret, -EINVAL); |
353 | } | |
354 | } | |
355 | ||
356 | TEST(DaemonConfig, InvalidFloats) { | |
357 | { | |
358 | double bad_value = 2 * (double)std::numeric_limits<float>::max(); | |
359 | string str = boost::lexical_cast<string>(-bad_value); | |
360 | int ret = g_ceph_context->_conf->set_val("log_stop_at_utilization", str); | |
361 | ASSERT_EQ(ret, -EINVAL); | |
362 | } | |
363 | { | |
364 | double bad_value = 2 * (double)std::numeric_limits<float>::max(); | |
365 | string str = boost::lexical_cast<string>(bad_value); | |
366 | int ret = g_ceph_context->_conf->set_val("log_stop_at_utilization", str); | |
367 | ASSERT_EQ(ret, -EINVAL); | |
368 | } | |
369 | { | |
370 | int ret = g_ceph_context->_conf->set_val("log_stop_at_utilization", "not a float"); | |
371 | ASSERT_EQ(ret, -EINVAL); | |
372 | } | |
373 | } | |
374 | ||
375 | /* | |
376 | * Local Variables: | |
377 | * compile-command: "cd .. ; make unittest_daemon_config && ./unittest_daemon_config" | |
378 | * End: | |
379 | */ |