1 #include "test/lib/common.hpp"
2 #include "test/lib/MemcachedCluster.hpp"
4 #include "libmemcached/instance.hpp"
6 static memcached_return_t
callback_counter(const memcached_st
*, memcached_result_st
*, void *context
) {
7 auto *counter
= reinterpret_cast<size_t *>(context
);
8 *counter
= *counter
+ 1;
10 return MEMCACHED_SUCCESS
;
15 TEST_CASE("memcached_regression_lp447342") {
16 auto test
= MemcachedCluster::mixed();
17 auto memc
= &test
.memc
;
19 REQUIRE_SUCCESS(memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS
, 2));
21 array
<string
, NUM_KEYS
> str
;
22 array
<char *, NUM_KEYS
> chr
;
23 array
<size_t, NUM_KEYS
> len
;
25 for (auto i
= 0U; i
< NUM_KEYS
; ++i
) {
26 str
[i
] = random_ascii_string(random_num(12, 16)) + to_string(i
);
27 chr
[i
] = str
[i
].data();
28 len
[i
] = str
[i
].length();
29 REQUIRE_SUCCESS(memcached_set(memc
, chr
[i
], len
[i
], chr
[i
], len
[i
], 0, 0));
33 ** We are using the qiet command to store the replicas, so we need
34 ** to ensure that all of them are processed before we can continue.
35 ** In the test we go directly from storing the object to trying to
36 ** receive the object from all of the different servers, so we
37 ** could end up in a race condition (the memcached server hasn't yet
38 ** processed the quiet command from the replication set when it process
39 ** the request from the other client (created by the clone)). As a
40 ** workaround for that we call memcached_quit to send the quit command
41 ** to the server and wait for the response ;-) If you use the test code
42 ** as an example for your own code, please note that you shouldn't need
48 REQUIRE_SUCCESS(memcached_mget(memc
, chr
.data(), len
.data(), NUM_KEYS
));
51 memcached_execute_fn cb
[] = {&callback_counter
};
52 REQUIRE_SUCCESS(memcached_fetch_execute(memc
, cb
, &counter
, 1));
53 REQUIRE(counter
== NUM_KEYS
);
58 * Don't do the following in your code. I am abusing the internal details
59 * within the library, and this is not a supported interface.
60 * This is to verify correct behavior in the library. Fake that two servers
63 auto instance_one
= memcached_server_instance_by_position(memc
, 0);
64 auto instance_two
= memcached_server_instance_by_position(memc
, 2);
65 in_port_t port0
= instance_one
->port();
66 in_port_t port2
= instance_two
->port();
68 const_cast<memcached_instance_st
*>(instance_one
)->port(0);
69 const_cast<memcached_instance_st
*>(instance_two
)->port(0);
71 REQUIRE_SUCCESS(memcached_mget(memc
, chr
.data(), len
.data(), NUM_KEYS
));
74 REQUIRE_SUCCESS(memcached_fetch_execute(memc
, cb
, &counter
, 1));
75 REQUIRE(counter
== NUM_KEYS
);
77 /* restore the memc handle */
78 const_cast<memcached_instance_st
*>(instance_one
)->port(port0
);
79 const_cast<memcached_instance_st
*>(instance_two
)->port(port2
);
83 for (auto i
= 0U; i
< NUM_KEYS
; ++i
) {
85 REQUIRE_SUCCESS(memcached_delete(memc
, chr
[i
], len
[i
], 0));
91 const_cast<memcached_instance_st
*>(instance_one
)->port(0);
92 const_cast<memcached_instance_st
*>(instance_two
)->port(0);
94 /* now retry the command, this time we should have cache misses */
95 REQUIRE_SUCCESS(memcached_mget(memc
, chr
.data(), len
.data(), NUM_KEYS
));
98 REQUIRE_SUCCESS(memcached_fetch_execute(memc
, cb
, &counter
, 1));
99 REQUIRE(counter
== NUM_KEYS
>>1U);