testDatahash1.cpp

Go to the documentation of this file.
00001 /*
00002  * testDathash1.cpp
00003  *
00004  * Copyright (C) 2008  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Test for the datahash routines.
00032  */
00033 
00034 // includes --------------------------------------------------------------------
00035 #include "datahash/datahash.h"  // always include our own header file first!
00036 
00037 #include <fstream>
00038 
00039 #include "common/wave_ex.h"
00040 #include "datahash/datahash_text.h"
00041 #include "datahash/datahash_util.h"
00042 #include "perf/perf.h"
00043 
00044 
00045 
00046 static const char * s_filename          = "testhash-1.txt";
00047 
00048 struct key_value_t {
00049         const char *    key;
00050         const char *    value;
00051 };
00052 
00053 
00054 static const key_value_t s_funkyLines[] = {
00055     { "funky",          "This is a funky line! [] @/^\\$() _~`<>,. { } | += --- \t yup!" },
00056     { "greek",          "Μπορῶ νὰ φάω σπασμένα γυαλιὰ χωρὶς νὰ πάθω τίποτα." },
00057     { "frenchProvencal","Pòdi manjar de veire, me nafrariá pas." },
00058     { "georgian",       "მინას ვჭამ და არა მტკივა." },
00059     { "macedonian",     "Можам да јадам стакло, а не ме штета." },
00060     { "japanese",       "私はガラスを食べられます。それは私を傷つけません。" },
00061     { "chinese",        "我能吞下玻璃而不伤身体。" },
00062 
00063     // keep this last
00064     { NULL, NULL }
00065 };
00066 
00067 
00068 ////////////////////////////////////////////////////////////////////////////////
00069 //
00070 //      static helper methods
00071 //
00072 ////////////////////////////////////////////////////////////////////////////////
00073 
00074 static void
00075 addSubhash
00076 (
00077 IN Datahash * h,
00078 IN const char * key
00079 )
00080 {
00081         ASSERT(h, "null");
00082         ASSERT(key, "null");
00083 
00084         smart_ptr<Datahash> subhash = Datahash::create();
00085         ASSERT(subhash, "out of memory");
00086 
00087         h->insert(key, subhash);
00088 }
00089 
00090 
00091 
00092 static void
00093 addToSubhash
00094 (
00095 IN Datahash * h,
00096 IN const char * hashname,
00097 IN const char * key,
00098 IN const char * value
00099 )
00100 {
00101         ASSERT(h, "null");
00102         ASSERT(hashname, "null");
00103         ASSERT(key, "null");
00104         ASSERT(value, "null");
00105 
00106         smart_ptr<Datahash> sub = getSubhash(h, hashname);
00107         ASSERT(sub, "null");
00108 
00109         sub->insert(key, value);
00110 }
00111 
00112 
00113 
00114 static void
00115 verifyBadAdd
00116 (
00117 IN Datahash * h,
00118 IN const char * key,
00119 IN const char * value
00120 )
00121 {
00122         ASSERT(h, "null");
00123         ASSERT(key, "null");
00124         ASSERT(value, "null");
00125 
00126         bool caughtException = false;
00127         try {
00128                 h->insert(key, value);
00129         } catch (std::exception& e) {
00130                 caughtException = true;
00131         }
00132 
00133         if (!caughtException) {
00134                 WAVE_EX(wex);
00135                 wex << "Illegal add-to-hash of key='" << key << "' and value='";
00136                 wex << value << "' should have thrown exception but did not!";
00137         }
00138 }
00139 
00140 
00141 
00142 static void
00143 writeHash
00144 (
00145 IN const Datahash * hash
00146 )
00147 {
00148         ASSERT(hash, "null");
00149 
00150         std::ofstream outfile(s_filename);
00151         if (!outfile.good()) {
00152                 WAVE_EX(wex);
00153                 wex << "Failed to open file for writing: " << s_filename;
00154         }
00155 
00156         writeHashToStream(hash, outfile);
00157 }
00158 
00159 
00160 
00161 static void
00162 verifySubhash
00163 (
00164 IN const Datahash * h,
00165 IN const char * name
00166 )
00167 {
00168         ASSERT(h, "null");
00169         ASSERT(name, "null");
00170 
00171         smart_ptr<Datahash> sub = getSubhash(h, name);
00172         ASSERT(sub, "null");
00173 }
00174 
00175 
00176 
00177 static void
00178 verifySubhashValue
00179 (
00180 IN const Datahash * h,
00181 IN const char * name,
00182 IN const char * key,
00183 IN const char * value
00184 )
00185 {
00186         ASSERT(h, "null");
00187         ASSERT(name, "null");
00188         ASSERT(key, "null");
00189         ASSERT(value, "null");
00190 
00191         smart_ptr<Datahash> sub = getSubhash(h, name);
00192         ASSERT(sub, "null");
00193 
00194         Datahash::iterator_t i;
00195         sub->getIterator(key, i);
00196         std::string k;
00197         hash_value_t hv;
00198         while (sub->getNextElement(i, k, hv)) {
00199                 if (eHashDataType_String != hv.type) {
00200                         continue;       // skip this non-string entry
00201                 }
00202                 const char * val = hv.text.c_str();
00203                 if (!strcmp(val, value))
00204                         return;
00205         }
00206 
00207         WAVE_EX(wex);
00208         wex << "Failed to find value '" << value << "' for key '" << key;
00209         wex << "' in subhash '" << name << "'";
00210 }
00211 
00212 
00213 
00214 static void
00215 verifyMissing
00216 (
00217 IN const Datahash * h,
00218 IN const char * key
00219 )
00220 {
00221         ASSERT(h, "null");
00222         ASSERT(key, "null");
00223 
00224         bool caughtException = false;
00225         try {
00226                 getString(h, key);
00227         } catch (std::exception& e) {
00228                 caughtException = true;
00229         }
00230 
00231         if (!caughtException) {
00232                 WAVE_EX(wex);
00233                 wex << "Should have failed to find key '" << key << "' ";
00234                 wex << "in hash, but no exception was thrown!";
00235         }
00236 }
00237 
00238 
00239 
00240 static void
00241 doTest
00242 (
00243 void
00244 )
00245 {
00246         // create a new, nested hash
00247         smart_ptr<Datahash> hash = Datahash::create();
00248         ASSERT(hash, "out of memory");
00249 
00250         addSubhash(hash, "foo");
00251         addSubhash(hash, "bar");
00252 
00253         addToSubhash(hash, "bar", "text", "This is long, long text!  Yessir.");
00254 
00255         addToSubhash(hash, "foo", "key1", "value1");
00256         addToSubhash(hash, "foo", "key1", "value2");
00257         addToSubhash(hash, "foo", "key1", "value3");
00258 
00259         // verify failure
00260         verifyBadAdd(hash, "key-1", "value-1");
00261         verifyBadAdd(hash, "0key", "value-1");
00262         verifyBadAdd(hash, "유리를", "value-2");     // korean
00263         verifyBadAdd(hash, "Можам", "value-3");            // macedonian
00264         // add a funky line to a deeper subhash
00265         smart_ptr<Datahash> subhash = getSubhash(hash, "foo");
00266         addSubhash(subhash, "xyz");
00267         for (const key_value_t * p = s_funkyLines; p->key; ++p) {
00268                 addToSubhash(subhash, "xyz", p->key, p->value);
00269         }
00270 
00271         // write to file
00272         writeHash(hash);
00273 
00274         // resurrect from file in new hash
00275         smart_ptr<Datahash> hash2 = readHashFromTextFile(s_filename);
00276         ASSERT(hash2, "failed to read hash?");
00277 
00278         // verify everything is there
00279         verifySubhash(hash2, "bar");
00280         verifySubhashValue(hash2, "bar", "text",
00281                 "This is long, long text!  Yessir.");
00282 
00283         verifySubhash(hash2, "foo");
00284         verifySubhashValue(hash2, "foo", "key1", "value1");
00285         verifySubhashValue(hash2, "foo", "key1", "value2");
00286         verifySubhashValue(hash2, "foo", "key1", "value3");
00287 
00288         smart_ptr<Datahash> subhash2 = getSubhash(hash2, "foo");
00289         verifySubhash(subhash2, "xyz");
00290         for (const key_value_t * p = s_funkyLines; p->key; ++p) {
00291                 verifySubhashValue(subhash2, "xyz", p->key, p->value);
00292         }
00293 
00294         // verify stuff is NOT there!
00295         verifyMissing(hash2, "key");
00296         verifyMissing(subhash2, "key1");
00297 }
00298 
00299 
00300 
00301 ////////////////////////////////////////////////////////////////////////////////
00302 //
00303 //      entry point
00304 //
00305 ////////////////////////////////////////////////////////////////////////////////
00306 
00307 int
00308 main
00309 (
00310 IN int argc,
00311 IN const char * argv[]
00312 )
00313 {
00314         int retval = 0;
00315         try {
00316                 perf::Timer timer("overall timer");
00317                 doTest();
00318 
00319         } catch (std::exception& e) {
00320                 DPRINTF("Exception: %s", e.what());
00321                 retval = 1;
00322         } catch (...) {
00323                 DPRINTF("Unknown exception!");
00324                 retval = 2;
00325         }
00326         perf::dumpTimingSummary(std::cerr);
00327 
00328         return retval;
00329 }
00330