#include "wvtest.h" #include "uniconfroot.h" #include "wvstream.h" WVTEST_MAIN("no generator") { UniConfRoot root1; WVPASS(root1.getme() == WvString::null); // verify that setting keys in unmounted space does not actually // set their values (or more likely, cause a segfault) UniConfRoot root2; root2["subt/mayo/baz"].mount("temp:"); root2["/"].setme("foo"); root2["subt"].setme("bar"); root2["subt/mayo"].setme("moo"); WVPASS(strcmp(root2["/"].getme().cstr(), "") == 0); WVPASS(strcmp(root2["subt"].getme().cstr(), "") == 0); WVPASS(strcmp(root2["subt/mayo"].getme().cstr(), "") == 0); WVFAIL(root2["dialer 2"].exists()); } WVTEST_MAIN("null generator") { UniConfRoot root("null:"); } // if this test compiles at all, we win! WVTEST_MAIN("type conversions") { UniConfRoot root("temp:"); UniConf cfg(root); cfg.setme("x"); cfg.setme(5); WVPASSEQ("5", cfg.getme("x")); WVPASSEQ("5", cfg.getme(5)); cfg["x"].setme("x"); cfg[5].setme("x"); int x = 5; WVPASSEQ("x", cfg[x].getme("x")); cfg[cfg.getme(5)].setme("x"); cfg.setme(cfg.getme(x)); cfg.setme(cfg.getmeint(x)); cfg.setmeint(cfg.getmeint(x)); cfg.setmeint(cfg.getme(x).num()); cfg[WvString(x)].setme("x"); cfg[WvFastString(x)].setme("x"); cfg[WvString(5)].setme("x"); cfg.setme(7); cfg[6].setme(*cfg); cfg.setme(cfg->num()); WVPASSEQ("7", *cfg); cfg.xset("sub", "y"); WVPASSEQ("y", *cfg["sub"]); WVPASSEQ("y", cfg.xget("sub", "foo")); WVPASSEQ(55, cfg.xgetint("sub", 55)); // unrecognizable string WVPASSEQ(7, cfg.xgetint(6)); cfg.xsetint("sub", 99); WVPASSEQ(99, cfg["sub"].getmeint(55)); WVPASSEQ("zz", cfg["blah"]->ifnull("zz")); } WVTEST_MAIN("case") { UniConfRoot root("temp:"); UniConf cfg(root); cfg.xset("eth0/IPAddr", "10"); WVPASSEQ("10", cfg.xget("eth0/IPAddr")); WVPASSEQ("10", cfg.xget("eth0/ipaddr")); } WVTEST_MAIN("haschildren() and exists()") { UniConfRoot root; { UniConf cfg(root); WVFAIL(cfg["/"].haschildren()); WVFAIL(cfg["/"].exists()); cfg.mount("temp:"); WVFAIL(cfg["/"].haschildren()); WVPASS(cfg["/"].exists()); } { UniConf cfg(root); WVFAIL(cfg["/bar"].haschildren()); WVFAIL(cfg["/bar"].exists()); cfg["/bar/config"].mount("temp:"); WVFAIL(cfg["/bar/config"].haschildren()); WVPASS(cfg["/bar/config"].exists()); //once something is mounted, parent keys should exist WVPASS(cfg["/"].haschildren()); WVPASS(cfg["/"].exists()); WVPASS(cfg["/bar"].haschildren()); WVPASS(cfg["/bar"].exists()); cfg.mount("temp:"); cfg.xset("/config/bar/foo", "goo"); WVPASS(cfg["/"].haschildren()); WVPASS(cfg["/"].exists()); WVFAIL(cfg["/foo"].exists()); cfg.xset("/foo", "bar"); WVPASS(cfg["/foo"].exists()); } } WVTEST_MAIN("section collapsing") { UniConfRoot r; WVPASSEQ(r[""][""]["/"]["simon"][""][""].fullkey().printable(), "simon/"); WVPASSEQ(r[""][""]["/"]["simon"][""]["/"].fullkey().printable(), "simon/"); } WVTEST_MAIN("fullkey()") { UniConfRoot root; root.mount("temp:"); UniConf cfg(root["cfg"]); cfg.xsetint("hello", 1); cfg.xsetint("hello/world", 2); WVPASSEQ(cfg["hello"].fullkey().printable(), "cfg/hello"); WVPASSEQ(cfg["hello/world"].fullkey(cfg).printable(), "hello/world"); WVPASSEQ(cfg["hello/world"].fullkey("cfg").printable(), "hello/world"); WVPASSEQ(cfg["hello/world"].fullkey("cfg/").printable(), "hello/world"); } static int itcount(const UniConf &cfg) { int count = 0; UniConf::Iter i(cfg); for (i.rewind(); i.next(); ) count++; return count; } static int ritcount(const UniConf &cfg) { int count = 0; UniConf::RecursiveIter i(cfg); for (i.rewind(); i.next(); ) count++; return count; } WVTEST_MAIN("iterators") { UniConfRoot root("temp:"); root["1"].setme("foo"); root["2"].setme("blah"); root["2/2b"].setme("sub"); root["x/y/z/a/b/1/2/3"].setme("something"); WVPASSEQ(itcount(root), 3); WVPASSEQ(itcount(root["2"]), 1); WVPASSEQ(itcount(root["1"]), 0); WVPASSEQ(itcount(root["2/2b"]), 0); WVPASSEQ(itcount(root["3"]), 0); WVPASSEQ(ritcount(root), 11); WVPASSEQ(ritcount(root["2"]), 1); WVPASSEQ(ritcount(root["1"]), 0); WVPASSEQ(ritcount(root["2/2b"]), 0); WVPASSEQ(ritcount(root["3"]), 0); WVPASSEQ(ritcount(root["x/y/z/a/b"]), 3); UniConf sub(root["x/y/z/a"]); UniConf::RecursiveIter i(sub); i.rewind(); i.next(); WVPASSEQ(i->fullkey(sub).printable(), "b"); i.next(); WVPASSEQ(i->fullkey(sub).printable(), "b/1"); } // bug 6869 static int compare(const UniConf &_a, const UniConf &_b) { return _a.key().compareto(_b.key()); } WVTEST_MAIN("sorted iterators") { UniConfRoot root("temp:"); root["3"].setme("foo1"); root["2"].setme("foo2"); root["1"].setme("foo3"); root["4"].setme("foo4"); UniConf sub(root); UniConf::Iter j(sub); for (j.rewind(); j.next(); ) wverr->print("fullkey=%s\n", j->fullkey()); UniConf::SortedIter i(sub, &compare); i.rewind(); i.next(); WVPASSEQ(i->fullkey(sub).printable(), "1"); i.next(); WVPASSEQ(i->fullkey(sub).printable(), "2"); i.next(); WVPASSEQ(i->fullkey(sub).printable(), "3"); i.next(); WVPASSEQ(i->fullkey(sub).printable(), "4"); } WVTEST_MAIN("nested iterators") { UniConfRoot root("temp:"); UniConf cfg(root); UniConf::Iter i1(cfg); cfg["foo"].setmeint(1); cfg["/foo/bar"].setmeint(1); cfg["/foo/car/bar"].setmeint(1); WVPASS(cfg["foo"].getmeint()); for (i1.rewind(); i1.next();) { UniConf::RecursiveIter i2(cfg); for (i2.rewind(); i2.next();) { i2->getme(); } } WVPASS(cfg["foo"].getmeint()); WVPASS(cfg["/foo/bar"].getmeint()); } WVTEST_MAIN("mounting with paths prefixed by /") { UniConfRoot root("temp:"); UniConf cfg1(root["/config"]); UniConf cfg2(root["config"]); int i = 0; for (i = 0; i < 5; i++) root.xsetint(WvString("/config/bloing%s", i), 1); for (i = 0; i < 5; i++) { WVPASS(cfg1.xgetint(WvString("/bloing%s", i))); WVPASS(cfg2.xgetint(WvString("/bloing%s", i))); } UniConf::Iter iter1(cfg1); UniConf::Iter iter2(cfg1); i = 0; for (iter1.rewind(); iter1.next(); i++) WVPASS(iter1->getmeint()); i = 0; for (iter2.rewind(); iter2.next(); i++) WVPASS(iter2->getmeint()); } WVTEST_MAIN("Deleting while iterating") { UniConfRoot root("temp:"); char *foo = new char[250]; //to make sure the hash moves in memory for (int i = 0; i < 10; i++) { root.xsetint(i, i); root[i].xsetint(i, i); } UniConf::Iter i(root); char *foo2 = new char[250]; for (i.rewind(); i.next(); ) { // fprintf(stderr, "%s\n", i->getme().cstr()); root[i->key()].setme(WvString::null); if (i->getme() != WvString::null) i.rewind(); } deletev foo; deletev foo2; } void verify_recursive_iter(UniConfRoot &root) { // verify that recursive iteration works as expected UniConf::RecursiveIter i(root); i.rewind(); WVPASS(i.next()); WVPASSEQ(i().key().printable().cstr(), "subt"); WVPASSEQ(i().getme(), ""); WVPASS(i.next()); WVPASSEQ(i().key().printable().cstr(), "mayo"); WVPASSEQ(i().getme(), "baz"); WVFAIL(i.next()); // verify that non-recursive iteration doesn't go over keys // it's not supposed to UniConf::Iter j(root); j.rewind(); WVPASS(j.next()); WVPASSEQ(j().key().printable().cstr(), "subt"); WVPASSEQ(j().getme(), ""); WVFAIL(j.next()); } WVTEST_MAIN("Recursive iteration with no generator at root") { // distance of "2" between first mount and unmounted root UniConfRoot root1; root1["subt/mayo"].mount("temp:"); root1["subt/mayo"].setme("baz"); verify_recursive_iter(root1); // distance of "1" between first mount and unmounted root UniConfRoot root2; root2["subt"].mount("temp:"); root2["subt/mayo"].setme("baz"); verify_recursive_iter(root2); }