2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2006 Net Integration Technologies, Inc.
5 * Basic sanity tests that all UniConf generators should probably pass
7 #include "uniconfgen-sanitytest.h"
10 #include "uniconfdaemon.h"
11 #include "uniconfgen.h"
12 #include "uniconfroot.h"
15 #include "wvistreamlist.h"
21 #include <sys/types.h>
27 void UniConfTestDaemon::boring_server_cb(WvStringParm sockname
,
28 WvStringParm server_moniker
)
32 time_t start
= time(NULL
);
34 UniConfRoot
uniconf(server_moniker
);
35 UniConfDaemon
daemon(uniconf
, false, NULL
);
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
52 void UniConfTestDaemon::autoinc_server_cb(WvStringParm sockname
,
53 WvStringParm server_moniker
)
57 time_t start
= time(NULL
);
59 UniConfRoot
uniconf(server_moniker
);
60 UniConfDaemon
daemon(uniconf
, false, NULL
);
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
78 UniConfTestDaemon::UniConfTestDaemon(WvStringParm _sockname
,
79 WvStringParm _server_moniker
,
80 UniConfDaemonServerCb server_cb
) :
82 server_moniker(_server_moniker
)
84 pid_t child
= wvfork();
86 server_cb(sockname
, server_moniker
);
94 UniConfTestDaemon::~UniConfTestDaemon()
97 // Never, ever, try to kill pids -1 or 0.
99 fprintf(stderr
, "Refusing to kill pid %i.\n", (int)server_pid
);
101 kill(server_pid
, 15);
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
)
111 WVPASSEQ(rv
, server_pid
);
112 WVPASS(WIFSIGNALED(status
));
118 void UniConfGenSanityTester::clear_generator(IUniConfGen
*g
)
120 WvLog
log("clear_generator");
121 UniConfGen::Iter
*ii
= g
->iterator("/");
124 for (ii
->rewind(); ii
->next(); )
126 log("removing %s (val %s)\n", ii
->key(), ii
->value());
127 g
->set(ii
->key(), WvString::null
);
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
)
147 WVFAIL(g
->haschildren("/"));
151 WVFAIL(g
->haschildren("/"));
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
);
165 WVFAIL(g
->haschildren("/"));
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
)
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 ¬ifywatcher
, _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;
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");
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");
214 WVPASSEQ(notifywatcher
.cbs
, old_cbs
);
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
224 // Don't send notifications if the key doesn't change
225 old_cbs
= notifywatcher
.cbs
;
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
);
237 void UniConfGenSanityTester::test_trailing_slashes(IUniConfGen
*g
,
238 WvStringParm moniker
)
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");
255 WVPASSEQ(g
->get("/Simon"), "law");
256 WVPASSEQ(g
->get("simon///"), WvString::null
);
258 g
->set("//simon/", "LAW");
260 WVPASSEQ(g
->get("/siMON"), "law");
261 WVPASSEQ(g
->get("simon///"), WvString::null
);
262 WVFAIL(g
->haschildren("simon//"));
264 g
->set("//simon/law", "1");
266 WVPASSEQ(g
->get("/simon/law"), "1");
267 g
->set("//simon/", WvString::null
);
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
274 g
->set("//simon/law", "1");
275 g
->set("//simon/law/foo", "1");
276 g
->set("//simon/law/foo/bar", "1");
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
);
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");
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
);
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///"));
308 UniConfRoot
cfg(moniker
);
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");
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");
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");
338 WVPASSEQ(cfg
[""][""]["/"]["simon"][""].xget("/law"), "1");
339 cfg
[""][""]["/"]["simon"]["law"].xset("", "2");
341 WVPASSEQ(cfg
[""][""]["/"]["simon"][""].xget("/law"), "1");
342 cfg
[""][""]["/"]["simon"]["law"].xset("/", "3");
344 WVPASSEQ(cfg
[""][""]["/"]["simon"][""].xget("/law"), "1");
345 cfg
[""]["/"][""]["simon"].xset("/", "LAW");
347 WVPASSEQ(cfg
[""][""]["/"].xget("simon"), "law");
348 WVPASSEQ(cfg
[""][""]["/"].xget("simon/"), "");
349 cfg
[""][""]["/"]["simon"][""].remove();
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
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
);
369 // FIXME: Won't run for generators that have no moniker
370 void UniConfGenSanityTester::test_iter_sanity(WvStringParm moniker
)
375 UniConfRoot
root(moniker
);
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"]);
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
395 // FIXME: Won't run for generators that have no moniker
396 void UniConfGenSanityTester::test_recursive_iter_sanity(WvStringParm moniker
)
401 UniConfRoot
root(moniker
);
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"]);
413 for (ii
.rewind(); ii
.next(); )
416 int val
= ii
->getmeint();
417 if (ii
->fullkey().printable() == "Foo/d")
420 // The fourth value we read is Foo/d, which is autovivified
424 WVFAILEQ(ii
->fullkey().printable(), ii
->getme());
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