1 #include "test/lib/common.hpp"
2 #include "test/lib/MemcachedCluster.hpp"
3 #include "test/fixtures/callbacks.hpp"
5 TEST_CASE("memcached_callbacks") {
6 auto test
{MemcachedCluster::mixed()};
7 auto memc
= &test
.memc
;
10 SECTION("user data") {
14 REQUIRE_SUCCESS(memcached_callback_set(memc
, MEMCACHED_CALLBACK_USER_DATA
, data
));
15 REQUIRE(data
== memcached_callback_get(memc
, MEMCACHED_CALLBACK_USER_DATA
, &rc
));
19 SECTION("delete callback") {
20 void *dptr
= reinterpret_cast<void *>(reinterpret_cast<intptr_t>(&delete_trigger
));
22 REQUIRE_SUCCESS(memcached_callback_set(memc
, MEMCACHED_CALLBACK_DELETE_TRIGGER
, dptr
));
23 REQUIRE(memcached_callback_get(memc
, MEMCACHED_CALLBACK_DELETE_TRIGGER
, &rc
) == dptr
);
26 SECTION("fails w/ NOREPLY") {
27 REQUIRE_SUCCESS(memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_NOREPLY
, true));
28 REQUIRE_RC(MEMCACHED_INVALID_ARGUMENTS
, memcached_callback_set(memc
, MEMCACHED_CALLBACK_DELETE_TRIGGER
, dptr
));
32 SECTION("get_failure callback") {
33 void *gptr
= reinterpret_cast<void *>(reinterpret_cast<intptr_t>(&get_failure
));
34 Malloced
empty(memcached_get(memc
, S(__func__
), nullptr, nullptr, &rc
));
35 REQUIRE_FALSE(*empty
);
36 REQUIRE_RC(MEMCACHED_NOTFOUND
, rc
);
38 uint64_t buffering
= GENERATE(0, 1);
40 DYNAMIC_SECTION("buffering: " << buffering
) {
41 REQUIRE_SUCCESS(memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS
, buffering
));
42 REQUIRE_SUCCESS(memcached_callback_set(memc
, MEMCACHED_CALLBACK_GET_FAILURE
, gptr
));
43 REQUIRE(gptr
== memcached_callback_get(memc
, MEMCACHED_CALLBACK_GET_FAILURE
, &rc
));
46 for (int twice
= 0; twice
< 2; ++twice
) {
49 Malloced
val(memcached_get(memc
, S(__func__
), &len
, &flags
, &rc
));
52 REQUIRE(string("updated by read through trigger") == string(*val
, len
));
53 REQUIRE_FALSE((*val
)[len
]);
56 REQUIRE_SUCCESS(memcached_set(memc
, S(__func__
), S("changed"), 0, 0));
58 Malloced
val(memcached_get(memc
, S(__func__
), nullptr, nullptr, &rc
));
60 REQUIRE("changed"s
== *val
);
64 SECTION("clone callback") {
65 void *cptr
= reinterpret_cast<void *>(reinterpret_cast<intptr_t>(&clone_callback
));
67 REQUIRE_SUCCESS(memcached_callback_set(memc
, MEMCACHED_CALLBACK_CLONE_FUNCTION
, cptr
));
68 REQUIRE(cptr
== memcached_callback_get(memc
, MEMCACHED_CALLBACK_CLONE_FUNCTION
, &rc
));
72 SECTION("cleanup callback") {
73 void *cptr
= reinterpret_cast<void *>(reinterpret_cast<intptr_t>(cleanup_callback
));
75 REQUIRE_SUCCESS(memcached_callback_set(memc
, MEMCACHED_CALLBACK_CLEANUP_FUNCTION
, cptr
));
76 REQUIRE(cptr
== memcached_callback_get(memc
, MEMCACHED_CALLBACK_CLEANUP_FUNCTION
, &rc
));
80 SECTION("namespace") {
83 REQUIRE_SUCCESS(memcached_callback_set(memc
, MEMCACHED_CALLBACK_NAMESPACE
, "ns"));
84 ns
= memcached_callback_get(memc
, MEMCACHED_CALLBACK_NAMESPACE
, &rc
);
86 REQUIRE("ns"s
== static_cast<char *>(ns
));
88 REQUIRE_SUCCESS(memcached_callback_set(memc
, MEMCACHED_CALLBACK_NAMESPACE
, nullptr));
89 ns
= memcached_callback_get(memc
, MEMCACHED_CALLBACK_NAMESPACE
, &rc
);
91 REQUIRE(nullptr == ns
);
94 uint64_t binary
= GENERATE(0, 1);
95 REQUIRE_SUCCESS(memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL
, binary
));
97 DYNAMIC_SECTION("too long (binary=" << binary
<< ")") {
100 blob
= random_ascii_string(MEMCACHED_MAX_NAMESPACE
-1, '@', 'Z');
101 REQUIRE_SUCCESS(memcached_callback_set(memc
, MEMCACHED_CALLBACK_NAMESPACE
, blob
.c_str()));
103 blob
= random_ascii_string(MEMCACHED_MAX_NAMESPACE
, '@', 'Z');
104 REQUIRE_RC(MEMCACHED_KEY_TOO_BIG
,memcached_callback_set(memc
, MEMCACHED_CALLBACK_NAMESPACE
, blob
.c_str()));
107 DYNAMIC_SECTION("verify key (binary=" << binary
<< ")") {
108 REQUIRE_RC(binary
? MEMCACHED_INVALID_ARGUMENTS
: MEMCACHED_SUCCESS
,
109 memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_VERIFY_KEY
, 1));
110 REQUIRE_RC(binary
? MEMCACHED_SUCCESS
: MEMCACHED_BAD_KEY_PROVIDED
,
111 memcached_callback_set(memc
, MEMCACHED_CALLBACK_NAMESPACE
, "with spaces"));