Logo Search packages:      
Sourcecode: wvstreams version File versions

conftest.cc

/*
 * Worldvisions Weaver Software:
 *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
 *
 * Test program for the new, hierarchical WvConf.
 */
#include "wvlog.h"
#include "wvlogrcv.h"
#include "wvdiriter.h"
#include "wvconf.h"
#include "wvfile.h"
#include "wvtclstring.h"
#include "uniconf.h"
#include "strutils.h"
#include "uniconfroot.h"
#include "uniconftree.h"
#include "uniconfgen.h"

#include <sys/stat.h>

static void copyall(UniConf &src, UniConf &dest)
{
    UniConf::RecursiveIter it(src);
    for (it.rewind(); it.next(); )
    {
        WvString value(it->getme());
        if (value.isnull())
            continue;
        //wverr->print("set: \"%s\" = \"%s\"\n", it->fullkey(), value);
        dest[it->fullkey()].setme(value);
        //wverr->print("get: \"%s\"\n", dest[it->fullkey()].get());
    }
}


#if 0
class HelloGen : public UniConfGen
{
public:
    WvString defstr;
    int count;
    
    HelloGen(WvStringParm _def = "Hello World") :
        UniConfGen(WvString("hello:%s", _def)),
        defstr(_def)
    {
        count = 0;
    }
    virtual void update(UniConf *&h);
};


void HelloGen::update(UniConf *&h)
{
    wvcon->print("Hello: updating %s\n", h->fullkey());
    h->setvalue(WvString("%s #%s", defstr, ++count));
    h->dirty = false;
    h->obsolete = false;
    h->waiting = false;
}
#endif

// FIXME: This class *REALLY* should be merged out.
#if 0
class UniConfFileTreeGen : public UniConfGen
{
public:
    WvString basedir;
    WvLog log;
    UniConfValueTree root;
    
    UniConfFileTreeGen(WvStringParm _basedir);
    virtual ~UniConfFileTreeGen() { }

    /***** Overridden members *****/

    virtual bool refresh();
    virtual WvString get(const UniConfKey &key);
    virtual bool exists(const UniConfKey &key);
    virtual bool haschildren(const UniConfKey &key);
    virtual void set(const UniConfKey &key, WvStringParm) { }

    virtual Iter *iterator(const UniConfKey &key);

private:
    UniConfValueTree *maketree(const UniConfKey &key);
    class NodeIter;
};


class UniConfFileTreeGen::NodeIter : public UniConfFileTreeGen::Iter
{
protected:
    UniConfValueTree::Iter xit;

public:
    NodeIter(UniConfValueTree &node) : xit(node)
        { }

    /***** Overridden methods *****/

    virtual void rewind()
        { xit.rewind(); }
    virtual bool next()
        { return xit.next(); }
    virtual UniConfKey key() const
        { return xit->key(); }
};


UniConfFileTreeGen::UniConfFileTreeGen(WvStringParm _basedir) :
    basedir(_basedir), log("FileTree", WvLog::Info),
    root(NULL, UniConfKey::EMPTY, "")
{
    log(WvLog::Notice,
      "Creating a new FileTree based on '%s'.\n", basedir);
}


bool UniConfFileTreeGen::refresh()
{
    WvString filename("%s%s", basedir, key);
    
    struct stat statbuf;
    bool exists = lstat(filename.cstr(), &statbuf) == 0;

    UniConfValueTree *node = root.find(key);
    if (!exists)
    {
        if (node != &root)
            delete node;
        return true;
    }
    node = maketree(key);
    node->zap();
    
    WvDirIter dirit(filename, true);
    UniConfKey dirkey(filename);
    for (dirit.rewind(); dirit.next(); )
    {
      log(WvLog::Debug2, ".");
        UniConfKey filekey(dirit->fullname);
        filekey = filekey.removefirst(dirkey.numsegments());
        maketree(filekey);
    }
    return true;
}


WvString UniConfFileTreeGen::get(const UniConfKey &key)
{
    // check the cache
    UniConfValueTree *node = root.find(key);
    if (node && !node->value().isnull())
        return node->value();

    // read the file and extract the first non-black line
    WvString filename("%s%s", basedir, key);
    WvFile file(filename, O_RDONLY);
    
    char *line;
    for (;;)
    {
        line = NULL;
        if (!file.isok())
            break;
      line = file.getline(-1);
      if (!line)
            break;
      line = trim_string(line);
      if (line[0])
            break;
    }

    if (file.geterr())
    {
      log("Error reading %s: %s\n", filename, file.errstr());
        line = "";
    }

    if (!node)
        node = maketree(key);
    WvString value(line);
    value.unique();
    node->setvalue(value);
    file.close();
    return value;
}


bool UniConfFileTreeGen::exists(const UniConfKey &key)
{
    UniConfValueTree *node = root.find(key);
    if (!node)
    {
        refresh();
        node = root.find(key);
    }
    return node != NULL;
}


bool UniConfFileTreeGen::haschildren(const UniConfKey &key)
{
    UniConfValueTree *node = root.find(key);
    if (!node || !node->haschildren())
    {
        refresh(key, UniConfDepth::CHILDREN);
        node = root.find(key);
    }
    return node != NULL && node->haschildren();
}


UniConfFileTreeGen::Iter *UniConfFileTreeGen::iterator(const UniConfKey &key)
{
    if (haschildren(key))
    {
        UniConfValueTree *node = root.find(key);
        if (node)
            return new NodeIter(*node);
    }
    return new NullIter();
}


UniConfValueTree *UniConfFileTreeGen::maketree(const UniConfKey &key)
{
    // construct a node for the file with a null value
    UniConfValueTree *node = &root;
    UniConfKey::Iter it(key);
    it.rewind();
    while (it.next())
    {
        UniConfValueTree *prev = node;
        node = node->findchild(it());
        if (!node)
            node = new UniConfValueTree(prev, it(), WvString::null);
    }
    return node;
}
#endif


int main()
{
    WvLog log("conftest", WvLog::Info);
    WvLog quiet("*", WvLog::Debug1);
    // try Debug5 for lots of messages
    WvLogConsole rcv(2, WvLog::Debug4);
    
    log("A wvconf instance is %s/%s/%s bytes long.\n",
      sizeof(WvConf), sizeof(WvConfigSection), sizeof(WvConfigEntry));
    log("A stringlist is %s bytes long.\n", sizeof(WvStringList));
    log("A UniConfValueTree instance is %s bytes long.\n", sizeof(UniConfValueTree));
    log("A UniConfKey instance is %s bytes long.\n", sizeof(UniConfKey));
    
    {
      wvcon->print("\n\n");
      log("-- Key test begins\n");
      
      UniConfKey key("/a/b/c/d/e/f/ghij////k/l/m/");
      UniConfKey key2(key), key2b(key, key);
        UniConfKey key3(key.removefirst(5));
        UniConfKey key4(key.removefirst(900));
        // FIXME: we're just barely scratching the surface here!
      log("key :  %s\n"
          "key2:  %s (%s, %s)\n"
          "key2b: %s (%s)\n"
          "key3:  %s\n"
          "key4:  %s\n",
          key, key2, key2.range(1, key2.numsegments()-1), key2.range(0, 0),
          key2b, key2b.numsegments(),
          key3, key4);
      
      log("keyiter test 2b: ");
      UniConfKey::Iter i(key2b);
      for (i.rewind(); i.next(); )
           log("'%s' ", *i);
      log("\n");
    }
    
    {
      wvcon->print("\n\n");
      log("-- Basic config test begins\n");
      
        UniConfRoot cfg("temp:");
      cfg["/foo/blah/weasels"].setme("chickens");
      
      cfg["foo"]["pah"]["meatballs"].setmeint(6);
      
      assert(cfg["/foo/blah"].haschildren());
      assert(!cfg["/foo/blah/weasels"].haschildren());
      
      UniConf x(cfg["snort/fish/munchkins"]);
      x["big/bad/weasels"].setmeint(7);
      x["foo"].setme("sneeze");
        x["blue"].setme("sneeze");
        x["true"].setme("sneeze");
      
      {
          log("get() test:\n");
          log("  '%s' '%s' '%s' '%s'/'%s' '%s'\n",
            cfg["foo/blah/weasels"].getme(),
            cfg["foo/blah"].getme(),
            cfg["foo"].getme(),
            cfg[""].getme(), cfg[UniConfKey::EMPTY].getme(),
            cfg.getme()
            );
      }
      
      {
          log("Toplevel dump:\n");
          UniConf::Iter i(cfg);
          for (i.rewind(); i.next(); )
            quiet.print("'%s' = '%s'\n", i->key(), i->getme());
      }
      
      log("Config dump:\n");
      cfg.dump(quiet, true);
    }
    
    {
      wvcon->print("\n\n");
      log("-- Simple deletion test begins\n");
      UniConfRoot cfg("temp:");
      UniConf a(cfg["admins"]), a1(a["1"]), a2(a["2"]);
      a1.setme("11");
      a2.setme("22");
      assert(a.haschildren());
      assert(!a2.haschildren());
      a1.remove();
      assert(a.exists());
      assert(!a1.exists());
      assert(a2.exists());
      assert(a.haschildren());
      assert(!a1.haschildren());
      assert(!a2.haschildren());
    }
    
#if 0
    {
      wvcon->print("\n\n");
      log("-- Inheritence test begins\n");
      
      UniConf cfg, *h;
      
      cfg.set("/default/users/*/comment", "defuser comment");
      cfg.set("/default/users/bob/comment", "defbob comment");
      
      // should be (nil)/(nil)
      log("Old comment settings are: %s/%s\n",
          cfg.get("/users/randomperson/comment"),
            cfg.get("/users/bob/comment"));
      
      cfg["/users"].defaults = &cfg["/default/users"];

      // should be defuser comment
      h = cfg["/users/randomperson/comment"].find_default();
      log("Default for randomperson(%s): '%s'\n",
            h ? h->fullkey() : "",
          h ? h->get() : WvString("NONE"));
      
      // should be defbob comment
      h = cfg["/users/bob/comment"].find_default();
      log("Default for bob: '%s'\n",
            h ? h->get() : WvString("NONE"));
      
      // should be defuser comment/defbob comment
      log("New comment settings are: %s/%s\n",
          cfg.get("/users/noperson/comment"),
            cfg.get("/users/bob/comment"));
      
      cfg.set("/users/bob/someone/comment", "fork");
      
      log("Config dump 2:\n");
      cfg.dump(quiet);
    }
#endif
    
#if 0
    {
      wvcon->print("\n\n");
      log("-- Hello Generator test begins\n");
      
      UniConf cfg;
      
        cfg["/hello"].mount(new HelloGen("Hello world"));
        cfg["/bonjour"].mount(new HelloGen("Bonjour tout le monde!"));
      
      cfg.get("/bonjour/1");
      cfg.get("/bonjour/2");
      cfg.get("/bonjour/3");
      cfg.get("/hello/3");
      cfg.get("/hello/2");
      cfg.get("/hello/1");
      
      log("Config dump:\n");
      cfg.dump(quiet);
    }
#endif

#if 0 
    {
      wvcon->print("\n\n");
      log("-- FileTree test begins\n");
      
        UniConfRoot root(new UniConfFileTreeGen("/etc/modutils"));
      UniConf cfg(root);
      
      log("Config dump:\n");
      cfg.dump(quiet);
    }
#endif

    {
      wvcon->print("\n\n");
      log("-- IniFile test begins\n");
      
        UniConfRoot root;
      UniConf cfg(root);
      UniConf cfg2(cfg["/weaver ini test"]);
      
        cfg.mount("readonly:ini:test.ini");
        cfg2.mount("readonly:ini:/tmp/weaver.ini");
      
      log("Config dump:\n");
      cfg.dump(quiet);
    }
    
    {
        wvcon->print("\n\n");
        log("-- Defaults test begins\n");

        log("Setting up config file...\n");
        UniConfRoot root("default:ini:uniconf.ini");
        root["*"].setme("go wild, bay-be!");
        root["*/drheld/whee"].setme("3");
        root["users/*/chicken/bork"].setme("b0rk3n g00dn3ss");
        root["users/*/chicken/*"].setme("happy");
        root["users/apenwarr"].setme("ooga booga");
        root["users/apenwarr/chicken/hammer"].setme("smashy!");
        root["users/apenwarr/ftp"].setme("1");
        root["wild/*/*/blink"].setme("*1");
        root["wild/*/*/blank"].setme("*2");
        root["wild/*/*/plunk"].setme("*3");
        root.commit();

        log("Starting tests...\n");

        WvString result = root["stupidthing"].getme();
        log("/stupidthing = %s (should = go wild, bay-be!)\n", result);

        result = root["home/drheld"]["whee"].getme();
        log("/home/drheld/whee = %s (should = 3)\n", result);

        result = root["/users/apenwarr/chicken/bork"].getme();
        log("/users/apenwarr/chicken/bork = %s (should = b0rk3n g00dn3ss)\n",
                                                                    result);

        result = root["/users/silly/chicken/die"].getme();
        log("/users/silly/chicken/die = %s (should = happy)\n", result);

        result = root["/wild/foo/bar/blink"].getme("outtaspace");
        log("/wild/foo/bar/blink = %s (should = bar)\n", result);
        
        result = root["/wild/foo/bar/blank"].getme("outtaspace");
        log("/wild/foo/bar/blank = %s (should = foo)\n", result);
        
        result = root["/wild/foo/bar/plunk"].getme("outtaspace");
        log("/wild/foo/bar/plunk = %s (should = outtaspace)\n", result);
    }

    {
        wvcon->print("\n\n");
        log("-- Generator List test begins\n");
        
        UniConfRoot root("list: readonly:ini:test.ini ini:test2.ini");
        root["chickens"]["boob"].setme("not_frank");

        log("[chickens][bob] = %s\n", root["chickens"]["bob"].getme());
        log("[chickens][boob] = %s\n", root["chickens"]["boob"].getme());

        root["chickens"]["bob"].setme("gooooblefish");
        root["chickens"]["boob"].setme("I like to wear funny hats");
        log("Setting [chickens][bob] = gooooblefish  **(read only on top)\n");
        log("Setting [chickens][boob] = I like to wear funny hats\n");

        log("[chickens][bob] = %s\n", root["chickens"]["bob"].getme());
        log("[chickens][boob] = %s\n", root["chickens"]["boob"].getme());

        root.commit();

    }

    {
      wvcon->print("\n\n");
      log("-- IniFile test2 begins\n");
      
        UniConfRoot root;
      UniConf cfg(root);
      UniConf h1(cfg["/1"]);
        UniConf h2(cfg["/"]);
      
      h1.mount("ini:test.ini", true);
        h2.mount("ini:test2.ini", true);
        
      log("Partial config dump (branch 1 only):\n");
      h1.dump(quiet);
        
      log("Trying to save unchanged branches:\n");
      cfg.commit();

        UniConfRoot newroot;
        UniConf newcfg(newroot);
        UniConf newh1(newcfg["/1"]);
        UniConf newh2(newcfg["/"]);
        
      newh1.mount("ini:test.ini.new", false);
        newh2.mount("ini:test2.ini.new", false);
      
        copyall(cfg, newcfg);
        newh1.dump(quiet);

        log("Trying to save copy:\n");
      newcfg.commit();
      
      log("Changing some data:\n");
      if (!newh1["big/fat/bob"].exists())
          newh1["big/fat/bob"].setmeint(0);
      newh1["big/fat/bob"].setmeint(newh1["big/fat/bob"].getmeint() + 1);
      newh1["chicken/hammer\ndesign"].setme("simple test");
      newh1["chicken/whammer/designer\\/code\nweasel"].setme(
            "this\n\tis a test  ");

        log("Full config dump:\n");
      newcfg.dump(quiet);
      
      log("Saving changed copy:\n");
      newcfg.commit();
    }
    
    return 0;
}

Generated by  Doxygen 1.6.0   Back to index