LUMIERA.clone/tests/library/symbol-hashtable-test.cpp
Ichthyostega ada5cefaaf re-arrange tests according to layer structure
the buildsystem will now pick up and link
all test cases according to the layer, e.g.
backend tests will automatically be linked
against the backend + library solely.
2013-01-07 05:43:01 +01:00

164 lines
5 KiB
C++

/*
SymbolHashtable(Test) - building a hashtable with Symbol (id) keys
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/util.hpp"
#include "lib/symbol.hpp"
#include <boost/functional/hash.hpp>
#include <tr1/unordered_map>
#include <cstring>
#include <string>
using util::contains;
using util::isnil;
namespace lib {
namespace test{
using std::string;
using boost::hash;
namespace { // test data
Symbol KEY1 ("Key1");
Symbol KEY2 ("Key2");
Symbol KEY3 ("Key3");
Symbol KEY4 ("Key4");
Symbol KEY5 ("Key5");
}
typedef std::tr1::unordered_map< Symbol, string, hash<Symbol> > HTable;
/*************************************************************
* @test build a hashtable using Symbol objects as Keys.
* Especially this verifies picking up a customised
* hash implementation via ADL
* @see symbol-impl.cpp
*/
class SymbolHashtable_test : public Test
{
virtual void
run (Arg)
{
checkHashFunction();
HTable table;
CHECK (isnil(table));
table[KEY1] = string (KEY1);
table[KEY2] = string (KEY2);
table[KEY3] = string (KEY3);
table[KEY4] = string (KEY4);
CHECK (!isnil(table));
CHECK (4 == table.size());
CHECK (contains (table, KEY1));
CHECK (contains (table, KEY2));
CHECK (contains (table, KEY3));
CHECK (contains (table, KEY4));
CHECK (!contains (table, KEY5));
CHECK (string (KEY1) == table[KEY1]);
CHECK (string (KEY2) == table[KEY2]);
CHECK (string (KEY3) == table[KEY3]);
CHECK (string (KEY4) == table[KEY4]);
table[KEY3] += "...";
CHECK (string(KEY3) != table[KEY3]);
CHECK (string(KEY3)+"..." == table[KEY3]);
CHECK (isnil (table[KEY5])); // adds a new empty value object as side effect
CHECK (5 == table.size());
}
void
checkHashFunction()
{
string random = randStr(STRING_MAX_RELEVANT+1);
string copy1(random);
copy1[5] = '\0'; // truncate the c-String to 5 chars
string copy2(random);
copy2[rand() % STRING_MAX_RELEVANT] = '*'; // modify a random position
string copy3(copy2);
copy3[STRING_MAX_RELEVANT] = '*'; // modify behind observation limit
Symbol l0;
Literal l51 (copy1.c_str());
Literal l52 (random.substr(0,5).c_str());
Literal l_1 (random.c_str());
Literal l_2 (copy2.c_str());
Literal l_3 (copy3.c_str());
CHECK (isnil (l0));
CHECK (l0 != l51);
CHECK (l51 == l52);
CHECK (l51 != l_1);
CHECK (l_1 != l_2);
CHECK (l_2 == l_3); // difference not detected due to observation limit...
CHECK (!std::strncmp (l_2, l_3, STRING_MAX_RELEVANT ));
CHECK ( std::strncmp (l_2, l_3, STRING_MAX_RELEVANT+1));
size_t h0 = hash_value (l0);
size_t h51 = hash_value (l51);
size_t h52 = hash_value (l52);
size_t h_1 = hash_value (l_1);
size_t h_2 = hash_value (l_2);
size_t h_3 = hash_value (l_3);
CHECK (h0 == 0);
CHECK (h51 != 0);
CHECK (h52 != 0);
CHECK (h_1 != 0);
CHECK (h_2 != 0);
CHECK (h_3 != 0);
CHECK (h51 == h52); // verify the hash function indeed stops at '\0'
CHECK (h51 != h_1); // share a common prefix, but the hash differs
CHECK (h_1 != h_2); // the single random modification is detected
CHECK (h_2 == h_3); // because l_2 and l_3 differ behind the fixed observation limit
CHECK (h_1 == hash_value (l_1)); //reproducible
CHECK (h_2 == hash_value (l_2));
CHECK (h_3 == hash_value (l_3));
}
};
LAUNCHER (SymbolHashtable_test, "function common");
}} // namespace lib::test