1 //=============================================================================
3 * @file Array_Map_Test.cpp
5 * Regression test for ACE_Array_Map.
7 * @author Ossama Othman
9 //=============================================================================
12 #include "test_config.h"
14 #include "ace/SString.h"
15 #include "ace/Array_Map.h"
18 //#include <map> /* For STL portability testing. */
20 static char const letters
[] =
21 { 'A', 'C', 'E', ' ', 'r', 'u', 'l', 'e', 'z', '!' };
23 static ACE_TString
const words
[] =
25 ACE_TEXT ("alpha"), // A
26 ACE_TEXT ("charlie"), // C
27 ACE_TEXT ("echo"), // E
29 ACE_TEXT ("romeo"), // r
30 ACE_TEXT ("uniform"), // u
31 ACE_TEXT ("lima"), // l
32 ACE_TEXT ("echo"), // e
33 ACE_TEXT ("zulu"), // z
37 static size_t const letters_len
= sizeof (letters
) / sizeof (letters
[0]);
38 static size_t const words_len
= sizeof (words
) / sizeof (words
[0]);
40 // --------------------------------------------------------------
43 insertion_removal_test ()
45 // Instantiate the map.
46 using Map
= ACE_Array_Map
<char, ACE_TString
>;
49 ACE_TEST_ASSERT (phonetic
[0] == phonetic
[1]); // Sanity check.
51 static size_t const phonetic_len
=
52 sizeof (phonetic
) / sizeof (phonetic
[0]);
54 unsigned int count
= 1;
56 // Test map insertion.
57 for (Map
* m
= phonetic
;
58 m
!= phonetic
+ phonetic_len
;
62 ACE_TEXT ("------------- Populating map %u -------------\n"),
66 ACE_TString
const * word
= words
;
67 for (char const * i
= letters
;
68 i
!= letters
+ letters_len
;
71 std::pair
<Map::iterator
, bool> const result
=
72 m
->insert (std::make_pair (*i
, *word
));
76 ACE_TEXT ("Inserted \"%c | %s\"\n"),
80 ACE_ERROR_RETURN ((LM_ERROR
,
81 ACE_TEXT ("Insertion of \"%c | %s\" failed.\n"),
87 ACE_TEST_ASSERT (m
->size () == letters_len
);
90 // Test equality of identically populated maps.
91 if (!(phonetic
[0] == phonetic
[1]))
93 ACE_ERROR_RETURN ((LM_ERROR
,
94 ACE_TEXT ("Equality comparison of two identical ")
95 ACE_TEXT ("maps failed.\n")),
98 else if (phonetic
[0] < phonetic
[1])
100 ACE_ERROR_RETURN ((LM_ERROR
,
101 ACE_TEXT ("Relational comparison of two identical ")
102 ACE_TEXT ("maps incorrectly passed.\n")),
106 ACE_TEST_ASSERT (!phonetic
[0].is_empty ()); // Sanity check.
108 Map
foo (phonetic
[0]); // Copy construction
109 Map bar
= foo
; // Assignment
113 ACE_ERROR_RETURN ((LM_ERROR
,
114 ACE_TEXT ("Second equality comparison of two ")
115 ACE_TEXT ("identical maps failed.\n")),
119 Map::value_type values
[letters_len
];
120 size_t const values_len
= sizeof (values
) / sizeof (values
[0]);
122 ACE_TString
const * word
= words
;
123 char const * letter
= letters
;
125 for (Map::value_type
* v
= values
;
126 v
!= values
+ values_len
;
127 ++v
, ++letter
, ++word
)
129 *v
= std::make_pair (*letter
, *word
);
132 Map
A (values
, values
+ values_len
);
136 ACE_ERROR_RETURN ((LM_ERROR
,
137 ACE_TEXT ("Third equality comparison of two ")
138 ACE_TEXT ("identical maps failed.\n")),
143 B
.insert (values
, values
+ values_len
);
147 ACE_ERROR_RETURN ((LM_ERROR
,
148 ACE_TEXT ("Fourth equality comparison of two ")
149 ACE_TEXT ("identical maps failed.\n")),
153 // ==== Removal tests ====
155 // Remove two elements from map.
156 Map::iterator letter_A
= A
.find ('A');
157 ACE_TEST_ASSERT (letter_A
== A
.begin ()); // Should be first map element.
158 ACE_TEST_ASSERT (A
.count ('A') == 1); // Should only be one letter 'A'.
161 if (A
.find ('A') != A
.end ()
162 || A
.count ('A') != 0)
164 ACE_ERROR_RETURN ((LM_ERROR
,
165 ACE_TEXT ("Letter '%c' not removed from map\n"),
170 static char const z
= 'z';
173 || A
.find (z
) != A
.end ())
175 ACE_ERROR_RETURN ((LM_ERROR
,
176 ACE_TEXT ("Letter '%c' not removed from map\n"),
182 // Remove range of letters from map.
183 static size_t const removed_len
= 3;
184 Map::iterator
const first
= B
.begin () + 2;
185 Map::iterator
const last
= first
+ removed_len
;
187 ACE_TEST_ASSERT (static_cast<Map::size_type
> (last
- first
) < B
.size ());
188 ACE_TEST_ASSERT (last
< B
.end ());
190 Map::value_type removed
[removed_len
];
192 for (Map::iterator x
= first
; x
!= last
; ++x
)
194 removed
[rcount
++] = *x
;
197 B
.erase (first
, last
);
199 for (size_t s
= 0; s
< removed_len
; ++s
)
201 Map::key_type
const key
= removed
[s
].first
;
203 if (B
.count (key
) != 0
204 || B
.find (key
) != B
.end ())
206 ACE_ERROR_RETURN ((LM_ERROR
,
207 ACE_TEXT ("Letter '%c' from range of letters ")
208 ACE_TEXT ("not removed from map\n"),
214 ACE_DEBUG ((LM_DEBUG
,
215 ACE_TEXT ("Insertion/removal test passed.\n")));
220 // --------------------------------------------------------------
223 index_operator_test ()
225 // Instantiate the map.
226 using Map
= ACE_Array_Map
<char, ACE_TString
>;
229 ACE_TEST_ASSERT (phonetic
.size () == 0 && phonetic
.is_empty ());
230 ACE_TEST_ASSERT (phonetic
.max_size () > 1);
232 // Run the same test twice, clearing the contents of the map between
233 // the iterations. The goal is to verify that the constant time
234 // clear() method performs as advertised.
235 for (unsigned int count
= 1; count
< 3; ++count
)
237 ACE_DEBUG ((LM_DEBUG
,
238 ACE_TEXT ("----- Index operator test ")
239 ACE_TEXT ("iteration %u -----\n"),
242 // Test map insertion through the index operator.
243 ACE_TString
const * word
= words
;
244 for (char const * i
= letters
;
245 i
!= letters
+ letters_len
;
248 phonetic
[*i
] = *word
;
251 ACE_TEST_ASSERT (phonetic
.size () == letters_len
);
253 using const_iterator
= Map::const_iterator
;
255 // Access the elements that were inserted into the map.
256 char const * letter
= letters
;
258 const_iterator
const last
= phonetic
.end ();
259 for (const_iterator n
= phonetic
.begin ();
261 ++n
, ++letter
, ++word
)
263 if ((*n
).first
!= *letter
|| (*n
).second
!= *word
)
264 ACE_ERROR_RETURN ((LM_ERROR
,
265 ACE_TEXT ("Key/Datum mismatch:\n")
266 ACE_TEXT (" key \"%c\" should be \"%c\"\n")
267 ACE_TEXT (" datum \"%s\" should be \"%s\"\n"),
270 (*n
).second
.c_str (),
274 ACE_DEBUG ((LM_DEBUG
,
275 ACE_TEXT ("\t%c\t%s\n"),
277 (*n
).second
.c_str ()));
280 // Now run the same test in reverse.
281 ACE_DEBUG ((LM_DEBUG
,
282 ACE_TEXT ("... in reverse ...\n")));
284 using const_reverse_iterator
= Map::const_reverse_iterator
;
286 letter
= letters
+ letters_len
- 1;
287 word
= words
+ words_len
- 1;
289 // Work around compiler / STL implementations that cannot
290 // handle implicit conversions from iterator to const_iterator
291 // (e.g. due to missing template constructor.)
293 // We don't strictly need a const Map for this test but having
294 // one allows us to exercise const iterators.
295 Map
const & const_phonetic
= phonetic
;
297 const_reverse_iterator
const rlast
= const_phonetic
.rend ();
298 for (const_reverse_iterator r
= const_phonetic
.rbegin ();
300 ++r
, --letter
, --word
)
302 if ((*r
).first
!= *letter
|| (*r
).second
!= *word
)
303 ACE_ERROR_RETURN ((LM_ERROR
,
304 ACE_TEXT ("Key/Datum mismatch:\n")
305 ACE_TEXT (" key \"%c\" should be \"%c\"\n")
306 ACE_TEXT (" datum \"%s\" should be \"%s\"\n"),
309 (*r
).second
.c_str (),
313 ACE_DEBUG ((LM_DEBUG
,
314 ACE_TEXT ("\t%c\t%s\n"),
316 (*r
).second
.c_str ()));
319 // The size should not have changed.
320 ACE_TEST_ASSERT (phonetic
.size () == letters_len
);
322 // Empty the map of its contents wholesale.
325 ACE_TEST_ASSERT (phonetic
.size () == 0 && phonetic
.is_empty ());
328 ACE_DEBUG ((LM_DEBUG
,
329 ACE_TEXT ("Index operator test passed.\n")));
334 // --------------------------------------------------------------
344 RefCounted (unsigned int * count
)
352 --(*this->refcount_
);
355 RefCounted (RefCounted
const & r
)
356 : refcount_ (r
.refcount_ptr ())
359 ++(*this->refcount_
);
363 operator= (RefCounted
const & r
)
366 std::swap (this->refcount_
, tmp
.refcount_
);
372 refcount_ptr () const
374 return this->refcount_
;
380 return *this->refcount_
;
384 unsigned int * refcount_
;
390 reference_count_test ()
392 using Map
= ACE_Array_Map
<ACE_TString
, RefCounted
>;
394 static Map::size_type
const CAPACITY
= 30;
396 unsigned int ref_count
= 1;
398 RefCounted
counted (&ref_count
);
400 ACE_TEST_ASSERT (counted
.refcount () == 1);
403 Map
map (CAPACITY
); // Preallocate storage for a number of
404 // elements even if they are not used to test
407 map
[ACE_TEXT("One")] = counted
;
409 ACE_TEST_ASSERT (counted
.refcount () == 2);
412 std::pair
<Map::iterator
, bool> result
;
415 result
= map
.insert (std::make_pair (ACE_TString (ACE_TEXT ("Two")),
418 ACE_TEST_ASSERT (result
.second
);
421 ACE_TEST_ASSERT (counted
.refcount () == 3);
424 result
= map
.insert (std::make_pair (ACE_TString (ACE_TEXT ("Three")),
427 ACE_TEST_ASSERT (result
.second
);
431 ACE_TEST_ASSERT (counted
.refcount () == 4);
433 Map::size_type
const erased
= map
.erase (ACE_TEXT ("One"));
435 ACE_TEST_ASSERT (erased
== 1);
436 ACE_TEST_ASSERT (counted
.refcount () == 3);
439 // Map instance no longer contains any references to the "counted"
440 // object so the reference count should be back to one.
442 ACE_TEST_ASSERT (counted
.refcount () == 1);
444 ACE_DEBUG ((LM_DEBUG
,
445 ACE_TEXT ("Reference count test passed.\n")));
450 // --------------------------------------------------------------
453 run_main (int, ACE_TCHAR
*[])
455 ACE_START_TEST (ACE_TEXT ("Array_Map_Test"));
457 ACE_TEST_ASSERT (::letters_len
== ::words_len
);
460 ::insertion_removal_test ()
461 && ::index_operator_test ()
462 && ::reference_count_test ();
466 return (success
? 0 : -1);