00001
00002
00003
00004
00005
00006 #include "wvbdbhash.h"
00007 #include "wvhashtable.h"
00008 #include "wvstream.h"
00009
00010 typedef WvBdbHash<WvString,WvString> StrStrMap;
00011
00012
00013
00014 struct KeyVal
00015 {
00016 WvString key;
00017 WvString val;
00018 KeyVal(WvStringParm k, WvStringParm v) : key(k), val(v) { }
00019 };
00020 DeclareWvDict(KeyVal, WvString, key);
00021 KeyValDict keyvals(3);
00022 KeyValDict::Iter gi(keyvals);
00023
00024 bool iterdone;
00025
00026 bool cmptest(WvStringParm wantkey, WvStringParm wantval, WvStringParm gotkey,
00027 WvStringParm gotval)
00028 {
00029 if (wantkey != gotkey || wantval != gotval) {
00030 wvcon->print("expect '%s'/'%s', got '%s'/'%s' - FAILED\n",
00031 wantkey, wantval, gotkey, gotval);
00032 return false;
00033 } else {
00034 wvcon->print("expect '%s'/'%s' - PASSED\n", wantkey, gotval);
00035 return true;
00036 }
00037 }
00038
00039 bool itertest(StrStrMap::Iter &i, WvStringParm key, WvStringParm want)
00040 {
00041 i.rewind(key); i.next();
00042 return cmptest(key, want, i.key(), i());
00043 }
00044
00045 bool itertest2(StrStrMap &ss, WvStringParm key, WvStringParm want)
00046 {
00047 StrStrMap::Iter i(ss);
00048 return itertest(i, key, want);
00049 }
00050
00051 void itertest3(WvStream &s, void *userdata)
00052 {
00053 StrStrMap &ss = *((StrStrMap *) userdata);
00054 iterdone = !gi.next();
00055 if (!iterdone) itertest2(ss, gi->key, gi->val);
00056 s.alarm(0);
00057 }
00058
00059
00060 int alpha(const KeyVal *a, const KeyVal *b)
00061 {
00062 return strcmp(a->key, b->key);
00063 }
00064
00065
00066 bool runtests(StrStrMap &ss)
00067 {
00068 bool good = true;
00069
00070 {
00071 wvcon->print("\nSimple iter:\n");
00072 StrStrMap::Iter i1(ss);
00073 KeyValDict::Sorter i2(keyvals, alpha);
00074 i1.rewind(); i2.rewind();
00075 for (;;)
00076 {
00077 bool i1ok = i1.next();
00078 bool i2ok = i2.next();
00079 if (i1ok != i2ok)
00080 wvcon->print("\nnext() return value out of sync: "
00081 "expected %s, got %s - FAILED\n", i2ok, i1ok);
00082 if (!i1ok || !i2ok) break;
00083
00084 good = cmptest(i2->key, i2->val, i1.key(), i1()) && good;
00085 }
00086 }
00087
00088 {
00089 wvcon->print("\nMultiple rewinds:\n");
00090 StrStrMap::Iter i(ss);
00091 KeyValDict::Iter i2(keyvals);
00092 for (i2.rewind(); i2.next(); )
00093 good = itertest(i, i2->key, i2->val) && good;
00094 }
00095
00096 {
00097 wvcon->print("\nRecreation of iter:\n");
00098 KeyValDict::Iter i2(keyvals);
00099 for (i2.rewind(); i2.next(); )
00100 good = itertest2(ss, i2->key, i2->val) && good;
00101 }
00102
00103 {
00104 wvcon->print("\nRecreation of iter through a callback:\n");
00105 WvStream s;
00106 s.setcallback(itertest3, &ss);
00107 s.alarm(0);
00108 gi.rewind();
00109 iterdone = false;
00110 while (!iterdone)
00111 if (s.select(-1)) s.callback();
00112 }
00113
00114 {
00115 wvcon->print("\nNested iters:\n");
00116 StrStrMap::Iter i1(ss);
00117 KeyValDict::Sorter i2(keyvals, alpha);
00118 i2.rewind(); i1.rewind();
00119 for (;;)
00120 {
00121 bool i1ok = i1.next();
00122 bool i2ok = i2.next();
00123 if (i1ok != i2ok)
00124 wvcon->print("\nnext() return value out of sync: "
00125 "expected %s, got %s - FAILED\n", i2ok, i1ok);
00126 if (!i1ok || !i2ok) break;
00127
00128 fprintf(stderr, "\n");
00129 good = cmptest(i2->key, i2->val, i1.key(), i1()) && good;
00130 fprintf(stderr, "\n");
00131 KeyValDict::Iter i3(keyvals);
00132 for (i3.rewind(); i3.next(); )
00133 good = itertest2(ss, i3->key, i3->val) && good;
00134 }
00135 }
00136
00137 {
00138 wvcon->print("\nUpdate during an iter:\n");
00139 StrStrMap::Iter i1(ss);
00140 KeyValDict::Sorter i2(keyvals, alpha);
00141 i2.rewind(); i1.rewind();
00142 for (;;)
00143 {
00144 bool i1ok = i1.next();
00145 bool i2ok = i2.next();
00146 if (i1ok != i2ok)
00147 wvcon->print("\nnext() return value out of sync: "
00148 "expected %s, got %s - FAILED\n", i2ok, i1ok);
00149 if (!i1ok || !i2ok) break;
00150
00151 if (i1.key() == "hello") {
00152 i1() = "everybody";
00153 i1.save();
00154 }
00155
00156 if (i2->key == "hello")
00157 good = cmptest(i2->key, "everybody", i1.key(), i1()) && good;
00158 else
00159 good = cmptest(i2->key, i2->val, i1.key(), i1()) && good;
00160 }
00161 }
00162
00163 {
00164 wvcon->print("\nDelete during an iter:\n");
00165 StrStrMap::Iter i1(ss);
00166 KeyValDict::Sorter i2(keyvals, alpha);
00167 i2.rewind(); i1.rewind();
00168 for (;;)
00169 {
00170 bool i1ok = i1.next();
00171 bool i2ok = i2.next();
00172 if (i1ok != i2ok)
00173 wvcon->print("\nnext() return value out of sync: "
00174 "expected %s, got %s - FAILED\n", i2ok, i1ok);
00175 if (!i1ok || !i2ok) break;
00176
00177 if (i1.key() == "hello")
00178 i1.xunlink();
00179
00180 if (i2->key == "hello") {
00181
00182
00183 }
00184 else
00185 good = cmptest(i2->key, i2->val, i1.key(), i1()) && good;
00186 }
00187 }
00188
00189 return good;
00190 }
00191
00192 int main()
00193 {
00194 keyvals.add(new KeyVal("hello", "world"), true);
00195 keyvals.add(new KeyVal("i like", "muffins"), true);
00196 keyvals.add(new KeyVal("/foo/bar", "baz"), true);
00197 keyvals.add(new KeyVal("/", "slash"), true);
00198 keyvals.add(new KeyVal("/foo", "kung foo!"), true);
00199
00200 {
00201
00202 StrStrMap ss("rewindfile");
00203 wvcon->print("\nPopulating named db... ");
00204 ss.zap();
00205 KeyValDict::Iter i(keyvals);
00206 for (i.rewind(); i.next(); )
00207 ss.add(i->key, i->val, true);
00208 wvcon->print("done\n");
00209
00210 runtests(ss);
00211
00212
00213 assert(ss.isok());
00214 ss.seterr("Fake err");
00215 assert(!ss.isok());
00216 ss.zap();
00217 fprintf(stderr, "After zap, isok is %d (%s)\n", ss.isok(), ss.errstr().cstr());
00218 }
00219
00220 {
00221
00222 StrStrMap ss;
00223 wvcon->print("\nPopulating anon db... ");
00224 KeyValDict::Iter i(keyvals);
00225 for (i.rewind(); i.next(); )
00226 ss.add(i->key, i->val);
00227 wvcon->print("done\n");
00228
00229 runtests(ss);
00230
00231
00232 assert(ss.isok());
00233 ss.seterr("Fake err");
00234 assert(!ss.isok());
00235 ss.zap();
00236 fprintf(stderr, "After zap, isok is %d (%s)\n", ss.isok(), ss.errstr().cstr());
00237 }
00238 }