]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | #include <gtest/gtest.h> |
2 | #include "common/ceph_context.h" | |
1e59de90 TL |
3 | #include "rgw_common.h" |
4 | #include "rgw_auth_registry.h" | |
5 | #include "rgw_process_env.h" | |
6 | #include "rgw_sal_rados.h" | |
7 | #include "rgw_lua_request.h" | |
8 | #include "rgw_lua_background.h" | |
9 | #include "rgw_lua_data_filter.h" | |
f67539c2 | 10 | |
20effc67 | 11 | using namespace std; |
f67539c2 | 12 | using namespace rgw; |
20effc67 TL |
13 | using boost::container::flat_set; |
14 | using rgw::auth::Identity; | |
15 | using rgw::auth::Principal; | |
f67539c2 TL |
16 | |
17 | class CctCleaner { | |
18 | CephContext* cct; | |
19 | public: | |
20 | CctCleaner(CephContext* _cct) : cct(_cct) {} | |
21 | ~CctCleaner() { | |
22 | #ifdef WITH_SEASTAR | |
23 | delete cct; | |
24 | #else | |
25 | cct->put(); | |
26 | #endif | |
27 | } | |
28 | }; | |
29 | ||
20effc67 | 30 | class FakeIdentity : public Identity { |
f67539c2 | 31 | public: |
20effc67 TL |
32 | FakeIdentity() = default; |
33 | ||
34 | uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const override { | |
35 | return 0; | |
36 | }; | |
37 | ||
38 | bool is_admin_of(const rgw_user& uid) const override { | |
39 | return false; | |
40 | } | |
41 | ||
42 | bool is_owner_of(const rgw_user& uid) const override { | |
43 | return false; | |
44 | } | |
45 | ||
46 | virtual uint32_t get_perm_mask() const override { | |
47 | return 0; | |
48 | } | |
49 | ||
50 | uint32_t get_identity_type() const override { | |
51 | return TYPE_RGW; | |
52 | } | |
53 | ||
54 | string get_acct_name() const override { | |
55 | return ""; | |
56 | } | |
57 | ||
58 | string get_subuser() const override { | |
59 | return ""; | |
60 | } | |
61 | ||
62 | void to_str(std::ostream& out) const override { | |
63 | return; | |
64 | } | |
65 | ||
66 | bool is_identity(const flat_set<Principal>& ids) const override { | |
67 | return false; | |
68 | } | |
69 | }; | |
70 | ||
1e59de90 | 71 | class TestUser : public sal::StoreUser { |
20effc67 TL |
72 | public: |
73 | virtual std::unique_ptr<User> clone() override { | |
74 | return std::unique_ptr<User>(new TestUser(*this)); | |
75 | } | |
76 | ||
77 | virtual int list_buckets(const DoutPrefixProvider *dpp, const string&, const string&, uint64_t, bool, sal::BucketList&, optional_yield y) override { | |
78 | return 0; | |
79 | } | |
80 | ||
81 | virtual int create_bucket(const DoutPrefixProvider* dpp, const rgw_bucket& b, const std::string& zonegroup_id, rgw_placement_rule& placement_rule, std::string& swift_ver_location, const RGWQuotaInfo* pquota_info, const RGWAccessControlPolicy& policy, sal::Attrs& attrs, RGWBucketInfo& info, obj_version& ep_objv, bool exclusive, bool obj_lock_enabled, bool* existed, req_info& req_info, std::unique_ptr<sal::Bucket>* bucket, optional_yield y) override { | |
82 | return 0; | |
83 | } | |
84 | ||
85 | virtual int read_attrs(const DoutPrefixProvider *dpp, optional_yield y) override { | |
86 | return 0; | |
87 | } | |
88 | ||
89 | virtual int read_stats(const DoutPrefixProvider *dpp, optional_yield y, RGWStorageStats* stats, ceph::real_time *last_stats_sync, ceph::real_time *last_stats_update) override { | |
90 | return 0; | |
91 | } | |
92 | ||
93 | virtual int read_stats_async(const DoutPrefixProvider *dpp, RGWGetUserStats_CB *cb) override { | |
94 | return 0; | |
95 | } | |
96 | ||
97 | virtual int complete_flush_stats(const DoutPrefixProvider *dpp, optional_yield y) override { | |
f67539c2 TL |
98 | return 0; |
99 | } | |
100 | ||
20effc67 TL |
101 | virtual int read_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch, uint32_t max_entries, bool *is_truncated, RGWUsageIter& usage_iter, map<rgw_user_bucket, rgw_usage_log_entry>& usage) override { |
102 | return 0; | |
103 | } | |
104 | ||
105 | virtual int trim_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch) override { | |
106 | return 0; | |
f67539c2 TL |
107 | } |
108 | ||
20effc67 | 109 | virtual int load_user(const DoutPrefixProvider *dpp, optional_yield y) override { |
f67539c2 TL |
110 | return 0; |
111 | } | |
112 | ||
20effc67 TL |
113 | virtual int store_user(const DoutPrefixProvider* dpp, optional_yield y, bool exclusive, RGWUserInfo* old_info) override { |
114 | return 0; | |
115 | } | |
116 | ||
117 | virtual int remove_user(const DoutPrefixProvider* dpp, optional_yield y) override { | |
118 | return 0; | |
119 | } | |
120 | virtual int merge_and_store_attrs(const DoutPrefixProvider *dpp, rgw::sal::Attrs& attrs, optional_yield y) override { | |
121 | return 0; | |
122 | } | |
1e59de90 TL |
123 | virtual int verify_mfa(const std::string& mfa_str, bool* verified, const DoutPrefixProvider* dpp, optional_yield y) override { |
124 | return 0; | |
125 | } | |
20effc67 | 126 | virtual ~TestUser() = default; |
f67539c2 TL |
127 | }; |
128 | ||
129 | class TestAccounter : public io::Accounter, public io::BasicClient { | |
130 | RGWEnv env; | |
131 | ||
132 | protected: | |
133 | virtual int init_env(CephContext *cct) override { | |
134 | return 0; | |
135 | } | |
136 | ||
137 | public: | |
138 | ~TestAccounter() = default; | |
139 | ||
140 | virtual void set_account(bool enabled) override { | |
141 | } | |
142 | ||
143 | virtual uint64_t get_bytes_sent() const override { | |
144 | return 0; | |
145 | } | |
146 | ||
147 | virtual uint64_t get_bytes_received() const override { | |
148 | return 0; | |
149 | } | |
150 | ||
151 | virtual RGWEnv& get_env() noexcept override { | |
152 | return env; | |
153 | } | |
154 | ||
155 | virtual size_t complete_request() override { | |
156 | return 0; | |
157 | } | |
158 | }; | |
159 | ||
1e59de90 TL |
160 | auto g_cct = new CephContext(CEPH_ENTITY_TYPE_CLIENT); |
161 | ||
162 | CctCleaner cleaner(g_cct); | |
f67539c2 | 163 | |
1e59de90 TL |
164 | tracing::Tracer tracer; |
165 | ||
166 | #define DEFINE_REQ_STATE RGWProcessEnv pe; RGWEnv e; req_state s(g_cct, pe, &e, 0); | |
167 | #define INIT_TRACE tracer.init("test"); \ | |
168 | s.trace = tracer.start_trace("test", true); | |
f67539c2 TL |
169 | |
170 | TEST(TestRGWLua, EmptyScript) | |
171 | { | |
172 | const std::string script; | |
173 | ||
1e59de90 | 174 | DEFINE_REQ_STATE; |
f67539c2 | 175 | |
39ae355f | 176 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
177 | ASSERT_EQ(rc, 0); |
178 | } | |
179 | ||
f67539c2 TL |
180 | TEST(TestRGWLua, SyntaxError) |
181 | { | |
182 | const std::string script = R"( | |
183 | if 3 < 5 then | |
184 | RGWDebugLog("missing 'end'") | |
185 | )"; | |
186 | ||
187 | DEFINE_REQ_STATE; | |
188 | ||
39ae355f | 189 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
190 | ASSERT_EQ(rc, -1); |
191 | } | |
192 | ||
193 | TEST(TestRGWLua, Hello) | |
194 | { | |
195 | const std::string script = R"( | |
196 | RGWDebugLog("hello from lua") | |
197 | )"; | |
198 | ||
199 | DEFINE_REQ_STATE; | |
200 | ||
39ae355f | 201 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
202 | ASSERT_EQ(rc, 0); |
203 | } | |
204 | ||
205 | TEST(TestRGWLua, RGWDebugLogNumber) | |
206 | { | |
207 | const std::string script = R"( | |
208 | RGWDebugLog(1234567890) | |
209 | )"; | |
210 | ||
211 | DEFINE_REQ_STATE; | |
212 | ||
39ae355f | 213 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
214 | ASSERT_EQ(rc, 0); |
215 | } | |
216 | ||
217 | TEST(TestRGWLua, RGWDebugNil) | |
218 | { | |
219 | const std::string script = R"( | |
220 | RGWDebugLog(nil) | |
221 | )"; | |
222 | ||
223 | DEFINE_REQ_STATE; | |
224 | ||
39ae355f | 225 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
226 | ASSERT_EQ(rc, -1); |
227 | } | |
228 | ||
229 | TEST(TestRGWLua, URI) | |
230 | { | |
231 | const std::string script = R"( | |
232 | RGWDebugLog(Request.DecodedURI) | |
233 | assert(Request.DecodedURI == "http://hello.world/") | |
234 | )"; | |
235 | ||
236 | DEFINE_REQ_STATE; | |
237 | s.decoded_uri = "http://hello.world/"; | |
238 | ||
39ae355f | 239 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
240 | ASSERT_EQ(rc, 0); |
241 | } | |
242 | ||
243 | TEST(TestRGWLua, Response) | |
244 | { | |
245 | const std::string script = R"( | |
246 | assert(Request.Response.Message == "This is a bad request") | |
247 | assert(Request.Response.HTTPStatus == "Bad Request") | |
248 | assert(Request.Response.RGWCode == 4000) | |
249 | assert(Request.Response.HTTPStatusCode == 400) | |
250 | )"; | |
251 | ||
252 | DEFINE_REQ_STATE; | |
253 | s.err.http_ret = 400; | |
254 | s.err.ret = 4000; | |
255 | s.err.err_code = "Bad Request"; | |
256 | s.err.message = "This is a bad request"; | |
257 | ||
39ae355f | 258 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
259 | ASSERT_EQ(rc, 0); |
260 | } | |
261 | ||
262 | TEST(TestRGWLua, SetResponse) | |
263 | { | |
264 | const std::string script = R"( | |
265 | assert(Request.Response.Message == "this is a bad request") | |
266 | Request.Response.Message = "this is a good request" | |
267 | assert(Request.Response.Message == "this is a good request") | |
268 | )"; | |
269 | ||
270 | DEFINE_REQ_STATE; | |
271 | s.err.message = "this is a bad request"; | |
272 | ||
39ae355f | 273 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
274 | ASSERT_EQ(rc, 0); |
275 | } | |
276 | ||
1e59de90 | 277 | TEST(TestRGWLua, RGWIdNotWriteable) |
f67539c2 TL |
278 | { |
279 | const std::string script = R"( | |
280 | assert(Request.RGWId == "foo") | |
281 | Request.RGWId = "bar" | |
282 | )"; | |
283 | ||
284 | DEFINE_REQ_STATE; | |
285 | s.host_id = "foo"; | |
286 | ||
39ae355f | 287 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
288 | ASSERT_NE(rc, 0); |
289 | } | |
290 | ||
291 | TEST(TestRGWLua, InvalidField) | |
292 | { | |
293 | const std::string script = R"( | |
294 | RGWDebugLog(Request.Kaboom) | |
295 | )"; | |
296 | ||
297 | DEFINE_REQ_STATE; | |
298 | s.host_id = "foo"; | |
299 | ||
39ae355f | 300 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
301 | ASSERT_EQ(rc, -1); |
302 | } | |
303 | ||
304 | TEST(TestRGWLua, InvalidSubField) | |
305 | { | |
306 | const std::string script = R"( | |
307 | RGWDebugLog(Request.Error.Kaboom) | |
308 | )"; | |
309 | ||
310 | DEFINE_REQ_STATE; | |
311 | ||
39ae355f | 312 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
313 | ASSERT_EQ(rc, -1); |
314 | } | |
315 | ||
316 | TEST(TestRGWLua, Bucket) | |
317 | { | |
318 | const std::string script = R"( | |
319 | assert(Request.Bucket) | |
320 | RGWDebugLog("Bucket Id: " .. Request.Bucket.Id) | |
321 | assert(Request.Bucket.Marker == "mymarker") | |
322 | assert(Request.Bucket.Name == "myname") | |
323 | assert(Request.Bucket.Tenant == "mytenant") | |
324 | assert(Request.Bucket.Count == 0) | |
325 | assert(Request.Bucket.Size == 0) | |
326 | assert(Request.Bucket.ZoneGroupId) | |
327 | assert(Request.Bucket.CreationTime) | |
328 | assert(Request.Bucket.MTime) | |
329 | assert(Request.Bucket.Quota.MaxSize == -1) | |
330 | assert(Request.Bucket.Quota.MaxObjects == -1) | |
331 | assert(tostring(Request.Bucket.Quota.Enabled)) | |
332 | assert(tostring(Request.Bucket.Quota.Rounded)) | |
333 | assert(Request.Bucket.User.Id) | |
334 | assert(Request.Bucket.User.Tenant) | |
335 | )"; | |
336 | ||
337 | DEFINE_REQ_STATE; | |
338 | ||
339 | rgw_bucket b; | |
340 | b.tenant = "mytenant"; | |
341 | b.name = "myname"; | |
342 | b.marker = "mymarker"; | |
343 | b.bucket_id = "myid"; | |
20effc67 | 344 | s.bucket.reset(new sal::RadosBucket(nullptr, b)); |
f67539c2 | 345 | |
39ae355f | 346 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
347 | ASSERT_EQ(rc, 0); |
348 | } | |
349 | ||
1e59de90 TL |
350 | TEST(TestRGWLua, WriteBucket) |
351 | { | |
352 | const std::string script = R"( | |
353 | assert(Request.Bucket) | |
354 | assert(Request.Bucket.Name == "myname") | |
355 | Request.Bucket.Name = "othername" | |
356 | )"; | |
357 | ||
358 | DEFINE_REQ_STATE; | |
359 | s.init_state.url_bucket = "myname"; | |
360 | ||
361 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); | |
362 | ASSERT_EQ(rc, 0); | |
363 | ASSERT_EQ(s.init_state.url_bucket, "othername"); | |
364 | } | |
365 | ||
366 | TEST(TestRGWLua, WriteBucketFail) | |
367 | { | |
368 | const std::string script = R"( | |
369 | assert(Request.Bucket) | |
370 | assert(Request.Bucket.Name == "myname") | |
371 | Request.Bucket.Name = "othername" | |
372 | )"; | |
373 | ||
374 | DEFINE_REQ_STATE; | |
375 | rgw_bucket b; | |
376 | b.name = "myname"; | |
377 | s.bucket.reset(new sal::RadosBucket(nullptr, b)); | |
378 | ||
379 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); | |
380 | ASSERT_NE(rc, 0); | |
381 | } | |
382 | ||
f67539c2 TL |
383 | TEST(TestRGWLua, GenericAttributes) |
384 | { | |
385 | const std::string script = R"( | |
386 | assert(Request.GenericAttributes["hello"] == "world") | |
387 | assert(Request.GenericAttributes["foo"] == "bar") | |
388 | assert(Request.GenericAttributes["kaboom"] == nil) | |
389 | assert(#Request.GenericAttributes == 4) | |
390 | for k, v in pairs(Request.GenericAttributes) do | |
391 | assert(k) | |
392 | assert(v) | |
393 | end | |
394 | )"; | |
395 | ||
396 | DEFINE_REQ_STATE; | |
397 | s.generic_attrs["hello"] = "world"; | |
398 | s.generic_attrs["foo"] = "bar"; | |
399 | s.generic_attrs["goodbye"] = "cruel world"; | |
400 | s.generic_attrs["ka"] = "boom"; | |
401 | ||
39ae355f | 402 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
403 | ASSERT_EQ(rc, 0); |
404 | } | |
405 | ||
406 | TEST(TestRGWLua, Environment) | |
407 | { | |
408 | const std::string script = R"( | |
409 | assert(Request.Environment[""] == "bar") | |
410 | assert(Request.Environment["goodbye"] == "cruel world") | |
411 | assert(Request.Environment["ka"] == "boom") | |
412 | assert(#Request.Environment == 3, #Request.Environment) | |
413 | for k, v in pairs(Request.Environment) do | |
414 | assert(k) | |
415 | assert(v) | |
416 | end | |
417 | )"; | |
418 | ||
419 | DEFINE_REQ_STATE; | |
20effc67 TL |
420 | s.env.emplace("", "bar"); |
421 | s.env.emplace("goodbye", "cruel world"); | |
422 | s.env.emplace("ka", "boom"); | |
f67539c2 | 423 | |
39ae355f | 424 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
425 | ASSERT_EQ(rc, 0); |
426 | } | |
427 | ||
428 | TEST(TestRGWLua, Tags) | |
429 | { | |
430 | const std::string script = R"( | |
431 | assert(#Request.Tags == 4) | |
432 | assert(Request.Tags["foo"] == "bar") | |
433 | for k, v in pairs(Request.Tags) do | |
434 | assert(k) | |
435 | assert(v) | |
436 | end | |
437 | )"; | |
438 | ||
439 | DEFINE_REQ_STATE; | |
440 | s.tagset.add_tag("hello", "world"); | |
441 | s.tagset.add_tag("foo", "bar"); | |
442 | s.tagset.add_tag("goodbye", "cruel world"); | |
443 | s.tagset.add_tag("ka", "boom"); | |
444 | ||
39ae355f | 445 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
446 | ASSERT_EQ(rc, 0); |
447 | } | |
448 | ||
449 | TEST(TestRGWLua, TagsNotWriteable) | |
450 | { | |
451 | const std::string script = R"( | |
452 | Request.Tags["hello"] = "goodbye" | |
453 | )"; | |
454 | ||
455 | DEFINE_REQ_STATE; | |
456 | s.tagset.add_tag("hello", "world"); | |
457 | ||
39ae355f | 458 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
459 | ASSERT_NE(rc, 0); |
460 | } | |
461 | ||
462 | TEST(TestRGWLua, Metadata) | |
463 | { | |
464 | const std::string script = R"( | |
465 | assert(#Request.HTTP.Metadata == 3) | |
466 | for k, v in pairs(Request.HTTP.Metadata) do | |
467 | assert(k) | |
468 | assert(v) | |
469 | end | |
470 | assert(Request.HTTP.Metadata["hello"] == "world") | |
471 | assert(Request.HTTP.Metadata["kaboom"] == nil) | |
472 | Request.HTTP.Metadata["hello"] = "goodbye" | |
473 | Request.HTTP.Metadata["kaboom"] = "boom" | |
474 | assert(#Request.HTTP.Metadata == 4) | |
475 | assert(Request.HTTP.Metadata["hello"] == "goodbye") | |
476 | assert(Request.HTTP.Metadata["kaboom"] == "boom") | |
477 | )"; | |
478 | ||
479 | DEFINE_REQ_STATE; | |
480 | s.info.x_meta_map["hello"] = "world"; | |
481 | s.info.x_meta_map["foo"] = "bar"; | |
482 | s.info.x_meta_map["ka"] = "boom"; | |
483 | ||
39ae355f | 484 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
485 | ASSERT_EQ(rc, 0); |
486 | } | |
487 | ||
488 | TEST(TestRGWLua, Acl) | |
489 | { | |
490 | const std::string script = R"( | |
491 | function print_grant(g) | |
492 | print("Grant Type: " .. g.Type) | |
493 | print("Grant Group Type: " .. g.GroupType) | |
494 | print("Grant Referer: " .. g.Referer) | |
495 | if (g.User) then | |
496 | print("Grant User.Tenant: " .. g.User.Tenant) | |
497 | print("Grant User.Id: " .. g.User.Id) | |
498 | end | |
499 | end | |
500 | ||
501 | assert(Request.UserAcl.Owner.DisplayName == "jack black", Request.UserAcl.Owner.DisplayName) | |
502 | assert(Request.UserAcl.Owner.User.Id == "black", Request.UserAcl.Owner.User.Id) | |
503 | assert(Request.UserAcl.Owner.User.Tenant == "jack", Request.UserAcl.Owner.User.Tenant) | |
504 | assert(#Request.UserAcl.Grants == 5) | |
505 | print_grant(Request.UserAcl.Grants[""]) | |
506 | for k, v in pairs(Request.UserAcl.Grants) do | |
507 | print_grant(v) | |
508 | if k == "john$doe" then | |
509 | assert(v.Permission == 4) | |
510 | elseif k == "jane$doe" then | |
511 | assert(v.Permission == 1) | |
512 | else | |
513 | assert(false) | |
514 | end | |
515 | end | |
516 | )"; | |
517 | ||
518 | DEFINE_REQ_STATE; | |
519 | ACLOwner owner; | |
520 | owner.set_id(rgw_user("jack", "black")); | |
521 | owner.set_name("jack black"); | |
1e59de90 | 522 | s.user_acl.reset(new RGWAccessControlPolicy(g_cct)); |
f67539c2 TL |
523 | s.user_acl->set_owner(owner); |
524 | ACLGrant grant1, grant2, grant3, grant4, grant5; | |
525 | grant1.set_canon(rgw_user("jane", "doe"), "her grant", 1); | |
526 | grant2.set_group(ACL_GROUP_ALL_USERS ,2); | |
527 | grant3.set_referer("http://localhost/ref2", 3); | |
528 | grant4.set_canon(rgw_user("john", "doe"), "his grant", 4); | |
529 | grant5.set_group(ACL_GROUP_AUTHENTICATED_USERS, 5); | |
530 | s.user_acl->get_acl().add_grant(&grant1); | |
531 | s.user_acl->get_acl().add_grant(&grant2); | |
532 | s.user_acl->get_acl().add_grant(&grant3); | |
533 | s.user_acl->get_acl().add_grant(&grant4); | |
534 | s.user_acl->get_acl().add_grant(&grant5); | |
39ae355f | 535 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
536 | ASSERT_EQ(rc, 0); |
537 | } | |
538 | ||
20effc67 TL |
539 | TEST(TestRGWLua, User) |
540 | { | |
541 | const std::string script = R"( | |
542 | assert(Request.User) | |
543 | assert(Request.User.Id == "myid") | |
544 | assert(Request.User.Tenant == "mytenant") | |
545 | )"; | |
546 | ||
547 | DEFINE_REQ_STATE; | |
548 | ||
549 | rgw_user u; | |
550 | u.tenant = "mytenant"; | |
551 | u.id = "myid"; | |
552 | s.user.reset(new sal::RadosUser(nullptr, u)); | |
553 | ||
39ae355f | 554 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
20effc67 TL |
555 | ASSERT_EQ(rc, 0); |
556 | } | |
557 | ||
558 | ||
f67539c2 TL |
559 | TEST(TestRGWLua, UseFunction) |
560 | { | |
561 | const std::string script = R"( | |
562 | function print_owner(owner) | |
563 | print("Owner Dispaly Name: " .. owner.DisplayName) | |
564 | print("Owner Id: " .. owner.User.Id) | |
565 | print("Owner Tenanet: " .. owner.User.Tenant) | |
566 | end | |
567 | ||
568 | print_owner(Request.ObjectOwner) | |
569 | ||
570 | function print_acl(acl_type) | |
571 | index = acl_type .. "ACL" | |
572 | acl = Request[index] | |
573 | if acl then | |
574 | print(acl_type .. "ACL Owner") | |
575 | print_owner(acl.Owner) | |
576 | else | |
577 | print("no " .. acl_type .. " ACL in request: " .. Request.Id) | |
578 | end | |
579 | end | |
580 | ||
581 | print_acl("User") | |
582 | print_acl("Bucket") | |
583 | print_acl("Object") | |
584 | )"; | |
585 | ||
586 | DEFINE_REQ_STATE; | |
587 | s.owner.set_name("user two"); | |
588 | s.owner.set_id(rgw_user("tenant2", "user2")); | |
589 | s.user_acl.reset(new RGWAccessControlPolicy()); | |
590 | s.user_acl->get_owner().set_name("user three"); | |
591 | s.user_acl->get_owner().set_id(rgw_user("tenant3", "user3")); | |
592 | s.bucket_acl.reset(new RGWAccessControlPolicy()); | |
593 | s.bucket_acl->get_owner().set_name("user four"); | |
594 | s.bucket_acl->get_owner().set_id(rgw_user("tenant4", "user4")); | |
595 | s.object_acl.reset(new RGWAccessControlPolicy()); | |
596 | s.object_acl->get_owner().set_name("user five"); | |
597 | s.object_acl->get_owner().set_id(rgw_user("tenant5", "user5")); | |
598 | ||
39ae355f | 599 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
600 | ASSERT_EQ(rc, 0); |
601 | } | |
602 | ||
603 | TEST(TestRGWLua, WithLib) | |
604 | { | |
605 | const std::string script = R"( | |
606 | expected_result = {"my", "bucket", "name", "is", "fish"} | |
607 | i = 1 | |
608 | for p in string.gmatch(Request.Bucket.Name, "%a+") do | |
609 | assert(p == expected_result[i]) | |
610 | i = i + 1 | |
611 | end | |
612 | )"; | |
613 | ||
614 | DEFINE_REQ_STATE; | |
615 | ||
616 | rgw_bucket b; | |
617 | b.name = "my-bucket-name-is-fish"; | |
20effc67 | 618 | s.bucket.reset(new sal::RadosBucket(nullptr, b)); |
f67539c2 | 619 | |
39ae355f | 620 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
621 | ASSERT_EQ(rc, 0); |
622 | } | |
623 | ||
624 | TEST(TestRGWLua, NotAllowedInLib) | |
625 | { | |
626 | const std::string script = R"( | |
627 | os.clock() -- this should be ok | |
628 | os.exit() -- this should fail (os.exit() is removed) | |
629 | )"; | |
630 | ||
631 | DEFINE_REQ_STATE; | |
632 | ||
39ae355f | 633 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); |
f67539c2 TL |
634 | ASSERT_NE(rc, 0); |
635 | } | |
f67539c2 | 636 | |
1e59de90 TL |
637 | #define MAKE_STORE auto store = std::unique_ptr<sal::RadosStore>(new sal::RadosStore); \ |
638 | store->setRados(new RGWRados); | |
f67539c2 TL |
639 | |
640 | TEST(TestRGWLua, OpsLog) | |
641 | { | |
f67539c2 TL |
642 | const std::string script = R"( |
643 | if Request.Response.HTTPStatusCode == 200 then | |
644 | assert(Request.Response.Message == "Life is great") | |
645 | else | |
646 | assert(Request.Bucket) | |
647 | assert(Request.Log() == 0) | |
648 | end | |
649 | )"; | |
650 | ||
1e59de90 TL |
651 | MAKE_STORE; |
652 | ||
653 | struct MockOpsLogSink : OpsLogSink { | |
654 | bool logged = false; | |
655 | int log(req_state*, rgw_log_entry&) override { logged = true; return 0; } | |
656 | }; | |
657 | MockOpsLogSink olog; | |
f67539c2 TL |
658 | |
659 | DEFINE_REQ_STATE; | |
660 | s.err.http_ret = 200; | |
661 | s.err.ret = 0; | |
662 | s.err.err_code = "200OK"; | |
663 | s.err.message = "Life is great"; | |
664 | rgw_bucket b; | |
665 | b.tenant = "tenant"; | |
666 | b.name = "name"; | |
667 | b.marker = "marker"; | |
668 | b.bucket_id = "id"; | |
20effc67 | 669 | s.bucket.reset(new sal::RadosBucket(nullptr, b)); |
f67539c2 TL |
670 | s.bucket_name = "name"; |
671 | s.enable_ops_log = true; | |
672 | s.enable_usage_log = false; | |
20effc67 | 673 | s.user.reset(new TestUser()); |
f67539c2 TL |
674 | TestAccounter ac; |
675 | s.cio = ∾ | |
676 | s.cct->_conf->rgw_ops_log_rados = false; | |
677 | ||
20effc67 TL |
678 | s.auth.identity = std::unique_ptr<rgw::auth::Identity>( |
679 | new FakeIdentity()); | |
680 | ||
1e59de90 | 681 | auto rc = lua::request::execute(store.get(), nullptr, &olog, &s, nullptr, script); |
f67539c2 | 682 | EXPECT_EQ(rc, 0); |
1e59de90 | 683 | EXPECT_FALSE(olog.logged); // don't log http_ret=200 |
f67539c2 TL |
684 | |
685 | s.err.http_ret = 400; | |
1e59de90 | 686 | rc = lua::request::execute(store.get(), nullptr, &olog, &s, nullptr, script); |
f67539c2 | 687 | EXPECT_EQ(rc, 0); |
1e59de90 TL |
688 | EXPECT_TRUE(olog.logged); |
689 | } | |
690 | ||
691 | class TestBackground : public rgw::lua::Background { | |
692 | const unsigned read_time; | |
693 | ||
694 | protected: | |
695 | int read_script() override { | |
696 | // don't read the object from the store | |
697 | std::this_thread::sleep_for(std::chrono::seconds(read_time)); | |
698 | return 0; | |
699 | } | |
700 | ||
701 | public: | |
702 | TestBackground(sal::RadosStore* store, const std::string& script, unsigned read_time = 0) : | |
703 | rgw::lua::Background(store, g_cct, "", /* luarocks path */ 1 /* run every second */), | |
704 | read_time(read_time) { | |
705 | // the script is passed in the constructor | |
706 | rgw_script = script; | |
707 | } | |
708 | ||
709 | ~TestBackground() override { | |
710 | shutdown(); | |
711 | } | |
712 | }; | |
713 | ||
714 | TEST(TestRGWLuaBackground, Start) | |
715 | { | |
716 | MAKE_STORE; | |
717 | { | |
718 | // ctr and dtor without running | |
719 | TestBackground lua_background(store.get(), ""); | |
720 | } | |
721 | { | |
722 | // ctr and dtor with running | |
723 | TestBackground lua_background(store.get(), ""); | |
724 | lua_background.start(); | |
725 | } | |
726 | } | |
727 | ||
728 | ||
729 | constexpr auto wait_time = std::chrono::seconds(3); | |
730 | ||
731 | template<typename T> | |
732 | const T& get_table_value(const TestBackground& b, const std::string& index) { | |
733 | try { | |
734 | return std::get<T>(b.get_table_value(index)); | |
735 | } catch (std::bad_variant_access const& ex) { | |
736 | std::cout << "expected RGW[" << index << "] to be: " << typeid(T).name() << std::endl; | |
737 | throw(ex); | |
738 | } | |
739 | } | |
740 | ||
741 | TEST(TestRGWLuaBackground, Script) | |
742 | { | |
743 | const std::string script = R"( | |
744 | local key = "hello" | |
745 | local value = "world" | |
746 | RGW[key] = value | |
747 | )"; | |
748 | ||
749 | MAKE_STORE; | |
750 | TestBackground lua_background(store.get(), script); | |
751 | lua_background.start(); | |
752 | std::this_thread::sleep_for(wait_time); | |
753 | EXPECT_EQ(get_table_value<std::string>(lua_background, "hello"), "world"); | |
754 | } | |
755 | ||
756 | TEST(TestRGWLuaBackground, RequestScript) | |
757 | { | |
758 | const std::string background_script = R"( | |
759 | local key = "hello" | |
760 | local value = "from background" | |
761 | RGW[key] = value | |
762 | )"; | |
763 | ||
764 | MAKE_STORE; | |
765 | TestBackground lua_background(store.get(), background_script); | |
766 | lua_background.start(); | |
767 | std::this_thread::sleep_for(wait_time); | |
768 | ||
769 | const std::string request_script = R"( | |
770 | local key = "hello" | |
771 | assert(RGW[key] == "from background") | |
772 | local value = "from request" | |
773 | RGW[key] = value | |
774 | )"; | |
775 | ||
776 | DEFINE_REQ_STATE; | |
777 | pe.lua.background = &lua_background; | |
778 | ||
779 | // to make sure test is consistent we have to puase the background | |
780 | lua_background.pause(); | |
781 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
782 | ASSERT_EQ(rc, 0); | |
783 | EXPECT_EQ(get_table_value<std::string>(lua_background, "hello"), "from request"); | |
784 | // now we resume and let the background set the value | |
785 | lua_background.resume(store.get()); | |
786 | std::this_thread::sleep_for(wait_time); | |
787 | EXPECT_EQ(get_table_value<std::string>(lua_background, "hello"), "from background"); | |
788 | } | |
789 | ||
790 | TEST(TestRGWLuaBackground, Pause) | |
791 | { | |
792 | const std::string script = R"( | |
793 | local key = "hello" | |
794 | local value = "1" | |
795 | if RGW[key] then | |
796 | RGW[key] = value..RGW[key] | |
797 | else | |
798 | RGW[key] = value | |
799 | end | |
800 | )"; | |
801 | ||
802 | MAKE_STORE; | |
803 | TestBackground lua_background(store.get(), script); | |
804 | lua_background.start(); | |
805 | std::this_thread::sleep_for(wait_time); | |
806 | const auto value_len = get_table_value<std::string>(lua_background, "hello").size(); | |
807 | EXPECT_GT(value_len, 0); | |
808 | lua_background.pause(); | |
809 | std::this_thread::sleep_for(wait_time); | |
810 | // no change in len | |
811 | EXPECT_EQ(value_len, get_table_value<std::string>(lua_background, "hello").size()); | |
812 | } | |
813 | ||
814 | TEST(TestRGWLuaBackground, PauseWhileReading) | |
815 | { | |
816 | const std::string script = R"( | |
817 | local key = "hello" | |
818 | local value = "world" | |
819 | RGW[key] = value | |
820 | if RGW[key] then | |
821 | RGW[key] = value..RGW[key] | |
822 | else | |
823 | RGW[key] = value | |
824 | end | |
825 | )"; | |
826 | ||
827 | MAKE_STORE; | |
828 | constexpr auto long_wait_time = std::chrono::seconds(6); | |
829 | TestBackground lua_background(store.get(), script, 2); | |
830 | lua_background.start(); | |
831 | std::this_thread::sleep_for(long_wait_time); | |
832 | const auto value_len = get_table_value<std::string>(lua_background, "hello").size(); | |
833 | EXPECT_GT(value_len, 0); | |
834 | lua_background.pause(); | |
835 | std::this_thread::sleep_for(long_wait_time); | |
836 | // one execution might occur after pause | |
837 | EXPECT_TRUE(value_len + 1 >= get_table_value<std::string>(lua_background, "hello").size()); | |
838 | } | |
839 | ||
840 | TEST(TestRGWLuaBackground, ReadWhilePaused) | |
841 | { | |
842 | const std::string script = R"( | |
843 | local key = "hello" | |
844 | local value = "world" | |
845 | RGW[key] = value | |
846 | )"; | |
847 | ||
848 | MAKE_STORE; | |
849 | TestBackground lua_background(store.get(), script); | |
850 | lua_background.pause(); | |
851 | lua_background.start(); | |
852 | std::this_thread::sleep_for(wait_time); | |
853 | EXPECT_EQ(get_table_value<std::string>(lua_background, "hello"), ""); | |
854 | lua_background.resume(store.get()); | |
855 | std::this_thread::sleep_for(wait_time); | |
856 | EXPECT_EQ(get_table_value<std::string>(lua_background, "hello"), "world"); | |
857 | } | |
858 | ||
859 | TEST(TestRGWLuaBackground, PauseResume) | |
860 | { | |
861 | const std::string script = R"( | |
862 | local key = "hello" | |
863 | local value = "1" | |
864 | if RGW[key] then | |
865 | RGW[key] = value..RGW[key] | |
866 | else | |
867 | RGW[key] = value | |
868 | end | |
869 | )"; | |
870 | ||
871 | MAKE_STORE; | |
872 | TestBackground lua_background(store.get(), script); | |
873 | lua_background.start(); | |
874 | std::this_thread::sleep_for(wait_time); | |
875 | const auto value_len = get_table_value<std::string>(lua_background, "hello").size(); | |
876 | EXPECT_GT(value_len, 0); | |
877 | lua_background.pause(); | |
878 | std::this_thread::sleep_for(wait_time); | |
879 | // no change in len | |
880 | EXPECT_EQ(value_len, get_table_value<std::string>(lua_background, "hello").size()); | |
881 | lua_background.resume(store.get()); | |
882 | std::this_thread::sleep_for(wait_time); | |
883 | // should be a change in len | |
884 | EXPECT_GT(get_table_value<std::string>(lua_background, "hello").size(), value_len); | |
885 | } | |
886 | ||
887 | TEST(TestRGWLuaBackground, MultipleStarts) | |
888 | { | |
889 | const std::string script = R"( | |
890 | local key = "hello" | |
891 | local value = "1" | |
892 | if RGW[key] then | |
893 | RGW[key] = value..RGW[key] | |
894 | else | |
895 | RGW[key] = value | |
896 | end | |
897 | )"; | |
898 | ||
899 | MAKE_STORE; | |
900 | TestBackground lua_background(store.get(), script); | |
901 | lua_background.start(); | |
902 | std::this_thread::sleep_for(wait_time); | |
903 | const auto value_len = get_table_value<std::string>(lua_background, "hello").size(); | |
904 | EXPECT_GT(value_len, 0); | |
905 | lua_background.start(); | |
906 | lua_background.shutdown(); | |
907 | lua_background.shutdown(); | |
908 | std::this_thread::sleep_for(wait_time); | |
909 | lua_background.start(); | |
910 | std::this_thread::sleep_for(wait_time); | |
911 | // should be a change in len | |
912 | EXPECT_GT(get_table_value<std::string>(lua_background, "hello").size(), value_len); | |
913 | } | |
914 | ||
915 | TEST(TestRGWLuaBackground, TableValues) | |
916 | { | |
917 | MAKE_STORE; | |
918 | TestBackground lua_background(store.get(), ""); | |
919 | ||
920 | const std::string request_script = R"( | |
921 | RGW["key1"] = "string value" | |
922 | RGW["key2"] = 42 | |
923 | RGW["key3"] = 42.2 | |
924 | RGW["key4"] = true | |
925 | )"; | |
926 | ||
927 | DEFINE_REQ_STATE; | |
928 | pe.lua.background = &lua_background; | |
929 | ||
930 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
931 | ASSERT_EQ(rc, 0); | |
932 | EXPECT_EQ(get_table_value<std::string>(lua_background, "key1"), "string value"); | |
933 | EXPECT_EQ(get_table_value<long long int>(lua_background, "key2"), 42); | |
934 | EXPECT_EQ(get_table_value<double>(lua_background, "key3"), 42.2); | |
935 | EXPECT_TRUE(get_table_value<bool>(lua_background, "key4")); | |
936 | } | |
937 | ||
938 | TEST(TestRGWLuaBackground, TablePersist) | |
939 | { | |
940 | MAKE_STORE; | |
941 | TestBackground lua_background(store.get(), ""); | |
942 | ||
943 | std::string request_script = R"( | |
944 | RGW["key1"] = "string value" | |
945 | RGW["key2"] = 42 | |
946 | )"; | |
947 | ||
948 | DEFINE_REQ_STATE; | |
949 | pe.lua.background = &lua_background; | |
950 | ||
951 | auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
952 | ASSERT_EQ(rc, 0); | |
953 | EXPECT_EQ(get_table_value<std::string>(lua_background, "key1"), "string value"); | |
954 | EXPECT_EQ(get_table_value<long long int>(lua_background, "key2"), 42); | |
955 | ||
956 | request_script = R"( | |
957 | RGW["key3"] = RGW["key1"] | |
958 | RGW["key4"] = RGW["key2"] | |
959 | )"; | |
960 | ||
961 | rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
962 | ASSERT_EQ(rc, 0); | |
963 | EXPECT_EQ(get_table_value<std::string>(lua_background, "key1"), "string value"); | |
964 | EXPECT_EQ(get_table_value<long long int>(lua_background, "key2"), 42); | |
965 | EXPECT_EQ(get_table_value<std::string>(lua_background, "key3"), "string value"); | |
966 | EXPECT_EQ(get_table_value<long long int>(lua_background, "key4"), 42); | |
967 | } | |
968 | ||
969 | TEST(TestRGWLuaBackground, TableValuesFromRequest) | |
970 | { | |
971 | MAKE_STORE; | |
972 | TestBackground lua_background(store.get(), ""); | |
973 | lua_background.start(); | |
974 | ||
975 | const std::string request_script = R"( | |
976 | RGW["key1"] = Request.Response.RGWCode | |
977 | RGW["key2"] = Request.Response.Message | |
978 | RGW["key3"] = Request.Response.RGWCode*0.1 | |
979 | RGW["key4"] = Request.Tags["key1"] == Request.Tags["key2"] | |
980 | )"; | |
981 | ||
982 | DEFINE_REQ_STATE; | |
983 | pe.lua.background = &lua_background; | |
984 | ||
985 | s.tagset.add_tag("key1", "val1"); | |
986 | s.tagset.add_tag("key2", "val1"); | |
987 | s.err.ret = -99; | |
988 | s.err.message = "hi"; | |
989 | ||
990 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
991 | ASSERT_EQ(rc, 0); | |
992 | EXPECT_EQ(get_table_value<long long int>(lua_background, "key1"), -99); | |
993 | EXPECT_EQ(get_table_value<std::string>(lua_background, "key2"), "hi"); | |
994 | EXPECT_EQ(get_table_value<double>(lua_background, "key3"), -9.9); | |
995 | EXPECT_EQ(get_table_value<bool>(lua_background, "key4"), true); | |
996 | } | |
997 | ||
998 | TEST(TestRGWLuaBackground, TableInvalidValue) | |
999 | { | |
1000 | MAKE_STORE; | |
1001 | TestBackground lua_background(store.get(), ""); | |
1002 | lua_background.start(); | |
1003 | ||
1004 | const std::string request_script = R"( | |
1005 | RGW["key1"] = "val1" | |
1006 | RGW["key2"] = 42 | |
1007 | RGW["key3"] = 42.2 | |
1008 | RGW["key4"] = true | |
1009 | RGW["key5"] = Request.Tags | |
1010 | )"; | |
1011 | ||
1012 | DEFINE_REQ_STATE; | |
1013 | pe.lua.background = &lua_background; | |
1014 | s.tagset.add_tag("key1", "val1"); | |
1015 | s.tagset.add_tag("key2", "val2"); | |
1016 | ||
1017 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
1018 | ASSERT_NE(rc, 0); | |
1019 | EXPECT_EQ(get_table_value<std::string>(lua_background, "key1"), "val1"); | |
1020 | EXPECT_EQ(get_table_value<long long int>(lua_background, "key2"), 42); | |
1021 | EXPECT_EQ(get_table_value<double>(lua_background, "key3"), 42.2); | |
1022 | EXPECT_EQ(get_table_value<bool>(lua_background, "key4"), true); | |
1023 | } | |
1024 | ||
1025 | TEST(TestRGWLuaBackground, TableErase) | |
1026 | { | |
1027 | MAKE_STORE; | |
1028 | TestBackground lua_background(store.get(), ""); | |
1029 | ||
1030 | std::string request_script = R"( | |
1031 | RGW["size"] = 0 | |
1032 | RGW["key1"] = "string value" | |
1033 | RGW["key2"] = 42 | |
1034 | RGW["key3"] = "another string value" | |
1035 | RGW["size"] = #RGW | |
1036 | )"; | |
1037 | ||
1038 | DEFINE_REQ_STATE; | |
1039 | pe.lua.background = &lua_background; | |
1040 | ||
1041 | auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
1042 | ASSERT_EQ(rc, 0); | |
1043 | EXPECT_EQ(get_table_value<std::string>(lua_background, "key1"), "string value"); | |
1044 | EXPECT_EQ(get_table_value<long long int>(lua_background, "key2"), 42); | |
1045 | EXPECT_EQ(get_table_value<std::string>(lua_background, "key3"), "another string value"); | |
1046 | EXPECT_EQ(get_table_value<long long int>(lua_background, "size"), 4); | |
1047 | ||
1048 | request_script = R"( | |
1049 | -- erase key1 | |
1050 | RGW["key1"] = nil | |
1051 | -- following should be a no op | |
1052 | RGW["key4"] = nil | |
1053 | RGW["size"] = #RGW | |
1054 | )"; | |
1055 | ||
1056 | rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
1057 | ASSERT_EQ(rc, 0); | |
1058 | EXPECT_EQ(get_table_value<std::string>(lua_background, "key1"), ""); | |
1059 | EXPECT_EQ(get_table_value<long long int>(lua_background, "key2"), 42); | |
1060 | EXPECT_EQ(get_table_value<std::string>(lua_background, "key3"), "another string value"); | |
1061 | EXPECT_EQ(get_table_value<long long int>(lua_background, "size"), 3); | |
1062 | } | |
1063 | ||
1064 | TEST(TestRGWLuaBackground, TableIterate) | |
1065 | { | |
1066 | MAKE_STORE; | |
1067 | TestBackground lua_background(store.get(), ""); | |
1068 | ||
1069 | const std::string request_script = R"( | |
1070 | RGW["key1"] = "string value" | |
1071 | RGW["key2"] = 42 | |
1072 | RGW["key3"] = 42.2 | |
1073 | RGW["key4"] = true | |
1074 | RGW["size"] = 0 | |
1075 | for k, v in pairs(RGW) do | |
1076 | RGW["size"] = RGW["size"] + 1 | |
1077 | end | |
1078 | )"; | |
1079 | ||
1080 | DEFINE_REQ_STATE; | |
1081 | pe.lua.background = &lua_background; | |
1082 | ||
1083 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
1084 | ASSERT_EQ(rc, 0); | |
1085 | EXPECT_EQ(get_table_value<std::string>(lua_background, "key1"), "string value"); | |
1086 | EXPECT_EQ(get_table_value<long long int>(lua_background, "key2"), 42); | |
1087 | EXPECT_EQ(get_table_value<double>(lua_background, "key3"), 42.2); | |
1088 | EXPECT_TRUE(get_table_value<bool>(lua_background, "key4")); | |
1089 | EXPECT_EQ(get_table_value<long long int>(lua_background, "size"), 5); | |
1090 | } | |
1091 | ||
1092 | TEST(TestRGWLuaBackground, TableIncrement) | |
1093 | { | |
1094 | MAKE_STORE; | |
1095 | TestBackground lua_background(store.get(), ""); | |
1096 | ||
1097 | const std::string request_script = R"( | |
1098 | RGW["key1"] = 42 | |
1099 | RGW["key2"] = 42.2 | |
1100 | RGW.increment("key1") | |
1101 | assert(RGW["key1"] == 43) | |
1102 | RGW.increment("key2") | |
1103 | assert(RGW["key2"] == 43.2) | |
1104 | )"; | |
1105 | ||
1106 | DEFINE_REQ_STATE; | |
1107 | pe.lua.background = &lua_background; | |
1108 | ||
1109 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
1110 | ASSERT_EQ(rc, 0); | |
1111 | } | |
1112 | ||
1113 | TEST(TestRGWLuaBackground, TableIncrementBy) | |
1114 | { | |
1115 | MAKE_STORE; | |
1116 | TestBackground lua_background(store.get(), ""); | |
1117 | ||
1118 | const std::string request_script = R"( | |
1119 | RGW["key1"] = 42 | |
1120 | RGW["key2"] = 42.2 | |
1121 | RGW.increment("key1", 10) | |
1122 | assert(RGW["key1"] == 52) | |
1123 | RGW.increment("key2", 10) | |
1124 | assert(RGW["key2"] == 52.2) | |
1125 | RGW.increment("key1", 0.2) | |
1126 | assert(RGW["key1"] == 52.2) | |
1127 | )"; | |
1128 | ||
1129 | DEFINE_REQ_STATE; | |
1130 | pe.lua.background = &lua_background; | |
1131 | ||
1132 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
1133 | ASSERT_EQ(rc, 0); | |
1134 | } | |
1135 | ||
1136 | TEST(TestRGWLuaBackground, TableDecrement) | |
1137 | { | |
1138 | MAKE_STORE; | |
1139 | TestBackground lua_background(store.get(), ""); | |
1140 | ||
1141 | const std::string request_script = R"( | |
1142 | RGW["key1"] = 42 | |
1143 | RGW["key2"] = 42.2 | |
1144 | RGW.decrement("key1") | |
1145 | assert(RGW["key1"] == 41) | |
1146 | RGW.decrement("key2") | |
1147 | assert(RGW["key2"] == 41.2) | |
1148 | )"; | |
1149 | ||
1150 | DEFINE_REQ_STATE; | |
1151 | pe.lua.background = &lua_background; | |
1152 | ||
1153 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
1154 | ASSERT_EQ(rc, 0); | |
1155 | } | |
1156 | ||
1157 | TEST(TestRGWLuaBackground, TableDecrementBy) | |
1158 | { | |
1159 | MAKE_STORE; | |
1160 | TestBackground lua_background(store.get(), ""); | |
1161 | ||
1162 | const std::string request_script = R"( | |
1163 | RGW["key1"] = 42 | |
1164 | RGW["key2"] = 42.2 | |
1165 | RGW.decrement("key1", 10) | |
1166 | assert(RGW["key1"] == 32) | |
1167 | RGW.decrement("key2", 10) | |
1168 | assert(RGW["key2"] == 32.2) | |
1169 | RGW.decrement("key1", 0.8) | |
1170 | assert(RGW["key1"] == 31.2) | |
1171 | )"; | |
1172 | ||
1173 | DEFINE_REQ_STATE; | |
1174 | pe.lua.background = &lua_background; | |
1175 | ||
1176 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
1177 | ASSERT_EQ(rc, 0); | |
1178 | } | |
1179 | ||
1180 | TEST(TestRGWLuaBackground, TableIncrementValueError) | |
1181 | { | |
1182 | MAKE_STORE; | |
1183 | TestBackground lua_background(store.get(), ""); | |
1184 | ||
1185 | std::string request_script = R"( | |
1186 | -- cannot increment string values | |
1187 | RGW["key1"] = "hello" | |
1188 | RGW.increment("key1") | |
1189 | )"; | |
f67539c2 | 1190 | |
1e59de90 TL |
1191 | DEFINE_REQ_STATE; |
1192 | pe.lua.background = &lua_background; | |
1193 | ||
1194 | auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
1195 | ASSERT_NE(rc, 0); | |
1196 | ||
1197 | request_script = R"( | |
1198 | -- cannot increment bool values | |
1199 | RGW["key1"] = true | |
1200 | RGW.increment("key1") | |
1201 | )"; | |
1202 | ||
1203 | rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
1204 | ASSERT_NE(rc, 0); | |
1205 | ||
1206 | request_script = R"( | |
1207 | -- cannot increment by string values | |
1208 | RGW["key1"] = 99 | |
1209 | RGW.increment("key1", "kaboom") | |
1210 | )"; | |
1211 | ||
1212 | rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
1213 | ASSERT_NE(rc, 0); | |
1214 | } | |
1215 | ||
1216 | TEST(TestRGWLuaBackground, TableIncrementError) | |
1217 | { | |
1218 | MAKE_STORE; | |
1219 | TestBackground lua_background(store.get(), ""); | |
1220 | ||
1221 | std::string request_script = R"( | |
1222 | -- missing argument | |
1223 | RGW["key1"] = 11 | |
1224 | RGW.increment() | |
1225 | )"; | |
1226 | ||
1227 | DEFINE_REQ_STATE; | |
1228 | pe.lua.background = &lua_background; | |
1229 | ||
1230 | auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
1231 | ASSERT_NE(rc, 0); | |
1232 | ||
1233 | request_script = R"( | |
1234 | -- used as settable field | |
1235 | RGW.increment = 11 | |
1236 | )"; | |
1237 | ||
1238 | rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); | |
1239 | ASSERT_NE(rc, 0); | |
1240 | } | |
1241 | ||
1242 | TEST(TestRGWLua, TracingSetAttribute) | |
1243 | { | |
1244 | const std::string script = R"( | |
1245 | Request.Trace.SetAttribute("str-attr", "value") | |
1246 | Request.Trace.SetAttribute("int-attr", 42) | |
1247 | Request.Trace.SetAttribute("double-attr", 42.5) | |
1248 | )"; | |
1249 | ||
1250 | DEFINE_REQ_STATE; | |
1251 | INIT_TRACE; | |
1252 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); | |
1253 | ASSERT_EQ(rc, 0); | |
1254 | } | |
1255 | ||
1256 | TEST(TestRGWLua, TracingSetBadAttribute) | |
1257 | { | |
1258 | const std::string script = R"( | |
1259 | Request.Trace.SetAttribute("attr", nil) | |
1260 | )"; | |
1261 | ||
1262 | DEFINE_REQ_STATE; | |
1263 | INIT_TRACE; | |
1264 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); | |
1265 | #ifdef HAVE_JAEGER | |
1266 | ASSERT_NE(rc, 0); | |
1267 | #else | |
1268 | ASSERT_EQ(rc, 0); | |
1269 | #endif | |
1270 | } | |
1271 | ||
1272 | TEST(TestRGWLua, TracingAddEvent) | |
1273 | { | |
1274 | const std::string script = R"( | |
1275 | event_attrs = {} | |
1276 | event_attrs["x"] = "value-x" | |
1277 | event_attrs[42] = 42 | |
1278 | event_attrs[42.5] = 42.5 | |
1279 | event_attrs["y"] = "value-y" | |
1280 | ||
1281 | Request.Trace.AddEvent("my_event", event_attrs) | |
1282 | )"; | |
1283 | ||
1284 | DEFINE_REQ_STATE; | |
1285 | INIT_TRACE; | |
1286 | const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); | |
1287 | ASSERT_EQ(rc, 0); | |
1288 | } | |
1289 | ||
1290 | TEST(TestRGWLua, Data) | |
1291 | { | |
1292 | const std::string script = R"( | |
1293 | local expected = "The quick brown fox jumps over the lazy dog" | |
1294 | local actual = "" | |
1295 | RGW["key1"] = 0 | |
1296 | ||
1297 | for i, c in pairs(Data) do | |
1298 | actual = actual .. c | |
1299 | RGW.increment("key1") | |
1300 | end | |
1301 | assert(expected == actual) | |
1302 | assert(#Data == #expected); | |
1303 | assert(RGW["key1"] == #Data) | |
1304 | assert(Request.RGWId == "foo") | |
1305 | assert(Offset == 12345678) | |
1306 | )"; | |
1307 | ||
1308 | MAKE_STORE; | |
1309 | TestBackground lua_background(store.get(), ""); | |
1310 | DEFINE_REQ_STATE; | |
1311 | s.host_id = "foo"; | |
1312 | pe.lua.background = &lua_background; | |
1313 | lua::RGWObjFilter filter(&s, script); | |
1314 | bufferlist bl; | |
1315 | bl.append("The quick brown fox jumps over the lazy dog"); | |
1316 | off_t offset = 12345678; | |
1317 | const auto rc = filter.execute(bl, offset, "put_obj"); | |
1318 | ASSERT_EQ(rc, 0); | |
1319 | } | |
1320 | ||
1321 | TEST(TestRGWLua, WriteDataFail) | |
1322 | { | |
1323 | const std::string script = R"( | |
1324 | Data[1] = "h" | |
1325 | Data[2] = "e" | |
1326 | Data[3] = "l" | |
1327 | Data[4] = "l" | |
1328 | Data[5] = "o" | |
1329 | )"; | |
1330 | ||
1331 | DEFINE_REQ_STATE; | |
1332 | lua::RGWObjFilter filter(&s, script); | |
1333 | bufferlist bl; | |
1334 | bl.append("The quick brown fox jumps over the lazy dog"); | |
1335 | const auto rc = filter.execute(bl, 0, "put_obj"); | |
1336 | ASSERT_NE(rc, 0); | |
f67539c2 TL |
1337 | } |
1338 |