Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / tests / Array_Map_Test.cpp
blob725814d7f33316cc361cd125abe907826b2c71bf
1 //=============================================================================
2 /**
3 * @file Array_Map_Test.cpp
5 * Regression test for ACE_Array_Map.
7 * @author Ossama Othman
8 */
9 //=============================================================================
12 #include "test_config.h"
14 #include "ace/SString.h"
15 #include "ace/Array_Map.h"
17 #include <algorithm>
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
28 ACE_TEXT (" "), //
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
34 ACE_TEXT ("!") // !
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 // --------------------------------------------------------------
42 bool
43 insertion_removal_test ()
45 // Instantiate the map.
46 using Map = ACE_Array_Map<char, ACE_TString>;
47 Map phonetic[2];
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;
59 ++m, ++count)
61 ACE_DEBUG ((LM_DEBUG,
62 ACE_TEXT ("------------- Populating map %u -------------\n"),
63 count));
66 ACE_TString const * word = words;
67 for (char const * i = letters;
68 i != letters + letters_len;
69 ++i, ++word)
71 std::pair<Map::iterator, bool> const result =
72 m->insert (std::make_pair (*i, *word));
74 if (result.second)
75 ACE_DEBUG ((LM_DEBUG,
76 ACE_TEXT ("Inserted \"%c | %s\"\n"),
77 *i,
78 word->c_str ()));
79 else
80 ACE_ERROR_RETURN ((LM_ERROR,
81 ACE_TEXT ("Insertion of \"%c | %s\" failed.\n"),
82 *i,
83 word->c_str ()),
84 false);
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")),
96 false);
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")),
103 false);
106 ACE_TEST_ASSERT (!phonetic[0].is_empty ()); // Sanity check.
108 Map foo (phonetic[0]); // Copy construction
109 Map bar = foo; // Assignment
111 if (!(foo == bar))
113 ACE_ERROR_RETURN ((LM_ERROR,
114 ACE_TEXT ("Second equality comparison of two ")
115 ACE_TEXT ("identical maps failed.\n")),
116 false);
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);
134 if (!(A == bar))
136 ACE_ERROR_RETURN ((LM_ERROR,
137 ACE_TEXT ("Third equality comparison of two ")
138 ACE_TEXT ("identical maps failed.\n")),
139 false);
142 Map B;
143 B.insert (values, values + values_len);
145 if (!(A == B))
147 ACE_ERROR_RETURN ((LM_ERROR,
148 ACE_TEXT ("Fourth equality comparison of two ")
149 ACE_TEXT ("identical maps failed.\n")),
150 false);
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'.
160 A.erase (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"),
166 (*letter_A).first),
167 false);
170 static char const z = 'z';
171 if (A.erase (z) != 1
172 || A.count (z) != 0
173 || A.find (z) != A.end ())
175 ACE_ERROR_RETURN ((LM_ERROR,
176 ACE_TEXT ("Letter '%c' not removed from map\n"),
178 false);
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];
191 size_t rcount = 0;
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"),
209 key),
210 false);
214 ACE_DEBUG ((LM_DEBUG,
215 ACE_TEXT ("Insertion/removal test passed.\n")));
217 return true;
220 // --------------------------------------------------------------
222 bool
223 index_operator_test ()
225 // Instantiate the map.
226 using Map = ACE_Array_Map<char, ACE_TString>;
227 Map phonetic;
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"),
240 count));
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;
246 ++i, ++word)
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;
257 word = words;
258 const_iterator const last = phonetic.end ();
259 for (const_iterator n = phonetic.begin ();
260 n != last;
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"),
268 (*n).first,
269 *letter,
270 (*n).second.c_str (),
271 word->c_str ()),
272 false);
274 ACE_DEBUG ((LM_DEBUG,
275 ACE_TEXT ("\t%c\t%s\n"),
276 (*n).first,
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 ();
299 (r != rlast);
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"),
307 (*r).first,
308 *letter,
309 (*r).second.c_str (),
310 word->c_str ()),
311 false);
313 ACE_DEBUG ((LM_DEBUG,
314 ACE_TEXT ("\t%c\t%s\n"),
315 (*r).first,
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.
323 phonetic.clear ();
325 ACE_TEST_ASSERT (phonetic.size () == 0 && phonetic.is_empty ());
328 ACE_DEBUG ((LM_DEBUG,
329 ACE_TEXT ("Index operator test passed.\n")));
331 return true;
334 // --------------------------------------------------------------
336 class RefCounted
338 public:
339 RefCounted ()
340 : refcount_ (0)
344 RefCounted (unsigned int * count)
345 : refcount_ (count)
349 ~RefCounted ()
351 if (this->refcount_)
352 --(*this->refcount_);
355 RefCounted (RefCounted const & r)
356 : refcount_ (r.refcount_ptr ())
358 if (this->refcount_)
359 ++(*this->refcount_);
362 RefCounted &
363 operator= (RefCounted const & r)
365 RefCounted tmp (r);
366 std::swap (this->refcount_, tmp.refcount_);
368 return *this;
371 unsigned int *
372 refcount_ptr () const
374 return this->refcount_;
377 unsigned int
378 refcount () const
380 return *this->refcount_;
383 private:
384 unsigned int * refcount_;
387 // --------
389 bool
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
405 // some internals.
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")),
416 counted));
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")),
425 counted));
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")));
447 return true;
450 // --------------------------------------------------------------
453 run_main (int, ACE_TCHAR *[])
455 ACE_START_TEST (ACE_TEXT ("Array_Map_Test"));
457 ACE_TEST_ASSERT (::letters_len == ::words_len);
459 bool const success =
460 ::insertion_removal_test ()
461 && ::index_operator_test ()
462 && ::reference_count_test ();
464 ACE_END_TEST;
466 return (success ? 0 : -1);