Fix several warnings that appear in gcc 4.3.2.
[wvstreams.git] / uniconf / t / uniconfgen-sanitytest.cc
blob13bb0fb3091d3a691b22845f235051496c80e8ba
1 /* -*- Mode: C++ -*-
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2006 Net Integration Technologies, Inc.
4 *
5 * Basic sanity tests that all UniConf generators should probably pass
6 */
7 #include "uniconfgen-sanitytest.h"
9 #include "uniconf.h"
10 #include "uniconfdaemon.h"
11 #include "uniconfgen.h"
12 #include "uniconfroot.h"
13 #include "uniwatch.h"
14 #include "wvfork.h"
15 #include "wvistreamlist.h"
16 #include "wvlog.h"
17 #include "wvtest.h"
19 #include <signal.h>
20 #include <time.h>
21 #include <sys/types.h>
23 #ifndef _WIN32
24 #include <sys/wait.h>
25 #endif
27 void UniConfTestDaemon::boring_server_cb(WvStringParm sockname,
28 WvStringParm server_moniker)
31 wverr->close();
32 time_t start = time(NULL);
34 UniConfRoot uniconf(server_moniker);
35 UniConfDaemon daemon(uniconf, false, NULL);
37 unlink(sockname);
38 daemon.listen(WvString("unix:%s", sockname));
40 WvIStreamList::globallist.append(&daemon, false, "uniconfd");
41 // Make sure to commit suicide after half an hour, just in case
42 while (time(NULL) < start + 30*60)
44 WvIStreamList::globallist.runonce();
45 // usleep(1000); // should not be necessary
48 _exit(0);
52 void UniConfTestDaemon::autoinc_server_cb(WvStringParm sockname,
53 WvStringParm server_moniker)
56 wverr->close();
57 time_t start = time(NULL);
59 UniConfRoot uniconf(server_moniker);
60 UniConfDaemon daemon(uniconf, false, NULL);
62 unlink(sockname);
63 daemon.listen(WvString("unix:%s", sockname));
65 WvIStreamList::globallist.append(&daemon, false, "uniconfd");
66 // Make sure to commit suicide after half an hour, just in case
67 while (time(NULL) < start + 30*60)
69 uniconf.setmeint(uniconf.getmeint()+1);
70 WvIStreamList::globallist.runonce();
71 // usleep(1000); // should not be necessary
74 _exit(0);
78 UniConfTestDaemon::UniConfTestDaemon(WvStringParm _sockname,
79 WvStringParm _server_moniker,
80 UniConfDaemonServerCb server_cb) :
81 sockname(_sockname),
82 server_moniker(_server_moniker)
84 pid_t child = wvfork();
85 if (child == 0)
86 server_cb(sockname, server_moniker);
87 WVPASS(child > 0);
89 server_pid = child;
91 return;
94 UniConfTestDaemon::~UniConfTestDaemon()
96 #ifndef _WIN32
97 // Never, ever, try to kill pids -1 or 0.
98 if (server_pid <= 0)
99 fprintf(stderr, "Refusing to kill pid %i.\n", (int)server_pid);
100 else
101 kill(server_pid, 15);
103 int status;
104 pid_t rv;
105 while ((rv = waitpid(server_pid, &status, 0)) != server_pid)
107 // in case a signal is in the process of being delivered...
108 if (rv == -1 && errno != EINTR)
109 break;
111 WVPASSEQ(rv, server_pid);
112 WVPASS(WIFSIGNALED(status));
113 #endif
115 unlink(sockname);
118 void UniConfGenSanityTester::clear_generator(IUniConfGen *g)
120 WvLog log("clear_generator");
121 UniConfGen::Iter *ii = g->iterator("/");
122 if (ii)
124 for (ii->rewind(); ii->next(); )
126 log("removing %s (val %s)\n", ii->key(), ii->value());
127 g->set(ii->key(), WvString::null);
129 delete ii;
134 void UniConfGenSanityTester::sanity_test(IUniConfGen *g, WvStringParm moniker)
136 test_haschildren_gen(g);
137 test_haschildren_moniker(moniker);
138 test_trailing_slashes(g, moniker);
139 test_iter_sanity(moniker);
140 test_recursive_iter_sanity(moniker);
143 void UniConfGenSanityTester::test_haschildren_gen(IUniConfGen *g)
145 clear_generator(g);
147 WVFAIL(g->haschildren("/"));
149 g->set("/", "blah");
150 g->commit();
151 WVFAIL(g->haschildren("/"));
153 g->set("/x", "pah");
154 g->commit();
155 WVPASS(g->haschildren("/"));
156 WVFAIL(g->haschildren("/x"));
158 // Setting a section to an empty string is different from deleting it.
159 g->set("/", WvString(""));
160 WVPASS(g->haschildren("/"));
161 WVFAIL(g->haschildren("/x"));
163 g->set("/", WvString::null);
164 g->commit();
165 WVFAIL(g->haschildren("/"));
167 clear_generator(g);
170 // FIXME: This tests different things from the non-moniker test. They should
171 // be combined, accept a regular UniConf as a parameter, and let the caller
172 // worry about how to make one.
173 void UniConfGenSanityTester::test_haschildren_moniker(WvStringParm moniker)
175 if (!moniker)
176 return;
178 // Checking notifications.. (we will assume that we are getting the
179 // right keys for now)
180 UniConfGenSanityTester::CbCounter notifywatcher;
182 UniConfRoot cfg(moniker);
183 UniWatch watcher(cfg["/"],
184 wv::bind(&UniConfGenSanityTester::CbCounter::callback,
185 &notifywatcher, _1, _2));
186 WVFAIL(cfg.haschildren());
188 WVPASSEQ(cfg.getme(), WvString::empty);
189 WVPASS(cfg.exists());
190 WVFAIL(cfg["x"].exists());
192 notifywatcher.cbs = 0;
194 cfg.setme("blah");
195 cfg.commit();
196 WVFAIL(cfg.haschildren());
197 WVPASS(cfg.exists());
198 // Note: We might get more than one notification for the change, e.g. if
199 // we are using a UniListGen.
200 WVPASSLT(0, notifywatcher.cbs);
201 int old_cbs = notifywatcher.cbs;
203 cfg["x"].setme("pah");
204 cfg.commit();
205 WVPASS(cfg["x"].exists());
206 WVPASS(cfg.haschildren());
207 WVFAIL(cfg["x"].haschildren());
208 WVPASSLT(old_cbs, notifywatcher.cbs);
210 // Don't send notifications if the key doesn't change
211 old_cbs = notifywatcher.cbs;
212 cfg["x"].setme("pah");
213 cfg.commit();
214 WVPASSEQ(notifywatcher.cbs, old_cbs);
216 cfg.remove();
217 cfg.commit();
218 WVFAIL(cfg.haschildren());
219 // We should get notifications for both /x and / being deleted
220 WVPASSLT(old_cbs + 1, notifywatcher.cbs);
222 // FIXME: UniIniGen fails this test. See BUGZID:22439
223 #if 0
224 // Don't send notifications if the key doesn't change
225 old_cbs = notifywatcher.cbs;
226 cfg.remove();
227 cfg.commit();
228 WVPASSEQ(notifywatcher.cbs, old_cbs);
230 WVFAIL(cfg.exists());
231 WVPASSEQ(cfg.getme(), WvString::null);
232 WVFAIL(cfg["x"].exists());
233 WVPASSEQ(cfg["x"].getme(), WvString::null);
234 #endif
237 void UniConfGenSanityTester::test_trailing_slashes(IUniConfGen *g,
238 WvStringParm moniker)
240 clear_generator(g);
242 g->set("", "xyzzy");
243 g->commit();
244 WVPASSEQ(g->get("/"), "xyzzy");
245 WVPASSEQ(g->get("///"), "xyzzy");
246 WVPASSEQ(g->get(""), "xyzzy");
247 WVPASSEQ(g->get("//"), "xyzzy");
249 WVPASSEQ(g->get("///simon"), WvString::null);
250 WVPASSEQ(g->get("///simon/"), WvString::null);
251 WVPASSEQ(g->get("/simon///"), WvString::null);
253 g->set("//simon", "law");
254 g->commit();
255 WVPASSEQ(g->get("/Simon"), "law");
256 WVPASSEQ(g->get("simon///"), WvString::null);
258 g->set("//simon/", "LAW");
259 g->commit();
260 WVPASSEQ(g->get("/siMON"), "law");
261 WVPASSEQ(g->get("simon///"), WvString::null);
262 WVFAIL(g->haschildren("simon//"));
264 g->set("//simon/law", "1");
265 g->commit();
266 WVPASSEQ(g->get("/simon/law"), "1");
267 g->set("//simon/", WvString::null);
268 g->commit();
269 WVPASSEQ(g->get("/simon/law"), WvString::null);
270 WVFAIL(g->haschildren("simon///"));
272 // Test that we delete immediate and recursive children when we delete a
273 // section
274 g->set("//simon/law", "1");
275 g->set("//simon/law/foo", "1");
276 g->set("//simon/law/foo/bar", "1");
277 g->commit();
278 WVPASSEQ(g->get("/simon/law"), "1");
279 WVPASSEQ(g->get("/simon/law/foo"), "1");
280 WVPASSEQ(g->get("/simon/law/foo/bar"), "1");
281 g->set("//simon/", WvString::null);
282 g->commit();
283 WVPASSEQ(g->get("/simon/law"), WvString::null);
284 WVPASSEQ(g->get("/simon/law/foo"), WvString::null);
285 WVPASSEQ(g->get("/simon/law/foo/bar"), WvString::null);
286 WVFAIL(g->haschildren("simon///law//foo"));
287 WVFAIL(g->haschildren("simon///law//"));
288 WVFAIL(g->haschildren("simon///"));
290 // Test that we delete immediate and recursive autovivified children when
291 // we delete a section
292 g->set("//simon/law/foo/bar", "1");
293 g->commit();
294 WVPASSEQ(g->get("/simon/law"), WvString::null);
295 WVPASSEQ(g->get("/simon/law/foo"), WvString::null);
296 WVPASSEQ(g->get("/simon/law/foo/bar"), "1");
297 g->set("//simon/", WvString::null);
298 g->commit();
299 WVPASSEQ(g->get("/simon/law"), WvString::null);
300 WVPASSEQ(g->get("/simon/law/foo"), WvString::null);
301 WVPASSEQ(g->get("/simon/law/foo/bar"), WvString::null);
302 WVFAIL(g->haschildren("simon///law//foo/"));
303 WVFAIL(g->haschildren("simon///law//"));
304 WVFAIL(g->haschildren("simon///"));
306 if (!!moniker)
308 UniConfRoot cfg(moniker);
309 cfg.setme("xyzzy");
310 cfg.commit();
311 WVPASSEQ(cfg.xget("/"), "xyzzy");
312 WVPASSEQ(cfg.xget("///"), "xyzzy");
313 WVPASSEQ(cfg[""].getme(), "xyzzy");
314 WVPASSEQ(cfg[""][""]["/"].xget("/"), "xyzzy");
316 WVPASSEQ(cfg[""][""]["/"]["simon"].xget(""), WvString::null);
317 WVPASSEQ(cfg[""][""]["/"]["simon"].xget("///"), WvString::null);
319 cfg[""]["/"][""]["simon"].setme("law");
320 cfg.commit();
321 WVPASSEQ(cfg[""][""]["/"].xget("simon"), "law");
322 WVPASSEQ(cfg[""][""]["/"]["simon"].getme(), "law");
323 WVPASSEQ(cfg[""][""]["/"]["simon"].xget(""), WvString::null);
324 WVPASSEQ(cfg[""][""]["/"]["simon"].xget("///"), WvString::null);
326 cfg[""]["/"][""]["simon"].xset("/", "LAW");
327 cfg.commit();
328 WVPASSEQ(cfg[""][""]["/"].xget("simon"), "law");
329 WVPASSEQ(cfg[""][""]["/"].xget("simon/"), "");
330 WVPASSEQ(cfg[""][""]["/"]["simon"].getme(), "law");
331 WVPASSEQ(cfg[""][""]["/"]["simon"].xget(""), WvString::null);
332 WVPASSEQ(cfg[""][""]["/"]["simon"].xget("///"), WvString::null);
333 WVFAIL(cfg[""]["simon"][""].haschildren());
334 WVFAIL(cfg["simon"]["/"].haschildren());
336 cfg[""][""]["/"]["simon"].xset("/law", "1");
337 cfg.commit();
338 WVPASSEQ(cfg[""][""]["/"]["simon"][""].xget("/law"), "1");
339 cfg[""][""]["/"]["simon"]["law"].xset("", "2");
340 cfg.commit();
341 WVPASSEQ(cfg[""][""]["/"]["simon"][""].xget("/law"), "1");
342 cfg[""][""]["/"]["simon"]["law"].xset("/", "3");
343 cfg.commit();
344 WVPASSEQ(cfg[""][""]["/"]["simon"][""].xget("/law"), "1");
345 cfg[""]["/"][""]["simon"].xset("/", "LAW");
346 cfg.commit();
347 WVPASSEQ(cfg[""][""]["/"].xget("simon"), "law");
348 WVPASSEQ(cfg[""][""]["/"].xget("simon/"), "");
349 cfg[""][""]["/"]["simon"][""].remove();
350 cfg.commit();
351 WVPASSEQ(cfg[""][""]["/"]["simon"][""].xget("/law"), WvString::null);
352 WVFAIL(cfg[""]["simon"]["/"].haschildren());
354 WVPASSEQ(cfg[""].getme(), "xyzzy");
356 // ensure keys with trailing slashes don't get created as blank
357 // keys
358 cfg["foo"]["bar"][""].setme("value");
359 WVFAIL(cfg["foo"]["bar"].haschildren());
360 WVPASSEQ(cfg["foo"]["bar"][""].getme(), WvString::null);
361 WVPASSEQ(cfg["foo"]["bar"].getme(), WvString::null);
362 WVPASSEQ(cfg["foo"].getme(), WvString::null);
365 clear_generator(g);
369 // FIXME: Won't run for generators that have no moniker
370 void UniConfGenSanityTester::test_iter_sanity(WvStringParm moniker)
372 if (!moniker)
373 return;
375 UniConfRoot root(moniker);
376 root.remove();
377 root.commit();
379 root.xset("Foo/0", "Bar");
380 root.xset("Foo/1", "Baz");
381 root.xset("Foo/1/a", "Baz");
382 root.xset("Foo/2", "Baz");
383 root.xset("Bar/q", "Baz");
385 UniConf::Iter ii(root["Foo"]);
386 int jj;
387 for (jj = 0, ii.rewind(); ii.next(); jj++)
389 WVPASSEQ(ii->key().printable(), WvString(jj));
391 // Check that we only iterated over three things
392 WVPASSEQ(jj, 3);
395 // FIXME: Won't run for generators that have no moniker
396 void UniConfGenSanityTester::test_recursive_iter_sanity(WvStringParm moniker)
398 if (!moniker)
399 return;
401 UniConfRoot root(moniker);
402 root.remove();
403 root.commit();
405 root.xset("Foo/a", "1");
406 root.xset("Foo/b", "2");
407 root.xset("Foo/b/c", "3");
408 root.xset("Foo/d/e", "5");
409 root.xset("Bar/q", "Baz");
411 UniConf::RecursiveIter ii(root["/Foo"]);
412 int jj = 0;
413 for (ii.rewind(); ii.next(); )
415 jj++;
416 int val = ii->getmeint();
417 if (ii->fullkey().printable() == "Foo/d")
419 WVPASSEQ(val, 0);
420 // The fourth value we read is Foo/d, which is autovivified
421 val = 4;
424 WVFAILEQ(ii->fullkey().printable(), ii->getme());
425 WVPASSEQ(val, jj);
426 //WVPASSEQ(ii->fullkey().printable(), ii->getme());
428 // Check that we iterated over the four entries under Foo, as well as the
429 // auto-vivified Foo/d
430 WVPASSEQ(jj, 5);