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>
44 #include <tests/ketama.h>
45 #include <tests/ketama_test_cases.h>
47 test_return_t
ketama_compatibility_libmemcached(memcached_st
*)
49 memcached_st
*memc
= memcached_create(NULL
);
52 test_compare(MEMCACHED_SUCCESS
,
53 memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
, 1));
55 test_compare(uint64_t(1), memcached_behavior_get(memc
, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
));
57 test_compare(MEMCACHED_SUCCESS
, memcached_behavior_set_distribution(memc
, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA
));
58 test_compare(MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA
, memcached_behavior_get_distribution(memc
));
60 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");
61 memcached_server_push(memc
, server_pool
);
63 /* verify that the server list was parsed okay. */
64 test_compare(8U, memcached_server_count(memc
));
65 test_strcmp(server_pool
[0].hostname
, "10.0.1.1");
66 test_compare(in_port_t(11211), server_pool
[0].port
);
67 test_compare(600U, server_pool
[0].weight
);
68 test_strcmp(server_pool
[2].hostname
, "10.0.1.3");
69 test_compare(in_port_t(11211), server_pool
[2].port
);
70 test_compare(200U, server_pool
[2].weight
);
71 test_strcmp(server_pool
[7].hostname
, "10.0.1.8");
72 test_compare(in_port_t(11211), server_pool
[7].port
);
73 test_compare(100U, server_pool
[7].weight
);
75 /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
76 * us test the boundary wraparound.
78 test_true(memcached_generate_hash(memc
, (char *)"VDEAAAAA", 8) == memc
->ketama
.continuum
[0].index
);
80 /* verify the standard ketama set. */
81 for (uint32_t x
= 0; x
< 99; x
++)
83 uint32_t server_idx
= memcached_generate_hash(memc
, ketama_test_cases
[x
].key
, strlen(ketama_test_cases
[x
].key
));
84 memcached_server_instance_st instance
=
85 memcached_server_instance_by_position(memc
, server_idx
);
86 const char *hostname
= memcached_server_name(instance
);
88 test_strcmp(hostname
, ketama_test_cases
[x
].server
);
91 memcached_server_list_free(server_pool
);
97 test_return_t
user_supplied_bug18(memcached_st
*trash
)
99 memcached_return_t rc
;
106 memc
= memcached_create(NULL
);
109 rc
= memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
, 1);
110 test_compare(MEMCACHED_SUCCESS
, rc
);
112 value
= memcached_behavior_get(memc
, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
);
113 test_true(value
== 1);
115 rc
= memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_KETAMA_HASH
, MEMCACHED_HASH_MD5
);
116 test_compare(MEMCACHED_SUCCESS
, rc
);
118 value
= memcached_behavior_get(memc
, MEMCACHED_BEHAVIOR_KETAMA_HASH
);
119 test_true(value
== MEMCACHED_HASH_MD5
);
121 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");
122 memcached_server_push(memc
, server_pool
);
124 /* verify that the server list was parsed okay. */
125 test_true(memcached_server_count(memc
) == 8);
126 test_strcmp(server_pool
[0].hostname
, "10.0.1.1");
127 test_true(server_pool
[0].port
== 11211);
128 test_true(server_pool
[0].weight
== 600);
129 test_strcmp(server_pool
[2].hostname
, "10.0.1.3");
130 test_true(server_pool
[2].port
== 11211);
131 test_true(server_pool
[2].weight
== 200);
132 test_strcmp(server_pool
[7].hostname
, "10.0.1.8");
133 test_true(server_pool
[7].port
== 11211);
134 test_true(server_pool
[7].weight
== 100);
136 /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
137 * us test the boundary wraparound.
139 test_true(memcached_generate_hash(memc
, (char *)"VDEAAAAA", 8) == memc
->ketama
.continuum
[0].index
);
141 /* verify the standard ketama set. */
142 for (x
= 0; x
< 99; x
++)
144 uint32_t server_idx
= memcached_generate_hash(memc
, ketama_test_cases
[x
].key
, strlen(ketama_test_cases
[x
].key
));
146 memcached_server_instance_st instance
=
147 memcached_server_instance_by_position(memc
, server_idx
);
149 const char *hostname
= memcached_server_name(instance
);
150 test_strcmp(hostname
, ketama_test_cases
[x
].server
);
153 memcached_server_list_free(server_pool
);
154 memcached_free(memc
);
159 test_return_t
auto_eject_hosts(memcached_st
*trash
)
162 memcached_server_instance_st instance
;
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 instance
= memcached_server_instance_by_position(memc
, 2);
204 ((memcached_server_write_instance_st
)instance
)->next_retry
= 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 (size_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 ((memcached_server_write_instance_st
)instance
)->next_retry
= time(NULL
) - 1;
219 memc
->ketama
.next_distribution_rebuild
= time(NULL
) - 1;
220 memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_DISTRIBUTION
,
222 for (size_t x
= 0; x
< 99; x
++)
224 uint32_t server_idx
= memcached_generate_hash(memc
, ketama_test_cases
[x
].key
, strlen(ketama_test_cases
[x
].key
));
225 // We re-use instance from above.
227 memcached_server_instance_by_position(memc
, server_idx
);
228 const char *hostname
= memcached_server_name(instance
);
229 test_strcmp(hostname
, ketama_test_cases
[x
].server
);
232 memcached_server_list_free(server_pool
);
233 memcached_free(memc
);
238 test_return_t
ketama_compatibility_spymemcached(memcached_st
*)
240 memcached_st
*memc
= memcached_create(NULL
);
243 test_compare(MEMCACHED_SUCCESS
,
244 memcached_behavior_set(memc
, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
, 1));
246 test_compare(UINT64_C(1), memcached_behavior_get(memc
, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
));
248 test_compare(MEMCACHED_SUCCESS
, memcached_behavior_set_distribution(memc
, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY
));
249 test_compare(MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY
, memcached_behavior_get_distribution(memc
));
251 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");
252 test_true(server_pool
);
253 memcached_server_push(memc
, server_pool
);
255 /* verify that the server list was parsed okay. */
256 test_compare(8U, memcached_server_count(memc
));
257 test_strcmp(server_pool
[0].hostname
, "10.0.1.1");
258 test_compare(in_port_t(11211), server_pool
[0].port
);
259 test_compare(600U, server_pool
[0].weight
);
260 test_strcmp(server_pool
[2].hostname
, "10.0.1.3");
261 test_compare(in_port_t(11211), server_pool
[2].port
);
262 test_compare(200U, server_pool
[2].weight
);
263 test_strcmp(server_pool
[7].hostname
, "10.0.1.8");
264 test_compare(in_port_t(11211), server_pool
[7].port
);
265 test_compare(100U, server_pool
[7].weight
);
267 /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
268 * us test the boundary wraparound.
270 test_true(memcached_generate_hash(memc
, (char *)"VDEAAAAA", 8) == memc
->ketama
.continuum
[0].index
);
272 /* verify the standard ketama set. */
273 for (uint32_t x
= 0; x
< 99; x
++)
275 uint32_t server_idx
= memcached_generate_hash(memc
, ketama_test_cases_spy
[x
].key
, strlen(ketama_test_cases_spy
[x
].key
));
277 memcached_server_instance_st instance
=
278 memcached_server_instance_by_position(memc
, server_idx
);
280 const char *hostname
= memcached_server_name(instance
);
282 test_strcmp(hostname
, ketama_test_cases_spy
[x
].server
);
285 memcached_server_list_free(server_pool
);
286 memcached_free(memc
);