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 <deque>
6 #include <algorithm>
7 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
8 # include <stdexcept>
9 #endif
10
11 #include "cppunit/cppunit_proxy.h"
12
13 #if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
14 using namespace std;
15 #endif
16
17 //
18 // TestCase class
19 //
20 class DequeTest : public CPPUNIT_NS::TestCase
21 {
22 CPPUNIT_TEST_SUITE(DequeTest);
23 CPPUNIT_TEST(deque1);
24 CPPUNIT_TEST(at);
25 CPPUNIT_TEST(insert);
26 CPPUNIT_TEST(erase);
27 CPPUNIT_TEST(auto_ref);
28 CPPUNIT_TEST(allocator_with_state);
29 #if defined (STLPORT) && defined (_STLP_NO_MEMBER_TEMPLATES)
30 CPPUNIT_IGNORE;
31 #endif
32 CPPUNIT_TEST(optimizations_check);
33 CPPUNIT_TEST_SUITE_END();
34
35 protected:
36 void deque1();
37 void insert();
38 void erase();
39 void at();
40 void auto_ref();
41 void allocator_with_state();
42 void optimizations_check();
43 };
44
45 CPPUNIT_TEST_SUITE_REGISTRATION(DequeTest);
46
47 //
48 // tests implementation
49 //
deque1()50 void DequeTest::deque1()
51 {
52 deque<int> d;
53 d.push_back(4);
54 d.push_back(9);
55 d.push_back(16);
56 d.push_front(1);
57
58 CPPUNIT_ASSERT( d[0] == 1 );
59 CPPUNIT_ASSERT( d[1] == 4 );
60 CPPUNIT_ASSERT( d[2] == 9 );
61 CPPUNIT_ASSERT( d[3] == 16 );
62
63 d.pop_front();
64 d[2] = 25;
65
66 CPPUNIT_ASSERT( d[0] == 4 );
67 CPPUNIT_ASSERT( d[1] == 9 );
68 CPPUNIT_ASSERT( d[2] == 25 );
69
70 //Some compile time tests:
71 deque<int>::iterator dit = d.begin();
72 deque<int>::const_iterator cdit(d.begin());
73 CPPUNIT_ASSERT( (dit - cdit) == 0 );
74 CPPUNIT_ASSERT( (cdit - dit) == 0 );
75 CPPUNIT_ASSERT( (dit - dit) == 0 );
76 CPPUNIT_ASSERT( (cdit - cdit) == 0 );
77 CPPUNIT_ASSERT(!((dit < cdit) || (dit > cdit) || (dit != cdit) || !(dit <= cdit) || !(dit >= cdit)));
78 }
79
insert()80 void DequeTest::insert()
81 {
82 deque<int> d;
83 d.push_back(0);
84 d.push_back(1);
85 d.push_back(2);
86 CPPUNIT_ASSERT( d.size() == 3 );
87
88 deque<int>::iterator dit;
89
90 //Insertion before begin:
91 dit = d.insert(d.begin(), 3);
92 CPPUNIT_ASSERT( dit != d.end() );
93 CPPUNIT_CHECK( *dit == 3 );
94 CPPUNIT_ASSERT( d.size() == 4 );
95 CPPUNIT_ASSERT( d[0] == 3 );
96
97 //Insertion after begin:
98 dit = d.insert(d.begin() + 1, 4);
99 CPPUNIT_ASSERT( dit != d.end() );
100 CPPUNIT_CHECK( *dit == 4 );
101 CPPUNIT_ASSERT( d.size() == 5 );
102 CPPUNIT_ASSERT( d[1] == 4 );
103
104 //Insertion at end:
105 dit = d.insert(d.end(), 5);
106 CPPUNIT_ASSERT( dit != d.end() );
107 CPPUNIT_CHECK( *dit == 5 );
108 CPPUNIT_ASSERT( d.size() == 6 );
109 CPPUNIT_ASSERT( d[5] == 5 );
110
111 //Insertion before last element:
112 dit = d.insert(d.end() - 1, 6);
113 CPPUNIT_ASSERT( dit != d.end() );
114 CPPUNIT_CHECK( *dit == 6 );
115 CPPUNIT_ASSERT( d.size() == 7 );
116 CPPUNIT_ASSERT( d[5] == 6 );
117
118 //Insertion of several elements before begin
119 d.insert(d.begin(), 2, 7);
120 CPPUNIT_ASSERT( d.size() == 9 );
121 CPPUNIT_ASSERT( d[0] == 7 );
122 CPPUNIT_ASSERT( d[1] == 7 );
123
124 //Insertion of several elements after begin
125 //There is more elements to insert than elements before insertion position
126 d.insert(d.begin() + 1, 2, 8);
127 CPPUNIT_ASSERT( d.size() == 11 );
128 CPPUNIT_ASSERT( d[1] == 8 );
129 CPPUNIT_ASSERT( d[2] == 8 );
130
131 //There is less elements to insert than elements before insertion position
132 d.insert(d.begin() + 3, 2, 9);
133 CPPUNIT_ASSERT( d.size() == 13 );
134 CPPUNIT_ASSERT( d[3] == 9 );
135 CPPUNIT_ASSERT( d[4] == 9 );
136
137 //Insertion of several elements at end:
138 d.insert(d.end(), 2, 10);
139 CPPUNIT_ASSERT( d.size() == 15 );
140 CPPUNIT_ASSERT( d[14] == 10 );
141 CPPUNIT_ASSERT( d[13] == 10 );
142
143 //Insertion of several elements before last:
144 //There is more elements to insert than elements after insertion position
145 d.insert(d.end() - 1, 2, 11);
146 CPPUNIT_ASSERT( d.size() == 17 );
147 CPPUNIT_ASSERT( d[15] == 11 );
148 CPPUNIT_ASSERT( d[14] == 11 );
149
150 //There is less elements to insert than elements after insertion position
151 d.insert(d.end() - 3, 2, 12);
152 CPPUNIT_ASSERT( d.size() == 19 );
153 CPPUNIT_ASSERT( d[15] == 12 );
154 CPPUNIT_ASSERT( d[14] == 12 );
155 }
156
at()157 void DequeTest::at() {
158 deque<int> d;
159 deque<int> const& cd = d;
160
161 d.push_back(10);
162 CPPUNIT_ASSERT( d.at(0) == 10 );
163 d.at(0) = 20;
164 CPPUNIT_ASSERT( cd.at(0) == 20 );
165
166 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
167 for (;;) {
168 try {
169 d.at(1) = 20;
170 CPPUNIT_ASSERT(false);
171 }
172 catch (out_of_range const&) {
173 return;
174 }
175 catch (...) {
176 CPPUNIT_ASSERT(false);
177 }
178 }
179 #endif
180 }
181
auto_ref()182 void DequeTest::auto_ref()
183 {
184 int i;
185 deque<int> ref;
186 for (i = 0; i < 5; ++i) {
187 ref.push_back(i);
188 }
189
190 deque<deque<int> > d_d_int(1, ref);
191 d_d_int.push_back(d_d_int[0]);
192 d_d_int.push_back(ref);
193 d_d_int.push_back(d_d_int[0]);
194 d_d_int.push_back(d_d_int[0]);
195 d_d_int.push_back(ref);
196
197 for (i = 0; i < 5; ++i) {
198 CPPUNIT_ASSERT( d_d_int[i] == ref );
199 }
200 }
201
allocator_with_state()202 void DequeTest::allocator_with_state()
203 {
204 char buf1[1024];
205 StackAllocator<int> stack1(buf1, buf1 + sizeof(buf1));
206
207 char buf2[1024];
208 StackAllocator<int> stack2(buf2, buf2 + sizeof(buf2));
209
210 {
211 typedef deque<int, StackAllocator<int> > DequeInt;
212 DequeInt dint1(10, 0, stack1);
213 DequeInt dint1Cpy(dint1);
214
215 DequeInt dint2(10, 1, stack2);
216 DequeInt dint2Cpy(dint2);
217
218 dint1.swap(dint2);
219
220 CPPUNIT_ASSERT( dint1.get_allocator().swaped() );
221 CPPUNIT_ASSERT( dint2.get_allocator().swaped() );
222
223 CPPUNIT_ASSERT( dint1 == dint2Cpy );
224 CPPUNIT_ASSERT( dint2 == dint1Cpy );
225 CPPUNIT_ASSERT( dint1.get_allocator() == stack2 );
226 CPPUNIT_ASSERT( dint2.get_allocator() == stack1 );
227 }
228 CPPUNIT_ASSERT( stack1.ok() );
229 CPPUNIT_ASSERT( stack2.ok() );
230 }
231
232 struct Point {
233 int x, y;
234 };
235
236 struct PointEx : public Point {
PointExPointEx237 PointEx() : builtFromBase(false) {}
PointExPointEx238 PointEx(const Point&) : builtFromBase(true) {}
239
240 bool builtFromBase;
241 };
242
243 #if defined (STLPORT)
244 # if defined (_STLP_USE_NAMESPACES)
245 namespace std {
246 # endif
247 _STLP_TEMPLATE_NULL
248 struct __type_traits<PointEx> {
249 typedef __false_type has_trivial_default_constructor;
250 typedef __true_type has_trivial_copy_constructor;
251 typedef __true_type has_trivial_assignment_operator;
252 typedef __true_type has_trivial_destructor;
253 typedef __true_type is_POD_type;
254 };
255 # if defined (_STLP_USE_NAMESPACES)
256 }
257 # endif
258 #endif
259
260 //This test check that deque implementation do not over optimize
261 //operation as PointEx copy constructor is trivial
optimizations_check()262 void DequeTest::optimizations_check()
263 {
264 #if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES)
265 deque<Point> d1(1);
266 CPPUNIT_ASSERT( d1.size() == 1 );
267
268 deque<PointEx> d2(d1.begin(), d1.end());
269 CPPUNIT_ASSERT( d2.size() == 1 );
270 CPPUNIT_ASSERT( d2[0].builtFromBase == true );
271
272 d2.insert(d2.end(), d1.begin(), d1.end());
273 CPPUNIT_ASSERT( d2.size() == 2 );
274 CPPUNIT_ASSERT( d2[1].builtFromBase == true );
275 #endif
276 }
277
erase()278 void DequeTest::erase()
279 {
280 deque<int> dint;
281 dint.push_back(3);
282 dint.push_front(2);
283 dint.push_back(4);
284 dint.push_front(1);
285 dint.push_back(5);
286 dint.push_front(0);
287 dint.push_back(6);
288
289 deque<int>::iterator it(dint.begin() + 1);
290 CPPUNIT_ASSERT( *it == 1 );
291
292 dint.erase(dint.begin());
293 CPPUNIT_ASSERT( *it == 1 );
294
295 it = dint.end() - 2;
296 CPPUNIT_ASSERT( *it == 5 );
297
298 dint.erase(dint.end() - 1);
299 CPPUNIT_ASSERT( *it == 5 );
300
301 dint.push_back(6);
302 dint.push_front(0);
303
304 it = dint.begin() + 2;
305 CPPUNIT_ASSERT( *it == 2 );
306
307 dint.erase(dint.begin(), dint.begin() + 2);
308 CPPUNIT_ASSERT( *it == 2 );
309
310 it = dint.end() - 3;
311 CPPUNIT_ASSERT( *it == 4 );
312
313 dint.erase(dint.end() - 2, dint.end());
314 CPPUNIT_ASSERT( *it == 4 );
315 }
316
317 #if (!defined (STLPORT) || \
318 (!defined (_STLP_USE_PTR_SPECIALIZATIONS) || defined (_STLP_CLASS_PARTIAL_SPECIALIZATION))) && \
319 (!defined (_MSC_VER) || (_MSC_VER > 1400)) && \
320 (!defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC_MINOR__ < 3))
321 /* Simple compilation test: Check that nested types like iterator
322 * can be access even if type used to instanciate container is not
323 * yet completely defined.
324 */
325 class IncompleteClass
326 {
327 deque<IncompleteClass> instances;
328 typedef deque<IncompleteClass>::size_type size;
329 };
330 #endif
331