1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "mds/mdstypes.h"
5 #include "include/buffer.h"
6 #include "include/rbd_types.h"
7 #include "include/rados/librados.h"
8 #include "include/rados/librados.hpp"
9 #include "include/stringify.h"
10 #include "test/librados/test.h"
12 #include "common/Cond.h"
14 #include "gtest/gtest.h"
20 using namespace librados;
22 using std::ostringstream;
25 TEST(LibRadosCmd, MonDescribe) {
27 ASSERT_EQ("", connect_cluster(&cluster));
35 cmd[0] = (char *)"{\"prefix\":\"get_command_descriptions\"}";
36 ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
37 ASSERT_LT(0u, buflen);
38 rados_buffer_free(buf);
39 rados_buffer_free(st);
41 cmd[0] = (char *)"get_command_descriptions";
42 ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
43 rados_buffer_free(buf);
44 rados_buffer_free(st);
46 cmd[0] = (char *)"asdfqwer";
47 ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "{}", 2, &buf, &buflen, &st, &stlen));
48 rados_buffer_free(buf);
49 rados_buffer_free(st);
52 ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "{}", 2, &buf, &buflen, &st, &stlen));
53 rados_buffer_free(buf);
54 rados_buffer_free(st);
56 cmd[0] = (char *)"{}";
57 ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
58 rados_buffer_free(buf);
59 rados_buffer_free(st);
61 cmd[0] = (char *)"{\"abc\":\"something\"}";
62 ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
63 rados_buffer_free(buf);
64 rados_buffer_free(st);
66 cmd[0] = (char *)"{\"prefix\":\"\"}";
67 ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
68 rados_buffer_free(buf);
69 rados_buffer_free(st);
71 cmd[0] = (char *)"{\"prefix\":\" \"}";
72 ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
73 rados_buffer_free(buf);
74 rados_buffer_free(st);
76 cmd[0] = (char *)"{\"prefix\":\";;;,,,;;,,\"}";
77 ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
78 rados_buffer_free(buf);
79 rados_buffer_free(st);
81 cmd[0] = (char *)"{\"prefix\":\"extra command\"}";
82 ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
83 rados_buffer_free(buf);
84 rados_buffer_free(st);
86 cmd[0] = (char *)"{\"prefix\":\"mon_status\"}";
87 ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
88 ASSERT_LT(0u, buflen);
89 //ASSERT_LT(0u, stlen);
90 rados_buffer_free(buf);
91 rados_buffer_free(st);
92 rados_shutdown(cluster);
95 TEST(LibRadosCmd, MonDescribePP) {
97 ASSERT_EQ("", connect_cluster_pp(cluster));
98 bufferlist inbl, outbl;
100 ASSERT_EQ(0, cluster.mon_command("{\"prefix\": \"get_command_descriptions\"}",
101 inbl, &outbl, &outs));
102 ASSERT_LT(0u, outbl.length());
103 ASSERT_LE(0u, outs.length());
107 TEST(LibRadosCmd, OSDCmd) {
109 ASSERT_EQ("", connect_cluster(&cluster));
112 size_t buflen, stlen;
116 // note: tolerate NXIO here in case the cluster is thrashing out underneath us.
117 cmd[0] = (char *)"asdfasdf";
118 r = rados_osd_command(cluster, 0, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen);
119 rados_buffer_free(buf);
120 rados_buffer_free(st);
121 ASSERT_TRUE(r == -22 || r == -ENXIO);
122 cmd[0] = (char *)"version";
123 r = rados_osd_command(cluster, 0, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen);
124 rados_buffer_free(buf);
125 rados_buffer_free(st);
126 ASSERT_TRUE(r == -22 || r == -ENXIO);
127 cmd[0] = (char *)"{\"prefix\":\"version\"}";
128 r = rados_osd_command(cluster, 0, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen);
129 ASSERT_TRUE((r == 0 && buflen > 0) || (r == -ENXIO && buflen == 0));
130 rados_buffer_free(buf);
131 rados_buffer_free(st);
132 rados_shutdown(cluster);
135 TEST(LibRadosCmd, OSDCmdPP) {
137 ASSERT_EQ("", connect_cluster_pp(cluster));
139 bufferlist inbl, outbl;
143 // note: tolerate NXIO here in case the cluster is thrashing out underneath us.
145 r = cluster.osd_command(0, cmd, inbl, &outbl, &outs);
146 ASSERT_TRUE(r == -22 || r == -ENXIO);
148 r = cluster.osd_command(0, cmd, inbl, &outbl, &outs);
149 ASSERT_TRUE(r == -22 || r == -ENXIO);
150 cmd = "{\"prefix\":\"version\"}";
151 r = cluster.osd_command(0, cmd, inbl, &outbl, &outs);
152 ASSERT_TRUE((r == 0 && outbl.length() > 0) || (r == -ENXIO && outbl.length() == 0));
156 TEST(LibRadosCmd, PGCmd) {
158 std::string pool_name = get_temp_pool_name();
159 ASSERT_EQ("", create_one_pool(pool_name, &cluster));
162 size_t buflen, stlen;
166 int64_t poolid = rados_pool_lookup(cluster, pool_name.c_str());
167 ASSERT_LT(0, poolid);
169 string pgid = stringify(poolid) + ".0";
171 cmd[0] = (char *)"asdfasdf";
172 // note: tolerate NXIO here in case the cluster is thrashing out underneath us.
173 int r = rados_pg_command(cluster, pgid.c_str(), (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen);
174 ASSERT_TRUE(r == -22 || r == -ENXIO);
175 rados_buffer_free(buf);
176 rados_buffer_free(st);
178 // make sure the pg exists on the osd before we query it
180 rados_ioctx_create(cluster, pool_name.c_str(), &io);
181 for (int i=0; i<100; i++) {
182 string oid = "obj" + stringify(i);
183 ASSERT_EQ(-ENOENT, rados_stat(io, oid.c_str(), NULL, NULL));
185 rados_ioctx_destroy(io);
187 string qstr = "{\"prefix\":\"pg\", \"cmd\":\"query\", \"pgid\":\"" + pgid + "\"}";
188 cmd[0] = (char *)qstr.c_str();
189 // note: tolerate ENOENT/ENXIO here if hte osd is thrashing out underneath us
190 r = rados_pg_command(cluster, pgid.c_str(), (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen);
191 ASSERT_TRUE(r == 0 || r == -ENOENT || r == -ENXIO);
193 ASSERT_LT(0u, buflen);
194 rados_buffer_free(buf);
195 rados_buffer_free(st);
197 ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
200 TEST(LibRadosCmd, PGCmdPP) {
202 std::string pool_name = get_temp_pool_name();
203 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
206 bufferlist inbl, outbl;
210 int64_t poolid = cluster.pool_lookup(pool_name.c_str());
211 ASSERT_LT(0, poolid);
213 string pgid = stringify(poolid) + ".0";
216 // note: tolerate NXIO here in case the cluster is thrashing out underneath us.
217 r = cluster.pg_command(pgid.c_str(), cmd, inbl, &outbl, &outs);
218 ASSERT_TRUE(r == -22 || r == -ENXIO);
220 // make sure the pg exists on the osd before we query it
222 cluster.ioctx_create(pool_name.c_str(), io);
223 for (int i=0; i<100; i++) {
224 string oid = "obj" + stringify(i);
225 ASSERT_EQ(-ENOENT, io.stat(oid, NULL, NULL));
229 cmd = "{\"prefix\":\"pg\", \"cmd\":\"query\", \"pgid\":\"" + pgid + "\"}";
230 // note: tolerate ENOENT/ENXIO here if hte osd is thrashing out underneath us
231 r = cluster.pg_command(pgid.c_str(), cmd, inbl, &outbl, &outs);
232 ASSERT_TRUE(r == 0 || r == -ENOENT || r == -ENXIO);
234 ASSERT_LT(0u, outbl.length());
236 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
244 Log() : lock("l::lock") {}
246 bool contains(string str) {
247 Mutex::Locker l(lock);
248 for (list<string>::iterator p = log.begin(); p != log.end(); ++p) {
249 if (p->find(str) != std::string::npos)
256 void log_cb(void *arg,
258 const char *who, uint64_t stampsec, uint64_t stamp_nsec,
259 uint64_t seq, const char *level,
261 Log *l = static_cast<Log *>(arg);
262 Mutex::Locker locker(l->lock);
263 l->log.push_back(line);
265 cout << "got: " << line << std::endl;
268 TEST(LibRadosCmd, WatchLog) {
270 ASSERT_EQ("", connect_cluster(&cluster));
274 size_t buflen, stlen;
277 ASSERT_EQ(0, rados_monitor_log(cluster, "info", log_cb, &l));
278 cmd[0] = (char *)"{\"prefix\":\"log\", \"logtext\":[\"onexx\"]}";
279 ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
280 for (int i=0; !l.contains("onexx"); i++) {
284 ASSERT_TRUE(l.contains("onexx"));
286 cmd[0] = (char *)"{\"prefix\":\"log\", \"logtext\":[\"twoxx\"]}";
287 ASSERT_EQ(0, rados_monitor_log(cluster, "err", log_cb, &l));
288 ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
290 ASSERT_FALSE(l.contains("twoxx"));
292 ASSERT_EQ(0, rados_monitor_log(cluster, "info", log_cb, &l));
293 cmd[0] = (char *)"{\"prefix\":\"log\", \"logtext\":[\"threexx\"]}";
294 ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
295 for (int i=0; !l.contains("threexx"); i++) {
300 ASSERT_EQ(0, rados_monitor_log(cluster, "info", NULL, NULL));
301 cmd[0] = (char *)"{\"prefix\":\"log\", \"logtext\":[\"fourxx\"]}";
302 ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
304 ASSERT_FALSE(l.contains("fourxx"));
305 rados_shutdown(cluster);