• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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