1 //Has to be first for StackAllocator swap overload to be taken
2 //into account (at least using GCC 4.0.1)
3 #include "stack_allocator.h"
4
5 #include <map>
6 #include <algorithm>
7
8 #include "cppunit/cppunit_proxy.h"
9
10 #if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
11 using namespace std;
12 #endif
13
14 //
15 // TestCase class
16 //
17 class MapTest : public CPPUNIT_NS::TestCase
18 {
19 CPPUNIT_TEST_SUITE(MapTest);
20 CPPUNIT_TEST(map1);
21 CPPUNIT_TEST(mmap1);
22 CPPUNIT_TEST(mmap2);
23 CPPUNIT_TEST(iterators);
24 CPPUNIT_TEST(equal_range);
25 CPPUNIT_TEST(allocator_with_state);
26 #if !defined (STLPORT) || !defined (_STLP_USE_CONTAINERS_EXTENSION)
27 CPPUNIT_IGNORE;
28 #endif
29 CPPUNIT_TEST(template_methods);
30 CPPUNIT_TEST_SUITE_END();
31
32 protected:
33 void map1();
34 void mmap1();
35 void mmap2();
36 void iterators();
37 void equal_range();
38 void allocator_with_state();
39 void template_methods();
40 };
41
42 CPPUNIT_TEST_SUITE_REGISTRATION(MapTest);
43
44 //
45 // tests implementation
46 //
map1()47 void MapTest::map1()
48 {
49 typedef map<char, int, less<char> > maptype;
50 maptype m;
51 // Store mappings between roman numerals and decimals.
52 m['l'] = 50;
53 m['x'] = 20; // Deliberate mistake.
54 m['v'] = 5;
55 m['i'] = 1;
56 // cout << "m['x'] = " << m['x'] << endl;
57 CPPUNIT_ASSERT( m['x']== 20 );
58 m['x'] = 10; // Correct mistake.
59 CPPUNIT_ASSERT( m['x']== 10 );
60 CPPUNIT_ASSERT( m['z']== 0 );
61 //cout << "m['z'] = " << m['z'] << endl; // Note default value is added.
62 CPPUNIT_ASSERT( m.count('z') == 1 );
63 //cout << "m.count('z') = " << m.count('z') << endl;
64 pair<maptype::iterator, bool> p = m.insert(pair<const char, int>('c', 100));
65 CPPUNIT_ASSERT( p.second );
66 CPPUNIT_ASSERT( p.first != m.end() );
67 CPPUNIT_ASSERT( (*p.first).first == 'c' );
68 CPPUNIT_ASSERT( (*p.first).second == 100 );
69
70 p = m.insert(pair<const char, int>('c', 100));
71 CPPUNIT_ASSERT( !p.second ); // already existing pair
72 CPPUNIT_ASSERT( p.first != m.end() );
73 CPPUNIT_ASSERT( (*p.first).first == 'c' );
74 CPPUNIT_ASSERT( (*p.first).second == 100 );
75 }
76
mmap1()77 void MapTest::mmap1()
78 {
79 typedef multimap<char, int, less<char> > mmap;
80 mmap m;
81 CPPUNIT_ASSERT(m.count('X')==0);
82
83 m.insert(pair<const char, int>('X', 10)); // Standard way.
84 CPPUNIT_ASSERT(m.count('X')==1);
85
86 m.insert(pair<const char, int>('X', 20)); // jbuck: standard way
87 CPPUNIT_ASSERT(m.count('X')==2);
88
89 m.insert(pair<const char, int>('Y', 32)); // jbuck: standard way
90 mmap::iterator i = m.find('X'); // Find first match.
91 #ifndef _STLP_CONST
92 # define _STLP_CONST const
93 #endif
94 pair<_STLP_CONST char, int> p('X', 10);
95 CPPUNIT_ASSERT(*i == p);
96 CPPUNIT_ASSERT((*i).first == 'X');
97 CPPUNIT_ASSERT((*i).second == 10);
98 i++;
99 CPPUNIT_ASSERT((*i).first == 'X');
100 CPPUNIT_ASSERT((*i).second == 20);
101 i++;
102 CPPUNIT_ASSERT((*i).first == 'Y');
103 CPPUNIT_ASSERT((*i).second == 32);
104 i++;
105 CPPUNIT_ASSERT(i == m.end());
106
107 size_t count = m.erase('X');
108 CPPUNIT_ASSERT(count==2);
109 }
mmap2()110 void MapTest::mmap2()
111 {
112 typedef pair<const int, char> pair_type;
113
114 pair_type p1(3, 'c');
115 pair_type p2(6, 'f');
116 pair_type p3(1, 'a');
117 pair_type p4(2, 'b');
118 pair_type p5(3, 'x');
119 pair_type p6(6, 'f');
120
121 typedef multimap<int, char, less<int> > mmap;
122
123 pair_type array [] = {
124 p1,
125 p2,
126 p3,
127 p4,
128 p5,
129 p6
130 };
131
132 mmap m(array + 0, array + 6);
133 mmap::iterator i;
134 i = m.lower_bound(3);
135 CPPUNIT_ASSERT((*i).first==3);
136 CPPUNIT_ASSERT((*i).second=='c');
137
138 i = m.upper_bound(3);
139 CPPUNIT_ASSERT((*i).first==6);
140 CPPUNIT_ASSERT((*i).second=='f');
141 }
142
143
iterators()144 void MapTest::iterators()
145 {
146 typedef map<int, char, less<int> > int_map;
147 int_map imap;
148 {
149 int_map::iterator ite(imap.begin());
150 int_map::const_iterator cite(imap.begin());
151 CPPUNIT_ASSERT( ite == cite );
152 CPPUNIT_ASSERT( !(ite != cite) );
153 CPPUNIT_ASSERT( cite == ite );
154 CPPUNIT_ASSERT( !(cite != ite) );
155 }
156
157 typedef multimap<int, char, less<int> > mmap;
158 typedef mmap::value_type pair_type;
159
160 pair_type p1(3, 'c');
161 pair_type p2(6, 'f');
162 pair_type p3(1, 'a');
163 pair_type p4(2, 'b');
164 pair_type p5(3, 'x');
165 pair_type p6(6, 'f');
166
167 pair_type array [] = {
168 p1,
169 p2,
170 p3,
171 p4,
172 p5,
173 p6
174 };
175
176 mmap m(array+0, array + 6);
177
178 {
179 mmap::iterator ite(m.begin());
180 mmap::const_iterator cite(m.begin());
181 //test compare between const_iterator and iterator
182 CPPUNIT_ASSERT( ite == cite );
183 CPPUNIT_ASSERT( !(ite != cite) );
184 CPPUNIT_ASSERT( cite == ite );
185 CPPUNIT_ASSERT( !(cite != ite) );
186 }
187
188 #if 0
189 /*
190 * A check that map and multimap iterators are NOT comparable
191 * the following code should generate a compile time error
192 */
193 {
194 int_map::iterator mite(imap.begin());
195 int_map::const_iterator mcite(imap.begin());
196 mmap::iterator mmite(m.begin());
197 mmap::const_iterator mmcite(m.begin());
198 CPPUNIT_ASSERT( !(mite == mmite) );
199 CPPUNIT_ASSERT( !(mcite == mmcite) );
200 CPPUNIT_ASSERT( mite != mmite );
201 CPPUNIT_ASSERT( mcite != mmcite );
202 CPPUNIT_ASSERT( !(mite == mmcite) );
203 CPPUNIT_ASSERT( !(mite == mmcite) );
204 CPPUNIT_ASSERT( mite != mmcite );
205 CPPUNIT_ASSERT( mite != mmcite );
206 }
207
208 #endif
209
210 mmap::reverse_iterator ri = m.rbegin();
211 CPPUNIT_ASSERT( ri != m.rend() );
212 CPPUNIT_ASSERT( ri == m.rbegin() );
213 CPPUNIT_ASSERT( (*ri).first == 6 );
214 CPPUNIT_ASSERT( (*ri++).second == 'f' );
215 CPPUNIT_ASSERT( (*ri).first == 6 );
216 CPPUNIT_ASSERT( (*ri).second == 'f' );
217
218 mmap const& cm = m;
219 mmap::const_reverse_iterator rci = cm.rbegin();
220 CPPUNIT_ASSERT( rci != cm.rend() );
221 CPPUNIT_ASSERT( (*rci).first == 6 );
222 CPPUNIT_ASSERT( (*rci++).second == 'f' );
223 CPPUNIT_ASSERT( (*rci).first == 6 );
224 CPPUNIT_ASSERT( (*rci).second == 'f' );
225 }
226
equal_range()227 void MapTest::equal_range()
228 {
229 typedef map<char, int, less<char> > maptype;
230 {
231 maptype m;
232 m['x'] = 10;
233
234 pair<maptype::iterator, maptype::iterator> ret;
235 ret = m.equal_range('x');
236 CPPUNIT_ASSERT( ret.first != ret.second );
237 CPPUNIT_ASSERT( (*(ret.first)).first == 'x' );
238 CPPUNIT_ASSERT( (*(ret.first)).second == 10 );
239 CPPUNIT_ASSERT( ++(ret.first) == ret.second );
240 }
241 {
242 {
243 maptype m;
244
245 maptype::iterator i = m.lower_bound( 'x' );
246 CPPUNIT_ASSERT( i == m.end() );
247
248 i = m.upper_bound( 'x' );
249 CPPUNIT_ASSERT( i == m.end() );
250
251 pair<maptype::iterator, maptype::iterator> ret;
252 ret = m.equal_range('x');
253 CPPUNIT_ASSERT( ret.first == ret.second );
254 CPPUNIT_ASSERT( ret.first == m.end() );
255 }
256
257 {
258 const maptype m;
259 pair<maptype::const_iterator, maptype::const_iterator> ret;
260 ret = m.equal_range('x');
261 CPPUNIT_ASSERT( ret.first == ret.second );
262 CPPUNIT_ASSERT( ret.first == m.end() );
263 }
264 }
265 }
266
allocator_with_state()267 void MapTest::allocator_with_state()
268 {
269 char buf1[1024];
270 StackAllocator<pair<const int, int> > stack1(buf1, buf1 + sizeof(buf1));
271
272 char buf2[1024];
273 StackAllocator<pair<const int, int> > stack2(buf2, buf2 + sizeof(buf2));
274
275 {
276 typedef map<int, int, less<int>, StackAllocator<pair<const int, int> > > MapInt;
277 less<int> intLess;
278 MapInt mint1(intLess, stack1);
279 int i;
280 for (i = 0; i < 5; ++i)
281 mint1.insert(MapInt::value_type(i, i));
282 MapInt mint1Cpy(mint1);
283
284 MapInt mint2(intLess, stack2);
285 for (; i < 10; ++i)
286 mint2.insert(MapInt::value_type(i, i));
287 MapInt mint2Cpy(mint2);
288
289 mint1.swap(mint2);
290
291 CPPUNIT_ASSERT( mint1.get_allocator().swaped() );
292 CPPUNIT_ASSERT( mint2.get_allocator().swaped() );
293
294 CPPUNIT_ASSERT( mint1 == mint2Cpy );
295 CPPUNIT_ASSERT( mint2 == mint1Cpy );
296 CPPUNIT_ASSERT( mint1.get_allocator() == stack2 );
297 CPPUNIT_ASSERT( mint2.get_allocator() == stack1 );
298 }
299 CPPUNIT_ASSERT( stack1.ok() );
300 CPPUNIT_ASSERT( stack2.ok() );
301 }
302
303 struct Key
304 {
KeyKey305 Key() : m_data(0) {}
KeyKey306 explicit Key(int data) : m_data(data) {}
307
308 int m_data;
309 };
310
311 struct KeyCmp
312 {
operator ()KeyCmp313 bool operator () (Key lhs, Key rhs) const
314 { return lhs.m_data < rhs.m_data; }
315
operator ()KeyCmp316 bool operator () (Key lhs, int rhs) const
317 { return lhs.m_data < rhs; }
318
operator ()KeyCmp319 bool operator () (int lhs, Key rhs) const
320 { return lhs < rhs.m_data; }
321 };
322
323 struct KeyCmpPtr
324 {
operator ()KeyCmpPtr325 bool operator () (Key const volatile *lhs, Key const volatile *rhs) const
326 { return (*lhs).m_data < (*rhs).m_data; }
327
operator ()KeyCmpPtr328 bool operator () (Key const volatile *lhs, int rhs) const
329 { return (*lhs).m_data < rhs; }
330
operator ()KeyCmpPtr331 bool operator () (int lhs, Key const volatile *rhs) const
332 { return lhs < (*rhs).m_data; }
333 };
334
template_methods()335 void MapTest::template_methods()
336 {
337 #if defined (STLPORT) && defined (_STLP_USE_CONTAINERS_EXTENSION)
338 {
339 typedef map<Key, int, KeyCmp> Container;
340 typedef Container::value_type value;
341 Container cont;
342 cont.insert(value(Key(1), 1));
343 cont.insert(value(Key(2), 2));
344 cont.insert(value(Key(3), 3));
345 cont.insert(value(Key(4), 4));
346
347 CPPUNIT_ASSERT( cont.count(Key(1)) == 1 );
348 CPPUNIT_ASSERT( cont.count(1) == 1 );
349 CPPUNIT_ASSERT( cont.count(5) == 0 );
350
351 CPPUNIT_ASSERT( cont.find(2) != cont.end() );
352 CPPUNIT_ASSERT( cont.lower_bound(2) != cont.end() );
353 CPPUNIT_ASSERT( cont.upper_bound(2) != cont.end() );
354 CPPUNIT_ASSERT( cont.equal_range(2) != make_pair(cont.begin(), cont.end()) );
355
356 Container const& ccont = cont;
357 CPPUNIT_ASSERT( ccont.find(2) != ccont.end() );
358 CPPUNIT_ASSERT( ccont.lower_bound(2) != ccont.end() );
359 CPPUNIT_ASSERT( ccont.upper_bound(2) != ccont.end() );
360 CPPUNIT_ASSERT( ccont.equal_range(2) != make_pair(ccont.end(), ccont.end()) );
361 }
362
363 {
364 typedef map<Key*, int, KeyCmpPtr> Container;
365 typedef Container::value_type value;
366 Container cont;
367 Key key1(1), key2(2), key3(3), key4(4);
368 cont.insert(value(&key1, 1));
369 cont.insert(value(&key2, 2));
370 cont.insert(value(&key3, 3));
371 cont.insert(value(&key4, 4));
372
373 CPPUNIT_ASSERT( cont.count(1) == 1 );
374 CPPUNIT_ASSERT( cont.count(5) == 0 );
375
376 CPPUNIT_ASSERT( cont.find(2) != cont.end() );
377 CPPUNIT_ASSERT( cont.lower_bound(2) != cont.end() );
378 CPPUNIT_ASSERT( cont.upper_bound(2) != cont.end() );
379 CPPUNIT_ASSERT( cont.equal_range(2) != make_pair(cont.begin(), cont.end()) );
380
381 Container const& ccont = cont;
382 CPPUNIT_ASSERT( ccont.find(2) != ccont.end() );
383 CPPUNIT_ASSERT( ccont.lower_bound(2) != ccont.end() );
384 CPPUNIT_ASSERT( ccont.upper_bound(2) != ccont.end() );
385 CPPUNIT_ASSERT( ccont.equal_range(2) != make_pair(ccont.begin(), ccont.end()) );
386 }
387 {
388 typedef multimap<Key, int, KeyCmp> Container;
389 typedef Container::value_type value;
390 Container cont;
391 cont.insert(value(Key(1), 1));
392 cont.insert(value(Key(2), 2));
393 cont.insert(value(Key(3), 3));
394 cont.insert(value(Key(4), 4));
395
396 CPPUNIT_ASSERT( cont.count(Key(1)) == 1 );
397 CPPUNIT_ASSERT( cont.count(1) == 1 );
398 CPPUNIT_ASSERT( cont.count(5) == 0 );
399
400 CPPUNIT_ASSERT( cont.find(2) != cont.end() );
401 CPPUNIT_ASSERT( cont.lower_bound(2) != cont.end() );
402 CPPUNIT_ASSERT( cont.upper_bound(2) != cont.end() );
403 CPPUNIT_ASSERT( cont.equal_range(2) != make_pair(cont.begin(), cont.end()) );
404
405 Container const& ccont = cont;
406 CPPUNIT_ASSERT( ccont.find(2) != ccont.end() );
407 CPPUNIT_ASSERT( ccont.lower_bound(2) != ccont.end() );
408 CPPUNIT_ASSERT( ccont.upper_bound(2) != ccont.end() );
409 CPPUNIT_ASSERT( ccont.equal_range(2) != make_pair(ccont.end(), ccont.end()) );
410 }
411
412 {
413 typedef multimap<Key const volatile*, int, KeyCmpPtr> Container;
414 typedef Container::value_type value;
415 Container cont;
416 Key key1(1), key2(2), key3(3), key4(4);
417 cont.insert(value(&key1, 1));
418 cont.insert(value(&key2, 2));
419 cont.insert(value(&key3, 3));
420 cont.insert(value(&key4, 4));
421
422 CPPUNIT_ASSERT( cont.count(1) == 1 );
423 CPPUNIT_ASSERT( cont.count(5) == 0 );
424
425 CPPUNIT_ASSERT( cont.find(2) != cont.end() );
426 CPPUNIT_ASSERT( cont.lower_bound(2) != cont.end() );
427 CPPUNIT_ASSERT( cont.upper_bound(2) != cont.end() );
428 CPPUNIT_ASSERT( cont.equal_range(2) != make_pair(cont.begin(), cont.end()) );
429
430 Container const& ccont = cont;
431 CPPUNIT_ASSERT( ccont.find(2) != ccont.end() );
432 CPPUNIT_ASSERT( ccont.lower_bound(2) != ccont.end() );
433 CPPUNIT_ASSERT( ccont.upper_bound(2) != ccont.end() );
434 CPPUNIT_ASSERT( ccont.equal_range(2) != make_pair(ccont.begin(), ccont.end()) );
435 }
436 #endif
437 }
438
439 #if !defined (STLPORT) || \
440 !defined (_STLP_USE_PTR_SPECIALIZATIONS) || defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
441 # if !defined (__DMC__)
442 /* Simple compilation test: Check that nested types like iterator
443 * can be access even if type used to instanciate container is not
444 * yet completely defined.
445 */
446 class IncompleteClass
447 {
448 map<IncompleteClass, IncompleteClass> instances;
449 typedef map<IncompleteClass, IncompleteClass>::iterator it;
450 multimap<IncompleteClass, IncompleteClass> minstances;
451 typedef multimap<IncompleteClass, IncompleteClass>::iterator mit;
452 };
453 # endif
454 #endif
455