X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Ftest%2Flibrados%2Fc_write_operations.cc;fp=src%2Fceph%2Fsrc%2Ftest%2Flibrados%2Fc_write_operations.cc;h=325a2f0a3e0dd0b520705e2effa58b5179c89d6f;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/test/librados/c_write_operations.cc b/src/ceph/src/test/librados/c_write_operations.cc new file mode 100644 index 0000000..325a2f0 --- /dev/null +++ b/src/ceph/src/test/librados/c_write_operations.cc @@ -0,0 +1,279 @@ +// Tests for the C API coverage of atomic write operations + +#include +#include "include/err.h" +#include "include/rados/librados.h" +#include "test/librados/test.h" +#include "gtest/gtest.h" + +TEST(LibradosCWriteOps, NewDelete) { + rados_write_op_t op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_release_write_op(op); +} + +TEST(LibRadosCWriteOps, assertExists) { + rados_t cluster; + rados_ioctx_t ioctx; + std::string pool_name = get_temp_pool_name(); + ASSERT_EQ("", create_one_pool(pool_name, &cluster)); + rados_ioctx_create(cluster, pool_name.c_str(), &ioctx); + + rados_write_op_t op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_assert_exists(op); + + // -2, ENOENT + ASSERT_EQ(-2, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + rados_release_write_op(op); + + rados_write_op_t op2 = rados_create_write_op(); + ASSERT_TRUE(op2); + rados_write_op_assert_exists(op2); + + rados_completion_t completion; + ASSERT_EQ(0, rados_aio_create_completion(NULL, NULL, NULL, &completion)); + ASSERT_EQ(0, rados_aio_write_op_operate(op2, ioctx, completion, "test", NULL, 0)); + rados_aio_wait_for_complete(completion); + ASSERT_EQ(-2, rados_aio_get_return_value(completion)); + rados_aio_release(completion); + + rados_ioctx_destroy(ioctx); + rados_release_write_op(op2); + ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster)); +} + +TEST(LibRadosCWriteOps, WriteOpAssertVersion) { + rados_t cluster; + rados_ioctx_t ioctx; + std::string pool_name = get_temp_pool_name(); + ASSERT_EQ("", create_one_pool(pool_name, &cluster)); + rados_ioctx_create(cluster, pool_name.c_str(), &ioctx); + + rados_write_op_t op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_create(op, LIBRADOS_CREATE_EXCLUSIVE, NULL); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + rados_release_write_op(op); + + // Write to the object a second time to guarantee that its + // version number is greater than 0 + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_write_full(op, "hi", 2); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + rados_release_write_op(op); + + uint64_t v = rados_get_last_version(ioctx); + + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_assert_version(op, v+1); + ASSERT_EQ(-EOVERFLOW, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + rados_release_write_op(op); + + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_assert_version(op, v-1); + ASSERT_EQ(-ERANGE, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + rados_release_write_op(op); + + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_assert_version(op, v); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + rados_release_write_op(op); + + rados_ioctx_destroy(ioctx); + ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster)); +} + +TEST(LibRadosCWriteOps, Xattrs) { + rados_t cluster; + rados_ioctx_t ioctx; + std::string pool_name = get_temp_pool_name(); + ASSERT_EQ("", create_one_pool(pool_name, &cluster)); + rados_ioctx_create(cluster, pool_name.c_str(), &ioctx); + + // Create an object with an xattr + rados_write_op_t op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_create(op, LIBRADOS_CREATE_EXCLUSIVE, NULL); + rados_write_op_setxattr(op, "key", "value", 5); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + rados_release_write_op(op); + + // Check that xattr exists, if it does, delete it. + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_create(op, LIBRADOS_CREATE_IDEMPOTENT, NULL); + rados_write_op_cmpxattr(op, "key", LIBRADOS_CMPXATTR_OP_EQ, "value", 5); + rados_write_op_rmxattr(op, "key"); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + rados_release_write_op(op); + + // Check the xattr exits, if it does, add it again (will fail) with -125 + // (ECANCELED) + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_cmpxattr(op, "key", LIBRADOS_CMPXATTR_OP_EQ, "value", 5); + rados_write_op_setxattr(op, "key", "value", 5); + ASSERT_EQ(-ECANCELED, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + + rados_release_write_op(op); + rados_ioctx_destroy(ioctx); + ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster)); +} + +TEST(LibRadosCWriteOps, Write) { + rados_t cluster; + rados_ioctx_t ioctx; + std::string pool_name = get_temp_pool_name(); + ASSERT_EQ("", create_one_pool(pool_name, &cluster)); + rados_ioctx_create(cluster, pool_name.c_str(), &ioctx); + + // Create an object, write and write full to it + rados_write_op_t op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_create(op, LIBRADOS_CREATE_EXCLUSIVE, NULL); + rados_write_op_write(op, "four", 4, 0); + rados_write_op_write_full(op, "hi", 2); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + char hi[4]; + ASSERT_EQ(2, rados_read(ioctx, "test", hi, 4, 0)); + rados_release_write_op(op); + + //create write op with iohint + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_write_full(op, "ceph", 4); + rados_write_op_set_flags(op, LIBRADOS_OP_FLAG_FADVISE_NOCACHE); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + ASSERT_EQ(4, rados_read(ioctx, "test", hi, 4, 0)); + rados_release_write_op(op); + + // Truncate and append + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_truncate(op, 1); + rados_write_op_append(op, "hi", 2); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + ASSERT_EQ(3, rados_read(ioctx, "test", hi, 4, 0)); + rados_release_write_op(op); + + // zero and remove + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_zero(op, 0, 3); + rados_write_op_remove(op); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + // ENOENT + ASSERT_EQ(-2, rados_read(ioctx, "test", hi, 4, 0)); + rados_release_write_op(op); + + rados_ioctx_destroy(ioctx); + ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster)); +} + +TEST(LibRadosCWriteOps, Exec) { + rados_t cluster; + rados_ioctx_t ioctx; + std::string pool_name = get_temp_pool_name(); + ASSERT_EQ("", create_one_pool(pool_name, &cluster)); + rados_ioctx_create(cluster, pool_name.c_str(), &ioctx); + + int rval = 1; + rados_write_op_t op = rados_create_write_op(); + rados_write_op_exec(op, "hello", "record_hello", "test", 4, &rval); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + rados_release_write_op(op); + ASSERT_EQ(0, rval); + + char hi[100]; + ASSERT_EQ(12, rados_read(ioctx, "test", hi, 100, 0)); + hi[12] = '\0'; + ASSERT_EQ(0, strcmp("Hello, test!", hi)); + + rados_ioctx_destroy(ioctx); + ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster)); +} + +TEST(LibRadosCWriteOps, WriteSame) { + rados_t cluster; + rados_ioctx_t ioctx; + std::string pool_name = get_temp_pool_name(); + ASSERT_EQ("", create_one_pool(pool_name, &cluster)); + rados_ioctx_create(cluster, pool_name.c_str(), &ioctx); + + // Create an object, write to it using writesame + rados_write_op_t op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_create(op, LIBRADOS_CREATE_EXCLUSIVE, NULL); + rados_write_op_writesame(op, "four", 4, 4 * 4, 0); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + char hi[4 * 4]; + ASSERT_EQ(sizeof(hi), static_cast( + rados_read(ioctx, "test", hi,sizeof(hi), 0))); + rados_release_write_op(op); + ASSERT_EQ(0, memcmp("fourfourfourfour", hi, sizeof(hi))); + + // cleanup + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_remove(op); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + rados_release_write_op(op); + + rados_ioctx_destroy(ioctx); + ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster)); +} + +TEST(LibRadosCWriteOps, CmpExt) { + rados_t cluster; + rados_ioctx_t ioctx; + std::string pool_name = get_temp_pool_name(); + ASSERT_EQ("", create_one_pool(pool_name, &cluster)); + rados_ioctx_create(cluster, pool_name.c_str(), &ioctx); + + // create an object, write to it using writesame + rados_write_op_t op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_create(op, LIBRADOS_CREATE_EXCLUSIVE, NULL); + rados_write_op_write(op, "four", 4, 0); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + rados_release_write_op(op); + char hi[4]; + ASSERT_EQ(sizeof(hi), static_cast(rados_read(ioctx, "test", hi, sizeof(hi), 0))); + ASSERT_EQ(0, memcmp("four", hi, sizeof(hi))); + + // compare and overwrite on (expected) match + int val = 0; + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_cmpext(op, "four", 4, 0, &val); + rados_write_op_write(op, "five", 4, 0); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + ASSERT_EQ(0, val); + rados_release_write_op(op); + ASSERT_EQ(sizeof(hi), static_cast(rados_read(ioctx, "test", hi, sizeof(hi), 0))); + ASSERT_EQ(0, memcmp("five", hi, sizeof(hi))); + + // compare and bail before write due to mismatch + val = 0; + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_cmpext(op, "four", 4, 0, &val); + rados_write_op_write(op, "six ", 4, 0); + ASSERT_EQ(-MAX_ERRNO - 1, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + + ASSERT_EQ(-MAX_ERRNO - 1, val); + + // cleanup + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_remove(op); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + + rados_ioctx_destroy(ioctx); + ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster)); +}