1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2011 New Dream Network
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.
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"
27 #include <boost/lexical_cast.hpp>
32 TEST(DaemonConfig
, SimpleSet
) {
34 ret
= g_ceph_context
->_conf
->set_val("log_graylog_port", "21");
36 g_ceph_context
->_conf
->apply_changes(NULL
);
38 memset(buf
, 0, sizeof(buf
));
40 ret
= g_ceph_context
->_conf
->get_val("log_graylog_port", &tmp
, sizeof(buf
));
42 ASSERT_EQ(string("21"), string(buf
));
45 TEST(DaemonConfig
, Substitution
) {
47 ret
= g_ceph_context
->_conf
->set_val("internal_safe_to_start_threads", "false");
49 ret
= g_ceph_context
->_conf
->set_val("host", "foo");
51 ret
= g_ceph_context
->_conf
->set_val("public_network", "bar$host.baz", false);
53 g_ceph_context
->_conf
->apply_changes(NULL
);
55 memset(buf
, 0, sizeof(buf
));
57 ret
= g_ceph_context
->_conf
->get_val("public_network", &tmp
, sizeof(buf
));
59 ASSERT_EQ(string("barfoo.baz"), string(buf
));
62 TEST(DaemonConfig
, SubstitutionTrailing
) {
64 ret
= g_ceph_context
->_conf
->set_val("internal_safe_to_start_threads", "false");
66 ret
= g_ceph_context
->_conf
->set_val("host", "foo");
68 ret
= g_ceph_context
->_conf
->set_val("public_network", "bar$host", false);
70 g_ceph_context
->_conf
->apply_changes(NULL
);
72 memset(buf
, 0, sizeof(buf
));
74 ret
= g_ceph_context
->_conf
->get_val("public_network", &tmp
, sizeof(buf
));
76 ASSERT_EQ(string("barfoo"), string(buf
));
79 TEST(DaemonConfig
, SubstitutionBraces
) {
81 ret
= g_ceph_context
->_conf
->set_val("internal_safe_to_start_threads", "false");
83 ret
= g_ceph_context
->_conf
->set_val("host", "foo");
85 ret
= g_ceph_context
->_conf
->set_val("public_network", "bar${host}baz", false);
87 g_ceph_context
->_conf
->apply_changes(NULL
);
89 memset(buf
, 0, sizeof(buf
));
91 ret
= g_ceph_context
->_conf
->get_val("public_network", &tmp
, sizeof(buf
));
93 ASSERT_EQ(string("barfoobaz"), string(buf
));
95 TEST(DaemonConfig
, SubstitutionBracesTrailing
) {
97 ret
= g_ceph_context
->_conf
->set_val("internal_safe_to_start_threads", "false");
99 ret
= g_ceph_context
->_conf
->set_val("host", "foo");
101 ret
= g_ceph_context
->_conf
->set_val("public_network", "bar${host}", false);
103 g_ceph_context
->_conf
->apply_changes(NULL
);
105 memset(buf
, 0, sizeof(buf
));
107 ret
= g_ceph_context
->_conf
->get_val("public_network", &tmp
, sizeof(buf
));
109 ASSERT_EQ(string("barfoo"), string(buf
));
112 // config: variable substitution happen only once http://tracker.ceph.com/issues/7103
113 TEST(DaemonConfig
, SubstitutionMultiple
) {
115 ret
= g_ceph_context
->_conf
->set_val("mon_host", "localhost", false);
117 ret
= g_ceph_context
->_conf
->set_val("keyring", "$mon_host/$cluster.keyring,$mon_host/$cluster.mon.keyring", false);
119 g_ceph_context
->_conf
->apply_changes(NULL
);
121 memset(buf
, 0, sizeof(buf
));
123 ret
= g_ceph_context
->_conf
->get_val("keyring", &tmp
, sizeof(buf
));
125 ASSERT_EQ(string("localhost/ceph.keyring,localhost/ceph.mon.keyring"), tmp
);
126 ASSERT_TRUE(strchr(buf
, '$') == NULL
);
129 TEST(DaemonConfig
, ArgV
) {
130 ASSERT_EQ(0, g_ceph_context
->_conf
->set_val("internal_safe_to_start_threads",
134 const char *argv
[] = { "foo", "--log-graylog-port", "22",
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
);
144 memset(buf
, 0, sizeof(buf
));
145 ret
= g_ceph_context
->_conf
->get_val("keyfile", &tmp
, sizeof(buf
));
147 ASSERT_EQ(string("/tmp/my-keyfile"), string(buf
));
149 memset(buf
, 0, sizeof(buf
));
150 ret
= g_ceph_context
->_conf
->get_val("log_graylog_port", &tmp
, sizeof(buf
));
152 ASSERT_EQ(string("22"), string(buf
));
154 ASSERT_EQ(0, g_ceph_context
->_conf
->set_val("internal_safe_to_start_threads",
158 TEST(DaemonConfig
, InjectArgs
) {
160 std::string
injection("--log-graylog-port 56 --leveldb-max-open-files 42");
161 ret
= g_ceph_context
->_conf
->injectargs(injection
, &cout
);
166 memset(buf
, 0, sizeof(buf
));
167 ret
= g_ceph_context
->_conf
->get_val("leveldb_max_open_files", &tmp
, sizeof(buf
));
169 ASSERT_EQ(string("42"), string(buf
));
171 memset(buf
, 0, sizeof(buf
));
172 ret
= g_ceph_context
->_conf
->get_val("log_graylog_port", &tmp
, sizeof(buf
));
174 ASSERT_EQ(string("56"), string(buf
));
176 injection
= "--log-graylog-port 57";
177 ret
= g_ceph_context
->_conf
->injectargs(injection
, &cout
);
179 ret
= g_ceph_context
->_conf
->get_val("log_graylog_port", &tmp
, sizeof(buf
));
181 ASSERT_EQ(string("57"), string(buf
));
184 TEST(DaemonConfig
, InjectArgsReject
) {
191 // We should complain about the garbage in the input
192 std::string
injection("--random-garbage-in-injectargs 26 --log-graylog-port 28");
193 ret
= g_ceph_context
->_conf
->injectargs(injection
, &cout
);
194 ASSERT_EQ(-EINVAL
, ret
);
196 // But, debug should still be set...
197 memset(buf
, 0, sizeof(buf
));
198 ret
= g_ceph_context
->_conf
->get_val("log_graylog_port", &tmp
, sizeof(buf
));
200 ASSERT_EQ(string("28"), string(buf
));
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
));
207 // Injectargs shouldn't let us change this, since it is a string-valued
208 // variable and there isn't an observer for it.
209 std::string
injection2("--osd_data /tmp/some-other-directory --log-graylog-port 4");
210 ret
= g_ceph_context
->_conf
->injectargs(injection2
, &cout
);
211 ASSERT_EQ(-ENOSYS
, ret
);
213 // It should be unchanged.
214 memset(buf2
, 0, sizeof(buf2
));
215 ret
= g_ceph_context
->_conf
->get_val("osd_data", &tmp2
, sizeof(buf2
));
217 ASSERT_EQ(string(buf
), string(buf2
));
219 // We should complain about the missing arguments.
220 std::string
injection3("--log-graylog-port 28 --debug_ms");
221 ret
= g_ceph_context
->_conf
->injectargs(injection3
, &cout
);
222 ASSERT_EQ(-EINVAL
, ret
);
225 TEST(DaemonConfig
, InjectArgsBooleans
) {
230 // Change log_to_syslog
231 std::string
injection("--log_to_syslog --log-graylog-port 28");
232 ret
= g_ceph_context
->_conf
->injectargs(injection
, &cout
);
235 // log_to_syslog should be set...
236 memset(buf
, 0, sizeof(buf
));
237 ret
= g_ceph_context
->_conf
->get_val("log_to_syslog", &tmp
, sizeof(buf
));
239 ASSERT_EQ(string("true"), string(buf
));
241 // Turn off log_to_syslog
242 injection
= "--log_to_syslog=false --log-graylog-port 28";
243 ret
= g_ceph_context
->_conf
->injectargs(injection
, &cout
);
246 // log_to_syslog should be cleared...
247 memset(buf
, 0, sizeof(buf
));
248 ret
= g_ceph_context
->_conf
->get_val("log_to_syslog", &tmp
, sizeof(buf
));
250 ASSERT_EQ(string("false"), string(buf
));
252 // Turn on log_to_syslog
253 injection
= "--log-graylog-port=1 --log_to_syslog=true --leveldb-max-open-files 40";
254 ret
= g_ceph_context
->_conf
->injectargs(injection
, &cout
);
257 // log_to_syslog should be set...
258 memset(buf
, 0, sizeof(buf
));
259 ret
= g_ceph_context
->_conf
->get_val("log_to_syslog", &tmp
, sizeof(buf
));
261 ASSERT_EQ(string("true"), string(buf
));
264 injection
= "--log-graylog-port 1 --log_to_syslog=falsey --leveldb-max-open-files 42";
265 ret
= g_ceph_context
->_conf
->injectargs(injection
, &cout
);
266 ASSERT_EQ(-EINVAL
, ret
);
268 // log_to_syslog should still be set...
269 memset(buf
, 0, sizeof(buf
));
270 ret
= g_ceph_context
->_conf
->get_val("log_to_syslog", &tmp
, sizeof(buf
));
272 ASSERT_EQ(string("true"), string(buf
));
274 // debug-ms should still become 42...
275 memset(buf
, 0, sizeof(buf
));
276 ret
= g_ceph_context
->_conf
->get_val("leveldb_max_open_files", &tmp
, sizeof(buf
));
278 ASSERT_EQ(string("42"), string(buf
));
281 TEST(DaemonConfig
, InjectArgsLogfile
) {
283 char tmpfile
[PATH_MAX
];
284 const char *tmpdir
= getenv("TMPDIR");
287 snprintf(tmpfile
, sizeof(tmpfile
), "%s/daemon_config_test.%d",
289 std::string
injection("--log_file ");
290 injection
+= tmpfile
;
291 // We're allowed to change log_file because there is an observer.
292 ret
= g_ceph_context
->_conf
->injectargs(injection
, &cout
);
295 // It should have taken effect.
298 memset(buf
, 0, sizeof(buf
));
299 ret
= g_ceph_context
->_conf
->get_val("log_file", &tmp
, sizeof(buf
));
301 ASSERT_EQ(string(buf
), string(tmpfile
));
303 // The logfile should exist.
304 ASSERT_EQ(0, access(tmpfile
, R_OK
));
306 // Let's turn off the logfile.
307 ret
= g_ceph_context
->_conf
->set_val("log_file", "");
309 g_ceph_context
->_conf
->apply_changes(NULL
);
310 ret
= g_ceph_context
->_conf
->get_val("log_file", &tmp
, sizeof(buf
));
312 ASSERT_EQ(string(""), string(buf
));
314 // Clean up the garbage
318 TEST(DaemonConfig
, ThreadSafety1
) {
320 // Verify that we can't change this, since internal_safe_to_start_threads has
322 ret
= g_ceph_context
->_conf
->set_val("osd_data", "");
323 ASSERT_EQ(-ENOSYS
, ret
);
325 ASSERT_EQ(0, g_ceph_context
->_conf
->set_val("internal_safe_to_start_threads",
328 // Ok, now we can change this. Since this is just a test, and there are no
329 // OSD threads running, we know changing osd_data won't actually blow up the
331 ret
= g_ceph_context
->_conf
->set_val("osd_data", "/tmp/crazydata");
336 memset(buf
, 0, sizeof(buf
));
337 ret
= g_ceph_context
->_conf
->get_val("osd_data", &tmp
, sizeof(buf
));
339 ASSERT_EQ(string("/tmp/crazydata"), string(buf
));
341 ASSERT_EQ(0, g_ceph_context
->_conf
->set_val("internal_safe_to_start_threads",
346 TEST(DaemonConfig
, InvalidIntegers
) {
348 int ret
= g_ceph_context
->_conf
->set_val("log_graylog_port", "rhubarb");
349 ASSERT_EQ(-EINVAL
, ret
);
353 int64_t max
= std::numeric_limits
<int64_t>::max();
354 string str
= boost::lexical_cast
<string
>(max
);
355 str
= str
+ "999"; // some extra digits to take us out of bounds
356 int ret
= g_ceph_context
->_conf
->set_val("log_graylog_port", str
);
357 ASSERT_EQ(-EINVAL
, ret
);
361 TEST(DaemonConfig
, InvalidFloats
) {
363 double bad_value
= 2 * (double)std::numeric_limits
<float>::max();
364 string str
= boost::lexical_cast
<string
>(-bad_value
);
365 int ret
= g_ceph_context
->_conf
->set_val("log_stop_at_utilization", str
);
366 ASSERT_EQ(-EINVAL
, ret
);
369 double bad_value
= 2 * (double)std::numeric_limits
<float>::max();
370 string str
= boost::lexical_cast
<string
>(bad_value
);
371 int ret
= g_ceph_context
->_conf
->set_val("log_stop_at_utilization", str
);
372 ASSERT_EQ(-EINVAL
, ret
);
375 int ret
= g_ceph_context
->_conf
->set_val("log_stop_at_utilization", "not a float");
376 ASSERT_EQ(-EINVAL
, ret
);
382 * compile-command: "cd .. ; make unittest_daemon_config && ./unittest_daemon_config"