Fix several warnings that appear in gcc 4.3.2.
[wvstreams.git] / uniconf / t / uniconfd.t.cc
blob2c35703426ce3f0aabac42c18027f6689a9dc404
1 #include "wvtest.h"
2 #include "uniclientconn.h"
3 #include "uniconfdaemon.h"
4 #include "uniconfroot.h"
5 #include "unitempgen.h"
6 #include "wvstringlist.h"
7 #include "wvistreamlist.h"
8 #include "wvunixsocket.h"
9 #include "wvstreamclone.h"
10 #include "wvlog.h"
11 #include "wvtclstring.h"
12 #include "wvtcp.h"
13 #include "wvfile.h"
14 #include "wvpipe.h"
15 #include "wvstringlist.h"
16 #include "wvfileutils.h"
17 #include <signal.h>
19 /**** Generic daemon testing helpers ****/
21 DeclareWvList(WvStringList);
23 class UniConfDaemonTestConn : public WvStreamClone
25 public:
26 UniConfDaemonTestConn(IWvStream *s, WvStringList *_commands,
27 WvStringListList *_expected_responses) :
28 WvStreamClone(s),
29 commands(_commands),
30 expected_responses(_expected_responses),
31 log("UniConfDaemonTestConn", WvLog::Debug)
33 uses_continue_select = true;
35 virtual ~UniConfDaemonTestConn()
37 log("Destructing\n");
38 terminate_continue_select();
41 virtual void close()
43 log("Closing connection\n");
44 WvStreamClone::close();
47 virtual void execute()
49 WvStreamClone::execute();
51 // order is always process responses to last command (or conn),
52 // then send the next command
53 // if we're out of expected responses, that means we're done
54 if (expected_responses->count())
56 while (expected_responses->first()->count())
58 WvString line = blocking_getline(-1);
59 WvString expected = expected_responses->first()->popstr();
60 log(">> '%s' (expect: '%s')\n", line, expected);
61 WVPASS(!strcmp(line.cstr(), expected.cstr()));
63 expected_responses->unlink_first();
65 if (commands->count() > 0)
67 WvString command = commands->popstr();
68 print("%s\n", command);
69 log("<< %s\n", command);
73 // expecting nothing more, can close
74 if (!expected_responses->count())
76 log("no more responses expected, closing\n");
77 close();
78 if (isok())
79 log("um, why are we still ok?\n");
83 private:
84 WvStringList *commands;
85 WvStringListList *expected_responses;
86 WvLog log;
90 /**** Daemon surprise close test and helpers ****/
91 #if 0
92 static void spin(WvIStreamList &l)
94 int max;
95 for (max = 0; max < 100 && l.select(10); max++)
97 wvcon->print(".");
98 l.callback();
100 wvcon->print("\n");
101 WVPASS(max < 100);
106 static void appendbuf(WvStream &s, void *_buf)
108 wvcon->print("append!\n");
109 WvDynBuf *buf = (WvDynBuf *)_buf;
110 s.read(*buf, 10240);
114 static void linecmp(WvIStreamList &sl, WvBuf &buf,
115 const char *w1, const char *w2 = NULL,
116 const char *w3 = NULL)
118 wvcon->print("Awaiting '%s' '%s' '%s'\n", w1, w2, w3);
119 spin(sl);
121 WvString line = wvtcl_getword(buf, "\r\n");
122 WVPASS(line);
123 if (!line) return;
125 WvStringList l;
126 wvtcl_decode(l, line);
128 size_t nargs = w3 ? 3 : (w2 ? 2 : 1);
129 WVPASS(l.count() < 4);
131 WVPASSEQ(l.popstr(), w1);
132 if (nargs >= 2) WVPASSEQ(l.popstr(), w2);
133 if (nargs >= 3) WVPASSEQ(l.popstr(), w3);
137 WVTEST_MAIN("daemon surprise close")
139 WvIStreamList l;
140 WVPASSEQ(WvIStreamList::globallist.count(), 0);
141 spin(WvIStreamList::globallist);
143 signal(SIGPIPE, SIG_IGN);
144 WvIPPortAddr addr("0.0.0.0:4113");
146 UniConfRoot cfg("temp:");
147 UniConfDaemon daemon(cfg, false, NULL);
149 spin(l);
151 WVPASS(daemon.isok());
152 daemon.setuptcpsocket(addr);
153 WVPASS(daemon.isok());
155 spin(l);
157 WvDynBuf buf;
158 WvTCPConn tcp(addr);
159 tcp.setcallback(appendbuf, &buf);
160 WVPASS(tcp.isok());
162 l.append(&daemon, false);
163 l.append(&tcp, false);
165 linecmp(l, buf, "HELLO");
166 WVPASS(tcp.isok());
168 tcp.write("SET /x/y z\n");
169 tcp.close();
170 spin(l);
171 //linecmp(l, buf, "NOTICE", "", "");
172 //linecmp(l, buf, "NOTICE", "x", "");
173 //linecmp(l, buf, "NOTICE", "x/y", "z");
175 #endif
177 /**** Daemon multimount test ****/
180 WVTEST_MAIN("daemon multimount")
182 signal(SIGPIPE, SIG_IGN);
184 UniConfRoot cfg("temp:");
186 cfg["pickles"].setme("foo");
187 cfg["subtree/fries"].setme("bar1");
188 cfg["subtree/ketchup"].setme("bar2");
189 cfg["subt"].mount("temp:");
190 cfg["subt/mayo"].setme("baz");
192 UniConfDaemon daemon(cfg, false, NULL);
194 WvStringList commands;
195 commands.append("subt / 1");
196 WvStringListList expected_responses;
197 WvStringList hello_response;
198 hello_response.append(WvString("HELLO {UniConf Server ready.} %s",
199 UNICONF_PROTOCOL_VERSION));
200 expected_responses.add(&hello_response, false);
201 WvStringList expected_quit_response;
202 expected_quit_response.append("VAL subtree {}");
203 expected_quit_response.append("VAL subtree/fries bar1");
204 expected_quit_response.append("VAL subtree/ketchup bar2");
205 expected_quit_response.append("VAL subt {}");
206 expected_quit_response.append("VAL subt/mayo baz");
207 expected_quit_response.append("VAL pickles foo");
208 expected_quit_response.append("OK ");
209 expected_responses.add(&expected_quit_response, false);
211 WvString pipename = wvtmpfilename("uniconfd.t-pipe");
212 daemon.listen(WvString("unix:%s", pipename));
213 WvUnixAddr addr(pipename);
214 WvUnixConn *sock = new WvUnixConn(addr);
215 UniConfDaemonTestConn conn(sock, &commands, &expected_responses);
217 WvIStreamList::globallist.append(&conn, false, "connection");
218 WvIStreamList::globallist.append(&daemon, false, "daemon");
219 wvcon->print("You are about to enter the no spin zone\n");
220 while (!WvIStreamList::globallist.isempty() &&
221 conn.isok() && daemon.isok())
223 wvcon->print("Spinning: streams left: %s\n",
224 WvIStreamList::globallist.count());
225 WvIStreamList::globallist.runonce();
228 WVPASS(daemon.isok());
229 WvIStreamList::globallist.zap();
233 /**** Daemon quit test ****/
235 // sort of useless: this functionality already exists in
236 // daemon/tests and is automatically exercised. furthermore, we only
237 // test that the server responds with 'OK' upon close (rather than
238 // actually testing whether or not it closed). leaving this
239 // here as a simple (generic) example to write future tests
240 WVTEST_MAIN("daemon quit")
242 UniConfRoot cfg("temp:");
243 signal(SIGPIPE, SIG_IGN);
245 cfg["pickles"].setme("foo");
246 cfg["subtree/fries"].setme("bar1");
247 cfg["subtree/ketchup"].setme("bar2");
248 UniConfDaemon daemon(cfg, false, NULL);
250 WvStringList commands;
251 commands.append("quit");
252 WvStringListList expected_responses;
253 WvStringList hello_response;
254 hello_response.append(WvString("HELLO {UniConf Server ready.} %s",
255 UNICONF_PROTOCOL_VERSION));
256 expected_responses.add(&hello_response, false);
257 WvStringList expected_quit_response;
258 expected_quit_response.append("OK ");
259 expected_responses.add(&expected_quit_response, false);
261 WvString pipename = wvtmpfilename("uniconfd.t-pipe");
262 daemon.listen(WvString("unix:%s", pipename));
263 WvUnixAddr addr(pipename);
264 WvUnixConn *sock = new WvUnixConn(addr);
265 UniConfDaemonTestConn conn(sock, &commands, &expected_responses);
267 WvIStreamList::globallist.append(&conn, false, "conn");
268 WvIStreamList::globallist.append(&daemon, false, "daemon");
269 wvcon->print("You are about to enter the no spin zone\n");
270 while (!WvIStreamList::globallist.isempty() &&
271 conn.isok() && daemon.isok())
273 wvcon->print("Spinning: streams left: %s\n",
274 WvIStreamList::globallist.count());
275 WvIStreamList::globallist.runonce();
278 WVPASS(daemon.isok());
279 WvIStreamList::globallist.zap();
283 /**** Daemon proxying test ****/
285 // test that proxying between two uniconf daemons works
286 // e.g.: client -> uniconfd -> uniconfd
288 static WvPipe * setup_master_daemon(bool implicit_root,
289 WvString &masterpipename, WvString &ininame)
291 ininame = wvtmpfilename("uniconfd.t-ini");
292 WvString pidfile = wvtmpfilename("uniconfd.t-mpid");
294 WvFile stuff(ininame, (O_CREAT | O_WRONLY));
295 stuff.print("pickles/apples/foo=1\n");
296 stuff.print("pickles/mangos/bar=1\n");
297 stuff.close();
299 masterpipename = wvtmpfilename("uniconfd.t-sock");
301 WvString inimount("/cfg=ini:%s", ininame);
302 WvString mount1, mount2;
303 if (implicit_root)
304 mount1 = inimount;
305 else
307 mount1 = "/=temp:";
308 mount2 = inimount;
311 WvString lmoniker("unix:%s", masterpipename);
312 const char * const uniconfd_args[] = {
313 "uniconf/daemon/uniconfd",
314 "-d", "--pid-file", pidfile.cstr(),
315 "-l", lmoniker.cstr(),
316 mount1.cstr(),
317 mount2.cstr(),
318 NULL
321 return new WvPipe(uniconfd_args[0], uniconfd_args, false, true, false);
325 static WvPipe * setup_slave_daemon(bool implicit_root, WvStringParm masterpipename,
326 WvString &slavepipename)
328 slavepipename = wvtmpfilename("uniconfd.t-sock");
329 WvString pidfile = wvtmpfilename("uiconfd.t-spid");
331 WvString rootmount;
332 if (implicit_root)
333 rootmount.append("/=retry:unix:%s", masterpipename);
334 else
335 rootmount.append("/=retry:cache:unix:%s", masterpipename);
337 WvString lmoniker("unix:%s", slavepipename);
338 const char * const uniconfd_args[] = {
339 "uniconf/daemon/uniconfd",
340 "--pid-file", pidfile.cstr(),
341 "-l", lmoniker,
342 rootmount.cstr(),
343 NULL
346 return new WvPipe(uniconfd_args[0], uniconfd_args, false, false, false);
350 static void wait_for_pipe_ready(WvStringParm pipename)
352 // If we can't get a connection in 100ms, something is seriously wrong..
354 WvUnixAddr addr(pipename);
355 WvUnixConn *sock = new WvUnixConn(addr);
357 WvString line;
358 line = sock->getline(100);
359 while (!line)
361 WVRELEASE(sock);
362 sock = new WvUnixConn(addr);
363 line = sock->getline(100);
365 WVRELEASE(sock);
366 wvcon->print("Pipe ready! (%s)\n", line);
370 static void daemon_proxy_test(bool implicit_root)
372 wvcon->print("Setting up master daemon.\n");
373 WvString masterpipename, ininame;
374 WvPipe *master = setup_master_daemon(implicit_root, masterpipename, ininame);
375 master->setcallback(wv::bind(WvPipe::ignore_read, wv::ref(*master)));
376 master->nowrite();
377 wait_for_pipe_ready(masterpipename);
379 wvcon->print("Setting up slave daemon.\n");
380 WvString slavepipename;
381 WvPipe *slave = setup_slave_daemon(implicit_root, masterpipename, slavepipename);
382 slave->setcallback(wv::bind(WvPipe::ignore_read, wv::ref(*slave)));
383 slave->nowrite();
384 wait_for_pipe_ready(slavepipename);
386 WvStringList commands;
387 commands.append("get /cfg/pickles/apples/foo");
388 commands.append("subt /");
389 WvStringListList expected_responses;
390 WvStringList hello_response;
391 hello_response.append(WvString("HELLO {UniConf Server ready.} %s",
392 UNICONF_PROTOCOL_VERSION));
393 expected_responses.add(&hello_response, false);
394 WvStringList expected_get_response;
395 expected_get_response.append("ONEVAL cfg/pickles/apples/foo 1");
396 expected_responses.add(&expected_get_response, false);
397 WvStringList expected_subt_response;
398 expected_subt_response.append("VAL cfg {}");
399 expected_responses.add(&expected_subt_response, false);
401 WvUnixAddr addr(slavepipename);
402 WvUnixConn *sock = new WvUnixConn(addr);
403 UniConfDaemonTestConn conn(sock, &commands, &expected_responses);
405 WvIStreamList::globallist.append(&conn, false, "conn");
407 wvcon->print("Spinning: streams left: %s\n",
408 WvIStreamList::globallist.count());
409 while (!WvIStreamList::globallist.isempty() &&
410 conn.isok())
412 wvcon->print("Spinning: streams left: %s\n",
413 WvIStreamList::globallist.count());
414 WvIStreamList::globallist.runonce();
417 WvIStreamList::globallist.zap();
418 WVRELEASE(master);
419 WVRELEASE(slave);
421 unlink(slavepipename.cstr());
422 unlink(masterpipename.cstr());
423 unlink(ininame.cstr());
427 WVTEST_MAIN("daemon proxying - with cache")
429 signal(SIGPIPE, SIG_IGN);
431 daemon_proxy_test(false);
435 WVTEST_MAIN("daemon proxying - cfg the only mount")
437 signal(SIGPIPE, SIG_IGN);
439 daemon_proxy_test(true);