2 //=============================================================================
4 * @file Hash_Map_Manager_Test.cpp
6 * This test illustrates the use of <ACE_Hash_Map_Manager> to
7 * maintain a hash table using strings. In addition, it also
8 * illustrates how the <ACE_Static_Allocator> works in
9 * conjunction with the <ACE_Hash_Map_Manager>.
11 * @author James Hu <jxh@cs.wustl.edu> and Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
13 //=============================================================================
16 #include "test_config.h"
17 #include "STL_algorithm_Test_T.h"
18 #include "ace/Hash_Map_Manager.h"
19 #include "ace/Malloc_T.h"
20 #include "ace/Null_Mutex.h"
23 static const size_t STRING_TABLE_ENTRIES
= 3 * 2;
24 static const size_t MAX_HASH
= 6;
26 using HASH_STRING_ENTRY
= ACE_Hash_Map_Entry
<const ACE_TCHAR
*, const ACE_TCHAR
*>;
28 // @@ The following requires too much internal implementation
29 // information about the <ACE_Hash_Map_Manager>. We need to figure
30 // out how to simplify this.
31 static const size_t STRING_TABLE_SIZE
=
32 sizeof (HASH_STRING_ENTRY
) * (STRING_TABLE_ENTRIES
+ MAX_HASH
);
34 static ACE_Static_Allocator
<STRING_TABLE_SIZE
> ace_test_allocator
;
36 using HASH_STRING_MAP
= ACE_Hash_Map_Manager_Ex
<const ACE_TCHAR
*, const ACE_TCHAR
*, ACE_Hash
<const ACE_TCHAR
*>, ACE_Equal_To
<const ACE_TCHAR
*>, ACE_Null_Mutex
>;
38 using HASH_STRING_ITER
= ACE_Hash_Map_Iterator_Ex
<const ACE_TCHAR
*, const ACE_TCHAR
*, ACE_Hash
<const ACE_TCHAR
*>, ACE_Equal_To
<const ACE_TCHAR
*>, ACE_Null_Mutex
>;
40 using HASH_STRING_CONST_ITER
= ACE_Hash_Map_Const_Iterator_Ex
<const ACE_TCHAR
*, const ACE_TCHAR
*, ACE_Hash
<const ACE_TCHAR
*>, ACE_Equal_To
<const ACE_TCHAR
*>, ACE_Null_Mutex
>;
42 using HASH_STRING_REVERSE_ITER
= ACE_Hash_Map_Reverse_Iterator_Ex
<const ACE_TCHAR
*, const ACE_TCHAR
*, ACE_Hash
<const ACE_TCHAR
*>, ACE_Equal_To
<const ACE_TCHAR
*>, ACE_Null_Mutex
>;
46 const ACE_TCHAR
*key_
;
47 const ACE_TCHAR
*value_
;
50 static String_Table string_table
[] =
54 ACE_TEXT ("guten Tag")
58 ACE_TEXT ("auf wiedersehen")
71 int test_two_allocators ()
73 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Testing both allocators\n")));
76 // Number of entries in string_table above:
78 size_t chunk_size
= sizeof (HASH_STRING_MAP::ENTRY
);
81 ACE_Dynamic_Cached_Allocator
<ACE_Null_Mutex
> table_alloc (1 , chunk_size
* chunks
);
82 ACE_Dynamic_Cached_Allocator
<ACE_Null_Mutex
> table_alloc_small (1, chunk_size
* chunks
- 1);
83 ACE_Cached_Allocator
<HASH_STRING_MAP::ENTRY
, ACE_Null_Mutex
> entry_alloc (chunks
);
85 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Testing hash map manager with %d elements...\n"), chunks
));
90 ACE_TEXT ("Opening hash map manager with ")
91 ACE_TEXT ("insufficient table allocator, should fail...\n")));
92 ACE_OS::last_error (0);
93 status
= hash
.open (chunks
, &table_alloc_small
, &entry_alloc
);
95 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("OK, failed: %d (%s)\n"),
96 status
, ACE_OS::strerror (ACE_OS::last_error ())));
98 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("*** Something is wrong...\n")), -1);
100 status
= hash
.close ();
102 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Table allocator depth: %d.\n"),
103 table_alloc
.pool_depth ()));
104 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Entry allocator depth: %d.\n"),
105 entry_alloc
.pool_depth ()));
109 ACE_TEXT ("Opening hash map manager again, should succeed...\n")));
110 ACE_OS::last_error (0);
111 status
= hash
.open (chunks
, &table_alloc
, &entry_alloc
);
113 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("*** Something is wrong: %d (%s)\n"),
114 status
, ACE_OS::strerror (ACE_OS::last_error ())), -1);
116 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("OK.\n")));
118 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Table allocator depth: %d\n"),
119 table_alloc
.pool_depth ()));
120 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Entry allocator depth: %d.\n"),
121 entry_alloc
.pool_depth ()));
123 for (size_t i
= 0; i
< chunks
; i
++)
125 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("- Binding ('%s', '%s'), should succeed...\n"),
126 string_table
[i
].key_
, string_table
[i
].value_
));
127 ACE_OS::last_error (0);
128 status
= hash
.bind (string_table
[i
].key_
, string_table
[i
].value_
);
130 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("*** Something is wrong: %d (%s)\n"),
131 status
, ACE_OS::strerror (ACE_OS::last_error ())), -1);
133 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("OK, entry allocator depth: %d\n"),
134 entry_alloc
.pool_depth ()));
137 const ACE_TCHAR
*key
= ACE_TEXT ("key");
138 const ACE_TCHAR
*val
= ACE_TEXT ("value");
140 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("- Binding ('%s', '%s'), should fail...\n"),
142 ACE_OS::last_error (0);
143 status
= hash
.bind (key
, val
);
145 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("OK, failed (%s).\n"),
146 ACE_OS::strerror (ACE_OS::last_error ())));
148 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("*** Something is wrong: %d (%s)\n"),
149 status
, ACE_OS::strerror (ACE_OS::last_error ())), -1);
151 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Closing hash map.\n")));
152 status
= hash
.close ();
154 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Table allocator depth: %d.\n"),
155 table_alloc
.pool_depth ()));
156 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Entry allocator depth: %d.\n"),
157 entry_alloc
.pool_depth ()));
165 ace_test_allocator
.dump ();
167 HASH_STRING_MAP
hash (MAX_HASH
, &ace_test_allocator
);
171 // Check the <bind> operation.
172 for (i
= 0; string_table
[i
].key_
!= 0; i
++)
173 if (hash
.bind (string_table
[i
].key_
,
174 string_table
[i
].value_
) == -1)
175 ACE_ERROR_RETURN ((LM_ERROR
,
176 ACE_TEXT ("%p failed for %s\n"),
178 string_table
[i
].key_
), -1);
180 const ACE_TCHAR
*entry
= 0;
182 // Check the <find> operation.
183 for (i
= 0; string_table
[i
].key_
!= 0; i
++)
184 if (hash
.find (string_table
[i
].key_
,
186 ACE_DEBUG ((LM_DEBUG
,
187 ACE_TEXT ("`%s' found `%s'\n"),
188 string_table
[i
].key_
,
191 ACE_ERROR_RETURN ((LM_ERROR
,
192 ACE_TEXT ("`%s' not found\n"),
193 string_table
[i
].key_
),
196 // Check the <trybind> operation.
198 const ACE_TCHAR
*pc
= string_table
[1].value_
;
199 if (hash
.trybind (string_table
[0].key_
,
201 ACE_ERROR_RETURN ((LM_ERROR
,
202 ACE_TEXT ("::trybind missed existing entry.")),
204 else if (pc
!= string_table
[0].value_
)
205 ACE_ERROR_RETURN ((LM_ERROR
,
206 ACE_TEXT ("::trybind doesn't return existing value.")),
210 // Let's test the iterator while we are at it.
212 HASH_STRING_ENTRY
*entry
= 0;
215 for (HASH_STRING_ITER
hash_iter (hash
);
216 hash_iter
.next (entry
) != 0;
217 hash_iter
.advance ())
219 ACE_DEBUG ((LM_DEBUG
,
220 ACE_TEXT ("iterating (%d): [%s, %s]\n"),
228 // And now test the const iterator
230 HASH_STRING_ENTRY
*entry
= 0;
233 for (HASH_STRING_CONST_ITER
hash_iter (hash
);
234 hash_iter
.next (entry
) != 0;
235 hash_iter
.advance ())
237 ACE_DEBUG ((LM_DEBUG
,
238 ACE_TEXT ("const iterating (%d): [%s, %s]\n"),
246 hash
.unbind (string_table
[2].key_
, entry
);
248 // Check the <find> operation again.
249 for (i
= 0; string_table
[i
].key_
!= 0; i
++)
250 if (hash
.find (string_table
[i
].key_
,
252 ACE_DEBUG ((LM_DEBUG
,
253 ACE_TEXT ("`%s' found `%s'\n"),
254 string_table
[i
].key_
,
257 ACE_ERROR_RETURN ((LM_ERROR
,
258 ACE_TEXT ("`%s' not found\n"),
259 string_table
[i
].key_
),
262 // Let's test the iterator backwards.
264 HASH_STRING_ENTRY
*entry
= 0;
267 for (HASH_STRING_REVERSE_ITER
hash_iter (hash
);
268 hash_iter
.next (entry
) != 0;
269 hash_iter
.advance ())
271 ACE_DEBUG ((LM_DEBUG
,
272 ACE_TEXT ("iterating (%d): [%s, %s]\n"),
280 // Remove all the entries.
281 if (hash
.unbind_all () != 0)
282 ACE_ERROR_RETURN ((LM_ERROR
,
283 ACE_TEXT ("unbind_all failed\n")),
286 // Redo the <bind> operations.
287 for (i
= 0; string_table
[i
].key_
!= 0; i
++)
288 if (hash
.bind (string_table
[i
].key_
,
289 string_table
[i
].value_
) != 0)
290 ACE_ERROR_RETURN ((LM_ERROR
,
291 ACE_TEXT ("%p failed for %s\n"),
293 string_table
[i
].key_
), -1);
295 ace_test_allocator
.dump ();
297 test_two_allocators();
299 // Run the STL algorithm test on the hash map.
300 const HASH_STRING_MAP
& chash
= hash
;
302 test_STL_algorithm (hash
);
303 test_STL_algorithm (chash
);
309 run_main (int, ACE_TCHAR
*[])
311 ACE_START_TEST (ACE_TEXT ("Hash_Map_Manager_Test"));