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