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