Merging bzr://gaz.tangent.org/libmemcached/build/ to Build branch
[awesomized/libmemcached] / libtest / server.h
1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2 *
3 * libtest
4 *
5 * Copyright (C) 2011 Data Differential, http://datadifferential.com/
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 3 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #pragma once
23
24 #include <libtest/cmdline.h>
25
26 #include <cassert>
27 #include <cstdio>
28 #include <cstring>
29 #include <netdb.h>
30 #include <netinet/in.h>
31 #include <string>
32 #include <unistd.h>
33 #include <vector>
34
35 namespace libtest {
36
37 struct Server {
38 private:
39 typedef std::vector< std::pair<std::string, std::string> > Options;
40
41 private:
42 uint64_t _magic;
43 bool _is_socket;
44 std::string _socket;
45 std::string _sasl;
46 std::string _pid_file;
47 std::string _log_file;
48 std::string _base_command; // executable command which include libtool, valgrind, gdb, etc
49 std::string _running; // Current string being used for system()
50
51 protected:
52 in_port_t _port;
53 std::string _hostname;
54 std::string _extra_args;
55
56 public:
57 Server(const std::string& hostname, const in_port_t port_arg,
58 const std::string& executable, const bool _is_libtool,
59 const bool is_socket_arg= false);
60
61 virtual ~Server();
62
63 virtual const char *name()= 0;
64 virtual bool is_libtool()= 0;
65
66 virtual bool has_socket_file_option() const
67 {
68 return false;
69 }
70
71 virtual void socket_file_option(Application& app, const std::string& socket_arg)
72 {
73 if (socket_arg.empty() == false)
74 {
75 std::string buffer("--socket=");
76 buffer+= socket_arg;
77 app.add_option(buffer);
78 }
79 }
80
81 virtual bool has_log_file_option() const
82 {
83 return false;
84 }
85
86 virtual void log_file_option(Application& app, const std::string& arg)
87 {
88 if (arg.empty() == false)
89 {
90 std::string buffer("--log-file=");
91 buffer+= arg;
92 app.add_option(buffer);
93 }
94 }
95
96 virtual void pid_file_option(Application& app, const std::string& arg)
97 {
98 if (arg.empty() == false)
99 {
100 std::string buffer("--pid-file=");
101 buffer+= arg;
102 app.add_option(buffer);
103 }
104 }
105
106 virtual bool has_port_option() const
107 {
108 return false;
109 }
110
111 virtual void port_option(Application& app, in_port_t arg)
112 {
113 if (arg > 0)
114 {
115 char buffer[1024];
116 snprintf(buffer, sizeof(buffer), "--port=%d", int(arg));
117 app.add_option(buffer);
118 }
119 }
120
121 virtual bool broken_socket_cleanup()
122 {
123 return false;
124 }
125
126 virtual bool broken_pid_file()
127 {
128 return false;
129 }
130
131 const std::string& pid_file() const
132 {
133 return _pid_file;
134 }
135
136 const std::string& base_command() const
137 {
138 return _base_command;
139 }
140
141 const std::string& log_file() const
142 {
143 return _log_file;
144 }
145
146 const std::string& hostname() const
147 {
148 return _hostname;
149 }
150
151 const std::string& socket() const
152 {
153 return _socket;
154 }
155
156 bool has_socket() const
157 {
158 return _is_socket;
159 }
160
161 bool cycle();
162
163 virtual bool ping()= 0;
164
165 virtual bool build(size_t argc, const char *argv[])= 0;
166
167 void add_option(const std::string&);
168 void add_option(const std::string&, const std::string&);
169
170 in_port_t port() const
171 {
172 return _port;
173 }
174
175 bool has_port() const
176 {
177 return (_port != 0);
178 }
179
180 virtual bool has_syslog() const
181 {
182 return false;
183 }
184
185 // Reset a server if another process has killed the server
186 void reset()
187 {
188 _pid_file.clear();
189 _log_file.clear();
190 }
191
192 bool args(Application&);
193
194 pid_t pid() const;
195
196 bool has_pid() const;
197
198 virtual bool wait_for_pidfile() const;
199
200 bool check_pid(pid_t pid_arg) const
201 {
202 return (pid_arg > 1);
203 }
204
205 bool is_socket() const
206 {
207 return _hostname[0] == '/';
208 }
209
210 const std::string running() const
211 {
212 return _running;
213 }
214
215 bool check();
216
217 std::string log_and_pid();
218
219 bool kill();
220 bool start();
221 bool command(libtest::Application& app);
222
223 bool validate();
224
225 protected:
226 bool set_pid_file();
227 Options _options;
228 Application _app;
229
230 private:
231 bool is_helgrind() const;
232 bool is_valgrind() const;
233 bool is_debug() const;
234 bool set_log_file();
235 bool set_socket_file();
236 void reset_pid();
237 };
238
239 std::ostream& operator<<(std::ostream& output, const libtest::Server &arg);
240
241 } // namespace libtest
242
243