X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Ftest%2Flibrados%2Fmisc.cc;fp=src%2Fceph%2Fsrc%2Ftest%2Flibrados%2Fmisc.cc;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=f7ce348b0a0f863e77d95147709e053ac6aec4df;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/test/librados/misc.cc b/src/ceph/src/test/librados/misc.cc deleted file mode 100644 index f7ce348..0000000 --- a/src/ceph/src/test/librados/misc.cc +++ /dev/null @@ -1,1380 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab -#include "gtest/gtest.h" - -#include "mds/mdstypes.h" -#include "include/err.h" -#include "include/buffer.h" -#include "include/rbd_types.h" -#include "include/rados/librados.h" -#include "include/rados/librados.hpp" -#include "include/stringify.h" -#include "common/Checksummer.h" -#include "global/global_context.h" -#include "test/librados/test.h" -#include "test/librados/TestCase.h" -#include "gtest/gtest.h" - -#include -#include -#include -#include -#include - -using namespace librados; -using std::map; -using std::ostringstream; -using std::string; - -typedef RadosTest LibRadosMisc; -typedef RadosTestPP LibRadosMiscPP; -typedef RadosTestECPP LibRadosMiscECPP; - -TEST(LibRadosMiscVersion, Version) { - int major, minor, extra; - rados_version(&major, &minor, &extra); -} - -TEST(LibRadosMiscVersion, VersionPP) { - int major, minor, extra; - Rados::version(&major, &minor, &extra); -} - -static void test_rados_log_cb(void *arg, - const char *line, - const char *who, - uint64_t sec, uint64_t nsec, - uint64_t seq, const char *level, - const char *msg) -{ - std::cerr << "monitor log callback invoked" << std::endl; -} - -TEST(LibRadosMiscConnectFailure, ConnectFailure) { - rados_t cluster; - - char *id = getenv("CEPH_CLIENT_ID"); - if (id) - std::cerr << "Client id is: " << id << std::endl; - - ASSERT_EQ(0, rados_create(&cluster, NULL)); - ASSERT_EQ(0, rados_conf_read_file(cluster, NULL)); - ASSERT_EQ(0, rados_conf_parse_env(cluster, NULL)); - - ASSERT_EQ(0, rados_conf_set(cluster, "client_mount_timeout", "0.000000001")); - ASSERT_EQ(0, rados_conf_set(cluster, "debug_monc", "20")); - ASSERT_EQ(0, rados_conf_set(cluster, "debug_ms", "1")); - ASSERT_EQ(0, rados_conf_set(cluster, "log_to_stderr", "true")); - - ASSERT_EQ(-ENOTCONN, rados_monitor_log(cluster, "error", - test_rados_log_cb, NULL)); - - // try this a few times; sometimes we don't schedule fast enough for the - // cond to time out - int r; - for (unsigned i=0; i<16; ++i) { - cout << i << std::endl; - r = rados_connect(cluster); - if (r < 0) - break; // yay, we timed out - // try again - rados_shutdown(cluster); - ASSERT_EQ(0, rados_create(&cluster, NULL)); - } - ASSERT_NE(0, r); - - rados_shutdown(cluster); -} - -TEST(LibRadosMiscPool, PoolCreationRace) { - rados_t cluster_a, cluster_b; - - char *id = getenv("CEPH_CLIENT_ID"); - if (id) - std::cerr << "Client id is: " << id << std::endl; - - ASSERT_EQ(0, rados_create(&cluster_a, NULL)); - ASSERT_EQ(0, rados_conf_read_file(cluster_a, NULL)); - // kludge: i want to --log-file foo and only get cluster b - //ASSERT_EQ(0, rados_conf_parse_env(cluster_a, NULL)); - ASSERT_EQ(0, rados_connect(cluster_a)); - - ASSERT_EQ(0, rados_create(&cluster_b, NULL)); - ASSERT_EQ(0, rados_conf_read_file(cluster_b, NULL)); - ASSERT_EQ(0, rados_conf_parse_env(cluster_b, NULL)); - ASSERT_EQ(0, rados_conf_set(cluster_b, - "objecter_debug_inject_relock_delay", "true")); - ASSERT_EQ(0, rados_connect(cluster_b)); - - char poolname[80]; - snprintf(poolname, sizeof(poolname), "poolrace.%d", rand()); - rados_pool_create(cluster_a, poolname); - rados_ioctx_t a, b; - rados_ioctx_create(cluster_a, poolname, &a); - int64_t poolid = rados_ioctx_get_id(a); - - rados_ioctx_create2(cluster_b, poolid+1, &b); - - char pool2name[80]; - snprintf(pool2name, sizeof(pool2name), "poolrace2.%d", rand()); - rados_pool_create(cluster_a, pool2name); - - list cls; - // this should normally trigger pretty easily, but we need to bound - // the requests because if we get too many we'll get stuck by always - // sending enough messages that we hit the socket failure injection. - int max = 512; - while (max--) { - char buf[100]; - rados_completion_t c; - rados_aio_create_completion(0, 0, 0, &c); - cls.push_back(c); - rados_aio_read(b, "PoolCreationRaceObj", c, buf, 100, 0); - cout << "started " << (void*)c << std::endl; - if (rados_aio_is_complete(cls.front())) { - break; - } - } - while (!rados_aio_is_complete(cls.front())) { - cout << "waiting 1 sec" << std::endl; - sleep(1); - } - - cout << " started " << cls.size() << " aios" << std::endl; - for (auto c : cls) { - cout << "waiting " << (void*)c << std::endl; - rados_aio_wait_for_complete_and_cb(c); - rados_aio_release(c); - } - cout << "done." << std::endl; - - rados_ioctx_destroy(a); - rados_ioctx_destroy(b); - rados_pool_delete(cluster_a, poolname); - rados_pool_delete(cluster_a, pool2name); - rados_shutdown(cluster_b); - rados_shutdown(cluster_a); -} - -TEST_F(LibRadosMisc, ClusterFSID) { - char fsid[37]; - ASSERT_EQ(-ERANGE, rados_cluster_fsid(cluster, fsid, sizeof(fsid) - 1)); - ASSERT_EQ(sizeof(fsid) - 1, - (size_t)rados_cluster_fsid(cluster, fsid, sizeof(fsid))); -} - -TEST_F(LibRadosMiscPP, WaitOSDMapPP) { - ASSERT_EQ(0, cluster.wait_for_latest_osdmap()); -} - -TEST_F(LibRadosMiscPP, LongNamePP) { - bufferlist bl; - bl.append("content"); - int maxlen = g_conf->osd_max_object_name_len; - ASSERT_EQ(0, ioctx.write(string(maxlen/2, 'a').c_str(), bl, bl.length(), 0)); - ASSERT_EQ(0, ioctx.write(string(maxlen-1, 'a').c_str(), bl, bl.length(), 0)); - ASSERT_EQ(0, ioctx.write(string(maxlen, 'a').c_str(), bl, bl.length(), 0)); - ASSERT_EQ(-ENAMETOOLONG, ioctx.write(string(maxlen+1, 'a').c_str(), bl, bl.length(), 0)); - ASSERT_EQ(-ENAMETOOLONG, ioctx.write(string(maxlen*2, 'a').c_str(), bl, bl.length(), 0)); -} - -TEST_F(LibRadosMiscPP, LongLocatorPP) { - bufferlist bl; - bl.append("content"); - int maxlen = g_conf->osd_max_object_name_len; - ioctx.locator_set_key( - string((maxlen/2), 'a')); - ASSERT_EQ( - 0, - ioctx.write( - string("a").c_str(), - bl, bl.length(), 0)); - ioctx.locator_set_key( - string(maxlen - 1, 'a')); - ASSERT_EQ( - 0, - ioctx.write( - string("a").c_str(), - bl, bl.length(), 0)); - ioctx.locator_set_key( - string(maxlen, 'a')); - ASSERT_EQ( - 0, - ioctx.write( - string("a").c_str(), - bl, bl.length(), 0)); - ioctx.locator_set_key( - string(maxlen+1, 'a')); - ASSERT_EQ( - -ENAMETOOLONG, - ioctx.write( - string("a").c_str(), - bl, bl.length(), 0)); - ioctx.locator_set_key( - string((maxlen*2), 'a')); - ASSERT_EQ( - -ENAMETOOLONG, - ioctx.write( - string("a").c_str(), - bl, bl.length(), 0)); -} - -TEST_F(LibRadosMiscPP, LongNSpacePP) { - bufferlist bl; - bl.append("content"); - int maxlen = g_conf->osd_max_object_namespace_len; - ioctx.set_namespace( - string((maxlen/2), 'a')); - ASSERT_EQ( - 0, - ioctx.write( - string("a").c_str(), - bl, bl.length(), 0)); - ioctx.set_namespace( - string(maxlen - 1, 'a')); - ASSERT_EQ( - 0, - ioctx.write( - string("a").c_str(), - bl, bl.length(), 0)); - ioctx.set_namespace( - string(maxlen, 'a')); - ASSERT_EQ( - 0, - ioctx.write( - string("a").c_str(), - bl, bl.length(), 0)); - ioctx.set_namespace( - string(maxlen+1, 'a')); - ASSERT_EQ( - -ENAMETOOLONG, - ioctx.write( - string("a").c_str(), - bl, bl.length(), 0)); - ioctx.set_namespace( - string((maxlen*2), 'a')); - ASSERT_EQ( - -ENAMETOOLONG, - ioctx.write( - string("a").c_str(), - bl, bl.length(), 0)); -} - -TEST_F(LibRadosMiscPP, LongAttrNamePP) { - bufferlist bl; - bl.append("content"); - int maxlen = g_conf->osd_max_attr_name_len; - ASSERT_EQ(0, ioctx.setxattr("bigattrobj", string(maxlen/2, 'a').c_str(), bl)); - ASSERT_EQ(0, ioctx.setxattr("bigattrobj", string(maxlen-1, 'a').c_str(), bl)); - ASSERT_EQ(0, ioctx.setxattr("bigattrobj", string(maxlen, 'a').c_str(), bl)); - ASSERT_EQ(-ENAMETOOLONG, ioctx.setxattr("bigattrobj", string(maxlen+1, 'a').c_str(), bl)); - ASSERT_EQ(-ENAMETOOLONG, ioctx.setxattr("bigattrobj", string(maxlen*2, 'a').c_str(), bl)); -} - -static std::string read_key_from_tmap(IoCtx& ioctx, const std::string &obj, - const std::string &key) -{ - bufferlist bl; - int r = ioctx.read(obj, bl, 0, 0); - if (r <= 0) { - ostringstream oss; - oss << "ioctx.read(" << obj << ", bl, 0, 0) returned " << r; - return oss.str(); - } - bufferlist::iterator p = bl.begin(); - bufferlist header; - map m; - ::decode(header, p); - ::decode(m, p); - map::iterator i = m.find(key); - if (i == m.end()) - return ""; - std::string retstring; - ::decode(retstring, i->second); - return retstring; -} - -static std::string add_key_to_tmap(IoCtx &ioctx, const std::string &obj, - const std::string &key, const std::string &val) -{ - __u8 c = CEPH_OSD_TMAP_SET; - - bufferlist tmbl; - ::encode(c, tmbl); - ::encode(key, tmbl); - bufferlist blbl; - ::encode(val, blbl); - ::encode(blbl, tmbl); - int ret = ioctx.tmap_update(obj, tmbl); - if (ret) { - ostringstream oss; - oss << "ioctx.tmap_update(obj=" << obj << ", key=" - << key << ", val=" << val << ") failed with error " << ret; - return oss.str(); - } - return ""; -} - -static int remove_key_from_tmap(IoCtx &ioctx, const std::string &obj, - const std::string &key) -{ - __u8 c = CEPH_OSD_TMAP_RM; - - bufferlist tmbl; - ::encode(c, tmbl); - ::encode(key, tmbl); - int ret = ioctx.tmap_update(obj, tmbl); - if (ret) { - ostringstream oss; - oss << "ioctx.tmap_update(obj=" << obj << ", key=" - << key << ") failed with error " << ret; - } - return ret; -} - -TEST_F(LibRadosMiscPP, TmapUpdatePP) { - // create tmap - { - __u8 c = CEPH_OSD_TMAP_CREATE; - std::string my_tmap("my_tmap"); - bufferlist emptybl; - - bufferlist tmbl; - ::encode(c, tmbl); - ::encode(my_tmap, tmbl); - ::encode(emptybl, tmbl); - ASSERT_EQ(0, ioctx.tmap_update("foo", tmbl)); - } - - ASSERT_EQ(string(""), add_key_to_tmap(ioctx, "foo", "key1", "val1")); - - ASSERT_EQ(string(""), add_key_to_tmap(ioctx, "foo", "key2", "val2")); - - // read key1 from the tmap - ASSERT_EQ(string("val1"), read_key_from_tmap(ioctx, "foo", "key1")); - - // remove key1 from tmap - ASSERT_EQ(0, remove_key_from_tmap(ioctx, "foo", "key1")); - ASSERT_EQ(-ENOENT, remove_key_from_tmap(ioctx, "foo", "key1")); - - // key should be removed - ASSERT_EQ(string(""), read_key_from_tmap(ioctx, "foo", "key1")); -} - -TEST_F(LibRadosMiscPP, TmapUpdateMisorderedPP) { - // create tmap - { - __u8 c = CEPH_OSD_TMAP_CREATE; - std::string my_tmap("my_tmap"); - bufferlist emptybl; - - bufferlist tmbl; - ::encode(c, tmbl); - ::encode(my_tmap, tmbl); - ::encode(emptybl, tmbl); - ASSERT_EQ(0, ioctx.tmap_update("foo", tmbl)); - } - - // good update - { - __u8 c = CEPH_OSD_TMAP_SET; - bufferlist tmbl; - ::encode(c, tmbl); - ::encode("a", tmbl); - bufferlist blbl; - ::encode("old", blbl); - ::encode(blbl, tmbl); - - ::encode(c, tmbl); - ::encode("b", tmbl); - ::encode(blbl, tmbl); - - ::encode(c, tmbl); - ::encode("c", tmbl); - ::encode(blbl, tmbl); - - ASSERT_EQ(0, ioctx.tmap_update("foo", tmbl)); - } - - // bad update - { - __u8 c = CEPH_OSD_TMAP_SET; - bufferlist tmbl; - ::encode(c, tmbl); - ::encode("b", tmbl); - bufferlist blbl; - ::encode("new", blbl); - ::encode(blbl, tmbl); - - ::encode(c, tmbl); - ::encode("a", tmbl); - ::encode(blbl, tmbl); - - ::encode(c, tmbl); - ::encode("c", tmbl); - ::encode(blbl, tmbl); - - ASSERT_EQ(0, ioctx.tmap_update("foo", tmbl)); - } - - // check - ASSERT_EQ(string("new"), read_key_from_tmap(ioctx, "foo", "a")); - ASSERT_EQ(string("new"), read_key_from_tmap(ioctx, "foo", "b")); - ASSERT_EQ(string("new"), read_key_from_tmap(ioctx, "foo", "c")); - - ASSERT_EQ(0, remove_key_from_tmap(ioctx, "foo", "a")); - ASSERT_EQ(string(""), read_key_from_tmap(ioctx, "foo", "a")); - - ASSERT_EQ(0, remove_key_from_tmap(ioctx, "foo", "b")); - ASSERT_EQ(string(""), read_key_from_tmap(ioctx, "foo", "a")); -} - -TEST_F(LibRadosMiscPP, TmapUpdateMisorderedPutPP) { - // create unsorted tmap - string h("header"); - bufferlist bl; - ::encode(h, bl); - uint32_t n = 3; - ::encode(n, bl); - ::encode(string("b"), bl); - ::encode(string("bval"), bl); - ::encode(string("a"), bl); - ::encode(string("aval"), bl); - ::encode(string("c"), bl); - ::encode(string("cval"), bl); - bufferlist orig = bl; // tmap_put steals bl content - ASSERT_EQ(0, ioctx.tmap_put("foo", bl)); - - // check - bufferlist newbl; - ioctx.read("foo", newbl, orig.length(), 0); - ASSERT_EQ(orig.contents_equal(newbl), false); -} - -TEST_F(LibRadosMiscPP, Tmap2OmapPP) { - // create tmap - bufferlist hdr; - hdr.append("header"); - map omap; - omap["1"].append("a"); - omap["2"].append("b"); - omap["3"].append("c"); - { - bufferlist bl; - ::encode(hdr, bl); - ::encode(omap, bl); - ASSERT_EQ(0, ioctx.tmap_put("foo", bl)); - } - - // convert tmap to omap - ASSERT_EQ(0, ioctx.tmap_to_omap("foo", false)); - - // if tmap was truncated ? - { - uint64_t size; - time_t mtime; - ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime)); - ASSERT_EQ(0U, size); - } - - // if 'nullok' works - ASSERT_EQ(0, ioctx.tmap_to_omap("foo", true)); - ASSERT_LE(ioctx.tmap_to_omap("foo", false), 0); - - { - // read omap - bufferlist got; - map m; - ObjectReadOperation o; - o.omap_get_header(&got, NULL); - o.omap_get_vals2("", 1024, &m, nullptr, nullptr); - ASSERT_EQ(0, ioctx.operate("foo", &o, NULL)); - - // compare header - ASSERT_TRUE(hdr.contents_equal(got)); - - // compare values - ASSERT_EQ(omap.size(), m.size()); - bool same = true; - for (map::iterator p = omap.begin(); p != omap.end(); ++p) { - map::iterator q = m.find(p->first); - if (q == m.end() || !p->second.contents_equal(q->second)) { - same = false; - break; - } - } - ASSERT_TRUE(same); - } -} - -TEST_F(LibRadosMisc, Exec) { - char buf[128]; - memset(buf, 0xcc, sizeof(buf)); - ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0)); - char buf2[512]; - int res = rados_exec(ioctx, "foo", "rbd", "get_all_features", - NULL, 0, buf2, sizeof(buf2)); - ASSERT_GT(res, 0); - bufferlist bl; - bl.append(buf2, res); - bufferlist::iterator iter = bl.begin(); - uint64_t all_features; - ::decode(all_features, iter); - // make sure *some* features are specified; don't care which ones - ASSERT_NE(all_features, (unsigned)0); -} - -TEST_F(LibRadosMiscPP, ExecPP) { - bufferlist bl; - ASSERT_EQ(0, ioctx.write("foo", bl, 0, 0)); - bufferlist bl2, out; - int r = ioctx.exec("foo", "rbd", "get_all_features", bl2, out); - ASSERT_EQ(0, r); - bufferlist::iterator iter = out.begin(); - uint64_t all_features; - ::decode(all_features, iter); - // make sure *some* features are specified; don't care which ones - ASSERT_NE(all_features, (unsigned)0); -} - -void set_completion_complete(rados_completion_t cb, void *arg) -{ - bool *my_aio_complete = (bool*)arg; - *my_aio_complete = true; -} - -TEST_F(LibRadosMiscPP, BadFlagsPP) { - unsigned badflags = CEPH_OSD_FLAG_PARALLELEXEC; - { - bufferlist bl; - bl.append("data"); - ASSERT_EQ(0, ioctx.write("badfoo", bl, bl.length(), 0)); - } - { - ASSERT_EQ(-EINVAL, ioctx.remove("badfoo", badflags)); - } -} - -TEST_F(LibRadosMiscPP, Operate1PP) { - ObjectWriteOperation o; - { - bufferlist bl; - o.write(0, bl); - } - std::string val1("val1"); - { - bufferlist bl; - bl.append(val1.c_str(), val1.size() + 1); - o.setxattr("key1", bl); - o.omap_clear(); // shouldn't affect attrs! - } - ASSERT_EQ(0, ioctx.operate("foo", &o)); - - ObjectWriteOperation empty; - ASSERT_EQ(0, ioctx.operate("foo", &empty)); - - { - bufferlist bl; - ASSERT_GT(ioctx.getxattr("foo", "key1", bl), 0); - ASSERT_EQ(0, strcmp(bl.c_str(), val1.c_str())); - } - ObjectWriteOperation o2; - { - bufferlist bl; - bl.append(val1); - o2.cmpxattr("key1", CEPH_OSD_CMPXATTR_OP_EQ, bl); - o2.rmxattr("key1"); - } - ASSERT_EQ(-ECANCELED, ioctx.operate("foo", &o2)); - ObjectWriteOperation o3; - { - bufferlist bl; - bl.append(val1); - o3.cmpxattr("key1", CEPH_OSD_CMPXATTR_OP_EQ, bl); - } - ASSERT_EQ(-ECANCELED, ioctx.operate("foo", &o3)); -} - -TEST_F(LibRadosMiscPP, Operate2PP) { - ObjectWriteOperation o; - { - bufferlist bl; - bl.append("abcdefg"); - o.write(0, bl); - } - std::string val1("val1"); - { - bufferlist bl; - bl.append(val1.c_str(), val1.size() + 1); - o.setxattr("key1", bl); - o.truncate(0); - } - ASSERT_EQ(0, ioctx.operate("foo", &o)); - uint64_t size; - time_t mtime; - ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime)); - ASSERT_EQ(0U, size); -} - -TEST_F(LibRadosMiscPP, BigObjectPP) { - bufferlist bl; - bl.append("abcdefg"); - ASSERT_EQ(0, ioctx.write("foo", bl, bl.length(), 0)); - - { - ObjectWriteOperation o; - o.truncate(500000000000ull); - ASSERT_EQ(-EFBIG, ioctx.operate("foo", &o)); - } - { - ObjectWriteOperation o; - o.zero(500000000000ull, 1); - ASSERT_EQ(-EFBIG, ioctx.operate("foo", &o)); - } - { - ObjectWriteOperation o; - o.zero(1, 500000000000ull); - ASSERT_EQ(-EFBIG, ioctx.operate("foo", &o)); - } - { - ObjectWriteOperation o; - o.zero(500000000000ull, 500000000000ull); - ASSERT_EQ(-EFBIG, ioctx.operate("foo", &o)); - } - -#ifdef __LP64__ - // this test only works on 64-bit platforms - ASSERT_EQ(-EFBIG, ioctx.write("foo", bl, bl.length(), 500000000000ull)); -#endif -} - -TEST_F(LibRadosMiscPP, AioOperatePP) { - bool my_aio_complete = false; - AioCompletion *my_completion = cluster.aio_create_completion( - (void*)&my_aio_complete, set_completion_complete, NULL); - AioCompletion *my_completion_null = NULL; - ASSERT_NE(my_completion, my_completion_null); - - ObjectWriteOperation o; - { - bufferlist bl; - o.write(0, bl); - } - std::string val1("val1"); - { - bufferlist bl; - bl.append(val1.c_str(), val1.size() + 1); - o.setxattr("key1", bl); - bufferlist bl2; - char buf2[1024]; - memset(buf2, 0xdd, sizeof(buf2)); - bl2.append(buf2, sizeof(buf2)); - o.append(bl2); - } - ASSERT_EQ(0, ioctx.aio_operate("foo", my_completion, &o)); - ASSERT_EQ(0, my_completion->wait_for_complete_and_cb()); - ASSERT_EQ(my_aio_complete, true); - my_completion->release(); - - uint64_t size; - time_t mtime; - ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime)); - ASSERT_EQ(1024U, size); -} - -TEST_F(LibRadosMiscPP, AssertExistsPP) { - char buf[64]; - memset(buf, 0xcc, sizeof(buf)); - bufferlist bl; - bl.append(buf, sizeof(buf)); - - ObjectWriteOperation op; - op.assert_exists(); - op.write(0, bl); - ASSERT_EQ(-ENOENT, ioctx.operate("asdffoo", &op)); - ASSERT_EQ(0, ioctx.create("asdffoo", true)); - ASSERT_EQ(0, ioctx.operate("asdffoo", &op)); - ASSERT_EQ(-EEXIST, ioctx.create("asdffoo", true)); -} - -TEST_F(LibRadosMiscPP, AssertVersionPP) { - char buf[64]; - memset(buf, 0xcc, sizeof(buf)); - bufferlist bl; - bl.append(buf, sizeof(buf)); - - // Create test object... - ASSERT_EQ(0, ioctx.create("asdfbar", true)); - // ...then write it again to guarantee that the - // (unsigned) version must be at least 1 (not 0) - // since we want to decrement it by 1 later. - ASSERT_EQ(0, ioctx.write_full("asdfbar", bl)); - - uint64_t v = ioctx.get_last_version(); - ObjectWriteOperation op1; - op1.assert_version(v+1); - op1.write(0, bl); - ASSERT_EQ(-EOVERFLOW, ioctx.operate("asdfbar", &op1)); - ObjectWriteOperation op2; - op2.assert_version(v-1); - op2.write(0, bl); - ASSERT_EQ(-ERANGE, ioctx.operate("asdfbar", &op2)); - ObjectWriteOperation op3; - op3.assert_version(v); - op3.write(0, bl); - ASSERT_EQ(0, ioctx.operate("asdfbar", &op3)); -} - -TEST_F(LibRadosMiscPP, BigAttrPP) { - char buf[64]; - memset(buf, 0xcc, sizeof(buf)); - bufferlist bl; - bl.append(buf, sizeof(buf)); - - ASSERT_EQ(0, ioctx.create("foo", true)); - - bufferlist got; - - cout << "osd_max_attr_size = " << g_conf->osd_max_attr_size << std::endl; - if (g_conf->osd_max_attr_size) { - bl.clear(); - got.clear(); - bl.append(buffer::create(g_conf->osd_max_attr_size)); - ASSERT_EQ(0, ioctx.setxattr("foo", "one", bl)); - ASSERT_EQ((int)bl.length(), ioctx.getxattr("foo", "one", got)); - ASSERT_TRUE(bl.contents_equal(got)); - - bl.clear(); - bl.append(buffer::create(g_conf->osd_max_attr_size+1)); - ASSERT_EQ(-EFBIG, ioctx.setxattr("foo", "one", bl)); - } else { - cout << "osd_max_attr_size == 0; skipping test" << std::endl; - } - - for (int i=0; i<1000; i++) { - bl.clear(); - got.clear(); - bl.append(buffer::create(MIN(g_conf->osd_max_attr_size, 1024))); - char n[10]; - snprintf(n, sizeof(n), "a%d", i); - ASSERT_EQ(0, ioctx.setxattr("foo", n, bl)); - ASSERT_EQ((int)bl.length(), ioctx.getxattr("foo", n, got)); - ASSERT_TRUE(bl.contents_equal(got)); - } -} - -TEST_F(LibRadosMiscPP, CopyPP) { - bufferlist bl, x; - bl.append("hi there"); - x.append("bar"); - - // small object - bufferlist blc = bl; - bufferlist xc = x; - ASSERT_EQ(0, ioctx.write_full("foo", blc)); - ASSERT_EQ(0, ioctx.setxattr("foo", "myattr", xc)); - - version_t uv = ioctx.get_last_version(); - { - // pass future version - ObjectWriteOperation op; - op.copy_from2("foo", ioctx, uv + 1, LIBRADOS_OP_FLAG_FADVISE_DONTNEED); - ASSERT_EQ(-EOVERFLOW, ioctx.operate("foo.copy", &op)); - } - { - // pass old version - ObjectWriteOperation op; - op.copy_from2("foo", ioctx, uv - 1, LIBRADOS_OP_FLAG_FADVISE_DONTNEED); - ASSERT_EQ(-ERANGE, ioctx.operate("foo.copy", &op)); - } - { - ObjectWriteOperation op; - op.copy_from2("foo", ioctx, uv, LIBRADOS_OP_FLAG_FADVISE_DONTNEED); - ASSERT_EQ(0, ioctx.operate("foo.copy", &op)); - - bufferlist bl2, x2; - ASSERT_EQ((int)bl.length(), ioctx.read("foo.copy", bl2, 10000, 0)); - ASSERT_TRUE(bl.contents_equal(bl2)); - ASSERT_EQ((int)x.length(), ioctx.getxattr("foo.copy", "myattr", x2)); - ASSERT_TRUE(x.contents_equal(x2)); - } - - // small object without a version - { - ObjectWriteOperation op; - op.copy_from2("foo", ioctx, 0, LIBRADOS_OP_FLAG_FADVISE_DONTNEED); - ASSERT_EQ(0, ioctx.operate("foo.copy2", &op)); - - bufferlist bl2, x2; - ASSERT_EQ((int)bl.length(), ioctx.read("foo.copy2", bl2, 10000, 0)); - ASSERT_TRUE(bl.contents_equal(bl2)); - ASSERT_EQ((int)x.length(), ioctx.getxattr("foo.copy2", "myattr", x2)); - ASSERT_TRUE(x.contents_equal(x2)); - } - - // do a big object - bl.append(buffer::create(g_conf->osd_copyfrom_max_chunk * 3)); - bl.zero(); - bl.append("tail"); - blc = bl; - xc = x; - ASSERT_EQ(0, ioctx.write_full("big", blc)); - ASSERT_EQ(0, ioctx.setxattr("big", "myattr", xc)); - - { - ObjectWriteOperation op; - op.copy_from2("big", ioctx, ioctx.get_last_version(), LIBRADOS_OP_FLAG_FADVISE_DONTNEED); - ASSERT_EQ(0, ioctx.operate("big.copy", &op)); - - bufferlist bl2, x2; - ASSERT_EQ((int)bl.length(), ioctx.read("big.copy", bl2, bl.length(), 0)); - ASSERT_TRUE(bl.contents_equal(bl2)); - ASSERT_EQ((int)x.length(), ioctx.getxattr("foo.copy", "myattr", x2)); - ASSERT_TRUE(x.contents_equal(x2)); - } - - { - ObjectWriteOperation op; - op.copy_from2("big", ioctx, 0, LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL); - ASSERT_EQ(0, ioctx.operate("big.copy2", &op)); - - bufferlist bl2, x2; - ASSERT_EQ((int)bl.length(), ioctx.read("big.copy2", bl2, bl.length(), 0)); - ASSERT_TRUE(bl.contents_equal(bl2)); - ASSERT_EQ((int)x.length(), ioctx.getxattr("foo.copy2", "myattr", x2)); - ASSERT_TRUE(x.contents_equal(x2)); - } -} - -class LibRadosTwoPoolsECPP : public RadosTestECPP -{ -public: - LibRadosTwoPoolsECPP() {}; - ~LibRadosTwoPoolsECPP() override {}; -protected: - static void SetUpTestCase() { - pool_name = get_temp_pool_name(); - ASSERT_EQ("", create_one_ec_pool_pp(pool_name, s_cluster)); - src_pool_name = get_temp_pool_name(); - ASSERT_EQ(0, s_cluster.pool_create(src_pool_name.c_str())); - - librados::IoCtx ioctx; - ASSERT_EQ(0, s_cluster.ioctx_create(pool_name.c_str(), ioctx)); - ioctx.application_enable("rados", true); - - librados::IoCtx src_ioctx; - ASSERT_EQ(0, s_cluster.ioctx_create(src_pool_name.c_str(), src_ioctx)); - src_ioctx.application_enable("rados", true); - } - static void TearDownTestCase() { - ASSERT_EQ(0, s_cluster.pool_delete(src_pool_name.c_str())); - ASSERT_EQ(0, destroy_one_ec_pool_pp(pool_name, s_cluster)); - } - static std::string src_pool_name; - - void SetUp() override { - RadosTestECPP::SetUp(); - ASSERT_EQ(0, cluster.ioctx_create(src_pool_name.c_str(), src_ioctx)); - src_ioctx.set_namespace(nspace); - } - void TearDown() override { - // wait for maps to settle before next test - cluster.wait_for_latest_osdmap(); - - RadosTestECPP::TearDown(); - - cleanup_default_namespace(src_ioctx); - cleanup_namespace(src_ioctx, nspace); - - src_ioctx.close(); - } - - librados::IoCtx src_ioctx; -}; -std::string LibRadosTwoPoolsECPP::src_pool_name; - -//copy_from between ecpool and no-ecpool. -TEST_F(LibRadosTwoPoolsECPP, CopyFrom) { - bufferlist z; - z.append_zero(4194304*2); - bufferlist b; - b.append("copyfrom"); - - // create big object w/ omapheader - { - ASSERT_EQ(0, src_ioctx.write_full("foo", z)); - ASSERT_EQ(0, src_ioctx.omap_set_header("foo", b)); - version_t uv = src_ioctx.get_last_version(); - ObjectWriteOperation op; - op.copy_from("foo", src_ioctx, uv); - ASSERT_EQ(-EOPNOTSUPP, ioctx.operate("foo.copy", &op)); - } - - // same with small object - { - ASSERT_EQ(0, src_ioctx.omap_set_header("bar", b)); - version_t uv = src_ioctx.get_last_version(); - ObjectWriteOperation op; - op.copy_from("bar", src_ioctx, uv); - ASSERT_EQ(-EOPNOTSUPP, ioctx.operate("bar.copy", &op)); - } -} - -TEST_F(LibRadosMiscPP, CopyScrubPP) { - bufferlist inbl, bl, x; - for (int i=0; i<100; ++i) - x.append("barrrrrrrrrrrrrrrrrrrrrrrrrr"); - bl.append(buffer::create(g_conf->osd_copyfrom_max_chunk * 3)); - bl.zero(); - bl.append("tail"); - bufferlist cbl; - - map to_set; - for (int i=0; i<1000; ++i) - to_set[string("foo") + stringify(i)] = x; - - // small - cbl = x; - ASSERT_EQ(0, ioctx.write_full("small", cbl)); - ASSERT_EQ(0, ioctx.setxattr("small", "myattr", x)); - - // big - cbl = bl; - ASSERT_EQ(0, ioctx.write_full("big", cbl)); - - // without header - cbl = bl; - ASSERT_EQ(0, ioctx.write_full("big2", cbl)); - ASSERT_EQ(0, ioctx.setxattr("big2", "myattr", x)); - ASSERT_EQ(0, ioctx.setxattr("big2", "myattr2", x)); - ASSERT_EQ(0, ioctx.omap_set("big2", to_set)); - - // with header - cbl = bl; - ASSERT_EQ(0, ioctx.write_full("big3", cbl)); - ASSERT_EQ(0, ioctx.omap_set_header("big3", x)); - ASSERT_EQ(0, ioctx.omap_set("big3", to_set)); - - // deep scrub to ensure digests are in place - { - for (int i=0; i<10; ++i) { - ostringstream ss; - ss << "{\"prefix\": \"pg deep-scrub\", \"pgid\": \"" - << ioctx.get_id() << "." << i - << "\"}"; - cluster.mon_command(ss.str(), inbl, NULL, NULL); - } - - // give it a few seconds to go. this is sloppy but is usually enough time - cout << "waiting for initial deep scrubs..." << std::endl; - sleep(30); - cout << "done waiting, doing copies" << std::endl; - } - - { - ObjectWriteOperation op; - op.copy_from("small", ioctx, 0); - ASSERT_EQ(0, ioctx.operate("small.copy", &op)); - } - - { - ObjectWriteOperation op; - op.copy_from("big", ioctx, 0); - ASSERT_EQ(0, ioctx.operate("big.copy", &op)); - } - - { - ObjectWriteOperation op; - op.copy_from("big2", ioctx, 0); - ASSERT_EQ(0, ioctx.operate("big2.copy", &op)); - } - - { - ObjectWriteOperation op; - op.copy_from("big3", ioctx, 0); - ASSERT_EQ(0, ioctx.operate("big3.copy", &op)); - } - - // deep scrub to ensure digests are correct - { - for (int i=0; i<10; ++i) { - ostringstream ss; - ss << "{\"prefix\": \"pg deep-scrub\", \"pgid\": \"" - << ioctx.get_id() << "." << i - << "\"}"; - cluster.mon_command(ss.str(), inbl, NULL, NULL); - } - - // give it a few seconds to go. this is sloppy but is usually enough time - cout << "waiting for final deep scrubs..." << std::endl; - sleep(30); - cout << "done waiting" << std::endl; - } -} - -TEST_F(LibRadosMiscPP, WriteSamePP) { - bufferlist bl; - char buf[128]; - bufferlist fl; - char full[128 * 4]; - char *cmp; - - /* zero the full range before using writesame */ - memset(full, 0, sizeof(full)); - fl.append(full, sizeof(full)); - ASSERT_EQ(0, ioctx.write("ws", fl, fl.length(), 0)); - - memset(buf, 0xcc, sizeof(buf)); - bl.clear(); - bl.append(buf, sizeof(buf)); - /* write the same buf four times */ - ASSERT_EQ(0, ioctx.writesame("ws", bl, sizeof(full), 0)); - - /* read back the full buffer and confirm that it matches */ - fl.clear(); - fl.append(full, sizeof(full)); - ASSERT_EQ((int)fl.length(), ioctx.read("ws", fl, fl.length(), 0)); - - for (cmp = fl.c_str(); cmp < fl.c_str() + fl.length(); cmp += sizeof(buf)) { - ASSERT_EQ(0, memcmp(cmp, buf, sizeof(buf))); - } - - /* write_len not a multiple of data_len should throw error */ - bl.clear(); - bl.append(buf, sizeof(buf)); - ASSERT_EQ(-EINVAL, ioctx.writesame("ws", bl, (sizeof(buf) * 4) - 1, 0)); - ASSERT_EQ(-EINVAL, - ioctx.writesame("ws", bl, bl.length() / 2, 0)); - /* write_len = data_len, i.e. same as write() */ - ASSERT_EQ(0, ioctx.writesame("ws", bl, sizeof(buf), 0)); - bl.clear(); - ASSERT_EQ(-EINVAL, - ioctx.writesame("ws", bl, sizeof(buf), 0)); -} - -TEST_F(LibRadosMisc, WriteSame) { - char buf[128]; - char full[128 * 4]; - char *cmp; - - /* zero the full range before using writesame */ - memset(full, 0, sizeof(full)); - ASSERT_EQ(0, rados_write(ioctx, "ws", full, sizeof(full), 0)); - - memset(buf, 0xcc, sizeof(buf)); - /* write the same buf four times */ - ASSERT_EQ(0, rados_writesame(ioctx, "ws", buf, sizeof(buf), sizeof(full), 0)); - - /* read back the full buffer and confirm that it matches */ - ASSERT_EQ((int)sizeof(full), rados_read(ioctx, "ws", full, sizeof(full), 0)); - - for (cmp = full; cmp < full + sizeof(full); cmp += sizeof(buf)) { - ASSERT_EQ(0, memcmp(cmp, buf, sizeof(buf))); - } - - /* write_len not a multiple of data_len should throw error */ - ASSERT_EQ(-EINVAL, rados_writesame(ioctx, "ws", buf, sizeof(buf), - (sizeof(buf) * 4) - 1, 0)); - ASSERT_EQ(-EINVAL, - rados_writesame(ioctx, "ws", buf, sizeof(buf), sizeof(buf) / 2, 0)); - ASSERT_EQ(-EINVAL, - rados_writesame(ioctx, "ws", buf, 0, sizeof(buf), 0)); - /* write_len = data_len, i.e. same as rados_write() */ - ASSERT_EQ(0, rados_writesame(ioctx, "ws", buf, sizeof(buf), sizeof(buf), 0)); -} - -template -class LibRadosChecksum : public LibRadosMiscPP { -public: - typedef typename T::alg_t alg_t; - typedef typename T::value_t value_t; - typedef typename alg_t::init_value_t init_value_t; - - static const rados_checksum_type_t type = T::type; - - bufferlist content_bl; - - using LibRadosMiscPP::SetUpTestCase; - using LibRadosMiscPP::TearDownTestCase; - - void SetUp() override { - LibRadosMiscPP::SetUp(); - - std::string content(4096, '\0'); - for (size_t i = 0; i < content.length(); ++i) { - content[i] = static_cast(rand() % (126 - 33) + 33); - } - content_bl.append(content); - ASSERT_EQ(0, ioctx.write("foo", content_bl, content_bl.length(), 0)); - } -}; - -template -class LibRadosChecksumParams { -public: - typedef AlgT alg_t; - typedef ValueT value_t; - static const rados_checksum_type_t type = _type; -}; - -typedef ::testing::Types< - LibRadosChecksumParams, - LibRadosChecksumParams, - LibRadosChecksumParams - > LibRadosChecksumTypes; - -TYPED_TEST_CASE(LibRadosChecksum, LibRadosChecksumTypes); - -TYPED_TEST(LibRadosChecksum, Subset) { - uint32_t chunk_size = 1024; - uint32_t csum_count = this->content_bl.length() / chunk_size; - - typename TestFixture::init_value_t init_value = -1; - bufferlist init_value_bl; - ::encode(init_value, init_value_bl); - - std::vector checksum_bls(csum_count); - std::vector checksum_rvals(csum_count); - - // individual checksum ops for each chunk - ObjectReadOperation op; - for (uint32_t i = 0; i < csum_count; ++i) { - op.checksum(TestFixture::type, init_value_bl, i * chunk_size, chunk_size, - 0, &checksum_bls[i], &checksum_rvals[i]); - } - ASSERT_EQ(0, this->ioctx.operate("foo", &op, NULL)); - - for (uint32_t i = 0; i < csum_count; ++i) { - ASSERT_EQ(0, checksum_rvals[i]); - - auto bl_it = checksum_bls[i].begin(); - uint32_t count; - ::decode(count, bl_it); - ASSERT_EQ(1U, count); - - typename TestFixture::value_t value; - ::decode(value, bl_it); - - bufferlist content_sub_bl; - content_sub_bl.substr_of(this->content_bl, i * chunk_size, chunk_size); - - typename TestFixture::value_t expected_value; - bufferptr expected_value_bp = buffer::create_static( - sizeof(expected_value), reinterpret_cast(&expected_value)); - Checksummer::template calculate( - init_value, chunk_size, 0, chunk_size, content_sub_bl, - &expected_value_bp); - ASSERT_EQ(expected_value, value); - } -} - -TYPED_TEST(LibRadosChecksum, Chunked) { - uint32_t chunk_size = 1024; - uint32_t csum_count = this->content_bl.length() / chunk_size; - - typename TestFixture::init_value_t init_value = -1; - bufferlist init_value_bl; - ::encode(init_value, init_value_bl); - - bufferlist checksum_bl; - int checksum_rval; - - // single op with chunked checksum results - ObjectReadOperation op; - op.checksum(TestFixture::type, init_value_bl, 0, this->content_bl.length(), - chunk_size, &checksum_bl, &checksum_rval); - ASSERT_EQ(0, this->ioctx.operate("foo", &op, NULL)); - ASSERT_EQ(0, checksum_rval); - - auto bl_it = checksum_bl.begin(); - uint32_t count; - ::decode(count, bl_it); - ASSERT_EQ(csum_count, count); - - std::vector expected_values(csum_count); - bufferptr expected_values_bp = buffer::create_static( - csum_count * sizeof(typename TestFixture::value_t), - reinterpret_cast(&expected_values[0])); - - Checksummer::template calculate( - init_value, chunk_size, 0, this->content_bl.length(), this->content_bl, - &expected_values_bp); - - for (uint32_t i = 0; i < csum_count; ++i) { - typename TestFixture::value_t value; - ::decode(value, bl_it); - ASSERT_EQ(expected_values[i], value); - } -} - -TEST_F(LibRadosMiscPP, CmpExtPP) { - bufferlist cmp_bl, bad_cmp_bl, write_bl; - char stored_str[] = "1234567891"; - char mismatch_str[] = "1234577777"; - - write_bl.append(stored_str); - ioctx.write("cmpextpp", write_bl, write_bl.length(), 0); - cmp_bl.append(stored_str); - ASSERT_EQ(0, ioctx.cmpext("cmpextpp", 0, cmp_bl)); - - bad_cmp_bl.append(mismatch_str); - ASSERT_EQ(-MAX_ERRNO - 5, ioctx.cmpext("cmpextpp", 0, bad_cmp_bl)); -} - -TEST_F(LibRadosMisc, CmpExt) { - bufferlist cmp_bl, bad_cmp_bl, write_bl; - char stored_str[] = "1234567891"; - char mismatch_str[] = "1234577777"; - - ASSERT_EQ(0, - rados_write(ioctx, "cmpextpp", stored_str, sizeof(stored_str), 0)); - - ASSERT_EQ(0, - rados_cmpext(ioctx, "cmpextpp", stored_str, sizeof(stored_str), 0)); - - ASSERT_EQ(-MAX_ERRNO - 5, - rados_cmpext(ioctx, "cmpextpp", mismatch_str, sizeof(mismatch_str), 0)); -} - -TEST_F(LibRadosMisc, Applications) { - const char *cmd[] = {"{\"prefix\":\"osd dump\"}", nullptr}; - char *buf, *st; - size_t buflen, stlen; - ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, - &buflen, &st, &stlen)); - ASSERT_LT(0u, buflen); - string result(buf); - rados_buffer_free(buf); - rados_buffer_free(st); - if (!boost::regex_search(result, boost::regex("require_osd_release [l-z]"))) { - std::cout << "SKIPPING"; - return; - } - - char apps[128]; - size_t app_len; - - app_len = sizeof(apps); - ASSERT_EQ(0, rados_application_list(ioctx, apps, &app_len)); - ASSERT_EQ(6U, app_len); - ASSERT_EQ(0, memcmp("rados\0", apps, app_len)); - - ASSERT_EQ(0, rados_application_enable(ioctx, "app1", 1)); - ASSERT_EQ(-EPERM, rados_application_enable(ioctx, "app2", 0)); - ASSERT_EQ(0, rados_application_enable(ioctx, "app2", 1)); - - ASSERT_EQ(-ERANGE, rados_application_list(ioctx, apps, &app_len)); - ASSERT_EQ(16U, app_len); - ASSERT_EQ(0, rados_application_list(ioctx, apps, &app_len)); - ASSERT_EQ(16U, app_len); - ASSERT_EQ(0, memcmp("app1\0app2\0rados\0", apps, app_len)); - - char keys[128]; - char vals[128]; - size_t key_len; - size_t val_len; - - key_len = sizeof(keys); - val_len = sizeof(vals); - ASSERT_EQ(-ENOENT, rados_application_metadata_list(ioctx, "dne", keys, - &key_len, vals, &val_len)); - ASSERT_EQ(0, rados_application_metadata_list(ioctx, "app1", keys, &key_len, - vals, &val_len)); - ASSERT_EQ(0U, key_len); - ASSERT_EQ(0U, val_len); - - ASSERT_EQ(-ENOENT, rados_application_metadata_set(ioctx, "dne", "key", - "value")); - ASSERT_EQ(0, rados_application_metadata_set(ioctx, "app1", "key1", "value1")); - ASSERT_EQ(0, rados_application_metadata_set(ioctx, "app1", "key2", "value2")); - - ASSERT_EQ(-ERANGE, rados_application_metadata_list(ioctx, "app1", keys, - &key_len, vals, &val_len)); - ASSERT_EQ(10U, key_len); - ASSERT_EQ(14U, val_len); - ASSERT_EQ(0, rados_application_metadata_list(ioctx, "app1", keys, &key_len, - vals, &val_len)); - ASSERT_EQ(10U, key_len); - ASSERT_EQ(14U, val_len); - ASSERT_EQ(0, memcmp("key1\0key2\0", keys, key_len)); - ASSERT_EQ(0, memcmp("value1\0value2\0", vals, val_len)); - - ASSERT_EQ(0, rados_application_metadata_remove(ioctx, "app1", "key1")); - ASSERT_EQ(0, rados_application_metadata_list(ioctx, "app1", keys, &key_len, - vals, &val_len)); - ASSERT_EQ(5U, key_len); - ASSERT_EQ(7U, val_len); - ASSERT_EQ(0, memcmp("key2\0", keys, key_len)); - ASSERT_EQ(0, memcmp("value2\0", vals, val_len)); -} - -TEST_F(LibRadosMiscPP, Applications) { - bufferlist inbl, outbl; - string outs; - ASSERT_EQ(0, cluster.mon_command("{\"prefix\": \"osd dump\"}", - inbl, &outbl, &outs)); - ASSERT_LT(0u, outbl.length()); - ASSERT_LE(0u, outs.length()); - if (!boost::regex_search(outbl.to_str(), - boost::regex("require_osd_release [l-z]"))) { - std::cout << "SKIPPING"; - return; - } - - std::set expected_apps = {"rados"}; - std::set apps; - ASSERT_EQ(0, ioctx.application_list(&apps)); - ASSERT_EQ(expected_apps, apps); - - ASSERT_EQ(0, ioctx.application_enable("app1", true)); - ASSERT_EQ(-EPERM, ioctx.application_enable("app2", false)); - ASSERT_EQ(0, ioctx.application_enable("app2", true)); - - expected_apps = {"app1", "app2", "rados"}; - ASSERT_EQ(0, ioctx.application_list(&apps)); - ASSERT_EQ(expected_apps, apps); - - std::map expected_meta; - std::map meta; - ASSERT_EQ(-ENOENT, ioctx.application_metadata_list("dne", &meta)); - ASSERT_EQ(0, ioctx.application_metadata_list("app1", &meta)); - ASSERT_EQ(expected_meta, meta); - - ASSERT_EQ(-ENOENT, ioctx.application_metadata_set("dne", "key1", "value1")); - ASSERT_EQ(0, ioctx.application_metadata_set("app1", "key1", "value1")); - ASSERT_EQ(0, ioctx.application_metadata_set("app1", "key2", "value2")); - - expected_meta = {{"key1", "value1"}, {"key2", "value2"}}; - ASSERT_EQ(0, ioctx.application_metadata_list("app1", &meta)); - ASSERT_EQ(expected_meta, meta); - - ASSERT_EQ(0, ioctx.application_metadata_remove("app1", "key1")); - - expected_meta = {{"key2", "value2"}}; - ASSERT_EQ(0, ioctx.application_metadata_list("app1", &meta)); - ASSERT_EQ(expected_meta, meta); -} - -TEST_F(LibRadosMiscECPP, CompareExtentRange) { - bufferlist bl1; - bl1.append("ceph"); - ObjectWriteOperation write; - write.write(0, bl1); - ASSERT_EQ(0, ioctx.operate("foo", &write)); - - bufferlist bl2; - bl2.append("ph"); - bl2.append(std::string(2, '\0')); - ObjectReadOperation read1; - read1.cmpext(2, bl2, nullptr); - ASSERT_EQ(0, ioctx.operate("foo", &read1, nullptr)); - - bufferlist bl3; - bl3.append(std::string(4, '\0')); - ObjectReadOperation read2; - read2.cmpext(2097152, bl3, nullptr); - ASSERT_EQ(0, ioctx.operate("foo", &read2, nullptr)); -}