libmemcached: add MEMCACHED_BEHAVIOR_META_PROTOCOL
[awesomized/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 <cstring>
20 #include <iostream>
21 #include <map>
22 #include <optional>
23 #include <string>
24 #include <sstream>
25 #include <stdexcept>
26 #include <thread>
27 #include <variant>
28 #include <vector>
29
30 #include "test/conf.h"
31 #include "test/lib/catch.hpp"
32 #include "test/lib/env.hpp"
33 #include "test/lib/random.hpp"
34
35 #include "libmemcached/memcached.h"
36
37 using namespace std;
38 using socket_or_port_t = variant<string, int>;
39
40 /**
41 * Useful macros for testing
42 */
43 #define S(s) (s), strlen(s)
44 #define LOOPED_SECTION(tests) \
45 for (auto &[name, test] : tests) DYNAMIC_SECTION("test " << name)
46 #define REQUIRE_SUCCESS(rc) \
47 do { \
48 REQUIRE_THAT(rc, test.returns.success()); \
49 } while (0)
50 #define REQUIRE_RC(rc, call) \
51 do { \
52 REQUIRE_THAT(call, test.returns(rc)); \
53 } while (0)
54
55 inline memcached_return_t fetch_all_results(memcached_st *memc, unsigned int &keys_returned,
56 memcached_return_t &rc) {
57 keys_returned = 0;
58
59 memcached_result_st *result = nullptr;
60 while ((result = memcached_fetch_result(memc, result, &rc))) {
61 REQUIRE(MEMCACHED_SUCCESS == rc);
62 keys_returned += 1;
63 }
64 memcached_result_free(result);
65 return MEMCACHED_SUCCESS;
66 }
67
68 inline memcached_return_t fetch_all_results(memcached_st *memc, unsigned int &keys_returned) {
69 memcached_return_t rc;
70 fetch_all_results(memc, keys_returned, rc);
71 return rc;
72 }
73
74 #include <cstdlib>
75 #include <unistd.h>
76
77 class Tempfile {
78 public:
79 explicit Tempfile(const char templ_[] = "memc.test.XXXXXX") {
80 *copy(S(templ_) + templ_, fn) = '\0';
81 fd = mkstemp(fn);
82 }
83 ~Tempfile() {
84 close(fd);
85 unlink(fn);
86 }
87 [[nodiscard]] int getFd() const { return fd; }
88 [[nodiscard]] const char *getFn() const { return fn; }
89 bool put(const char *buf, size_t len) const {
90 return static_cast<ssize_t>(len) == write(fd, buf, len);
91 }
92 string get() const {
93 string all;
94 char buf[200];
95 ssize_t len;
96
97 lseek(fd, 0, SEEK_SET);
98 while (0 < (len = read(fd, buf, sizeof(buf)))) {
99 all.append(buf, len);
100 }
101 return all;
102 }
103
104 private:
105 char fn[80];
106 int fd;
107 };
108
109 class MemcachedPtr {
110 public:
111 memcached_st *memc;
112
113 explicit MemcachedPtr(memcached_st *memc_) {
114 memc = memc_;
115 }
116 MemcachedPtr()
117 : MemcachedPtr(memcached_create(nullptr)) {}
118 ~MemcachedPtr() {
119 memcached_free(memc);
120 }
121 memcached_st *operator*() const {
122 return memc;
123 }
124 auto operator->() const {
125 return memc;
126 }
127 };
128
129 template<class T>
130 class Malloced {
131 T *ptr;
132
133 public:
134 explicit Malloced(T *ptr_)
135 : ptr{ptr_} {}
136 Malloced &operator=(T *ptr_) {
137 if (ptr)
138 free(ptr);
139 ptr = ptr_;
140 return *this;
141 }
142 ~Malloced() {
143 if (ptr)
144 free(ptr);
145 }
146 auto operator*() const { return ptr; }
147 auto operator->() const { return ptr; }
148 };