1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3 * Libmemcached Client and Server
5 * Copyright (C) 2011 Data Differential, http://datadifferential.com/
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following disclaimer
17 * in the documentation and/or other materials provided with the
20 * * The names of its contributors may not be used to endorse or
21 * promote products derived from this software without specific prior
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 #include <libtest/test.hpp>
41 using namespace libtest
;
48 #include <semaphore.h>
50 #include <libmemcached/memcached.h>
51 #include <libmemcached/util.h>
52 #include <tests/pool.h>
54 #ifndef __INTEL_COMPILER
55 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
59 test_return_t
memcached_pool_test(memcached_st
*)
61 memcached_return_t rc
;
62 const char *config_string
= "--SERVER=host10.example.com --SERVER=host11.example.com --SERVER=host10.example.com --POOL-MIN=10 --POOL-MAX=32";
65 rc
= libmemcached_check_configuration(config_string
, sizeof(config_string
) -1, buffer
, sizeof(buffer
));
67 test_true_got(rc
!= MEMCACHED_SUCCESS
, buffer
);
69 memcached_pool_st
* pool
= memcached_pool(config_string
, strlen(config_string
));
70 test_true_got(pool
, strerror(errno
));
72 memcached_st
*memc
= memcached_pool_pop(pool
, false, &rc
);
74 test_true(rc
== MEMCACHED_SUCCESS
);
78 Release the memc_ptr that was pulled from the pool
80 memcached_pool_push(pool
, memc
);
85 memcached_pool_destroy(pool
);
92 test_return_t
connection_pool_test(memcached_st
*memc
)
94 memcached_pool_st
* pool
= memcached_pool_create(memc
, 5, POOL_SIZE
);
96 memcached_st
*mmc
[POOL_SIZE
];
98 // Fill up our array that we will store the memc that are in the pool
99 for (size_t x
= 0; x
< POOL_SIZE
; ++x
)
101 memcached_return_t rc
;
102 mmc
[x
]= memcached_pool_fetch(pool
, NULL
, &rc
);
103 test_compare(MEMCACHED_SUCCESS
, rc
);
107 // All memc should be gone
109 memcached_return_t rc
;
110 test_null(memcached_pool_fetch(pool
, NULL
, &rc
));
111 test_compare(MEMCACHED_NOTFOUND
, rc
);
115 for (size_t x
= 0; x
< POOL_SIZE
; ++x
)
119 test_compare(MEMCACHED_SUCCESS
, memcached_pool_release(pool
, mmc
[x
]));
122 test_true(memcached_pool_destroy(pool
) == memc
);
127 test_return_t
connection_pool2_test(memcached_st
*memc
)
129 memcached_pool_st
* pool
= memcached_pool_create(memc
, 5, POOL_SIZE
);
131 memcached_st
*mmc
[POOL_SIZE
];
133 // Fill up our array that we will store the memc that are in the pool
134 for (size_t x
= 0; x
< POOL_SIZE
; ++x
)
136 memcached_return_t rc
;
137 mmc
[x
]= memcached_pool_fetch(pool
, NULL
, &rc
);
138 test_compare(MEMCACHED_SUCCESS
, rc
);
142 // All memc should be gone
144 memcached_return_t rc
;
145 test_null(memcached_pool_fetch(pool
, NULL
, &rc
));
146 test_compare(MEMCACHED_NOTFOUND
, rc
);
149 // verify that I can do ops with all connections
150 test_compare(MEMCACHED_SUCCESS
,
151 memcached_set(mmc
[0],
152 test_literal_param("key"),
155 for (uint64_t x
= 0; x
< POOL_SIZE
; ++x
)
157 uint64_t number_value
;
158 test_compare(MEMCACHED_SUCCESS
,
159 memcached_increment(mmc
[x
],
160 test_literal_param("key"),
162 test_compare(number_value
, (x
+1));
166 for (size_t x
= 0; x
< POOL_SIZE
; ++x
)
168 test_compare(MEMCACHED_SUCCESS
, memcached_pool_release(pool
, mmc
[x
]));
172 /* verify that I can set behaviors on the pool when I don't have all
173 * of the connections in the pool. It should however be enabled
174 * when I push the item into the pool
176 mmc
[0]= memcached_pool_fetch(pool
, NULL
, NULL
);
179 test_compare(MEMCACHED_SUCCESS
,
180 memcached_pool_behavior_set(pool
, MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK
, 9999));
183 memcached_return_t rc
;
184 mmc
[1]= memcached_pool_fetch(pool
, NULL
, &rc
);
186 test_compare(MEMCACHED_SUCCESS
, rc
);
189 test_compare(UINT64_C(9999), memcached_behavior_get(mmc
[1], MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK
));
190 test_compare(MEMCACHED_SUCCESS
, memcached_pool_release(pool
, mmc
[1]));
191 test_compare(MEMCACHED_SUCCESS
, memcached_pool_release(pool
, mmc
[0]));
194 memcached_return_t rc
;
195 mmc
[0]= memcached_pool_fetch(pool
, NULL
, &rc
);
197 test_compare(MEMCACHED_SUCCESS
, rc
);
200 test_compare(UINT64_C(9999), memcached_behavior_get(mmc
[0], MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK
));
201 test_compare(MEMCACHED_SUCCESS
, memcached_pool_release(pool
, mmc
[0]));
203 test_true(memcached_pool_destroy(pool
) == memc
);
208 struct test_pool_context_st
{
209 volatile memcached_return_t rc
;
210 memcached_pool_st
* pool
;
214 test_pool_context_st(memcached_pool_st
*pool_arg
, memcached_st
*memc_arg
):
215 rc(MEMCACHED_FAILURE
),
219 sem_init(&_lock
, 0, 0);
232 ~test_pool_context_st()
238 static void* connection_release(void *arg
)
240 test_pool_context_st
*resource
= static_cast<test_pool_context_st
*>(arg
);
242 if (resource
== NULL
)
247 // Release all of the memc we are holding
248 resource
->rc
= memcached_pool_release(resource
->pool
, resource
->mmc
);
254 test_return_t
connection_pool3_test(memcached_st
*memc
)
260 memcached_pool_st
* pool
= memcached_pool_create(memc
, 1, 1);
263 memcached_st
*pool_memc
;
265 memcached_return_t rc
;
266 pool_memc
= memcached_pool_fetch(pool
, NULL
, &rc
);
267 test_compare(MEMCACHED_SUCCESS
, rc
);
268 test_true(pool_memc
);
272 @note This comment was written to describe what was believed to be the original authors intent.
274 This portion of the test creates a thread that will wait until told to free a memcached_st
275 that will be grabbed by the main thread.
277 It is believed that this tests whether or not we are handling ownership correctly.
280 test_pool_context_st
item(pool
, pool_memc
);
282 test_zero(pthread_create(&tid
, NULL
, connection_release
, &item
));
285 memcached_return_t rc
;
286 memcached_st
*pop_memc
;
287 // We do a hard loop, and try N times
291 struct timespec relative_time
= { 0, 0 };
292 pop_memc
= memcached_pool_fetch(pool
, &relative_time
, &rc
);
294 if (memcached_success(rc
))
299 if (memcached_failed(rc
))
302 test_true(rc
!= MEMCACHED_TIMEOUT
); // As long as relative_time is zero, MEMCACHED_TIMEOUT is invalid
306 if (memcached_failed(rc
)) // Cleanup thread since we will exit once we test.
308 pthread_join(tid
, NULL
);
309 test_compare(MEMCACHED_SUCCESS
, rc
);
313 int pthread_ret
= pthread_join(tid
, NULL
);
314 test_true(pthread_ret
== 0 or pthread_ret
== ESRCH
);
316 test_compare(MEMCACHED_SUCCESS
, rc
);
317 test_true(pool_memc
== pop_memc
);
319 test_true(memcached_pool_destroy(pool
) == memc
);