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 test_return_t
memcached_pool_test(memcached_st
*)
56 memcached_return_t rc
;
57 const char *config_string
= "--SERVER=host10.example.com --SERVER=host11.example.com --SERVER=host10.example.com --POOL-MIN=10 --POOL-MAX=32";
60 rc
= libmemcached_check_configuration(config_string
, sizeof(config_string
) -1, buffer
, sizeof(buffer
));
62 test_true_got(rc
!= MEMCACHED_SUCCESS
, buffer
);
64 memcached_pool_st
* pool
= memcached_pool(config_string
, strlen(config_string
));
65 test_true_got(pool
, strerror(errno
));
67 memcached_st
*memc
= memcached_pool_pop(pool
, false, &rc
);
69 test_true(rc
== MEMCACHED_SUCCESS
);
73 Release the memc_ptr that was pulled from the pool
75 memcached_pool_push(pool
, memc
);
80 memcached_pool_destroy(pool
);
87 test_return_t
connection_pool_test(memcached_st
*memc
)
89 memcached_pool_st
* pool
= memcached_pool_create(memc
, 5, POOL_SIZE
);
91 memcached_st
*mmc
[POOL_SIZE
];
93 // Fill up our array that we will store the memc that are in the pool
94 for (size_t x
= 0; x
< POOL_SIZE
; ++x
)
96 memcached_return_t rc
;
97 mmc
[x
]= memcached_pool_fetch(pool
, NULL
, &rc
);
98 test_compare(MEMCACHED_SUCCESS
, rc
);
102 // All memc should be gone
104 memcached_return_t rc
;
105 test_null(memcached_pool_fetch(pool
, NULL
, &rc
));
106 test_compare(MEMCACHED_NOTFOUND
, rc
);
110 for (size_t x
= 0; x
< POOL_SIZE
; ++x
)
114 test_compare(MEMCACHED_SUCCESS
, memcached_pool_release(pool
, mmc
[x
]));
117 test_true(memcached_pool_destroy(pool
) == memc
);
122 test_return_t
connection_pool2_test(memcached_st
*memc
)
124 memcached_pool_st
* pool
= memcached_pool_create(memc
, 5, POOL_SIZE
);
126 memcached_st
*mmc
[POOL_SIZE
];
128 // Fill up our array that we will store the memc that are in the pool
129 for (size_t x
= 0; x
< POOL_SIZE
; ++x
)
131 memcached_return_t rc
;
132 mmc
[x
]= memcached_pool_fetch(pool
, NULL
, &rc
);
133 test_compare(MEMCACHED_SUCCESS
, rc
);
137 // All memc should be gone
139 memcached_return_t rc
;
140 test_null(memcached_pool_fetch(pool
, NULL
, &rc
));
141 test_compare(MEMCACHED_NOTFOUND
, rc
);
144 // verify that I can do ops with all connections
145 test_compare(MEMCACHED_SUCCESS
,
146 memcached_set(mmc
[0],
147 test_literal_param("key"),
150 for (uint64_t x
= 0; x
< POOL_SIZE
; ++x
)
152 uint64_t number_value
;
153 test_compare(MEMCACHED_SUCCESS
,
154 memcached_increment(mmc
[x
],
155 test_literal_param("key"),
157 test_compare(number_value
, (x
+1));
161 for (size_t x
= 0; x
< POOL_SIZE
; ++x
)
163 test_compare(MEMCACHED_SUCCESS
, memcached_pool_release(pool
, mmc
[x
]));
167 /* verify that I can set behaviors on the pool when I don't have all
168 * of the connections in the pool. It should however be enabled
169 * when I push the item into the pool
171 mmc
[0]= memcached_pool_fetch(pool
, NULL
, NULL
);
174 test_compare(MEMCACHED_SUCCESS
,
175 memcached_pool_behavior_set(pool
, MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK
, 9999));
178 memcached_return_t rc
;
179 mmc
[1]= memcached_pool_fetch(pool
, NULL
, &rc
);
181 test_compare(MEMCACHED_SUCCESS
, rc
);
184 test_compare(UINT64_C(9999), memcached_behavior_get(mmc
[1], MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK
));
185 test_compare(MEMCACHED_SUCCESS
, memcached_pool_release(pool
, mmc
[1]));
186 test_compare(MEMCACHED_SUCCESS
, memcached_pool_release(pool
, mmc
[0]));
189 memcached_return_t rc
;
190 mmc
[0]= memcached_pool_fetch(pool
, NULL
, &rc
);
192 test_compare(MEMCACHED_SUCCESS
, rc
);
195 test_compare(UINT64_C(9999), memcached_behavior_get(mmc
[0], MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK
));
196 test_compare(MEMCACHED_SUCCESS
, memcached_pool_release(pool
, mmc
[0]));
198 test_true(memcached_pool_destroy(pool
) == memc
);
203 struct test_pool_context_st
{
204 volatile memcached_return_t rc
;
205 memcached_pool_st
* pool
;
209 test_pool_context_st(memcached_pool_st
*pool_arg
, memcached_st
*memc_arg
):
210 rc(MEMCACHED_FAILURE
),
214 sem_init(&_lock
, 0, 0);
227 ~test_pool_context_st()
233 static void* connection_release(void *arg
)
235 test_pool_context_st
*resource
= static_cast<test_pool_context_st
*>(arg
);
237 if (resource
== NULL
)
242 // Release all of the memc we are holding
243 resource
->rc
= memcached_pool_release(resource
->pool
, resource
->mmc
);
249 test_return_t
connection_pool3_test(memcached_st
*memc
)
255 memcached_pool_st
* pool
= memcached_pool_create(memc
, 1, 1);
258 memcached_st
*pool_memc
;
260 memcached_return_t rc
;
261 pool_memc
= memcached_pool_fetch(pool
, NULL
, &rc
);
262 test_compare(MEMCACHED_SUCCESS
, rc
);
263 test_true(pool_memc
);
267 @note This comment was written to describe what was believed to be the original authors intent.
269 This portion of the test creates a thread that will wait until told to free a memcached_st
270 that will be grabbed by the main thread.
272 It is believed that this tests whether or not we are handling ownership correctly.
275 test_pool_context_st
item(pool
, pool_memc
);
277 test_zero(pthread_create(&tid
, NULL
, connection_release
, &item
));
280 memcached_return_t rc
;
281 memcached_st
*pop_memc
;
282 // We do a hard loop, and try N times
286 struct timespec relative_time
= { 0, 0 };
287 pop_memc
= memcached_pool_fetch(pool
, &relative_time
, &rc
);
289 if (memcached_success(rc
))
294 if (memcached_failed(rc
))
297 test_true(rc
!= MEMCACHED_TIMEOUT
); // As long as relative_time is zero, MEMCACHED_TIMEOUT is invalid
301 if (memcached_failed(rc
)) // Cleanup thread since we will exit once we test.
303 pthread_join(tid
, NULL
);
304 test_compare(MEMCACHED_SUCCESS
, rc
);
308 int pthread_ret
= pthread_join(tid
, NULL
);
309 test_true(pthread_ret
== 0 or pthread_ret
== ESRCH
);
311 test_compare(MEMCACHED_SUCCESS
, rc
);
312 test_true(pool_memc
== pop_memc
);
314 test_true(memcached_pool_destroy(pool
) == memc
);