1 #include "testing/lib/common.hpp"
2 #include "testing/lib/MemcachedCluster.hpp"
4 #include "ketama_test_cases.h"
6 #include "libmemcached/continuum.hpp"
7 #include "libmemcached/instance.hpp"
11 TEST_CASE("memcached ketama_compat") {
12 auto test
= MemcachedCluster::network();
13 auto memc
= &test
.memc
;
15 REQUIRE_SUCCESS(memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
, 1));
16 REQUIRE(uint64_t(1) == memcached_behavior_get(memc
, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
));
18 SECTION("generate hash") {
19 REQUIRE_SUCCESS(memcached_behavior_set_distribution(memc
, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA
));
20 REQUIRE(MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA
== memcached_behavior_get_distribution(memc
));
22 memcached_server_st
*server_pool
= memcached_servers_parse(
23 "10.0.1.1:11211 600,10.0.1.2:11211 300,10.0.1.3:11211 200,10.0.1.4:11211 350,10.0.1.5:11211 1000,10.0.1.6:11211 800,10.0.1.7:11211 950,10.0.1.8:11211 100"
25 memcached_servers_reset(memc
);
26 memcached_server_push(memc
, server_pool
);
28 /* verify that the server list was parsed okay. */
29 REQUIRE(8U == memcached_server_count(memc
));
30 REQUIRE(strequal(server_pool
[0].hostname
, "10.0.1.1"));
31 REQUIRE(in_port_t(11211) == server_pool
[0].port
);
32 REQUIRE(600U == server_pool
[0].weight
);
33 REQUIRE(strequal(server_pool
[2].hostname
, "10.0.1.3"));
34 REQUIRE(in_port_t(11211) == server_pool
[2].port
);
35 REQUIRE(200U == server_pool
[2].weight
);
36 REQUIRE(strequal(server_pool
[7].hostname
, "10.0.1.8"));
37 REQUIRE(in_port_t(11211) == server_pool
[7].port
);
38 REQUIRE(100U == server_pool
[7].weight
);
40 /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
41 * us test the boundary wraparound.
43 REQUIRE(memcached_generate_hash(memc
, (char *) "VDEAAAAA", 8) == memc
->ketama
.continuum
[0].index
);
45 /* verify the standard ketama set. */
46 for (uint32_t x
= 0; x
< 99; x
++) {
47 uint32_t server_idx
= memcached_generate_hash(memc
, ketama_test_cases
[x
].key
, strlen(ketama_test_cases
[x
].key
));
48 const memcached_instance_st
*instance
=
49 memcached_server_instance_by_position(memc
, server_idx
);
50 const char *hostname
= memcached_server_name(instance
);
52 REQUIRE(strequal(hostname
, ketama_test_cases
[x
].server
));
55 memcached_server_list_free(server_pool
);
58 SECTION("user bug 18") {
60 REQUIRE_SUCCESS(memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_KETAMA_HASH
, MEMCACHED_HASH_MD5
));
61 REQUIRE(MEMCACHED_HASH_MD5
== memcached_behavior_get(memc
, MEMCACHED_BEHAVIOR_KETAMA_HASH
));
63 memcached_server_st
*server_pool
= memcached_servers_parse(
64 "10.0.1.1:11211 600,10.0.1.2:11211 300,10.0.1.3:11211 200,10.0.1.4:11211 350,10.0.1.5:11211 1000,10.0.1.6:11211 800,10.0.1.7:11211 950,10.0.1.8:11211 100"
66 memcached_servers_reset(memc
);
67 memcached_server_push(memc
, server_pool
);
69 /* verify that the server list was parsed okay. */
70 REQUIRE(memcached_server_count(memc
) == 8);
71 REQUIRE(strequal(server_pool
[0].hostname
, "10.0.1.1"));
72 REQUIRE(server_pool
[0].port
== 11211);
73 REQUIRE(server_pool
[0].weight
== 600);
74 REQUIRE(strequal(server_pool
[2].hostname
, "10.0.1.3"));
75 REQUIRE(server_pool
[2].port
== 11211);
76 REQUIRE(server_pool
[2].weight
== 200);
77 REQUIRE(strequal(server_pool
[7].hostname
, "10.0.1.8"));
78 REQUIRE(server_pool
[7].port
== 11211);
79 REQUIRE(server_pool
[7].weight
== 100);
81 /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
82 * us test the boundary wraparound.
84 REQUIRE(memcached_generate_hash(memc
, (char *) "VDEAAAAA", 8) == memc
->ketama
.continuum
[0].index
);
86 /* verify the standard ketama set. */
87 for (auto x
= 0; x
< 99; x
++) {
88 uint32_t server_idx
= memcached_generate_hash(memc
, ketama_test_cases
[x
].key
, strlen(ketama_test_cases
[x
].key
));
90 const memcached_instance_st
*instance
=
91 memcached_server_instance_by_position(memc
, server_idx
);
93 const char *hostname
= memcached_server_name(instance
);
94 REQUIRE(strequal(hostname
, ketama_test_cases
[x
].server
));
97 memcached_server_list_free(server_pool
);
100 SECTION("auto_eject_hosts") {
101 memcached_servers_reset(memc
);
103 REQUIRE_SUCCESS(memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_KETAMA_HASH
, MEMCACHED_HASH_MD5
));
104 REQUIRE(MEMCACHED_HASH_MD5
== memcached_behavior_get(memc
, MEMCACHED_BEHAVIOR_KETAMA_HASH
));
106 /* server should be removed when in delay */
107 REQUIRE_SUCCESS(memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS
, 1));
108 REQUIRE(memcached_behavior_get(memc
, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS
));
110 memcached_server_st
*server_pool
;
111 server_pool
= memcached_servers_parse(
112 "10.0.1.1:11211 600,10.0.1.2:11211 300,10.0.1.3:11211 200,10.0.1.4:11211 350,10.0.1.5:11211 1000,10.0.1.6:11211 800,10.0.1.7:11211 950,10.0.1.8:11211 100"
114 memcached_servers_reset(memc
);
115 memcached_server_push(memc
, server_pool
);
117 /* verify that the server list was parsed okay. */
118 REQUIRE(memcached_server_count(memc
) == 8);
119 REQUIRE(strequal(server_pool
[0].hostname
, "10.0.1.1"));
120 REQUIRE(server_pool
[0].port
== 11211);
121 REQUIRE(server_pool
[0].weight
== 600);
122 REQUIRE(strequal(server_pool
[2].hostname
, "10.0.1.3"));
123 REQUIRE(server_pool
[2].port
== 11211);
124 REQUIRE(server_pool
[2].weight
== 200);
125 REQUIRE(strequal(server_pool
[7].hostname
, "10.0.1.8"));
126 REQUIRE(server_pool
[7].port
== 11211);
127 REQUIRE(server_pool
[7].weight
== 100);
129 const memcached_instance_st
*instance
= memcached_server_instance_by_position(memc
, 2);
130 memcached_instance_next_retry(instance
, time(nullptr) + 15);
131 memc
->ketama
.next_distribution_rebuild
= time(nullptr) - 1;
134 This would not work if there were only two hosts.
136 for (auto x
= 0; x
< 99; x
++) {
137 memcached_autoeject(memc
);
138 uint32_t server_idx
= memcached_generate_hash(memc
, ketama_test_cases
[x
].key
, strlen(ketama_test_cases
[x
].key
));
139 REQUIRE(server_idx
!= 2);
142 /* and re-added when it's back. */
143 time_t absolute_time
= time(nullptr) - 1;
144 memcached_instance_next_retry(instance
, absolute_time
);
145 memc
->ketama
.next_distribution_rebuild
= absolute_time
;
146 memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_DISTRIBUTION
, memc
->distribution
);
147 for (auto x
= 0; x
< 99; x
++) {
148 uint32_t server_idx
= memcached_generate_hash(memc
, ketama_test_cases
[x
].key
, strlen(ketama_test_cases
[x
].key
));
149 // We re-use instance from above.
150 instance
= memcached_server_instance_by_position(memc
, server_idx
);
151 const char *hostname
= memcached_server_name(instance
);
152 REQUIRE(strequal(hostname
, ketama_test_cases
[x
].server
));
155 memcached_server_list_free(server_pool
);
158 SECTION("spymemcached") {
159 memcached_servers_reset(memc
);
160 REQUIRE_SUCCESS(memcached_behavior_set_distribution(memc
, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY
));
161 REQUIRE(MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY
== memcached_behavior_get_distribution(memc
));
163 memcached_server_st
*server_pool
= memcached_servers_parse(
164 "10.0.1.1:11211 600,10.0.1.2:11211 300,10.0.1.3:11211 200,10.0.1.4:11211 350,10.0.1.5:11211 1000,10.0.1.6:11211 800,10.0.1.7:11211 950,10.0.1.8:11211 100"
166 REQUIRE(server_pool
);
167 memcached_server_push(memc
, server_pool
);
169 /* verify that the server list was parsed okay. */
170 REQUIRE(8U == memcached_server_count(memc
));
171 REQUIRE(strequal(server_pool
[0].hostname
, "10.0.1.1"));
172 REQUIRE(in_port_t(11211) == server_pool
[0].port
);
173 REQUIRE(600U == server_pool
[0].weight
);
174 REQUIRE(strequal(server_pool
[2].hostname
, "10.0.1.3"));
175 REQUIRE(in_port_t(11211) == server_pool
[2].port
);
176 REQUIRE(200U == server_pool
[2].weight
);
177 REQUIRE(strequal(server_pool
[7].hostname
, "10.0.1.8"));
178 REQUIRE(in_port_t(11211) == server_pool
[7].port
);
179 REQUIRE(100U == server_pool
[7].weight
);
181 /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
182 * us test the boundary wraparound.
184 REQUIRE(memcached_generate_hash(memc
, (char *) "VDEAAAAA", 8) == memc
->ketama
.continuum
[0].index
);
186 /* verify the standard ketama set. */
187 for (uint32_t x
= 0; x
< 99; x
++) {
188 uint32_t server_idx
= memcached_generate_hash(memc
, ketama_test_cases_spy
[x
].key
,
189 strlen(ketama_test_cases_spy
[x
].key
));
191 const memcached_instance_st
*instance
=
192 memcached_server_instance_by_position(memc
, server_idx
);
194 const char *hostname
= memcached_server_name(instance
);
195 REQUIRE(strequal(hostname
, ketama_test_cases_spy
[x
].server
));
198 memcached_server_list_free(server_pool
);