~brianaker/libmemcached/1164440

« back to all changes in this revision

Viewing changes to tests/libmemcached-1.0/ketama.cc

Merging bzr://gaz.tangent.org/libmemcached/build/ to Build branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
2
 * 
 
3
 *  Libmemcached library
 
4
 *
 
5
 *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
 
6
 *
 
7
 *  Redistribution and use in source and binary forms, with or without
 
8
 *  modification, are permitted provided that the following conditions are
 
9
 *  met:
 
10
 *
 
11
 *      * Redistributions of source code must retain the above copyright
 
12
 *  notice, this list of conditions and the following disclaimer.
 
13
 *
 
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
 
17
 *  distribution.
 
18
 *
 
19
 *      * The names of its contributors may not be used to endorse or
 
20
 *  promote products derived from this software without specific prior
 
21
 *  written permission.
 
22
 *
 
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.
 
34
 *
 
35
 */
 
36
 
 
37
#include <config.h>
 
38
#include <libtest/test.hpp>
 
39
 
 
40
#include <libmemcached/memcached.h>
 
41
#include <libmemcached/server_instance.h>
 
42
#include <libmemcached/continuum.hpp>
 
43
 
 
44
#include <tests/ketama.h>
 
45
#include <tests/ketama_test_cases.h>
 
46
 
 
47
test_return_t ketama_compatibility_libmemcached(memcached_st *)
 
48
{
 
49
  memcached_st *memc= memcached_create(NULL);
 
50
  test_true(memc);
 
51
 
 
52
  test_compare(MEMCACHED_SUCCESS,
 
53
               memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, 1));
 
54
 
 
55
  test_compare(uint64_t(1), memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED));
 
56
 
 
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));
 
59
 
 
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);
 
62
 
 
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);
 
74
 
 
75
  /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
 
76
   * us test the boundary wraparound.
 
77
   */
 
78
  test_true(memcached_generate_hash(memc, (char *)"VDEAAAAA", 8) == memc->ketama.continuum[0].index);
 
79
 
 
80
  /* verify the standard ketama set. */
 
81
  for (uint32_t x= 0; x < 99; x++)
 
82
  {
 
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);
 
87
 
 
88
    test_strcmp(hostname, ketama_test_cases[x].server);
 
89
  }
 
90
 
 
91
  memcached_server_list_free(server_pool);
 
92
  memcached_free(memc);
 
93
 
 
94
  return TEST_SUCCESS;
 
95
}
 
96
 
 
97
test_return_t user_supplied_bug18(memcached_st *trash)
 
98
{
 
99
  memcached_return_t rc;
 
100
  uint64_t value;
 
101
  int x;
 
102
  memcached_st *memc;
 
103
 
 
104
  (void)trash;
 
105
 
 
106
  memc= memcached_create(NULL);
 
107
  test_true(memc);
 
108
 
 
109
  rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, 1);
 
110
  test_compare(MEMCACHED_SUCCESS, rc);
 
111
 
 
112
  value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED);
 
113
  test_true(value == 1);
 
114
 
 
115
  rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_HASH, MEMCACHED_HASH_MD5);
 
116
  test_compare(MEMCACHED_SUCCESS, rc);
 
117
 
 
118
  value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_KETAMA_HASH);
 
119
  test_true(value == MEMCACHED_HASH_MD5);
 
120
 
 
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);
 
123
 
 
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);
 
135
 
 
136
  /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
 
137
   * us test the boundary wraparound.
 
138
   */
 
139
  test_true(memcached_generate_hash(memc, (char *)"VDEAAAAA", 8) == memc->ketama.continuum[0].index);
 
140
 
 
141
  /* verify the standard ketama set. */
 
142
  for (x= 0; x < 99; x++)
 
143
  {
 
144
    uint32_t server_idx = memcached_generate_hash(memc, ketama_test_cases[x].key, strlen(ketama_test_cases[x].key));
 
145
 
 
146
    memcached_server_instance_st instance=
 
147
      memcached_server_instance_by_position(memc, server_idx);
 
148
 
 
149
    const char *hostname = memcached_server_name(instance);
 
150
    test_strcmp(hostname, ketama_test_cases[x].server);
 
151
  }
 
152
 
 
153
  memcached_server_list_free(server_pool);
 
154
  memcached_free(memc);
 
155
 
 
156
  return TEST_SUCCESS;
 
157
}
 
158
 
 
159
test_return_t auto_eject_hosts(memcached_st *trash)
 
160
{
 
161
  (void) trash;
 
162
  memcached_server_instance_st instance;
 
163
 
 
164
  memcached_return_t rc;
 
165
  memcached_st *memc= memcached_create(NULL);
 
166
  test_true(memc);
 
167
 
 
168
  rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, 1);
 
169
  test_compare(MEMCACHED_SUCCESS, rc);
 
170
 
 
171
  uint64_t value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED);
 
172
  test_true(value == 1);
 
173
 
 
174
  rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_HASH, MEMCACHED_HASH_MD5);
 
175
  test_compare(MEMCACHED_SUCCESS, rc);
 
176
 
 
177
  value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_KETAMA_HASH);
 
178
  test_true(value == MEMCACHED_HASH_MD5);
 
179
 
 
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);
 
183
 
 
184
  value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS);
 
185
  test_true(value == 1);
 
186
 
 
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);
 
190
 
 
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);
 
202
 
 
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;
 
206
 
 
207
  /*
 
208
    This would not work if there were only two hosts.
 
209
  */
 
210
  for (ptrdiff_t x= 0; x < 99; x++)
 
211
  {
 
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);
 
215
  }
 
216
 
 
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,
 
221
                         memc->distribution);
 
222
  for (ptrdiff_t x= 0; x < 99; x++)
 
223
  {
 
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.
 
226
    instance=
 
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);
 
230
  }
 
231
 
 
232
  memcached_server_list_free(server_pool);
 
233
  memcached_free(memc);
 
234
 
 
235
  return TEST_SUCCESS;
 
236
}
 
237
 
 
238
test_return_t ketama_compatibility_spymemcached(memcached_st *)
 
239
{
 
240
  memcached_st *memc= memcached_create(NULL);
 
241
  test_true(memc);
 
242
 
 
243
  test_compare(MEMCACHED_SUCCESS,
 
244
               memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, 1));
 
245
 
 
246
  test_compare(UINT64_C(1), memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED));
 
247
 
 
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));
 
250
 
 
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);
 
254
 
 
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);
 
266
 
 
267
  /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
 
268
   * us test the boundary wraparound.
 
269
   */
 
270
  test_true(memcached_generate_hash(memc, (char *)"VDEAAAAA", 8) == memc->ketama.continuum[0].index);
 
271
 
 
272
  /* verify the standard ketama set. */
 
273
  for (uint32_t x= 0; x < 99; x++)
 
274
  {
 
275
    uint32_t server_idx= memcached_generate_hash(memc, ketama_test_cases_spy[x].key, strlen(ketama_test_cases_spy[x].key));
 
276
 
 
277
    memcached_server_instance_st instance=
 
278
      memcached_server_instance_by_position(memc, server_idx);
 
279
 
 
280
    const char *hostname= memcached_server_name(instance);
 
281
 
 
282
    test_strcmp(hostname, ketama_test_cases_spy[x].server);
 
283
  }
 
284
 
 
285
  memcached_server_list_free(server_pool);
 
286
  memcached_free(memc);
 
287
 
 
288
  return TEST_SUCCESS;
 
289
}