Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / librados / c_write_operations.cc
1 // Tests for the C API coverage of atomic write operations
2
3 #include <errno.h>
4 #include "include/err.h"
5 #include "include/rados/librados.h"
6 #include "test/librados/test.h"
7 #include "gtest/gtest.h"
8
9 TEST(LibradosCWriteOps, NewDelete) {
10   rados_write_op_t op = rados_create_write_op();
11   ASSERT_TRUE(op);
12   rados_release_write_op(op);
13 }
14
15 TEST(LibRadosCWriteOps, assertExists) {
16   rados_t cluster;
17   rados_ioctx_t ioctx;
18   std::string pool_name = get_temp_pool_name();
19   ASSERT_EQ("", create_one_pool(pool_name, &cluster));
20   rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
21
22   rados_write_op_t op = rados_create_write_op();
23   ASSERT_TRUE(op);
24   rados_write_op_assert_exists(op);
25
26   // -2, ENOENT
27   ASSERT_EQ(-2, rados_write_op_operate(op, ioctx, "test", NULL, 0));
28   rados_release_write_op(op);
29
30   rados_write_op_t op2 = rados_create_write_op();
31   ASSERT_TRUE(op2);
32   rados_write_op_assert_exists(op2);
33
34   rados_completion_t completion;
35   ASSERT_EQ(0, rados_aio_create_completion(NULL, NULL, NULL, &completion));
36   ASSERT_EQ(0, rados_aio_write_op_operate(op2, ioctx, completion, "test", NULL, 0));
37   rados_aio_wait_for_complete(completion);
38   ASSERT_EQ(-2, rados_aio_get_return_value(completion));
39   rados_aio_release(completion);
40
41   rados_ioctx_destroy(ioctx);
42   rados_release_write_op(op2);
43   ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
44 }
45
46 TEST(LibRadosCWriteOps, WriteOpAssertVersion) {
47   rados_t cluster;
48   rados_ioctx_t ioctx;
49   std::string pool_name = get_temp_pool_name();
50   ASSERT_EQ("", create_one_pool(pool_name, &cluster));
51   rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
52
53   rados_write_op_t op = rados_create_write_op();
54   ASSERT_TRUE(op);
55   rados_write_op_create(op, LIBRADOS_CREATE_EXCLUSIVE, NULL);
56   ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
57   rados_release_write_op(op);
58
59   // Write to the object a second time to guarantee that its
60   // version number is greater than 0
61   op = rados_create_write_op();
62   ASSERT_TRUE(op);
63   rados_write_op_write_full(op, "hi", 2);
64   ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
65   rados_release_write_op(op);
66
67   uint64_t v = rados_get_last_version(ioctx);
68
69   op = rados_create_write_op();
70   ASSERT_TRUE(op);
71   rados_write_op_assert_version(op, v+1);
72   ASSERT_EQ(-EOVERFLOW, rados_write_op_operate(op, ioctx, "test", NULL, 0));
73   rados_release_write_op(op);
74
75   op = rados_create_write_op();
76   ASSERT_TRUE(op);
77   rados_write_op_assert_version(op, v-1);
78   ASSERT_EQ(-ERANGE, rados_write_op_operate(op, ioctx, "test", NULL, 0));
79   rados_release_write_op(op);
80
81   op = rados_create_write_op();
82   ASSERT_TRUE(op);
83   rados_write_op_assert_version(op, v);
84   ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
85   rados_release_write_op(op);
86
87   rados_ioctx_destroy(ioctx);
88   ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
89 }
90
91 TEST(LibRadosCWriteOps, Xattrs) {
92   rados_t cluster;
93   rados_ioctx_t ioctx;
94   std::string pool_name = get_temp_pool_name();
95   ASSERT_EQ("", create_one_pool(pool_name, &cluster));
96   rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
97
98   // Create an object with an xattr
99   rados_write_op_t op = rados_create_write_op();
100   ASSERT_TRUE(op);
101   rados_write_op_create(op, LIBRADOS_CREATE_EXCLUSIVE, NULL);
102   rados_write_op_setxattr(op, "key", "value", 5);
103   ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
104   rados_release_write_op(op);
105
106   // Check that xattr exists, if it does, delete it.
107   op = rados_create_write_op();
108   ASSERT_TRUE(op);
109   rados_write_op_create(op, LIBRADOS_CREATE_IDEMPOTENT, NULL);
110   rados_write_op_cmpxattr(op, "key", LIBRADOS_CMPXATTR_OP_EQ, "value", 5);
111   rados_write_op_rmxattr(op, "key");
112   ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
113   rados_release_write_op(op);
114
115   // Check the xattr exits, if it does, add it again (will fail) with -125
116   // (ECANCELED)
117   op = rados_create_write_op();
118   ASSERT_TRUE(op);
119   rados_write_op_cmpxattr(op, "key", LIBRADOS_CMPXATTR_OP_EQ, "value", 5);
120   rados_write_op_setxattr(op, "key", "value", 5);
121   ASSERT_EQ(-ECANCELED, rados_write_op_operate(op, ioctx, "test", NULL, 0));
122
123   rados_release_write_op(op);
124   rados_ioctx_destroy(ioctx);
125   ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
126 }
127
128 TEST(LibRadosCWriteOps, Write) {
129   rados_t cluster;
130   rados_ioctx_t ioctx;
131   std::string pool_name = get_temp_pool_name();
132   ASSERT_EQ("", create_one_pool(pool_name, &cluster));
133   rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
134
135   // Create an object, write and write full to it
136   rados_write_op_t op = rados_create_write_op();
137   ASSERT_TRUE(op);
138   rados_write_op_create(op, LIBRADOS_CREATE_EXCLUSIVE, NULL);
139   rados_write_op_write(op, "four", 4, 0);
140   rados_write_op_write_full(op, "hi", 2);
141   ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
142   char hi[4];
143   ASSERT_EQ(2, rados_read(ioctx, "test", hi, 4, 0));
144   rados_release_write_op(op);
145
146   //create write op with iohint
147   op = rados_create_write_op();
148   ASSERT_TRUE(op);
149   rados_write_op_write_full(op, "ceph", 4);
150   rados_write_op_set_flags(op, LIBRADOS_OP_FLAG_FADVISE_NOCACHE);
151   ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
152   ASSERT_EQ(4, rados_read(ioctx, "test", hi, 4, 0));
153   rados_release_write_op(op);
154
155   // Truncate and append
156   op = rados_create_write_op();
157   ASSERT_TRUE(op);
158   rados_write_op_truncate(op, 1);
159   rados_write_op_append(op, "hi", 2);
160   ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
161   ASSERT_EQ(3, rados_read(ioctx, "test", hi, 4, 0));
162   rados_release_write_op(op);
163
164   // zero and remove
165   op = rados_create_write_op();
166   ASSERT_TRUE(op);
167   rados_write_op_zero(op, 0, 3);
168   rados_write_op_remove(op);
169   ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
170   // ENOENT
171   ASSERT_EQ(-2, rados_read(ioctx, "test", hi, 4, 0));
172   rados_release_write_op(op);
173
174   rados_ioctx_destroy(ioctx);
175   ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
176 }
177
178 TEST(LibRadosCWriteOps, Exec) {
179   rados_t cluster;
180   rados_ioctx_t ioctx;
181   std::string pool_name = get_temp_pool_name();
182   ASSERT_EQ("", create_one_pool(pool_name, &cluster));
183   rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
184
185   int rval = 1;
186   rados_write_op_t op = rados_create_write_op();
187   rados_write_op_exec(op, "hello", "record_hello", "test", 4, &rval);
188   ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
189   rados_release_write_op(op);
190   ASSERT_EQ(0, rval);
191
192   char hi[100];
193   ASSERT_EQ(12, rados_read(ioctx, "test", hi, 100, 0));
194   hi[12] = '\0';
195   ASSERT_EQ(0, strcmp("Hello, test!", hi));
196
197   rados_ioctx_destroy(ioctx);
198   ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
199 }
200
201 TEST(LibRadosCWriteOps, WriteSame) {
202   rados_t cluster;
203   rados_ioctx_t ioctx;
204   std::string pool_name = get_temp_pool_name();
205   ASSERT_EQ("", create_one_pool(pool_name, &cluster));
206   rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
207
208   // Create an object, write to it using writesame
209   rados_write_op_t op = rados_create_write_op();
210   ASSERT_TRUE(op);
211   rados_write_op_create(op, LIBRADOS_CREATE_EXCLUSIVE, NULL);
212   rados_write_op_writesame(op, "four", 4, 4 * 4, 0);
213   ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
214   char hi[4 * 4];
215   ASSERT_EQ(sizeof(hi), static_cast<std::size_t>(
216                 rados_read(ioctx, "test", hi,sizeof(hi), 0)));
217   rados_release_write_op(op);
218   ASSERT_EQ(0, memcmp("fourfourfourfour", hi, sizeof(hi)));
219
220   // cleanup
221   op = rados_create_write_op();
222   ASSERT_TRUE(op);
223   rados_write_op_remove(op);
224   ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
225   rados_release_write_op(op);
226
227   rados_ioctx_destroy(ioctx);
228   ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
229 }
230
231 TEST(LibRadosCWriteOps, CmpExt) {
232   rados_t cluster;
233   rados_ioctx_t ioctx;
234   std::string pool_name = get_temp_pool_name();
235   ASSERT_EQ("", create_one_pool(pool_name, &cluster));
236   rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
237
238   // create an object, write to it using writesame
239   rados_write_op_t op = rados_create_write_op();
240   ASSERT_TRUE(op);
241   rados_write_op_create(op, LIBRADOS_CREATE_EXCLUSIVE, NULL);
242   rados_write_op_write(op, "four", 4, 0);
243   ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
244   rados_release_write_op(op);
245   char hi[4];
246   ASSERT_EQ(sizeof(hi), static_cast<std::size_t>(rados_read(ioctx, "test", hi, sizeof(hi), 0)));
247   ASSERT_EQ(0, memcmp("four", hi, sizeof(hi)));
248
249   // compare and overwrite on (expected) match
250   int val = 0;
251   op = rados_create_write_op();
252   ASSERT_TRUE(op);
253   rados_write_op_cmpext(op, "four", 4, 0, &val);
254   rados_write_op_write(op, "five", 4, 0);
255   ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
256   ASSERT_EQ(0, val);
257   rados_release_write_op(op);
258   ASSERT_EQ(sizeof(hi), static_cast<std::size_t>(rados_read(ioctx, "test", hi, sizeof(hi), 0)));
259   ASSERT_EQ(0, memcmp("five", hi, sizeof(hi)));
260
261   // compare and bail before write due to mismatch
262   val = 0;
263   op = rados_create_write_op();
264   ASSERT_TRUE(op);
265   rados_write_op_cmpext(op, "four", 4, 0, &val);
266   rados_write_op_write(op, "six ", 4, 0);
267   ASSERT_EQ(-MAX_ERRNO - 1, rados_write_op_operate(op, ioctx, "test", NULL, 0));
268
269   ASSERT_EQ(-MAX_ERRNO - 1, val);
270
271   // cleanup
272   op = rados_create_write_op();
273   ASSERT_TRUE(op);
274   rados_write_op_remove(op);
275   ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
276
277   rados_ioctx_destroy(ioctx);
278   ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
279 }