1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
5 * Copyright (C) 2011 Data Differential, http://datadifferential.com/
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following disclaimer
16 * in the documentation and/or other materials provided with the
19 * * The names of its contributors may not be used to endorse or
20 * promote products derived from this software without specific prior
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 #include <libtest/test.hpp>
40 #include <libmemcached/memcached.h>
41 #include <libmemcached/server_instance.h>
42 #include <libmemcached/continuum.hpp>
43 #include <libmemcached/instance.h>
45 #include <tests/ketama.h>
46 #include <tests/ketama_test_cases.h>
48 test_return_t
ketama_compatibility_libmemcached(memcached_st
*)
50 memcached_st
*memc
= memcached_create(NULL
);
53 test_compare(MEMCACHED_SUCCESS
,
54 memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
, 1));
56 test_compare(uint64_t(1), memcached_behavior_get(memc
, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
));
58 test_compare(MEMCACHED_SUCCESS
, memcached_behavior_set_distribution(memc
, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA
));
59 test_compare(MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA
, memcached_behavior_get_distribution(memc
));
61 memcached_server_st
*server_pool
= memcached_servers_parse("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");
62 memcached_server_push(memc
, server_pool
);
64 /* verify that the server list was parsed okay. */
65 test_compare(8U, memcached_server_count(memc
));
66 test_strcmp(server_pool
[0].hostname
, "10.0.1.1");
67 test_compare(in_port_t(11211), server_pool
[0].port
);
68 test_compare(600U, server_pool
[0].weight
);
69 test_strcmp(server_pool
[2].hostname
, "10.0.1.3");
70 test_compare(in_port_t(11211), server_pool
[2].port
);
71 test_compare(200U, server_pool
[2].weight
);
72 test_strcmp(server_pool
[7].hostname
, "10.0.1.8");
73 test_compare(in_port_t(11211), server_pool
[7].port
);
74 test_compare(100U, server_pool
[7].weight
);
76 /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
77 * us test the boundary wraparound.
79 test_true(memcached_generate_hash(memc
, (char *)"VDEAAAAA", 8) == memc
->ketama
.continuum
[0].index
);
81 /* verify the standard ketama set. */
82 for (uint32_t x
= 0; x
< 99; x
++)
84 uint32_t server_idx
= memcached_generate_hash(memc
, ketama_test_cases
[x
].key
, strlen(ketama_test_cases
[x
].key
));
85 memcached_server_instance_st instance
=
86 memcached_server_instance_by_position(memc
, server_idx
);
87 const char *hostname
= memcached_server_name(instance
);
89 test_strcmp(hostname
, ketama_test_cases
[x
].server
);
92 memcached_server_list_free(server_pool
);
98 test_return_t
user_supplied_bug18(memcached_st
*trash
)
100 memcached_return_t rc
;
107 memc
= memcached_create(NULL
);
110 rc
= memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
, 1);
111 test_compare(MEMCACHED_SUCCESS
, rc
);
113 value
= memcached_behavior_get(memc
, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
);
114 test_true(value
== 1);
116 rc
= memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_KETAMA_HASH
, MEMCACHED_HASH_MD5
);
117 test_compare(MEMCACHED_SUCCESS
, rc
);
119 value
= memcached_behavior_get(memc
, MEMCACHED_BEHAVIOR_KETAMA_HASH
);
120 test_true(value
== MEMCACHED_HASH_MD5
);
122 memcached_server_st
*server_pool
= memcached_servers_parse("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");
123 memcached_server_push(memc
, server_pool
);
125 /* verify that the server list was parsed okay. */
126 test_true(memcached_server_count(memc
) == 8);
127 test_strcmp(server_pool
[0].hostname
, "10.0.1.1");
128 test_true(server_pool
[0].port
== 11211);
129 test_true(server_pool
[0].weight
== 600);
130 test_strcmp(server_pool
[2].hostname
, "10.0.1.3");
131 test_true(server_pool
[2].port
== 11211);
132 test_true(server_pool
[2].weight
== 200);
133 test_strcmp(server_pool
[7].hostname
, "10.0.1.8");
134 test_true(server_pool
[7].port
== 11211);
135 test_true(server_pool
[7].weight
== 100);
137 /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
138 * us test the boundary wraparound.
140 test_true(memcached_generate_hash(memc
, (char *)"VDEAAAAA", 8) == memc
->ketama
.continuum
[0].index
);
142 /* verify the standard ketama set. */
143 for (x
= 0; x
< 99; x
++)
145 uint32_t server_idx
= memcached_generate_hash(memc
, ketama_test_cases
[x
].key
, strlen(ketama_test_cases
[x
].key
));
147 memcached_server_instance_st instance
=
148 memcached_server_instance_by_position(memc
, server_idx
);
150 const char *hostname
= memcached_server_name(instance
);
151 test_strcmp(hostname
, ketama_test_cases
[x
].server
);
154 memcached_server_list_free(server_pool
);
155 memcached_free(memc
);
160 test_return_t
auto_eject_hosts(memcached_st
*trash
)
164 memcached_return_t rc
;
165 memcached_st
*memc
= memcached_create(NULL
);
168 rc
= memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
, 1);
169 test_compare(MEMCACHED_SUCCESS
, rc
);
171 uint64_t value
= memcached_behavior_get(memc
, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
);
172 test_true(value
== 1);
174 rc
= memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_KETAMA_HASH
, MEMCACHED_HASH_MD5
);
175 test_compare(MEMCACHED_SUCCESS
, rc
);
177 value
= memcached_behavior_get(memc
, MEMCACHED_BEHAVIOR_KETAMA_HASH
);
178 test_true(value
== MEMCACHED_HASH_MD5
);
180 /* server should be removed when in delay */
181 rc
= memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS
, 1);
182 test_compare(MEMCACHED_SUCCESS
, rc
);
184 value
= memcached_behavior_get(memc
, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS
);
185 test_true(value
== 1);
187 memcached_server_st
*server_pool
;
188 server_pool
= memcached_servers_parse("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");
189 memcached_server_push(memc
, server_pool
);
191 /* verify that the server list was parsed okay. */
192 test_true(memcached_server_count(memc
) == 8);
193 test_strcmp(server_pool
[0].hostname
, "10.0.1.1");
194 test_true(server_pool
[0].port
== 11211);
195 test_true(server_pool
[0].weight
== 600);
196 test_strcmp(server_pool
[2].hostname
, "10.0.1.3");
197 test_true(server_pool
[2].port
== 11211);
198 test_true(server_pool
[2].weight
== 200);
199 test_strcmp(server_pool
[7].hostname
, "10.0.1.8");
200 test_true(server_pool
[7].port
== 11211);
201 test_true(server_pool
[7].weight
== 100);
203 memcached_server_instance_st instance
= memcached_server_instance_by_position(memc
, 2);
204 memcached_instance_next_retry(instance
, time(NULL
) +15);
205 memc
->ketama
.next_distribution_rebuild
= time(NULL
) - 1;
208 This would not work if there were only two hosts.
210 for (ptrdiff_t x
= 0; x
< 99; x
++)
212 memcached_autoeject(memc
);
213 uint32_t server_idx
= memcached_generate_hash(memc
, ketama_test_cases
[x
].key
, strlen(ketama_test_cases
[x
].key
));
214 test_true(server_idx
!= 2);
217 /* and re-added when it's back. */
218 time_t absolute_time
= time(NULL
) -1;
219 memcached_instance_next_retry(instance
, absolute_time
);
220 memc
->ketama
.next_distribution_rebuild
= absolute_time
;
221 memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_DISTRIBUTION
,
223 for (ptrdiff_t x
= 0; x
< 99; x
++)
225 uint32_t server_idx
= memcached_generate_hash(memc
, ketama_test_cases
[x
].key
, strlen(ketama_test_cases
[x
].key
));
226 // We re-use instance from above.
228 memcached_server_instance_by_position(memc
, server_idx
);
229 const char *hostname
= memcached_server_name(instance
);
230 test_strcmp(hostname
, ketama_test_cases
[x
].server
);
233 memcached_server_list_free(server_pool
);
234 memcached_free(memc
);
239 test_return_t
ketama_compatibility_spymemcached(memcached_st
*)
241 memcached_st
*memc
= memcached_create(NULL
);
244 test_compare(MEMCACHED_SUCCESS
,
245 memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
, 1));
247 test_compare(UINT64_C(1), memcached_behavior_get(memc
, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
));
249 test_compare(MEMCACHED_SUCCESS
, memcached_behavior_set_distribution(memc
, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY
));
250 test_compare(MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY
, memcached_behavior_get_distribution(memc
));
252 memcached_server_st
*server_pool
= memcached_servers_parse("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");
253 test_true(server_pool
);
254 memcached_server_push(memc
, server_pool
);
256 /* verify that the server list was parsed okay. */
257 test_compare(8U, memcached_server_count(memc
));
258 test_strcmp(server_pool
[0].hostname
, "10.0.1.1");
259 test_compare(in_port_t(11211), server_pool
[0].port
);
260 test_compare(600U, server_pool
[0].weight
);
261 test_strcmp(server_pool
[2].hostname
, "10.0.1.3");
262 test_compare(in_port_t(11211), server_pool
[2].port
);
263 test_compare(200U, server_pool
[2].weight
);
264 test_strcmp(server_pool
[7].hostname
, "10.0.1.8");
265 test_compare(in_port_t(11211), server_pool
[7].port
);
266 test_compare(100U, server_pool
[7].weight
);
268 /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
269 * us test the boundary wraparound.
271 test_true(memcached_generate_hash(memc
, (char *)"VDEAAAAA", 8) == memc
->ketama
.continuum
[0].index
);
273 /* verify the standard ketama set. */
274 for (uint32_t x
= 0; x
< 99; x
++)
276 uint32_t server_idx
= memcached_generate_hash(memc
, ketama_test_cases_spy
[x
].key
, strlen(ketama_test_cases_spy
[x
].key
));
278 memcached_server_instance_st instance
=
279 memcached_server_instance_by_position(memc
, server_idx
);
281 const char *hostname
= memcached_server_name(instance
);
283 test_strcmp(hostname
, ketama_test_cases_spy
[x
].server
);
286 memcached_server_list_free(server_pool
);
287 memcached_free(memc
);