e522f9cc194b19412460a136c491f1f318c810b4
[m6w6/libmemcached] / test / lib / common.hpp
1 /*
2 +--------------------------------------------------------------------+
3 | libmemcached - C/C++ Client Library for memcached |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted under the terms of the BSD license. |
7 | You should have received a copy of the license in a bundled file |
8 | named LICENSE; in case you did not receive a copy you can review |
9 | the terms online at: https://opensource.org/licenses/BSD-3-Clause |
10 +--------------------------------------------------------------------+
11 | Copyright (c) 2006-2014 Brian Aker https://datadifferential.com/ |
12 | Copyright (c) 2020 Michael Wallner <mike@php.net> |
13 +--------------------------------------------------------------------+
14 */
15
16 #pragma once
17
18 #include <chrono>
19 #include <iostream>
20 #include <map>
21 #include <optional>
22 #include <string>
23 #include <sstream>
24 #include <stdexcept>
25 #include <thread>
26 #include <variant>
27 #include <vector>
28
29 #include "test/conf.h"
30 #include "test/lib/catch.hpp"
31 #include "test/lib/env.hpp"
32 #include "test/lib/random.hpp"
33
34 #include "libmemcached/memcached.h"
35
36 using namespace std;
37 using socket_or_port_t = variant<string, int>;
38
39 /**
40 * Useful macros for testing
41 */
42 #define S(s) (s), strlen(s)
43 #define LOOPED_SECTION(tests) \
44 for (auto &[name, test] : tests) DYNAMIC_SECTION("test " << name)
45 #define REQUIRE_SUCCESS(rc) \
46 do { \
47 INFO("expected: SUCCESS"); \
48 REQUIRE_THAT(rc, test.returns.success()); \
49 } while (0)
50 #define REQUIRE_RC(rc, call) \
51 do { \
52 INFO("expected: " << memcached_strerror(nullptr, rc)); \
53 REQUIRE_THAT(call, test.returns(rc)); \
54 } while (0)
55
56 inline memcached_return_t fetch_all_results(memcached_st *memc, unsigned int &keys_returned,
57 memcached_return_t &rc) {
58 keys_returned = 0;
59
60 memcached_result_st *result = nullptr;
61 while ((result = memcached_fetch_result(memc, result, &rc))) {
62 REQUIRE(MEMCACHED_SUCCESS == rc);
63 keys_returned += 1;
64 }
65 memcached_result_free(result);
66 return MEMCACHED_SUCCESS;
67 }
68
69 inline memcached_return_t fetch_all_results(memcached_st *memc, unsigned int &keys_returned) {
70 memcached_return_t rc;
71 fetch_all_results(memc, keys_returned, rc);
72 return rc;
73 }
74
75 #include <cstdlib>
76 #include <unistd.h>
77
78 class Tempfile {
79 public:
80 explicit Tempfile(const char templ_[] = "memc.test.XXXXXX") {
81 *copy(S(templ_) + templ_, fn) = '\0';
82 fd = mkstemp(fn);
83 }
84 ~Tempfile() {
85 close(fd);
86 unlink(fn);
87 }
88 [[nodiscard]] int getFd() const { return fd; }
89 [[nodiscard]] const char *getFn() const { return fn; }
90 bool put(const char *buf, size_t len) const {
91 return static_cast<ssize_t>(len) == write(fd, buf, len);
92 }
93 string get() const {
94 string all;
95 char buf[200];
96 ssize_t len;
97
98 lseek(fd, 0, SEEK_SET);
99 while (0 < (len = read(fd, buf, sizeof(buf)))) {
100 all.append(buf, len);
101 }
102 return all;
103 }
104
105 private:
106 char fn[80];
107 int fd;
108 };
109
110 class MemcachedPtr {
111 public:
112 memcached_st *memc;
113
114 explicit MemcachedPtr(memcached_st *memc_) {
115 memc = memc_;
116 }
117 MemcachedPtr()
118 : MemcachedPtr(memcached_create(nullptr)) {}
119 ~MemcachedPtr() {
120 memcached_free(memc);
121 }
122 memcached_st *operator*() const {
123 return memc;
124 }
125 auto operator->() const {
126 return memc;
127 }
128 };
129
130 template<class T>
131 class Malloced {
132 T *ptr;
133
134 public:
135 explicit Malloced(T *ptr_)
136 : ptr{ptr_} {}
137 Malloced &operator=(T *ptr_) {
138 if (ptr)
139 free(ptr);
140 ptr = ptr_;
141 return *this;
142 }
143 ~Malloced() {
144 if (ptr)
145 free(ptr);
146 }
147 auto operator*() const { return ptr; }
148 auto operator->() const { return ptr; }
149 };