1 #include "test/lib/common.hpp"
2 #include "test/lib/MemcachedCluster.hpp"
3 #include "test/fixtures/callbacks.hpp"
4 #include "libmemcached/instance.hpp"
8 TEST_CASE("memcached_regression_lp447342") {
9 auto test
= MemcachedCluster::network();
10 auto memc
= &test
.memc
;
12 REQUIRE_SUCCESS(memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS
, 2));
14 array
<string
, NUM_KEYS
> str
;
15 array
<char *, NUM_KEYS
> chr
;
16 array
<size_t, NUM_KEYS
> len
;
18 for (auto i
= 0U; i
< NUM_KEYS
; ++i
) {
19 str
[i
] = random_ascii_string(random_num(12, 16)) + to_string(i
);
20 chr
[i
] = str
[i
].data();
21 len
[i
] = str
[i
].length();
22 REQUIRE_SUCCESS(memcached_set(memc
, chr
[i
], len
[i
], chr
[i
], len
[i
], 0, 0));
26 ** We are using the quit command to store the replicas, so we need
27 ** to ensure that all of them are processed before we can continue.
28 ** In the test we go directly from storing the object to trying to
29 ** receive the object from all of the different servers, so we
30 ** could end up in a race condition (the memcached server hasn't yet
31 ** processed the quiet command from the replication set when it process
32 ** the request from the other client (created by the clone)). As a
33 ** workaround for that we call memcached_quit to send the quit command
34 ** to the server and wait for the response ;-) If you use the test code
35 ** as an example for your own code, please note that you shouldn't need
41 REQUIRE_SUCCESS(memcached_mget(memc
, chr
.data(), len
.data(), NUM_KEYS
));
44 memcached_execute_fn cb
[] = {&callback_counter
};
45 REQUIRE_SUCCESS(memcached_fetch_execute(memc
, cb
, &counter
, 1));
46 REQUIRE(counter
== NUM_KEYS
);
51 * Don't do the following in your code. I am abusing the internal details
52 * within the library, and this is not a supported interface.
53 * This is to verify correct behavior in the library. Fake that two servers
56 auto instance_one
= memcached_server_instance_by_position(memc
, 0);
57 auto instance_two
= memcached_server_instance_by_position(memc
, 2);
58 in_port_t port0
= instance_one
->port();
59 in_port_t port2
= instance_two
->port();
61 const_cast<memcached_instance_st
*>(instance_one
)->port(0);
62 const_cast<memcached_instance_st
*>(instance_two
)->port(0);
64 REQUIRE_SUCCESS(memcached_mget(memc
, chr
.data(), len
.data(), NUM_KEYS
));
67 REQUIRE_SUCCESS(memcached_fetch_execute(memc
, cb
, &counter
, 1));
68 REQUIRE(counter
== NUM_KEYS
);
70 /* restore the memc handle */
71 const_cast<memcached_instance_st
*>(instance_one
)->port(port0
);
72 const_cast<memcached_instance_st
*>(instance_two
)->port(port2
);
76 for (auto i
= 0U; i
< NUM_KEYS
; ++i
) {
78 REQUIRE_SUCCESS(memcached_delete(memc
, chr
[i
], len
[i
], 0));
84 const_cast<memcached_instance_st
*>(instance_one
)->port(0);
85 const_cast<memcached_instance_st
*>(instance_two
)->port(0);
87 /* now retry the command, this time we should have cache misses */
88 REQUIRE_SUCCESS(memcached_mget(memc
, chr
.data(), len
.data(), NUM_KEYS
));
91 REQUIRE_SUCCESS(memcached_fetch_execute(memc
, cb
, &counter
, 1));
92 REQUIRE(counter
== NUM_KEYS
>>1U);