]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/cls_hello/test_cls_hello.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / test / cls_hello / test_cls_hello.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) 2013 Inktank
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 <iostream>
16#include <errno.h>
9f95a23c 17#include <string>
7c673cae
FG
18
19#include "include/rados/librados.hpp"
20#include "include/encoding.h"
11fdf7f2 21#include "test/librados/test_cxx.h"
7c673cae 22#include "gtest/gtest.h"
9f95a23c 23#include "json_spirit/json_spirit.h"
7c673cae
FG
24
25using namespace librados;
26
27TEST(ClsHello, SayHello) {
28 Rados cluster;
29 std::string pool_name = get_temp_pool_name();
30 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
31 IoCtx ioctx;
32 cluster.ioctx_create(pool_name.c_str(), ioctx);
33
34 bufferlist in, out;
35 ASSERT_EQ(-ENOENT, ioctx.exec("myobject", "hello", "say_hello", in, out));
36 ASSERT_EQ(0, ioctx.write_full("myobject", in));
37 ASSERT_EQ(0, ioctx.exec("myobject", "hello", "say_hello", in, out));
38 ASSERT_EQ(std::string("Hello, world!"), std::string(out.c_str(), out.length()));
39
40 out.clear();
41 in.append("Tester");
42 ASSERT_EQ(0, ioctx.exec("myobject", "hello", "say_hello", in, out));
43 ASSERT_EQ(std::string("Hello, Tester!"), std::string(out.c_str(), out.length()));
44
45 out.clear();
46 in.clear();
47 char buf[4096];
48 memset(buf, 1, sizeof(buf));
49 in.append(buf, sizeof(buf));
50 ASSERT_EQ(-EINVAL, ioctx.exec("myobject", "hello", "say_hello", in, out));
51
52 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
53}
54
55TEST(ClsHello, RecordHello) {
56 Rados cluster;
57 std::string pool_name = get_temp_pool_name();
58 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
59 IoCtx ioctx;
60 cluster.ioctx_create(pool_name.c_str(), ioctx);
61
62 bufferlist in, out;
63 ASSERT_EQ(0, ioctx.exec("myobject", "hello", "record_hello", in, out));
64 ASSERT_EQ(-EEXIST, ioctx.exec("myobject", "hello", "record_hello", in, out));
65
66 in.append("Tester");
67 ASSERT_EQ(0, ioctx.exec("myobject2", "hello", "record_hello", in, out));
68 ASSERT_EQ(-EEXIST, ioctx.exec("myobject2", "hello", "record_hello", in, out));
69 ASSERT_EQ(0u, out.length());
70
71 in.clear();
72 out.clear();
73 ASSERT_EQ(0, ioctx.exec("myobject", "hello", "replay", in, out));
74 ASSERT_EQ(std::string("Hello, world!"), std::string(out.c_str(), out.length()));
75 out.clear();
76 ASSERT_EQ(0, ioctx.exec("myobject2", "hello", "replay", in, out));
77 ASSERT_EQ(std::string("Hello, Tester!"), std::string(out.c_str(), out.length()));
78
79 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
80}
81
9f95a23c
TL
82static std::string _get_required_osd_release(Rados& cluster)
83{
84 bufferlist inbl;
85 std::string cmd = std::string("{\"prefix\": \"osd dump\",\"format\":\"json\"}");
86 bufferlist outbl;
87 int r = cluster.mon_command(cmd, inbl, &outbl, NULL);
88 ceph_assert(r >= 0);
89 std::string outstr(outbl.c_str(), outbl.length());
90 json_spirit::Value v;
91 if (!json_spirit::read(outstr, v)) {
92 std::cerr <<" unable to parse json " << outstr << std::endl;
93 return "";
94 }
95
96 json_spirit::Object& o = v.get_obj();
97 for (json_spirit::Object::size_type i=0; i<o.size(); i++) {
98 json_spirit::Pair& p = o[i];
99 if (p.name_ == "require_osd_release") {
100 std::cout << "require_osd_release = " << p.value_.get_str() << std::endl;
101 return p.value_.get_str();
102 }
103 }
104 std::cerr << "didn't find require_osd_release in " << outstr << std::endl;
105 return "";
106}
107
7c673cae
FG
108TEST(ClsHello, WriteReturnData) {
109 Rados cluster;
110 std::string pool_name = get_temp_pool_name();
111 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
112 IoCtx ioctx;
113 cluster.ioctx_create(pool_name.c_str(), ioctx);
114
9f95a23c
TL
115 // skip test if not yet mimic
116 if (_get_required_osd_release(cluster) < "octopus") {
117 std::cout << "cluster is not yet octopus, skipping test" << std::endl;
118 return;
119 }
120
f67539c2 121 // this will return nothing -- no flag is set
7c673cae 122 bufferlist in, out;
9f95a23c 123 ASSERT_EQ(0, ioctx.exec("myobject", "hello", "write_return_data", in, out));
7c673cae
FG
124 ASSERT_EQ(std::string(), std::string(out.c_str(), out.length()));
125
9f95a23c
TL
126 // this will return an error due to unexpected input.
127 // note that we set the RETURNVEC flag here so that we *reliably* get the
128 // "too much input data!" return data string. do it lots of times so we are
129 // more likely to resend a request and hit the dup op handling path.
7c673cae
FG
130 char buf[4096];
131 memset(buf, 1, sizeof(buf));
9f95a23c
TL
132 for (unsigned i=0; i<1000; ++i) {
133 std::cout << i << std::endl;
134 in.clear();
135 in.append(buf, sizeof(buf));
136 int rval;
137 ObjectWriteOperation o;
138 o.exec("hello", "write_return_data", in, &out, &rval);
139 librados::AioCompletion *completion = cluster.aio_create_completion();
140 ASSERT_EQ(0, ioctx.aio_operate("foo", completion, &o,
141 librados::OPERATION_RETURNVEC));
142 completion->wait_for_complete();
143 ASSERT_EQ(-EINVAL, completion->get_return_value());
144 ASSERT_EQ(-EINVAL, rval);
145 ASSERT_EQ(std::string("too much input data!"), std::string(out.c_str(), out.length()));
146 }
7c673cae
FG
147 ASSERT_EQ(-ENOENT, ioctx.getxattr("myobject2", "foo", out));
148
9f95a23c
TL
149 // this *will* return data due to the RETURNVEC flag
150 // using a-sync call
151 {
152 in.clear();
153 out.clear();
154 int rval;
155 ObjectWriteOperation o;
156 o.exec("hello", "write_return_data", in, &out, &rval);
157 librados::AioCompletion *completion = cluster.aio_create_completion();
158 ASSERT_EQ(0, ioctx.aio_operate("foo", completion, &o,
159 librados::OPERATION_RETURNVEC));
160 completion->wait_for_complete();
161 ASSERT_EQ(42, completion->get_return_value());
162 ASSERT_EQ(42, rval);
163 out.hexdump(std::cout);
164 ASSERT_EQ("you might see this", std::string(out.c_str(), out.length()));
165 }
166 // using sync call
167 {
168 in.clear();
169 out.clear();
170 int rval;
171 ObjectWriteOperation o;
172 o.exec("hello", "write_return_data", in, &out, &rval);
173 ASSERT_EQ(42, ioctx.operate("foo", &o,
174 librados::OPERATION_RETURNVEC));
175 ASSERT_EQ(42, rval);
176 out.hexdump(std::cout);
177 ASSERT_EQ("you might see this", std::string(out.c_str(), out.length()));
178 }
179
180 // this will overflow because the return data is too big
181 {
182 in.clear();
183 out.clear();
184 int rval;
185 ObjectWriteOperation o;
186 o.exec("hello", "write_too_much_return_data", in, &out, &rval);
187 librados::AioCompletion *completion = cluster.aio_create_completion();
188 ASSERT_EQ(0, ioctx.aio_operate("foo", completion, &o,
189 librados::OPERATION_RETURNVEC));
190 completion->wait_for_complete();
191 ASSERT_EQ(-EOVERFLOW, completion->get_return_value());
192 ASSERT_EQ(-EOVERFLOW, rval);
193 ASSERT_EQ("", std::string(out.c_str(), out.length()));
194 }
195
7c673cae
FG
196 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
197}
198
199TEST(ClsHello, Loud) {
200 Rados cluster;
201 std::string pool_name = get_temp_pool_name();
202 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
203 IoCtx ioctx;
204 cluster.ioctx_create(pool_name.c_str(), ioctx);
205
206 bufferlist in, out;
207 ASSERT_EQ(0, ioctx.exec("myobject", "hello", "record_hello", in, out));
208 ASSERT_EQ(0, ioctx.exec("myobject", "hello", "replay", in, out));
209 ASSERT_EQ(std::string("Hello, world!"), std::string(out.c_str(), out.length()));
210
211 ASSERT_EQ(0, ioctx.exec("myobject", "hello", "turn_it_to_11", in, out));
212 ASSERT_EQ(0, ioctx.exec("myobject", "hello", "replay", in, out));
213 ASSERT_EQ(std::string("HELLO, WORLD!"), std::string(out.c_str(), out.length()));
214
215 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
216}
217
218TEST(ClsHello, BadMethods) {
219 Rados cluster;
220 std::string pool_name = get_temp_pool_name();
221 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
222 IoCtx ioctx;
223 cluster.ioctx_create(pool_name.c_str(), ioctx);
224
225 bufferlist in, out;
226
227 ASSERT_EQ(0, ioctx.write_full("myobject", in));
228 ASSERT_EQ(-EIO, ioctx.exec("myobject", "hello", "bad_reader", in, out));
229 ASSERT_EQ(-EIO, ioctx.exec("myobject", "hello", "bad_writer", in, out));
230
231 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
232}
233
234TEST(ClsHello, Filter) {
235 Rados cluster;
236 std::string pool_name = get_temp_pool_name();
237 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
238 IoCtx ioctx;
239 cluster.ioctx_create(pool_name.c_str(), ioctx);
240
241 char buf[128];
242 memset(buf, 0xcc, sizeof(buf));
243 bufferlist obj_content;
244 obj_content.append(buf, sizeof(buf));
245
246 std::string target_str = "content";
247
248 // Write xattr bare, no ::encod'ing
249 bufferlist target_val;
250 target_val.append(target_str);
251 bufferlist nontarget_val;
252 nontarget_val.append("rhubarb");
253
254 ASSERT_EQ(0, ioctx.write("has_xattr", obj_content, obj_content.length(), 0));
255 ASSERT_EQ(0, ioctx.write("has_wrong_xattr", obj_content, obj_content.length(), 0));
256 ASSERT_EQ(0, ioctx.write("no_xattr", obj_content, obj_content.length(), 0));
257
258 ASSERT_EQ(0, ioctx.setxattr("has_xattr", "theattr", target_val));
259 ASSERT_EQ(0, ioctx.setxattr("has_wrong_xattr", "theattr", nontarget_val));
260
261 bufferlist filter_bl;
262 std::string filter_name = "hello.hello";
11fdf7f2
TL
263 encode(filter_name, filter_bl);
264 encode("_theattr", filter_bl);
265 encode(target_str, filter_bl);
7c673cae
FG
266
267 NObjectIterator iter(ioctx.nobjects_begin(filter_bl));
268 bool foundit = false;
269 int k = 0;
270 while (iter != ioctx.nobjects_end()) {
271 foundit = true;
272 // We should only see the object that matches the filter
273 ASSERT_EQ((*iter).get_oid(), "has_xattr");
274 // We should only see it once
275 ASSERT_EQ(k, 0);
276 ++iter;
277 ++k;
278 }
279 ASSERT_TRUE(foundit);
280
281 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
282}
283