tests: run memcached verbosely, catch output and show it on failure
[awesomized/libmemcached] / libtest / server.h
1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2 *
3 * Data Differential YATL (i.e. libtest) library
4 *
5 * Copyright (C) 2012 Data Differential, http://datadifferential.com/
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following disclaimer
16 * in the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * * The names of its contributors may not be used to endorse or
20 * promote products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 */
36
37 #pragma once
38
39 #include <libtest/cmdline.h>
40
41 #include <cassert>
42 #include <cstdio>
43 #include <cstring>
44 #include <netdb.h>
45 #include <netinet/in.h>
46 #include <string>
47 #include <unistd.h>
48 #include <vector>
49
50 namespace libtest {
51
52 struct Server {
53 private:
54 typedef std::vector< std::pair<std::string, std::string> > Options;
55
56 private:
57 uint64_t _magic;
58 bool _is_socket;
59 std::string _socket;
60 std::string _sasl;
61 std::string _pid_file;
62 std::string _log_file;
63 std::string _base_command; // executable command which include libtool, valgrind, gdb, etc
64 std::string _running; // Current string being used for system()
65
66 protected:
67 in_port_t _port;
68 std::string _hostname;
69 std::string _extra_args;
70
71 public:
72 Server(const std::string& hostname, const in_port_t port_arg,
73 const std::string& executable, const bool _is_libtool,
74 const bool is_socket_arg= false);
75
76 virtual ~Server();
77
78 virtual const char *name()= 0;
79 virtual bool is_libtool()= 0;
80
81 virtual bool has_socket_file_option() const
82 {
83 return false;
84 }
85
86 virtual void socket_file_option(Application& app, const std::string& socket_arg)
87 {
88 if (socket_arg.empty() == false)
89 {
90 std::string buffer("--socket=");
91 buffer+= socket_arg;
92 app.add_option(buffer);
93 }
94 }
95
96 virtual bool has_log_file_option() const
97 {
98 return false;
99 }
100
101 virtual void log_file_option(Application& app, const std::string& arg)
102 {
103 if (arg.empty() == false)
104 {
105 std::string buffer("--log-file=");
106 buffer+= arg;
107 app.add_option(buffer);
108 }
109 }
110
111 virtual void pid_file_option(Application& app, const std::string& arg)
112 {
113 if (arg.empty() == false)
114 {
115 std::string buffer("--pid-file=");
116 buffer+= arg;
117 app.add_option(buffer);
118 }
119 }
120
121 virtual bool has_port_option() const
122 {
123 return false;
124 }
125
126 virtual void port_option(Application& app, in_port_t arg)
127 {
128 if (arg > 0)
129 {
130 char buffer[1024];
131 snprintf(buffer, sizeof(buffer), "--port=%d", int(arg));
132 app.add_option(buffer);
133 }
134 }
135
136 virtual bool broken_socket_cleanup()
137 {
138 return false;
139 }
140
141 virtual bool broken_pid_file()
142 {
143 return false;
144 }
145
146 const std::string& pid_file() const
147 {
148 return _pid_file;
149 }
150
151 const std::string& base_command() const
152 {
153 return _base_command;
154 }
155
156 const std::string& log_file() const
157 {
158 return _log_file;
159 }
160
161 const std::string& hostname() const
162 {
163 return _hostname;
164 }
165
166 const std::string& socket() const
167 {
168 return _socket;
169 }
170
171 bool has_socket() const
172 {
173 return _is_socket;
174 }
175
176 bool cycle();
177
178 virtual bool ping()= 0;
179
180 bool init(const char *argv[]);
181 virtual bool build()= 0;
182
183 void add_option(const std::string&);
184 void add_option(const std::string&, const std::string&);
185
186 in_port_t port() const
187 {
188 return _port;
189 }
190
191 bool has_port() const
192 {
193 return (_port != 0);
194 }
195
196 virtual bool has_syslog() const
197 {
198 return false;
199 }
200
201 // Reset a server if another process has killed the server
202 void reset()
203 {
204 _pid_file.clear();
205 _log_file.clear();
206 }
207
208 std::pair<std::string, std::string> output();
209
210 pid_t pid() const;
211
212 bool has_pid() const;
213
214 virtual bool has_pid_file() const
215 {
216 return true;
217 }
218
219 const std::string& error()
220 {
221 return _error;
222 }
223
224 void error(std::string arg)
225 {
226 _error= arg;
227 }
228
229 void reset_error()
230 {
231 _error.clear();
232 }
233
234 virtual bool wait_for_pidfile() const;
235
236 bool check_pid(pid_t pid_arg) const
237 {
238 return (pid_arg > 1);
239 }
240
241 bool is_socket() const
242 {
243 return _is_socket;
244 }
245
246 const std::string running() const
247 {
248 return _running;
249 }
250
251 bool check();
252
253 std::string log_and_pid();
254
255 bool kill();
256 bool start();
257 bool command(libtest::Application& app);
258
259 bool validate();
260
261 void out_of_ban_killed(bool arg)
262 {
263 out_of_ban_killed_= arg;
264 }
265
266 bool out_of_ban_killed()
267 {
268 return out_of_ban_killed_;
269 }
270
271 void timeout(uint32_t timeout_)
272 {
273 _timeout= timeout_;
274 }
275
276 protected:
277 bool set_pid_file();
278 Options _options;
279 Application _app;
280
281 private:
282 bool is_helgrind() const;
283 bool is_valgrind() const;
284 bool is_debug() const;
285 bool set_log_file();
286 bool set_socket_file();
287 void reset_pid();
288 bool out_of_ban_killed_;
289 bool args(Application&);
290
291 std::string _error;
292 uint32_t _timeout; // This number should be high enough for valgrind startup (which is slow)
293 };
294
295 std::ostream& operator<<(std::ostream& output, const libtest::Server &arg);
296
297 } // namespace libtest
298
299