Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / cls_lua / test_cls_lua.cc
1 #include <errno.h>
2 #include <lua.hpp>
3 #include "include/types.h"
4 #include "include/rados/librados.h"
5 #include "gtest/gtest.h"
6 #include "test/librados/test.h"
7 #include "cls/lua/cls_lua_client.h"
8 #include "cls/lua/cls_lua.h"
9
10 /*
11  * JSON script to test JSON I/O protocol with cls_lua
12  */
13 const std::string json_test_script = R"jsonscript(
14 {
15   "script": "function json_echo(input, output) output:append(input:str()); end objclass.register(json_echo)",
16   "handler": "json_echo",
17   "input": "omg it works",
18 }
19 )jsonscript";
20
21 /*
22  * Lua test script thanks to the magical c++11 string literal syntax
23  */
24 const std::string test_script = R"luascript(
25 --
26 -- This Lua script file contains all of the handlers used in the cls_lua unit
27 -- tests (src/test/cls_lua/test_cls_lua.cc). Each section header corresponds
28 -- to the ClsLua.XYZ test.
29 --
30
31 --
32 -- Read
33 --
34 function read(input, output)
35   size = objclass.stat()
36   bl = objclass.read(0, size)
37   output:append(bl:str())
38 end
39
40 objclass.register(read)
41
42 --
43 -- Write
44 --
45 function write(input, output)
46   objclass.write(0, #input, input)
47 end
48
49 objclass.register(write)
50
51 --
52 -- MapGetVal
53 --
54 function map_get_val_foo(input, output)
55   bl = objclass.map_get_val('foo')
56   output:append(bl:str())
57 end
58
59 function map_get_val_dne()
60   bl = objclass.map_get_val('dne')
61 end
62
63 objclass.register(map_get_val_foo)
64 objclass.register(map_get_val_dne)
65
66 --
67 -- Stat
68 --
69 function stat_ret(input, output)
70   size, mtime = objclass.stat()
71   output:append(size .. "," .. mtime)
72 end
73
74 function stat_sdne()
75   size, mtime = objclass.stat()
76 end
77
78 function stat_sdne_pcall()
79   ok, ret, size, mtime = pcall(objclass.stat, o)
80   assert(ok == false)
81   assert(ret == -objclass.ENOENT)
82   return ret
83 end
84
85 objclass.register(stat_ret)
86 objclass.register(stat_sdne)
87 objclass.register(stat_sdne_pcall)
88
89 --
90 -- RetVal
91 --
92 function rv_h() end
93 function rv_h1() return 1; end
94 function rv_h0() return 0; end
95 function rv_hn1() return -1; end
96 function rv_hs1() return '1'; end
97 function rv_hs0() return '0'; end
98 function rv_hsn1() return '-1'; end
99 function rv_hnil() return nil; end
100 function rv_ht() return {}; end
101 function rv_hstr() return 'asdf'; end
102
103 objclass.register(rv_h)
104 objclass.register(rv_h1)
105 objclass.register(rv_h0)
106 objclass.register(rv_hn1)
107 objclass.register(rv_hs1)
108 objclass.register(rv_hs0)
109 objclass.register(rv_hsn1)
110 objclass.register(rv_hnil)
111 objclass.register(rv_ht)
112 objclass.register(rv_hstr)
113
114 --
115 -- Create
116 --
117 function create_c() objclass.create(true); end
118 function create_cne() objclass.create(false); end
119
120 objclass.register(create_c)
121 objclass.register(create_cne)
122
123 --
124 -- Pcall
125 --
126 function pcall_c() objclass.create(true); end
127
128 function pcall_pc()
129   ok, ret = pcall(objclass.create, true)
130   assert(ok == false)
131   assert(ret == -objclass.EEXIST)
132 end
133
134 function pcall_pcr()
135   ok, ret = pcall(objclass.create, true)
136   assert(ok == false)
137   assert(ret == -objclass.EEXIST)
138   return ret
139 end
140
141 function pcall_pcr2()
142   ok, ret = pcall(objclass.create, true)
143   assert(ok == false)
144   assert(ret == -objclass.EEXIST)
145   ok, ret = pcall(objclass.create, true)
146   assert(ok == false)
147   assert(ret == -objclass.EEXIST)
148   return -9999
149 end
150
151 objclass.register(pcall_c)
152 objclass.register(pcall_pc)
153 objclass.register(pcall_pcr)
154 objclass.register(pcall_pcr2)
155
156 --
157 -- Remove
158 --
159 function remove_c() objclass.create(true); end
160 function remove_r() objclass.remove(); end
161
162 objclass.register(remove_c)
163 objclass.register(remove_r)
164
165 --
166 -- MapSetVal
167 --
168 function map_set_val(input, output)
169   objclass.map_set_val('foo', input)
170 end
171
172 objclass.register(map_set_val)
173
174 --
175 -- MapClear
176 --
177 function map_clear()
178   objclass.map_clear()
179 end
180
181 objclass.register(map_clear)
182
183 --
184 -- BufferlistEquality
185 --
186 function bl_eq_empty_equal(input, output)
187   bl1 = bufferlist.new()
188   bl2 = bufferlist.new()
189   assert(bl1 == bl2)
190 end
191
192 function bl_eq_empty_selfequal()
193   bl1 = bufferlist.new()
194   assert(bl1 == bl1)
195 end
196
197 function bl_eq_selfequal()
198   bl1 = bufferlist.new()
199   bl1:append('asdf')
200   assert(bl1 == bl1)
201 end
202
203 function bl_eq_equal()
204   bl1 = bufferlist.new()
205   bl2 = bufferlist.new()
206   bl1:append('abc')
207   bl2:append('abc')
208   assert(bl1 == bl2)
209 end
210
211 function bl_eq_notequal()
212   bl1 = bufferlist.new()
213   bl2 = bufferlist.new()
214   bl1:append('abc')
215   bl2:append('abcd')
216   assert(bl1 ~= bl2)
217 end
218
219 objclass.register(bl_eq_empty_equal)
220 objclass.register(bl_eq_empty_selfequal)
221 objclass.register(bl_eq_selfequal)
222 objclass.register(bl_eq_equal)
223 objclass.register(bl_eq_notequal)
224
225 --
226 -- Bufferlist Compare
227 --
228 function bl_lt()
229   local a = bufferlist.new()
230   local b = bufferlist.new()
231   a:append('A')
232   b:append('B')
233   assert(a < b)
234 end
235
236 function bl_le()
237   local a = bufferlist.new()
238   local b = bufferlist.new()
239   a:append('A')
240   b:append('B')
241   assert(a <= b)
242 end
243
244 objclass.register(bl_lt)
245 objclass.register(bl_le)
246
247 --
248 -- Bufferlist concat
249 --
250 function bl_concat_eq()
251   local a = bufferlist.new()
252   local b = bufferlist.new()
253   local ab = bufferlist.new()
254   a:append('A')
255   b:append('B')
256   ab:append('AB')
257   assert(a .. b == ab)
258 end
259
260 function bl_concat_ne()
261   local a = bufferlist.new()
262   local b = bufferlist.new()
263   local ab = bufferlist.new()
264   a:append('A')
265   b:append('B')
266   ab:append('AB')
267   assert(b .. a ~= ab)
268 end
269
270 function bl_concat_immut()
271   local a = bufferlist.new()
272   local b = bufferlist.new()
273   local ab = bufferlist.new()
274   a:append('A')
275   b:append('B')
276   ab:append('AB')
277   x = a .. b
278   assert(x == ab)
279   b:append('C')
280   assert(x == ab)
281   local bc = bufferlist.new()
282   bc:append('BC')
283   assert(b == bc)
284 end
285
286 objclass.register(bl_concat_eq)
287 objclass.register(bl_concat_ne)
288 objclass.register(bl_concat_immut)
289
290 --
291 -- RunError
292 --
293 function runerr_a()
294   error('WTF')
295 end
296
297 function runerr_b()
298   runerr_a()
299 end
300
301 function runerr_c()
302   runerr_b()
303 end
304
305 -- only runerr_c is called
306 objclass.register(runerr_c)
307
308 --
309 -- GetXattr
310 --
311 function getxattr(input, output)
312   bl = objclass.getxattr("fooz")
313   output:append(bl:str())
314 end
315
316 objclass.register(getxattr)
317
318 --
319 -- SetXattr
320 --
321 function setxattr(input, output)
322   objclass.setxattr("fooz2", input)
323 end
324
325 objclass.register(setxattr)
326
327 --
328 -- WriteFull
329 --
330 function write_full(input, output)
331     objclass.write_full(input)
332 end
333
334 objclass.register(write_full)
335
336 --
337 -- GetXattrs
338 --
339 function getxattrs(input, output)
340     -- result
341     xattrs = objclass.getxattrs()
342
343     -- sort for determisitic test
344     arr = {}
345     for n in pairs(xattrs) do
346         table.insert(arr, n)
347     end
348     table.sort(arr)
349
350     output_str = ""
351     for i,key in ipairs(arr) do
352         output_str = output_str .. key .. "/" .. xattrs[key]:str() .. "/"
353     end
354     output:append(output_str)
355 end
356
357 objclass.register(getxattrs)
358
359 --
360 -- MapGetKeys
361 --
362 function map_get_keys(input, output)
363     -- result
364     keys = objclass.map_get_keys("", 5)
365
366     -- sort for determisitic test
367     arr = {}
368     for n in pairs(keys) do
369         table.insert(arr, n)
370     end
371     table.sort(arr)
372
373     output_str = ""
374     for i,key in ipairs(arr) do
375         output_str = output_str .. key .. "/"
376     end
377
378     output:append(output_str)
379 end
380
381 objclass.register(map_get_keys)
382
383 --
384 -- MapGetVals
385 --
386 function map_get_vals(input, output)
387     -- result
388     kvs = objclass.map_get_vals("", "", 10)
389
390     -- sort for determisitic test
391     arr = {}
392     for n in pairs(kvs) do
393         table.insert(arr, n)
394     end
395     table.sort(arr)
396
397     output_str = ""
398     for i,key in ipairs(arr) do
399         output_str = output_str .. key .. "/" .. kvs[key]:str() .. "/"
400     end
401     output:append(output_str)
402 end
403
404 objclass.register(map_get_vals)
405
406 --
407 -- MapHeader (write)
408 --
409 function map_write_header(input, output)
410     objclass.map_write_header(input)
411 end
412
413 objclass.register(map_write_header)
414
415 --
416 -- MapHeader (read)
417 --
418 function map_read_header(input, output)
419     hdr = objclass.map_read_header()
420     output:append(hdr:str())
421 end
422
423 objclass.register(map_read_header)
424
425 --
426 -- MapSetVals
427 --
428 function map_set_vals_empty(input, output)
429     record = {}
430     objclass.map_set_vals(record)
431 end
432
433 function map_set_vals_one(input, output)
434     record = {
435         a = "a_val"
436     }
437     objclass.map_set_vals(record)
438 end
439
440 function map_set_vals_two(input, output)
441     record = {
442         a = "a_val",
443         b = "b_val"
444     }
445     objclass.map_set_vals(record)
446 end
447
448 function map_set_vals_three(input, output)
449     record = {
450         a = "a_val",
451         b = "b_val",
452         c = "c_val"
453     }
454     objclass.map_set_vals(record)
455 end
456
457 function map_set_vals_array(input, output)
458     array = {}
459     array[1] = "1_val"
460     array[2] = "2_val"
461     objclass.map_set_vals(array)
462 end
463
464 function map_set_vals_mixed(input, output)
465     record = {
466         a = "a_val",
467         b = "b_val"
468     }
469     record[1] = "1_val"
470     record[2] = "2_val"
471     objclass.map_set_vals(record)
472 end
473
474 function map_set_vals_bad_val(input, output)
475     record = {
476         a = {}
477     }
478     objclass.map_set_vals(record)
479 end
480
481 objclass.register(map_set_vals_empty)
482 objclass.register(map_set_vals_one)
483 objclass.register(map_set_vals_two)
484 objclass.register(map_set_vals_three)
485 objclass.register(map_set_vals_array)
486 objclass.register(map_set_vals_mixed)
487 objclass.register(map_set_vals_bad_val)
488
489 --
490 -- MapRemoveKey
491 --
492 function map_remove_key(input, output)
493     objclass.map_remove_key("a")
494 end
495
496 objclass.register(map_remove_key)
497
498 --
499 -- Version/Subop
500 --
501 function current_version(input, output)
502     ret = objclass.current_version()
503     output:append("" .. ret)
504     objclass.log(0, ret)
505 end
506
507 function current_subop_num(input, output)
508     ret = objclass.current_subop_num()
509     output:append("" .. ret)
510     objclass.log(0, ret)
511 end
512
513 function current_subop_version(input, output)
514     ret = objclass.current_subop_version()
515     output:append("" .. ret)
516     objclass.log(0, ret)
517 end
518
519 objclass.register(current_version)
520 objclass.register(current_subop_num)
521 objclass.register(current_subop_version)
522
523 )luascript";
524
525 /*
526  * Test harness uses single pool for the entire test case, and generates
527  * unique object names for each test.
528  */
529 class ClsLua : public ::testing::Test {
530   protected:
531     static void SetUpTestCase() {
532       pool_name = get_temp_pool_name();
533       ASSERT_EQ("", create_one_pool_pp(pool_name, rados));
534       ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx));
535     }
536
537     static void TearDownTestCase() {
538       ioctx.close();
539       ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
540     }
541
542     void SetUp() override {
543       /* Grab test names to build unique objects */
544       const ::testing::TestInfo* const test_info =
545         ::testing::UnitTest::GetInstance()->current_test_info();
546
547       /* Create unique string using test/testname/pid */
548       std::stringstream ss_oid;
549       ss_oid << test_info->test_case_name() << "_" <<
550         test_info->name() << "_" << getpid();
551
552       /* Unique object for test to use */
553       oid = ss_oid.str();
554     }
555
556     void TearDown() override {
557     }
558
559     /*
560      * Helper function. This functionality should eventually make its way into
561      * a clslua client library of some sort.
562      */
563     int __clslua_exec(const string& oid, const string& script,
564         librados::bufferlist *input = NULL,  const string& funcname = "")
565     {
566       bufferlist inbl;
567       if (input)
568         inbl = *input;
569
570       reply_output.clear();
571
572       return cls_lua_client::exec(ioctx, oid, script, funcname, inbl,
573           reply_output);
574     }
575
576     int clslua_exec(const string& script, librados::bufferlist *input = NULL,
577         const string& funcname = "")
578     {
579       return __clslua_exec(oid, script, input, funcname);
580     }
581
582     static librados::Rados rados;
583     static librados::IoCtx ioctx;
584     static string pool_name;
585
586     string oid;
587     bufferlist reply_output;
588 };
589
590 librados::Rados ClsLua::rados;
591 librados::IoCtx ClsLua::ioctx;
592 string ClsLua::pool_name;
593
594 TEST_F(ClsLua, Write) {
595   /* write some data into object */
596   string written = "Hello World";
597   bufferlist inbl;
598   ::encode(written, inbl);
599   ASSERT_EQ(0, clslua_exec(test_script, &inbl, "write"));
600
601   /* have Lua read out of the object */
602   uint64_t size;
603   bufferlist outbl;
604   ASSERT_EQ(0, ioctx.stat(oid, &size, NULL));
605   ASSERT_EQ(size, (uint64_t)ioctx.read(oid, outbl, size, 0) );
606
607   /* compare what Lua read to what we wrote */
608   string read;
609   ::decode(read, outbl);
610   ASSERT_EQ(read, written);
611 }
612
613 TEST_F(ClsLua, SyntaxError) {
614   ASSERT_EQ(-EIO, clslua_exec("-"));
615 }
616
617 TEST_F(ClsLua, EmptyScript) {
618   ASSERT_EQ(0, clslua_exec(""));
619 }
620
621 TEST_F(ClsLua, RetVal) {
622   /* handlers can return numeric values */
623   ASSERT_EQ(1, clslua_exec(test_script, NULL, "rv_h1"));
624   ASSERT_EQ(0, clslua_exec(test_script, NULL, "rv_h0"));
625   ASSERT_EQ(-1, clslua_exec(test_script, NULL, "rv_hn1"));
626   ASSERT_EQ(1, clslua_exec(test_script, NULL, "rv_hs1"));
627   ASSERT_EQ(0, clslua_exec(test_script, NULL, "rv_hs0"));
628   ASSERT_EQ(-1, clslua_exec(test_script, NULL, "rv_hsn1"));
629
630   /* no return value is success */
631   ASSERT_EQ(0, clslua_exec(test_script, NULL, "rv_h"));
632
633   /* non-numeric return values are errors */
634   ASSERT_EQ(-EIO, clslua_exec(test_script, NULL, "rv_hnil"));
635   ASSERT_EQ(-EIO, clslua_exec(test_script, NULL, "rv_ht"));
636   ASSERT_EQ(-EIO, clslua_exec(test_script, NULL, "rv_hstr"));
637 }
638
639 TEST_F(ClsLua, Create) {
640   /* create works */
641   ASSERT_EQ(0, clslua_exec(test_script, NULL, "create_c"));
642
643   /* exclusive works */
644   ASSERT_EQ(-EEXIST, clslua_exec(test_script, NULL, "create_c"));
645   ASSERT_EQ(0, clslua_exec(test_script, NULL, "create_cne"));
646 }
647
648 TEST_F(ClsLua, Pcall) {
649   /* create and error works */
650   ASSERT_EQ(0, clslua_exec(test_script, NULL, "pcall_c"));
651   ASSERT_EQ(-EEXIST, clslua_exec(test_script, NULL, "pcall_c"));
652
653   /* pcall masks the error */
654   ASSERT_EQ(0, clslua_exec(test_script, NULL, "pcall_pc"));
655
656   /* pcall lets us get the failed return value */
657   ASSERT_EQ(-EEXIST, clslua_exec(test_script, NULL, "pcall_pcr"));
658
659   /*
660    * the first call in pcr2 will fail (check ret != 0), and the second pcall
661    * should also fail (we check with a bogus return value to mask real
662    * errors). This is also an important check for our error handling because
663    * we need a case where two functions in the same handler fail to exercise
664    * our internal error book keeping.
665    */
666   ASSERT_EQ(-9999, clslua_exec(test_script, NULL, "pcall_pcr2"));
667 }
668
669 TEST_F(ClsLua, Remove) {
670   /* object doesn't exist */
671   ASSERT_EQ(-ENOENT, clslua_exec(test_script, NULL, "remove_r"));
672
673   /* can remove */
674   ASSERT_EQ(0, clslua_exec(test_script, NULL, "remove_c"));
675   ASSERT_EQ(0, clslua_exec(test_script, NULL, "remove_r"));
676   ASSERT_EQ(-ENOENT, clslua_exec(test_script, NULL, "remove_r"));
677 }
678
679 TEST_F(ClsLua, Stat) {
680   /* build object and stat */
681   char buf[1024];
682   bufferlist bl;
683   bl.append(buf, sizeof(buf));
684   ASSERT_EQ(0, ioctx.write_full(oid, bl));
685   uint64_t size;
686   time_t mtime;
687   ASSERT_EQ(0, ioctx.stat(oid, &size, &mtime));
688
689   /* test stat success */
690   ASSERT_EQ(0, clslua_exec(test_script, NULL, "stat_ret"));
691
692   // size,mtime from ioctx call
693   std::stringstream s1;
694   s1 << size << "," << mtime;
695
696   // lua constructed size,mtime string
697   std::string s2(reply_output.c_str(), reply_output.length());
698
699   ASSERT_EQ(s1.str(), s2);
700
701   /* test object dne */
702   ASSERT_EQ(-ENOENT, __clslua_exec("dne", test_script, NULL, "stat_sdne"));
703
704   /* can capture error with pcall */
705   ASSERT_EQ(-ENOENT, __clslua_exec("dne", test_script, NULL, "stat_sdne_pcall"));
706 }
707
708 TEST_F(ClsLua, MapClear) {
709   /* write some data into a key */
710   string msg = "This is a test message";
711   bufferlist val;
712   val.append(msg.c_str(), msg.size());
713   map<string, bufferlist> map;
714   map["foo"] = val;
715   ASSERT_EQ(0, ioctx.omap_set(oid, map));
716
717   /* test we can get it back out */
718   set<string> keys;
719   keys.insert("foo");
720   map.clear();
721   ASSERT_EQ(0, (int)map.count("foo"));
722   ASSERT_EQ(0, ioctx.omap_get_vals_by_keys(oid, keys, &map));
723   ASSERT_EQ(1, (int)map.count("foo"));
724
725   /* now clear it */
726   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_clear"));
727
728   /* test that the map we get back is empty now */
729   map.clear();
730   ASSERT_EQ(0, (int)map.count("foo"));
731   ASSERT_EQ(0, ioctx.omap_get_vals_by_keys(oid, keys, &map));
732   ASSERT_EQ(0, (int)map.count("foo"));
733 }
734
735 TEST_F(ClsLua, MapSetVal) {
736   /* build some input value */
737   bufferlist orig_val;
738   ::encode("this is the original value yay", orig_val);
739
740   /* have the lua script stuff the data into a map value */
741   ASSERT_EQ(0, clslua_exec(test_script, &orig_val, "map_set_val"));
742
743   /* grap the key now and compare to orig */
744   map<string, bufferlist> out_map;
745   set<string> out_keys;
746   out_keys.insert("foo");
747   ASSERT_EQ(0, ioctx.omap_get_vals_by_keys(oid, out_keys, &out_map));
748   bufferlist out_bl = out_map["foo"];
749   string out_val;
750   ::decode(out_val, out_bl);
751   ASSERT_EQ(out_val, "this is the original value yay");
752 }
753
754 TEST_F(ClsLua, MapGetVal) {
755   /* write some data into a key */
756   string msg = "This is a test message";
757   bufferlist orig_val;
758   orig_val.append(msg.c_str(), msg.size());
759   map<string, bufferlist> orig_map;
760   orig_map["foo"] = orig_val;
761   ASSERT_EQ(0, ioctx.omap_set(oid, orig_map));
762
763   /* now compare to what we put it */
764   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_get_val_foo"));
765
766   /* check return */
767   string ret_val;
768   ret_val.assign(reply_output.c_str(), reply_output.length());
769   ASSERT_EQ(ret_val, msg);
770
771   /* error case */
772   ASSERT_EQ(-ENOENT, clslua_exec(test_script, NULL, "map_get_val_dne"));
773 }
774
775 TEST_F(ClsLua, Read) {
776   /* put data into object */
777   string msg = "This is a test message";
778   bufferlist bl;
779   bl.append(msg.c_str(), msg.size());
780   ASSERT_EQ(0, ioctx.write_full(oid, bl));
781
782   /* get lua to read it and send it back */
783   ASSERT_EQ(0, clslua_exec(test_script, NULL, "read"));
784
785   /* check return */
786   string ret_val;
787   ret_val.assign(reply_output.c_str(), reply_output.length());
788   ASSERT_EQ(ret_val, msg);
789 }
790
791 TEST_F(ClsLua, Log) {
792   ASSERT_EQ(0, clslua_exec("objclass.log()"));
793   ASSERT_EQ(0, clslua_exec("s = objclass.log(); objclass.log(s);"));
794   ASSERT_EQ(0, clslua_exec("objclass.log(1)"));
795   ASSERT_EQ(0, clslua_exec("objclass.log(-1)"));
796   ASSERT_EQ(0, clslua_exec("objclass.log('x')"));
797   ASSERT_EQ(0, clslua_exec("objclass.log(0, 0)"));
798   ASSERT_EQ(0, clslua_exec("objclass.log(1, 1)"));
799   ASSERT_EQ(0, clslua_exec("objclass.log(-10, -10)"));
800   ASSERT_EQ(0, clslua_exec("objclass.log('x', 'y')"));
801   ASSERT_EQ(0, clslua_exec("objclass.log(1, 'one')"));
802   ASSERT_EQ(0, clslua_exec("objclass.log(1, 'one', 'two')"));
803   ASSERT_EQ(0, clslua_exec("objclass.log('one', 'two', 'three')"));
804   ASSERT_EQ(0, clslua_exec("s = objclass.log('one', 'two', 'three'); objclass.log(s);"));
805 }
806
807 TEST_F(ClsLua, BufferlistEquality) {
808   ASSERT_EQ(0, clslua_exec(test_script, NULL, "bl_eq_empty_equal"));
809   ASSERT_EQ(0, clslua_exec(test_script, NULL, "bl_eq_empty_selfequal"));
810   ASSERT_EQ(0, clslua_exec(test_script, NULL, "bl_eq_selfequal"));
811   ASSERT_EQ(0, clslua_exec(test_script, NULL, "bl_eq_equal"));
812   ASSERT_EQ(0, clslua_exec(test_script, NULL, "bl_eq_notequal"));
813 }
814
815 TEST_F(ClsLua, RunError) {
816   ASSERT_EQ(-EIO, clslua_exec(test_script, NULL, "runerr_c"));
817 }
818
819 TEST_F(ClsLua, HandleNotFunc) {
820   string script = "x = 1;";
821   ASSERT_EQ(-EOPNOTSUPP, clslua_exec(script, NULL, "x"));
822 }
823
824 TEST_F(ClsLua, Register) {
825   /* normal cases: register and maybe call the handler */
826   string script = "function h() end; objclass.register(h);";
827   ASSERT_EQ(0, clslua_exec(script, NULL, ""));
828   ASSERT_EQ(0, clslua_exec(script, NULL, "h"));
829
830   /* can register and call multiple handlers */
831   script = "function h1() end; function h2() end;"
832     "objclass.register(h1); objclass.register(h2);";
833   ASSERT_EQ(0, clslua_exec(script, NULL, ""));
834   ASSERT_EQ(0, clslua_exec(script, NULL, "h1"));
835   ASSERT_EQ(0, clslua_exec(script, NULL, "h2"));
836
837   /* normal cases: register before function is defined */
838   script = "objclass.register(h); function h() end;";
839   ASSERT_EQ(-EIO, clslua_exec(script, NULL, ""));
840   ASSERT_EQ(-EIO, clslua_exec(script, NULL, "h"));
841
842   /* cannot call handler that isn't registered */
843   script = "function h() end;";
844   ASSERT_EQ(-EIO, clslua_exec(script, NULL, "h"));
845
846   /* handler doesn't exist */
847   script = "objclass.register(lalala);";
848   ASSERT_EQ(-EIO, clslua_exec(script, NULL, ""));
849
850   /* handler isn't a function */
851   script = "objclass.register('some string');";
852   ASSERT_EQ(-EIO, clslua_exec(script, NULL, ""));
853
854   /* cannot register handler multiple times */
855   script = "function h() end; objclass.register(h); objclass.register(h);";
856   ASSERT_EQ(-EIO, clslua_exec(script, NULL, ""));
857 }
858
859 TEST_F(ClsLua, BufferlistCompare) {
860   ASSERT_EQ(0, clslua_exec(test_script, NULL, "bl_lt"));
861   ASSERT_EQ(0, clslua_exec(test_script, NULL, "bl_le"));
862 }
863
864 TEST_F(ClsLua, BufferlistConcat) {
865   ASSERT_EQ(0, clslua_exec(test_script, NULL, "bl_concat_eq"));
866   ASSERT_EQ(0, clslua_exec(test_script, NULL, "bl_concat_ne"));
867   ASSERT_EQ(0, clslua_exec(test_script, NULL, "bl_concat_immut"));
868 }
869
870 TEST_F(ClsLua, GetXattr) {
871   bufferlist bl;
872   bl.append("blahblahblahblahblah");
873   ASSERT_EQ(0, ioctx.setxattr(oid, "fooz", bl));
874   ASSERT_EQ(0, clslua_exec(test_script, NULL, "getxattr"));
875   ASSERT_TRUE(reply_output == bl);
876 }
877
878 TEST_F(ClsLua, SetXattr) {
879   bufferlist inbl;
880   inbl.append("blahblahblahblahblah");
881   ASSERT_EQ(0, clslua_exec(test_script, &inbl, "setxattr"));
882   bufferlist outbl;
883   ASSERT_EQ((int)inbl.length(), ioctx.getxattr(oid, "fooz2", outbl));
884   ASSERT_TRUE(outbl == inbl);
885 }
886
887 TEST_F(ClsLua, WriteFull) {
888   // write some data
889   char buf[1024];
890   bufferlist blin;
891   blin.append(buf, sizeof(buf));
892   ASSERT_EQ(0, ioctx.write(oid, blin, blin.length(), 0));
893   bufferlist blout;
894   ASSERT_EQ((int)blin.length(), ioctx.read(oid, blout, 0, 0));
895   ASSERT_EQ(blin, blout);
896
897   // execute write_full from lua
898   blin.clear();
899   char buf2[200];
900   sprintf(buf2, "%s", "data replacing content");
901   blin.append(buf2, sizeof(buf2));
902   ASSERT_EQ(0, clslua_exec(test_script, &blin, "write_full"));
903
904   // read it back
905   blout.clear();
906   ASSERT_EQ((int)blin.length(), ioctx.read(oid, blout, 0, 0));
907   ASSERT_EQ(blin, blout);
908 }
909
910 TEST_F(ClsLua, GetXattrs) {
911   ASSERT_EQ(0, ioctx.create(oid, false));
912
913   ASSERT_EQ(0, clslua_exec(test_script, NULL, "getxattrs"));
914   ASSERT_EQ(0, (int)reply_output.length());
915
916   string key1str("key1str");
917   bufferlist key1bl;
918   key1bl.append(key1str);
919   ASSERT_EQ(0, ioctx.setxattr(oid, "key1", key1bl));
920   ASSERT_EQ(0, clslua_exec(test_script, NULL, "getxattrs"));
921   string out1(reply_output.c_str(), reply_output.length()); // add the trailing \0
922   ASSERT_STREQ(out1.c_str(), "key1/key1str/");
923
924   string key2str("key2str");
925   bufferlist key2bl;
926   key2bl.append(key2str);
927   ASSERT_EQ(0, ioctx.setxattr(oid, "key2", key2bl));
928   ASSERT_EQ(0, clslua_exec(test_script, NULL, "getxattrs"));
929   string out2(reply_output.c_str(), reply_output.length()); // add the trailing \0
930   ASSERT_STREQ(out2.c_str(), "key1/key1str/key2/key2str/");
931
932   string key3str("key3str");
933   bufferlist key3bl;
934   key3bl.append(key3str);
935   ASSERT_EQ(0, ioctx.setxattr(oid, "key3", key3bl));
936   ASSERT_EQ(0, clslua_exec(test_script, NULL, "getxattrs"));
937   string out3(reply_output.c_str(), reply_output.length()); // add the trailing \0
938   ASSERT_STREQ(out3.c_str(), "key1/key1str/key2/key2str/key3/key3str/");
939 }
940
941 TEST_F(ClsLua, MapGetKeys) {
942   ASSERT_EQ(0, ioctx.create(oid, false));
943
944   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_get_keys"));
945   ASSERT_EQ(0, (int)reply_output.length());
946
947   map<string, bufferlist> kvpairs;
948
949   kvpairs["k1"] = bufferlist();
950   ASSERT_EQ(0, ioctx.omap_set(oid, kvpairs));
951   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_get_keys"));
952   string out1(reply_output.c_str(), reply_output.length()); // add the trailing \0
953   ASSERT_STREQ(out1.c_str(), "k1/");
954
955   kvpairs["k2"] = bufferlist();
956   ASSERT_EQ(0, ioctx.omap_set(oid, kvpairs));
957   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_get_keys"));
958   string out2(reply_output.c_str(), reply_output.length()); // add the trailing \0
959   ASSERT_STREQ(out2.c_str(), "k1/k2/");
960
961   kvpairs["xxx"] = bufferlist();
962   ASSERT_EQ(0, ioctx.omap_set(oid, kvpairs));
963   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_get_keys"));
964   string out3(reply_output.c_str(), reply_output.length()); // add the trailing \0
965   ASSERT_STREQ(out3.c_str(), "k1/k2/xxx/");
966 }
967
968 TEST_F(ClsLua, MapGetVals) {
969   ASSERT_EQ(0, ioctx.create(oid, false));
970
971   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_get_vals"));
972   ASSERT_EQ(0, (int)reply_output.length());
973
974   map<string, bufferlist> kvpairs;
975
976   kvpairs["key1"] = bufferlist();
977   kvpairs["key1"].append(string("key1str"));
978   ASSERT_EQ(0, ioctx.omap_set(oid, kvpairs));
979   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_get_vals"));
980   string out1(reply_output.c_str(), reply_output.length()); // add the trailing \0
981   ASSERT_STREQ(out1.c_str(), "key1/key1str/");
982
983   kvpairs["key2"] = bufferlist();
984   kvpairs["key2"].append(string("key2str"));
985   ASSERT_EQ(0, ioctx.omap_set(oid, kvpairs));
986   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_get_vals"));
987   string out2(reply_output.c_str(), reply_output.length()); // add the trailing \0
988   ASSERT_STREQ(out2.c_str(), "key1/key1str/key2/key2str/");
989
990   kvpairs["key3"] = bufferlist();
991   kvpairs["key3"].append(string("key3str"));
992   ASSERT_EQ(0, ioctx.omap_set(oid, kvpairs));
993   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_get_vals"));
994   string out3(reply_output.c_str(), reply_output.length()); // add the trailing \0
995   ASSERT_STREQ(out3.c_str(), "key1/key1str/key2/key2str/key3/key3str/");
996 }
997
998 TEST_F(ClsLua, MapHeader) {
999   ASSERT_EQ(0, ioctx.create(oid, false));
1000
1001   bufferlist bl_out;
1002   ASSERT_EQ(0, ioctx.omap_get_header(oid, &bl_out));
1003   ASSERT_EQ(0, (int)bl_out.length());
1004
1005   std::string val("this is a value");
1006   bufferlist hdr;
1007   hdr.append(val);
1008
1009   ASSERT_EQ(0, clslua_exec(test_script, &hdr, "map_write_header"));
1010   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_read_header"));
1011
1012   ASSERT_EQ(reply_output, hdr);
1013 }
1014
1015 TEST_F(ClsLua, MapSetVals) {
1016   ASSERT_EQ(0, ioctx.create(oid, false));
1017
1018   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_set_vals_empty"));
1019
1020   std::map<string, bufferlist> out_vals;
1021   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_set_vals_one"));
1022   ASSERT_EQ(0, ioctx.omap_get_vals(oid, "", 100, &out_vals));
1023   ASSERT_EQ(1, (int)out_vals.size());
1024   ASSERT_STREQ("a_val", std::string(out_vals["a"].c_str(), out_vals["a"].length()).c_str());
1025
1026   out_vals.clear();
1027   ASSERT_EQ(0, ioctx.omap_clear(oid));
1028   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_set_vals_two"));
1029   ASSERT_EQ(0, ioctx.omap_get_vals(oid, "", 100, &out_vals));
1030   ASSERT_EQ(2, (int)out_vals.size());
1031   ASSERT_STREQ("a_val", std::string(out_vals["a"].c_str(), out_vals["a"].length()).c_str());
1032   ASSERT_STREQ("b_val", std::string(out_vals["b"].c_str(), out_vals["b"].length()).c_str());
1033
1034   out_vals.clear();
1035   ASSERT_EQ(0, ioctx.omap_clear(oid));
1036   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_set_vals_three"));
1037   ASSERT_EQ(0, ioctx.omap_get_vals(oid, "", 100, &out_vals));
1038   ASSERT_EQ(3, (int)out_vals.size());
1039   ASSERT_STREQ("a_val", std::string(out_vals["a"].c_str(), out_vals["a"].length()).c_str());
1040   ASSERT_STREQ("b_val", std::string(out_vals["b"].c_str(), out_vals["b"].length()).c_str());
1041   ASSERT_STREQ("c_val", std::string(out_vals["c"].c_str(), out_vals["c"].length()).c_str());
1042
1043   out_vals.clear();
1044   ASSERT_EQ(0, ioctx.omap_clear(oid));
1045   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_set_vals_array"));
1046   ASSERT_EQ(0, ioctx.omap_get_vals(oid, "", 100, &out_vals));
1047   ASSERT_EQ(2, (int)out_vals.size());
1048   ASSERT_STREQ("1_val", std::string(out_vals["1"].c_str(), out_vals["1"].length()).c_str());
1049   ASSERT_STREQ("2_val", std::string(out_vals["2"].c_str(), out_vals["2"].length()).c_str());
1050
1051   out_vals.clear();
1052   ASSERT_EQ(0, ioctx.omap_clear(oid));
1053   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_set_vals_mixed"));
1054   ASSERT_EQ(0, ioctx.omap_get_vals(oid, "", 100, &out_vals));
1055   ASSERT_EQ(4, (int)out_vals.size());
1056   ASSERT_STREQ("a_val", std::string(out_vals["a"].c_str(), out_vals["a"].length()).c_str());
1057   ASSERT_STREQ("b_val", std::string(out_vals["b"].c_str(), out_vals["b"].length()).c_str());
1058   ASSERT_STREQ("1_val", std::string(out_vals["1"].c_str(), out_vals["1"].length()).c_str());
1059   ASSERT_STREQ("2_val", std::string(out_vals["2"].c_str(), out_vals["2"].length()).c_str());
1060
1061   ASSERT_EQ(-EINVAL, clslua_exec(test_script, NULL, "map_set_vals_bad_val"));
1062 }
1063
1064 TEST_F(ClsLua, MapRemoveKey) {
1065   ASSERT_EQ(0, ioctx.create(oid, false));
1066
1067   std::map<string, bufferlist> out_vals;
1068   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_set_vals_two"));
1069   ASSERT_EQ(0, ioctx.omap_get_vals(oid, "", 100, &out_vals));
1070   ASSERT_EQ(2, (int)out_vals.size());
1071   ASSERT_STREQ("a_val", std::string(out_vals["a"].c_str(), out_vals["a"].length()).c_str());
1072   ASSERT_STREQ("b_val", std::string(out_vals["b"].c_str(), out_vals["b"].length()).c_str());
1073
1074   out_vals.clear();
1075   ASSERT_EQ(0, clslua_exec(test_script, NULL, "map_remove_key"));
1076   ASSERT_EQ(0, ioctx.omap_get_vals(oid, "", 100, &out_vals));
1077   ASSERT_EQ(1, (int)out_vals.size());
1078   ASSERT_STREQ("b_val", std::string(out_vals["b"].c_str(), out_vals["b"].length()).c_str());
1079 }
1080
1081 TEST_F(ClsLua, VersionSubop) {
1082   ASSERT_EQ(0, ioctx.create(oid, false));
1083
1084   ASSERT_EQ(0, clslua_exec(test_script, NULL, "current_version"));
1085   ASSERT_GT((int)reply_output.length(), 0);
1086
1087   ASSERT_EQ(0, clslua_exec(test_script, NULL, "current_subop_num"));
1088   ASSERT_GT((int)reply_output.length(), 0);
1089
1090   ASSERT_EQ(0, clslua_exec(test_script, NULL, "current_subop_version"));
1091   ASSERT_GT((int)reply_output.length(), 0);
1092 }
1093
1094 TEST_F(ClsLua, Json) {
1095   ASSERT_EQ(0, ioctx.create(oid, false));
1096
1097   bufferlist inbl, outbl;
1098
1099   inbl.append(json_test_script);
1100
1101   int ret = ioctx.exec(oid, "lua", "eval_json", inbl, outbl);
1102   ASSERT_EQ(ret, 0);
1103
1104   std::string out(outbl.c_str(), outbl.length());
1105   ASSERT_STREQ(out.c_str(), "omg it works");
1106 }