semver: 1.0 -> 1
[m6w6/libmemcached] / test / tests / memcached / regression / lp_000-962-815.cpp
1 #include "test/lib/common.hpp"
2 #include "test/lib/MemcachedCluster.hpp"
3
4 #include "libmemcachedutil-1/pool.h"
5
6 #include <atomic>
7 #include <sstream>
8
9 static atomic<bool> running = false;
10
11 static inline void set_running(bool is) {
12 running.store(is, memory_order_release);
13 }
14 static inline bool is_running() {
15 return running.load(memory_order_consume);
16 }
17
18 struct worker_ctx {
19 memcached_pool_st *pool;
20
21 explicit worker_ctx(memcached_st *memc)
22 : pool{memcached_pool_create(memc, 5, 10)}
23 {
24 }
25
26 ~worker_ctx() {
27 memcached_pool_destroy(pool);
28 }
29 };
30
31 static void *worker(void *arg) {
32 auto *ctx = static_cast<worker_ctx *>(arg);
33
34 while (is_running()) {
35 memcached_return_t rc;
36 timespec block{0, 1000};
37 auto *mc = memcached_pool_fetch(ctx->pool, &block, &rc);
38
39 if (!mc && rc == MEMCACHED_TIMEOUT) {
40 continue;
41 }
42 if (!mc || memcached_failed(rc)) {
43 cerr << "failed to fetch connection from pool: "
44 << memcached_strerror(nullptr, rc)
45 << endl;
46 continue;
47 }
48
49 auto rs = random_ascii_string(12);
50 rc = memcached_set(mc, rs.c_str(), rs.length(), rs.c_str(), rs.length(), 0, 0);
51 if (memcached_failed(rc)) {
52 cerr << "failed to memcached_set() "
53 << memcached_last_error_message(mc)
54 << endl;
55 }
56 rc = memcached_pool_release(ctx->pool, mc);
57 if (memcached_failed(rc)) {
58 cerr << "failed to release connection to pool: "
59 << memcached_strerror(nullptr, rc)
60 << endl;
61 }
62 }
63
64 return ctx;
65 }
66
67 TEST_CASE("memcached_regression_lp962815") {
68 auto test = MemcachedCluster::mixed();
69 auto memc = &test.memc;
70
71 constexpr auto NUM_THREADS = 20;
72 array<pthread_t, NUM_THREADS> tid;
73 worker_ctx ctx{memc};
74
75 set_running(true);
76
77 for (auto &t : tid) {
78 REQUIRE(0 == pthread_create(&t, nullptr, worker, &ctx));
79 }
80
81 this_thread::sleep_for(1s);
82 set_running(false);
83
84 for (auto t : tid) {
85 void *ret = nullptr;
86 REQUIRE(0 == pthread_join(t, &ret));
87 REQUIRE(ret == &ctx);
88 }
89 }