Lumiera  0.pre.03
»edit your freedom«
symbol-hashtable-test.cpp
Go to the documentation of this file.
1 /*
2  SymbolHashtable(Test) - building a hashtable with Symbol (id) keys
3 
4  Copyright (C) Lumiera.org
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
29 #include "lib/test/run.hpp"
30 #include "lib/test/test-helper.hpp"
31 #include "lib/util.hpp"
32 
33 #include "lib/symbol.hpp"
34 
35 #include <boost/functional/hash.hpp>
36 #include <unordered_map>
37 #include <cstring>
38 #include <string>
39 
40 using util::contains;
41 using util::isnil;
42 
43 
44 
45 namespace lib {
46 namespace test{
47 
48  using std::string;
49  using boost::hash;
50 
51 
52  namespace { // test data
53  Symbol KEY1 ("Key1");
54  Symbol KEY2 ("Key2");
55  Symbol KEY3 ("Key3");
56  Symbol KEY4 ("Key4");
57  Symbol KEY5 ("Key5");
58 
59  }
60 
61  typedef std::unordered_map< Symbol, string, hash<Symbol>> HTable;
62 
63 
64  /*********************************************************/
70  class SymbolHashtable_test : public Test
71  {
72 
73  virtual void
74  run (Arg)
75  {
76  checkHashFunction();
77 
78  HTable table;
79  CHECK (isnil(table));
80 
81  table[KEY1] = string (KEY1);
82  table[KEY2] = string (KEY2);
83  table[KEY3] = string (KEY3);
84  table[KEY4] = string (KEY4);
85 
86  CHECK (!isnil(table));
87  CHECK (4 == table.size());
88  CHECK (contains (table, KEY1));
89  CHECK (contains (table, KEY2));
90  CHECK (contains (table, KEY3));
91  CHECK (contains (table, KEY4));
92  CHECK (!contains (table, KEY5));
93 
94  CHECK (string (KEY1) == table[KEY1]);
95  CHECK (string (KEY2) == table[KEY2]);
96  CHECK (string (KEY3) == table[KEY3]);
97  CHECK (string (KEY4) == table[KEY4]);
98 
99  table[KEY3] += "...";
100  CHECK (string(KEY3) != table[KEY3]);
101  CHECK (string(KEY3)+"..." == table[KEY3]);
102 
103  CHECK (isnil (table[KEY5])); // adds a new empty value object as side effect
104  CHECK (5 == table.size());
105  }
106 
107 
108  void
109  checkHashFunction()
110  {
111  string random = randStr(STRING_MAX_RELEVANT+1);
112 
113  string copy1(random);
114  copy1[5] = '\0'; // truncate the c-String to 5 chars
115 
116  string copy2(random);
117  copy2[rand() % STRING_MAX_RELEVANT] = '*'; // modify a random position
118 
119  string copy3(copy2);
120  copy3[STRING_MAX_RELEVANT] = '*'; // modify behind observation limit
121 
122  Symbol l0;
123  Literal l51 (copy1.c_str());
124  Literal l52 (random.substr(0,5).c_str());
125 
126  Literal l_1 (random.c_str());
127  Literal l_2 (copy2.c_str());
128  Literal l_3 (copy3.c_str());
129 
130  CHECK (isnil (l0));
131  CHECK (l0 != l51);
132  CHECK (l51 == l52);
133 
134  CHECK (l51 != l_1);
135  CHECK (l_1 != l_2);
136  CHECK (l_2 == l_3); // difference not detected due to observation limit...
137  CHECK (!std::strncmp (l_2, l_3, STRING_MAX_RELEVANT ));
138  CHECK ( std::strncmp (l_2, l_3, STRING_MAX_RELEVANT+1));
139 
140  size_t h0 = hash_value (l0);
141  size_t h51 = hash_value (l51);
142  size_t h52 = hash_value (l52);
143  size_t h_1 = hash_value (l_1);
144  size_t h_2 = hash_value (l_2);
145  size_t h_3 = hash_value (l_3);
146 
147  CHECK (h0 == 0);
148  CHECK (h51 != 0);
149  CHECK (h52 != 0);
150  CHECK (h_1 != 0);
151  CHECK (h_2 != 0);
152  CHECK (h_3 != 0);
153 
154  CHECK (h51 == h52); // verify the hash function indeed stops at '\0'
155  CHECK (h51 != h_1); // share a common prefix, but the hash differs
156  CHECK (h_1 != h_2); // the single random modification is detected
157  CHECK (h_2 == h_3); // because l_2 and l_3 differ behind the fixed observation limit
158 
159  CHECK (h_1 == hash_value (l_1)); //reproducible
160  CHECK (h_2 == hash_value (l_2));
161  CHECK (h_3 == hash_value (l_3));
162  }
163  };
164 
165  LAUNCHER (SymbolHashtable_test, "function common");
166 
167 
168 }} // namespace lib::test
Definition: run.hpp:49
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:85
const size_t STRING_MAX_RELEVANT
safety guard: maximum number of chars to process.
Definition: symbol-impl.cpp:55
Implementation namespace for support and library code.
string randStr(size_t len)
create garbage string of given length
Definition: test-helper.cpp:69
Token or Atom with distinct identity.
Definition: symbol.hpp:126
Marker types to indicate a literal string and a Symbol.
Simple test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
A collection of frequently used helper functions to support unit testing.
HashVal hash_value(QueryText const &entry)
support using queries in hashtables.
Definition: query-text.cpp:61
bool contains(SEQ const &cont, typename SEQ::const_reference val)
shortcut for brute-force containment test in any sequential container
Definition: util.hpp:255