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) 2015 Red Hat, Inc.
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.
21 #include <boost/algorithm/string.hpp>
24 #include "include/rados/librgw.h"
25 #include "include/rados/rgw_file.h"
26 #include "rgw/rgw_file.h"
28 #include "gtest/gtest.h"
29 #include "common/ceph_argparse.h"
30 #include "common/errno.h"
31 #include "common/debug.h"
32 #include "global/global_init.h"
33 #include "include/ceph_assert.h"
35 #define dout_context g_ceph_context
36 #define dout_subsys ceph_subsys_rgw
42 string
uid("testuser");
43 string
access_key("");
44 string
secret_key("");
46 librgw_t rgw_h
= nullptr;
47 struct rgw_fs
*fs
= nullptr;
49 uint32_t owner_uid
= 867;
50 uint32_t owner_gid
= 5309;
51 uint32_t create_mask
= RGW_SETATTR_UID
| RGW_SETATTR_GID
| RGW_SETATTR_MODE
;
53 string bucket_name
{"v4recov"};
54 string object_path
{"node0/clientids"};
57 string val1
{"metallic"};
59 struct rgw_file_handle
*bucket_fh
= nullptr;
60 struct rgw_file_handle
*object_fh
= nullptr;
62 typedef std::tuple
<string
,uint64_t, struct rgw_file_handle
*> fid_type
;
63 std::vector
<fid_type
> fids
;
69 struct rgw_file_handle
* fh
;
70 struct rgw_file_handle
* parent_fh
;
71 RGWFileHandle
* rgw_fh
; // alias into fh
75 state() : readdir(false) {}
78 obj_rec(string _name
, struct rgw_file_handle
* _fh
,
79 struct rgw_file_handle
* _parent_fh
, RGWFileHandle
* _rgw_fh
)
80 : name(std::move(_name
)), fh(_fh
), parent_fh(_parent_fh
),
90 rgw_fh
= get_rgwfh(fh
);
93 friend ostream
& operator<<(ostream
& os
, const obj_rec
& rec
);
96 ostream
& operator<<(ostream
& os
, const obj_rec
& rec
)
98 RGWFileHandle
* rgw_fh
= rec
.rgw_fh
;
100 const char* type
= rgw_fh
->is_dir() ? "DIR " : "FILE ";
101 os
<< rec
.rgw_fh
->full_object_name()
102 << " (" << rec
.rgw_fh
->object_name() << "): "
108 typedef std::vector
<obj_rec
> obj_vec
;
111 bool do_stat
= false;
112 bool do_create
= false;
113 bool do_delete
= false;
114 bool do_hexdump
= false;
115 bool verbose
= false;
124 int ret
= librgw_create(&rgw_h
, saved_args
.argc
, saved_args
.argv
);
126 ASSERT_NE(rgw_h
, nullptr);
129 TEST(LibRGW
, MOUNT
) {
130 int ret
= rgw_mount(rgw_h
, uid
.c_str(), access_key
.c_str(),
131 secret_key
.c_str(), &fs
, RGW_MOUNT_FLAG_NONE
);
133 ASSERT_NE(fs
, nullptr);
136 TEST(LibRGW
, LOOKUP_BUCKET
) {
137 int ret
= rgw_lookup(fs
, fs
->root_fh
, bucket_name
.c_str(), &bucket_fh
,
138 nullptr, 0, RGW_LOOKUP_FLAG_NONE
);
142 TEST(LibRGW
, CREATE_BUCKET
) {
143 if ((! bucket_fh
) && do_create
) {
146 st
.st_uid
= owner_uid
;
147 st
.st_gid
= owner_gid
;
150 int ret
= rgw_mkdir(fs
, fs
->root_fh
, bucket_name
.c_str(), &st
, create_mask
,
151 &bucket_fh
, RGW_MKDIR_FLAG_NONE
);
156 TEST(LibRGW
, CREATE_PATH
) {
162 boost::split(segs
, object_path
, boost::is_any_of("/"));
165 st
.st_uid
= owner_uid
;
166 st
.st_gid
= owner_gid
;
169 int ix
, ret
, sz
= segs
.size();
170 for (ix
= 0; ix
< sz
; ++ix
) {
171 auto& seg
= segs
[ix
];
172 struct rgw_file_handle
* parent_fh
= (ix
> 0) ? ovec
[ix
-1].fh
: bucket_fh
;
173 obj_rec dir
{seg
, nullptr, parent_fh
, nullptr};
175 ret
= rgw_mkdir(fs
, dir
.parent_fh
, dir
.name
.c_str(), &st
, create_mask
,
176 &dir
.fh
, RGW_MKDIR_FLAG_NONE
);
178 ret
= rgw_lookup(fs
, dir
.parent_fh
, dir
.name
.c_str(), &dir
.fh
,
179 nullptr, 0, RGW_LOOKUP_FLAG_NONE
);
185 std::cout
<< "create: " << dir
.name
<< std::endl
;
190 TEST(LibRGW
, CHECK_PATH_REFS
) {
195 int ix
, sz
= ovec
.size();
196 for (ix
= 0; ix
< sz
; ++ix
) {
197 auto& dir
= ovec
[ix
];
199 std::cout
<< "name: " << dir
.name
200 << " refcnt: " << dir
.rgw_fh
->get_refcnt()
204 // sentinel, +1 parent, +1 path
205 ASSERT_EQ(dir
.rgw_fh
->get_refcnt(), 3U);
209 ASSERT_EQ(dir
.rgw_fh
->get_refcnt(), 2U);
214 TEST(LibRGW
, SETXATTR1
) {
219 auto& dir
= ovec
[ovec
.size()-1];
220 rgw_xattrstr xattr_k
= { const_cast<char*>(key1
.c_str()),
221 uint32_t(key1
.length()) };
222 rgw_xattrstr xattr_v
= { const_cast<char*>(val1
.c_str()),
223 uint32_t(val1
.length()) };
225 rgw_xattr xattr
= { xattr_k
, xattr_v
};
226 rgw_xattrlist xattrlist
= { &xattr
, 1 };
228 int ret
= rgw_setxattrs(fs
, dir
.fh
, &xattrlist
, RGW_SETXATTR_FLAG_NONE
);
233 static int getattr_cb(rgw_xattrlist
*attrs
, void *arg
, uint32_t flags
)
236 *(static_cast<std::map
<std::string
, std::string
>*>(arg
));
237 for (uint32_t ix
= 0; ix
< attrs
->xattr_cnt
; ++ix
) {
238 auto& xattr
= attrs
->xattrs
[ix
];
239 string k
{xattr
.key
.val
, xattr
.key
.len
};
240 string v
{xattr
.val
.val
, xattr
.val
.len
};
242 std::cout
<< __func__
243 << " attr k: " << k
<< " v: " << v
246 attrmap
.insert(std::map
<std::string
, std::string
>::value_type(k
, v
));
252 TEST(LibRGW
, GETXATTR1
) {
258 auto& dir
= ovec
[ovec
.size()-1];
260 rgw_xattrstr xattr_k1
=
261 {const_cast<char*>(key1
.c_str()), uint32_t(key1
.length())};
262 rgw_xattrstr xattr_v1
= {nullptr, 0};
264 std::string key2
= "user.rgw.etag";
265 rgw_xattrstr xattr_k2
=
266 {const_cast<char*>(key2
.c_str()), uint32_t(key2
.length())};
267 rgw_xattrstr xattr_v2
= {nullptr, 0};
269 rgw_xattr xattrs
[2] = {{xattr_k1
, xattr_v1
},
270 {xattr_k2
, xattr_v2
}};
272 /* XXX gcc won't accept static_cast here, don't see why */
273 rgw_xattrlist xattrlist
= {reinterpret_cast<rgw_xattr
*>(&xattrs
), 2};
275 std::map
<std::string
, std::string
> out_attrmap
;
277 int ret
= rgw_getxattrs(fs
, dir
.fh
, &xattrlist
, getattr_cb
, &out_attrmap
,
278 RGW_GETXATTR_FLAG_NONE
);
280 /* check exposed attrs */
281 ASSERT_TRUE(out_attrmap
.find("user.rgw.etag") != out_attrmap
.end());
282 /* check our user attr */
283 ASSERT_TRUE(out_attrmap
.find(key1
) != out_attrmap
.end());
286 TEST(LibRGW
, LSXATTR1
) {
292 auto& dir
= ovec
[ovec
.size()-1];
294 rgw_xattrstr filter_prefix
= { nullptr, 0}; // XXX ignored, for now
296 std::map
<std::string
, std::string
> out_attrmap
;
298 int ret
= rgw_lsxattrs(fs
, dir
.fh
, &filter_prefix
, getattr_cb
,
299 &out_attrmap
, RGW_LSXATTR_FLAG_NONE
);
302 /* check exposed attrs */
303 ASSERT_TRUE(out_attrmap
.find("user.rgw.etag") != out_attrmap
.end());
306 TEST(LibRGW
, RMXATTR1
) {
312 auto& dir
= ovec
[ovec
.size()-1];
314 rgw_xattrstr xattr_k
= { const_cast<char*>(key1
.c_str()),
315 uint32_t(key1
.length()) };
316 rgw_xattrstr xattr_v
= { nullptr, 0 };
318 rgw_xattr xattr
= { xattr_k
, xattr_v
};
319 rgw_xattrlist xattrlist
= { &xattr
, 1 };
321 int ret
= rgw_rmxattrs(fs
, dir
.fh
, &xattrlist
, RGW_RMXATTR_FLAG_NONE
);
325 TEST(LibRGW
, LSXATTR2
) {
331 auto& dir
= ovec
[ovec
.size()-1];
333 rgw_xattrstr filter_prefix
= { nullptr, 0 }; // XXX ignored, for now
335 std::map
<std::string
, std::string
> out_attrmap
;
337 int ret
= rgw_lsxattrs(fs
, dir
.fh
, &filter_prefix
, getattr_cb
,
338 &out_attrmap
, RGW_LSXATTR_FLAG_NONE
);
340 /* check exposed attrs */
341 ASSERT_TRUE(out_attrmap
.find("user.rgw.etag") != out_attrmap
.end());
342 /* verify deletion */
343 ASSERT_TRUE(out_attrmap
.find(key1
) == out_attrmap
.end());
346 TEST(LibRGW
, CLEANUP
) {
349 ret
= rgw_fh_rele(fs
, object_fh
, 0 /* flags */);
353 ret
= rgw_fh_rele(fs
, bucket_fh
, 0 /* flags */);
358 TEST(LibRGW
, UMOUNT
) {
362 int ret
= rgw_umount(fs
, RGW_UMOUNT_FLAG_NONE
);
366 TEST(LibRGW
, SHUTDOWN
) {
367 librgw_shutdown(rgw_h
);
370 int main(int argc
, char *argv
[])
374 vector
<const char*> args
;
376 argv_to_vec(argc
, const_cast<const char**>(argv
), args
);
379 v
= getenv("AWS_ACCESS_KEY_ID");
384 v
= getenv("AWS_SECRET_ACCESS_KEY");
389 for (auto arg_iter
= args
.begin(); arg_iter
!= args
.end();) {
390 if (ceph_argparse_witharg(args
, arg_iter
, &val
, "--access",
393 } else if (ceph_argparse_witharg(args
, arg_iter
, &val
, "--secret",
396 } else if (ceph_argparse_witharg(args
, arg_iter
, &val
, "--uid",
399 } else if (ceph_argparse_witharg(args
, arg_iter
, &val
, "--bn",
402 } else if (ceph_argparse_flag(args
, arg_iter
, "--stat",
405 } else if (ceph_argparse_flag(args
, arg_iter
, "--create",
408 } else if (ceph_argparse_flag(args
, arg_iter
, "--delete",
411 } else if (ceph_argparse_flag(args
, arg_iter
, "--hexdump",
414 } else if (ceph_argparse_flag(args
, arg_iter
, "--verbose",
422 /* dont accidentally run as anonymous */
423 if ((access_key
== "") ||
424 (secret_key
== "")) {
425 std::cout
<< argv
[0] << " no AWS credentials, exiting" << std::endl
;
429 saved_args
.argc
= argc
;
430 saved_args
.argv
= argv
;
432 ::testing::InitGoogleTest(&argc
, argv
);
433 return RUN_ALL_TESTS();