update TODO
[awesomized/libmemcached] / test / tests / memcached / replication.cpp
1 #include "test/lib/common.hpp"
2 #include "test/lib/MemcachedCluster.hpp"
3
4 #include "libmemcached/instance.hpp"
5
6 TEST_CASE("memcached_replication") {
7 MemcachedCluster test = MemcachedCluster::network();
8 auto memc = &test.memc;
9
10 test.enableBinaryProto();
11 test.enableReplication();
12
13 SECTION("replicates one key to all servers") {
14 REQUIRE_SUCCESS(memcached_set(memc, S(__func__), S(__func__), 0, 0));
15 memcached_quit(memc);
16
17 for (const auto &server : test.cluster.getServers()) {
18 MemcachedPtr check;
19
20 REQUIRE_SUCCESS(memcached_server_add(*check, "localhost", get<int>(server.getSocketOrPort())));
21
22 memcached_return_t rc;
23 Malloced val(memcached_get(*check, S(__func__), nullptr, nullptr, &rc));
24 REQUIRE_SUCCESS(rc);
25 REQUIRE(string(__func__) == *val);
26 }
27 }
28
29 #define NUM_KEYS 100
30
31 SECTION("replicates many keys to all servers") {
32 array<string, NUM_KEYS> str;
33 array<char *, NUM_KEYS> chr;
34 array<size_t, NUM_KEYS> len;
35
36 for (auto i = 0U; i < NUM_KEYS; ++i) {
37 str[i] = random_binary_string(12) + to_string(i);
38 chr[i] = str[i].data();
39 len[i] = str[i].length();
40
41 REQUIRE_SUCCESS(memcached_set(memc, chr[i], len[i], chr[i], len[i], 0, 0));
42 }
43 memcached_quit(memc);
44
45 for (auto i = 0U; i < memcached_server_count(memc); ++i) {
46 auto pos = i % memcached_server_count(memc);
47 auto ins = memcached_server_instance_by_position(memc, pos);
48 MemcachedPtr single;
49 memcached_result_st r;
50 memcached_return_t rc;
51
52 REQUIRE(memcached_result_create(*single, &r));
53 REQUIRE_SUCCESS(memcached_server_add(*single, "localhost", ins->port()));
54 REQUIRE_SUCCESS(memcached_behavior_set(*single, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1));
55 REQUIRE_SUCCESS(memcached_mget(*single, chr.data(), len.data(), NUM_KEYS));
56
57 size_t n = 0;
58 while (memcached_fetch_result(*single, &r, &rc)) {
59 ++n;
60 REQUIRE_SUCCESS(rc);
61 }
62 CHECK(n == NUM_KEYS);
63 REQUIRE_RC(MEMCACHED_END, rc);
64 memcached_result_free(&r);
65 }
66
67 SECTION("deletes and randomize reads") {
68 REQUIRE_SUCCESS(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ, 1));
69 for (auto i = 0; i < NUM_KEYS; ++i) {
70 memcached_return_t rc;
71 auto result = memcached_result_create(memc, nullptr);
72
73 REQUIRE(result);
74 REQUIRE_SUCCESS(memcached_mget_by_key(memc, chr[i], len[i], chr.data(), len.data(), NUM_KEYS));
75
76 size_t n = 0;
77 while (memcached_fetch_result(memc, result, &rc)) {
78 ++n;
79 REQUIRE_SUCCESS(rc);
80 }
81 CHECK(n + i == NUM_KEYS);
82 REQUIRE_RC(MEMCACHED_END, rc);
83
84 REQUIRE_SUCCESS(memcached_delete(memc, chr[i], len[i], 0));
85 }
86 }
87
88 #if 0
89 # warning I think the old test is bogus and the functionality does not exist as advertised
90
91 SECTION("deleted from primary") {
92 for (auto i = 0; i < NUM_KEYS; ++i) {
93 memcached_return_t rc;
94
95 CHECK(MEMCACHED_SUCCESS == memcached_delete(memc, chr[i], len[i], 0));
96 Malloced val(memcached_get(memc, chr[i], len[i], nullptr, nullptr, &rc));
97 CHECK(MEMCACHED_SUCCESS == rc);
98 CHECK(*val);
99 }
100 }
101 SECTION("dead replica") {
102 test.killOneServer();
103
104 for (auto i = 0; i < NUM_KEYS; ++i) {
105 memcached_return_t rc;
106
107 Malloced val(memcached_get(memc, chr[i], len[i], nullptr, nullptr, &rc));
108 CHECK(MEMCACHED_SUCCESS == rc);
109 CHECK(*val);
110 }
111 }
112 #endif
113 }
114 }