]>
git.proxmox.com Git - ceph.git/blob - ceph/src/test/admin_socket.cc
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 "common/Mutex.h"
16 #include "common/Cond.h"
17 #include "common/admin_socket.h"
18 #include "common/admin_socket_client.h"
19 #include "common/ceph_argparse.h"
20 #include "gtest/gtest.h"
30 explicit AdminSocketTest(AdminSocket
*asokc
)
34 bool init(const std::string
&uri
) {
35 return m_asokc
->init(uri
);
37 string
bind_and_listen(const std::string
&sock_path
, int *fd
) {
38 return m_asokc
->bind_and_listen(sock_path
, fd
);
47 TEST(AdminSocket
, Teardown
) {
48 std::unique_ptr
<AdminSocket
>
49 asokc(new AdminSocket(g_ceph_context
));
50 AdminSocketTest
asoct(asokc
.get());
51 ASSERT_EQ(true, asoct
.shutdown());
54 TEST(AdminSocket
, TeardownSetup
) {
55 std::unique_ptr
<AdminSocket
>
56 asokc(new AdminSocket(g_ceph_context
));
57 AdminSocketTest
asoct(asokc
.get());
58 ASSERT_EQ(true, asoct
.shutdown());
59 ASSERT_EQ(true, asoct
.init(get_rand_socket_path()));
60 ASSERT_EQ(true, asoct
.shutdown());
63 TEST(AdminSocket
, SendHelp
) {
64 std::unique_ptr
<AdminSocket
>
65 asokc(new AdminSocket(g_ceph_context
));
66 AdminSocketTest
asoct(asokc
.get());
67 ASSERT_EQ(true, asoct
.shutdown());
68 ASSERT_EQ(true, asoct
.init(get_rand_socket_path()));
69 AdminSocketClient
client(get_rand_socket_path());
73 ASSERT_EQ("", client
.do_request("{\"prefix\":\"help\"}", &help
));
74 ASSERT_NE(string::npos
, help
.find("\"list available commands\""));
78 ASSERT_EQ("", client
.do_request("{"
79 " \"prefix\":\"help\","
80 " \"format\":\"xml\","
82 ASSERT_NE(string::npos
, help
.find(">list available commands<"));
86 ASSERT_EQ("", client
.do_request("{"
87 " \"prefix\":\"help\","
88 " \"format\":\"UNSUPPORTED\","
90 ASSERT_NE(string::npos
, help
.find("\"list available commands\""));
92 ASSERT_EQ(true, asoct
.shutdown());
95 TEST(AdminSocket
, SendNoOp
) {
96 std::unique_ptr
<AdminSocket
>
97 asokc(new AdminSocket(g_ceph_context
));
98 AdminSocketTest
asoct(asokc
.get());
99 ASSERT_EQ(true, asoct
.shutdown());
100 ASSERT_EQ(true, asoct
.init(get_rand_socket_path()));
101 AdminSocketClient
client(get_rand_socket_path());
103 ASSERT_EQ("", client
.do_request("{\"prefix\":\"0\"}", &version
));
104 ASSERT_EQ(CEPH_ADMIN_SOCK_VERSION
, version
);
105 ASSERT_EQ(true, asoct
.shutdown());
108 TEST(AdminSocket
, SendTooLongRequest
) {
109 std::unique_ptr
<AdminSocket
>
110 asokc(new AdminSocket(g_ceph_context
));
111 AdminSocketTest
asoct(asokc
.get());
112 ASSERT_EQ(true, asoct
.shutdown());
113 ASSERT_EQ(true, asoct
.init(get_rand_socket_path()));
114 AdminSocketClient
client(get_rand_socket_path());
116 string
request(16384, 'a');
117 //if admin_socket cannot handle it, segfault will happened.
118 ASSERT_NE("", client
.do_request(request
, &version
));
119 ASSERT_EQ(true, asoct
.shutdown());
122 class MyTest
: public AdminSocketHook
{
123 bool call(std::string command
, cmdmap_t
& cmdmap
, std::string format
, bufferlist
& result
) override
{
124 std::vector
<std::string
> args
;
125 cmd_getval(g_ceph_context
, cmdmap
, "args", args
);
126 result
.append(command
);
129 for (std::vector
<std::string
>::iterator it
= args
.begin();
130 it
!= args
.end(); ++it
) {
131 if (it
!= args
.begin())
135 result
.append(resultstr
);
140 TEST(AdminSocket
, RegisterCommand
) {
141 std::unique_ptr
<AdminSocket
>
142 asokc(new AdminSocket(g_ceph_context
));
143 AdminSocketTest
asoct(asokc
.get());
144 ASSERT_EQ(true, asoct
.shutdown());
145 ASSERT_EQ(true, asoct
.init(get_rand_socket_path()));
146 AdminSocketClient
client(get_rand_socket_path());
147 ASSERT_EQ(0, asoct
.m_asokc
->register_command("test", "test", new MyTest(), ""));
149 ASSERT_EQ("", client
.do_request("{\"prefix\":\"test\"}", &result
));
150 ASSERT_EQ("test|", result
);
151 ASSERT_EQ(true, asoct
.shutdown());
154 class MyTest2
: public AdminSocketHook
{
155 bool call(std::string command
, cmdmap_t
& cmdmap
, std::string format
, bufferlist
& result
) override
{
156 std::vector
<std::string
> args
;
157 cmd_getval(g_ceph_context
, cmdmap
, "args", args
);
158 result
.append(command
);
161 for (std::vector
<std::string
>::iterator it
= args
.begin();
162 it
!= args
.end(); ++it
) {
163 if (it
!= args
.begin())
167 result
.append(resultstr
);
172 TEST(AdminSocket
, RegisterCommandPrefixes
) {
173 std::unique_ptr
<AdminSocket
>
174 asokc(new AdminSocket(g_ceph_context
));
175 AdminSocketTest
asoct(asokc
.get());
176 ASSERT_EQ(true, asoct
.shutdown());
177 ASSERT_EQ(true, asoct
.init(get_rand_socket_path()));
178 AdminSocketClient
client(get_rand_socket_path());
179 ASSERT_EQ(0, asoct
.m_asokc
->register_command("test", "test name=args,type=CephString,n=N", new MyTest(), ""));
180 ASSERT_EQ(0, asoct
.m_asokc
->register_command("test command", "test command name=args,type=CephString,n=N", new MyTest2(), ""));
182 ASSERT_EQ("", client
.do_request("{\"prefix\":\"test\"}", &result
));
183 ASSERT_EQ("test|", result
);
184 ASSERT_EQ("", client
.do_request("{\"prefix\":\"test command\"}", &result
));
185 ASSERT_EQ("test command|", result
);
186 ASSERT_EQ("", client
.do_request("{\"prefix\":\"test command\",\"args\":[\"post\"]}", &result
));
187 ASSERT_EQ("test command|post", result
);
188 ASSERT_EQ("", client
.do_request("{\"prefix\":\"test command\",\"args\":[\" post\"]}", &result
));
189 ASSERT_EQ("test command| post", result
);
190 ASSERT_EQ("", client
.do_request("{\"prefix\":\"test\",\"args\":[\"this thing\"]}", &result
));
191 ASSERT_EQ("test|this thing", result
);
193 ASSERT_EQ("", client
.do_request("{\"prefix\":\"test\",\"args\":[\" command post\"]}", &result
));
194 ASSERT_EQ("test| command post", result
);
195 ASSERT_EQ("", client
.do_request("{\"prefix\":\"test\",\"args\":[\" this thing\"]}", &result
));
196 ASSERT_EQ("test| this thing", result
);
197 ASSERT_EQ(true, asoct
.shutdown());
200 class BlockingHook
: public AdminSocketHook
{
205 BlockingHook() : _lock("BlockingHook::_lock") {}
207 bool call(std::string command
, cmdmap_t
& cmdmap
, std::string format
, bufferlist
& result
) override
{
208 Mutex::Locker
l(_lock
);
214 TEST(AdminSocketClient
, Ping
) {
215 string path
= get_rand_socket_path();
216 std::unique_ptr
<AdminSocket
>
217 asokc(new AdminSocket(g_ceph_context
));
218 AdminSocketClient
client(path
);
222 std::string result
= client
.ping(&ok
);
223 EXPECT_NE(std::string::npos
, result
.find("No such file or directory"));
226 // file exists but does not allow connections (no process, wrong type...)
227 ASSERT_TRUE(::creat(path
.c_str(), 0777));
230 std::string result
= client
.ping(&ok
);
231 #if defined(__APPLE__) || defined(__FreeBSD__)
232 const char* errmsg
= "Socket operation on non-socket";
234 const char* errmsg
= "Connection refused";
236 EXPECT_NE(std::string::npos
, result
.find(errmsg
));
239 // a daemon is connected to the socket
241 AdminSocketTest
asoct(asokc
.get());
242 ASSERT_TRUE(asoct
.init(path
));
244 std::string result
= client
.ping(&ok
);
245 EXPECT_EQ("", result
);
247 ASSERT_TRUE(asoct
.shutdown());
249 // hardcoded five seconds timeout prevents infinite blockage
251 AdminSocketTest
asoct(asokc
.get());
252 BlockingHook
*blocking
= new BlockingHook();
253 ASSERT_EQ(0, asoct
.m_asokc
->register_command("0", "0", blocking
, ""));
254 ASSERT_TRUE(asoct
.init(path
));
256 std::string result
= client
.ping(&ok
);
257 EXPECT_NE(std::string::npos
, result
.find("Resource temporarily unavailable"));
260 Mutex::Locker
l(blocking
->_lock
);
261 blocking
->_cond
.Signal();
263 ASSERT_TRUE(asoct
.shutdown());
268 TEST(AdminSocket
, bind_and_listen
) {
269 string path
= get_rand_socket_path();
270 std::unique_ptr
<AdminSocket
>
271 asokc(new AdminSocket(g_ceph_context
));
273 AdminSocketTest
asoct(asokc
.get());
278 message
= asoct
.bind_and_listen(path
, &fd
);
280 ASSERT_EQ("", message
);
281 ASSERT_EQ(0, ::close(fd
));
282 ASSERT_EQ(0, ::unlink(path
.c_str()));
284 // silently discard an existing file
288 ASSERT_TRUE(::creat(path
.c_str(), 0777));
289 message
= asoct
.bind_and_listen(path
, &fd
);
291 ASSERT_EQ("", message
);
292 ASSERT_EQ(0, ::close(fd
));
293 ASSERT_EQ(0, ::unlink(path
.c_str()));
295 // do not take over a live socket
297 ASSERT_TRUE(asoct
.init(path
));
300 message
= asoct
.bind_and_listen(path
, &fd
);
301 std::cout
<< "message: " << message
<< std::endl
;
302 EXPECT_NE(std::string::npos
, message
.find("File exists"));
303 ASSERT_TRUE(asoct
.shutdown());
309 * compile-command: "cd .. ;
310 * make unittest_admin_socket &&
312 * --max-stackframe=20000000 --tool=memcheck \
313 * ./unittest_admin_socket --debug-asok 20 # --gtest_filter=AdminSocket*.*