1 // 1999-06-29 bkoz
2 
3 // Copyright (C) 1999-2018 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING3.  If not see
18 // <http://www.gnu.org/licenses/>.
19 
20 // 23.2.4.1 vector constructors, copy, and assignment
21 
22 #include <vector>
23 #include <string>
24 #include <testsuite_allocator.h>
25 #include <testsuite_hooks.h>
26 
27 using __gnu_test::copy_tracker;
28 using __gnu_test::tracker_allocator_counter;
29 using __gnu_test::tracker_allocator;
30 using __gnu_test::copy_constructor;
31 using __gnu_test::assignment_operator;
32 
33 // @fn test_default_ctor_exception_gurantee This test verifies that if
34 // one of the vector's contained objects throws an exception from its
35 // constructor while the vector is being constructed and filled with
36 // default values, all memory is returned to the allocator whence it
37 // came.
38 void
test_default_ctor_exception_gurantee()39 test_default_ctor_exception_gurantee()
40 {
41   // setup
42   typedef copy_tracker T;
43   typedef std::vector<T, tracker_allocator<T> > X;
44 
45   copy_tracker::reset();
46   copy_constructor::throw_on(3);
47   tracker_allocator_counter::reset();
48 
49   // run test
50   try
51   {
52     T ref;
53     X a(7, ref);
54     VERIFY(false);
55   }
56   catch (...)
57   {
58   }
59 
60   // assert postconditions
61   VERIFY( tracker_allocator_counter::get_allocation_count() == tracker_allocator_counter::get_deallocation_count() );
62 
63   // teardown
64 }
65 
66 // @fn test_copy_ctor_exception_gurantee This test verifies that if
67 // one of the vector's contained objects throws an exception from its
68 // constructor while the vector is being copy constructed, all memory
69 // is returned to the allocator whence it came.
70 void
test_copy_ctor_exception_gurantee()71 test_copy_ctor_exception_gurantee()
72 {
73   // setup
74   typedef copy_tracker T;
75   typedef std::vector<T, tracker_allocator<T> > X;
76 
77   tracker_allocator_counter::reset();
78   {
79     X a(7);
80     copy_tracker::reset();
81     copy_constructor::throw_on(3);
82 
83     // run test
84     try
85     {
86       X u(a);
87       VERIFY(false);
88     }
89     catch (...)
90     {
91     }
92   }
93 
94   // assert postconditions
95   VERIFY(tracker_allocator_counter::get_allocation_count() == tracker_allocator_counter::get_deallocation_count());
96 
97   // teardown
98   copy_tracker::reset();
99   tracker_allocator_counter::reset();
100 }
101 
102 // operator=()
103 //
104 // case 1: lhs.size() > rhs.size()
105 // case 2: lhs.size() < rhs.size() < lhs.capacity()
106 // case 3: lhs.capacity() < rhs.size()
107 //
108 void
test_assignment_operator_1()109 test_assignment_operator_1()
110 {
111   // setup
112   typedef copy_tracker T;
113   typedef std::vector<T, tracker_allocator<T> > X;
114 
115   X r(9);
116   X a(r.size() - 2);
117   copy_tracker::reset();
118   tracker_allocator_counter::reset();
119 
120   // preconditions
121   VERIFY(r.size() > a.size());
122 
123   // run test
124   r = a;
125 
126   // assert postconditions
127   VERIFY(r == a);
128   VERIFY(tracker_allocator_counter::get_allocation_count() == 0);
129 
130   // teardown
131   copy_tracker::reset();
132   tracker_allocator_counter::reset();
133 }
134 
135 void
test_assignment_operator_2()136 test_assignment_operator_2()
137 {
138   // setup
139   typedef copy_tracker T;
140   typedef std::vector<T, tracker_allocator<T> > X;
141 
142   X r(1);
143   r.reserve(17);
144   X a(r.size() + 7);
145   copy_tracker::reset();
146   tracker_allocator_counter::reset();
147 
148   // preconditions
149   VERIFY(r.size() < a.size());
150   VERIFY(a.size() < r.capacity());
151 
152   // run test
153   r = a;
154 
155   // assert postconditions
156   VERIFY(r == a);
157   VERIFY(tracker_allocator_counter::get_allocation_count() == 0);
158 
159   // teardown
160   copy_tracker::reset();
161   tracker_allocator_counter::reset();
162 }
163 
164 void
test_assignment_operator_3()165 test_assignment_operator_3()
166 {
167   // setup
168   typedef copy_tracker T;
169   typedef std::vector<T, tracker_allocator<T> > X;
170 
171   tracker_allocator_counter::reset();
172   {
173     X r(1);
174     X a(r.capacity() + 7);
175     copy_tracker::reset();
176 
177     // preconditions
178     VERIFY(r.capacity() < a.size());
179 
180     // run test
181     r = a;
182 
183     // assert postconditions
184     VERIFY(r == a);
185   }
186   VERIFY(tracker_allocator_counter::get_allocation_count() == tracker_allocator_counter::get_deallocation_count());
187 
188   // teardown
189   copy_tracker::reset();
190   tracker_allocator_counter::reset();
191 }
192 
193 void
test_assignment_operator_3_exception_guarantee()194 test_assignment_operator_3_exception_guarantee()
195 {
196   // setup
197   typedef copy_tracker T;
198   typedef std::vector<T, tracker_allocator<T> > X;
199 
200   tracker_allocator_counter::reset();
201   {
202     X r(1);
203     X a(r.capacity() + 7);
204     copy_tracker::reset();
205     copy_constructor::throw_on(3);
206 
207     // preconditions
208     VERIFY(r.capacity() < a.size());
209 
210     // run test
211     try
212     {
213       r = a;
214       VERIFY(false);
215     }
216     catch (...)
217     {
218     }
219   }
220 
221   // assert postconditions
222   VERIFY(tracker_allocator_counter::get_allocation_count() == tracker_allocator_counter::get_deallocation_count());
223 
224   // teardown
225   copy_tracker::reset();
226   tracker_allocator_counter::reset();
227 }
228 
229 // fill assign()
230 //
231 // case 1: [23.2.4.1 (3)] n <= size()
232 // case 2: [23.2.4.1 (3)] size() < n <= capacity()
233 // case 3: [23.2.4.1 (3)] n > capacity()
234 // case 4: [23.2.4.1 (3)] n > capacity(), exception guarantees
235 // case 5: [23.1.1 (9)] fill assign disguised as a range assign
236 //
237 void
test_fill_assign_1()238 test_fill_assign_1()
239 {
240   // setup
241   typedef copy_tracker T;
242   typedef std::vector<T, tracker_allocator<T> > X;
243 
244   X a(7);
245   X::size_type old_size = a.size();
246   X::size_type new_size = old_size - 2;
247   const T t;
248 
249   copy_tracker::reset();
250   tracker_allocator_counter::reset();
251 
252   // run test
253   a.assign(new_size, t);
254 
255   // assert postconditions
256   VERIFY(a.size() == new_size);
257   VERIFY(tracker_allocator_counter::get_allocation_count() == 0);
258 
259   // teardown
260   copy_tracker::reset();
261   tracker_allocator_counter::reset();
262 }
263 
264 void
test_fill_assign_2()265 test_fill_assign_2()
266 {
267   // setup
268   typedef copy_tracker T;
269   typedef std::vector<T, tracker_allocator<T> > X;
270 
271   X a(7);
272   a.reserve(11);
273   X::size_type old_size     = a.size();
274   X::size_type old_capacity = a.capacity();
275   X::size_type new_size     = old_size + 2;
276   const T t;
277 
278   copy_tracker::reset();
279   tracker_allocator_counter::reset();
280 
281   // assert preconditions
282   VERIFY(old_size < new_size);
283   VERIFY(new_size <= old_capacity);
284 
285   // run test
286   a.assign(new_size, t);
287 
288   // assert postconditions
289   VERIFY(a.size() == new_size);
290   VERIFY(tracker_allocator_counter::get_allocation_count() == 0);
291 
292   // teardown
293   copy_tracker::reset();
294   tracker_allocator_counter::reset();
295 }
296 
297 void
test_fill_assign_3()298 test_fill_assign_3()
299 {
300   // setup
301   typedef copy_tracker T;
302   typedef std::vector<T, tracker_allocator<T> > X;
303 
304   tracker_allocator_counter::reset();
305   {
306     X a(7);
307     X::size_type old_capacity = a.capacity();
308     X::size_type new_size     = old_capacity + 4;
309     const T t;
310 
311     copy_tracker::reset();
312 
313     // assert preconditions
314     VERIFY(new_size > old_capacity);
315 
316     // run test
317     a.assign(new_size, t);
318 
319     // assert postconditions
320     VERIFY(a.size() == new_size);
321   }
322 
323   VERIFY(tracker_allocator_counter::get_allocation_count() > 0);
324   VERIFY(tracker_allocator_counter::get_allocation_count() == tracker_allocator_counter::get_deallocation_count());
325 
326   // teardown
327   copy_tracker::reset();
328   tracker_allocator_counter::reset();
329 }
330 
331 void
test_fill_assign_3_exception_guarantee()332 test_fill_assign_3_exception_guarantee()
333 {
334   // setup
335   typedef copy_tracker T;
336   typedef std::vector<T, tracker_allocator<T> > X;
337 
338   tracker_allocator_counter::reset();
339   {
340     X a(7);
341     X::size_type old_size     = a.size();
342     X::size_type old_capacity = a.capacity();
343     X::size_type new_size     = old_capacity + 4;
344     const T t;
345 
346     copy_tracker::reset();
347     copy_constructor::throw_on(3);
348 
349     // assert preconditions
350     VERIFY(new_size > old_capacity);
351 
352     // run test
353     try
354     {
355       a.assign(new_size, t);
356       VERIFY(false);
357     }
358     catch (...)
359     {
360     }
361 
362     // assert postconditions
363     VERIFY(a.size() == old_size);
364     VERIFY(a.capacity() == old_capacity);
365   }
366 
367   VERIFY(tracker_allocator_counter::get_allocation_count() > 0);
368   VERIFY(tracker_allocator_counter::get_allocation_count() == tracker_allocator_counter::get_deallocation_count());
369 
370   // teardown
371   copy_tracker::reset();
372   tracker_allocator_counter::reset();
373 }
374 
375 void
test_fill_assign_4()376 test_fill_assign_4()
377 {
378   // setup
379   typedef copy_tracker T;
380   typedef std::vector<T, tracker_allocator<T> > X;
381 
382   X a(7);
383   X::size_type old_size  = a.size();
384   X::size_type new_size  = old_size - 2;
385   X::size_type new_value = 117;
386 
387   copy_tracker::reset();
388   tracker_allocator_counter::reset();
389 
390   // run test
391   a.assign(new_size, new_value);
392 
393   // assert postconditions
394   VERIFY(a.size() == new_size);
395   VERIFY(tracker_allocator_counter::get_allocation_count() == 0);
396 
397   // teardown
398   copy_tracker::reset();
399   tracker_allocator_counter::reset();
400 }
401 
402 // range assign()
403 //
404 // case 1: [23.2.4.1 (2)] input iterator
405 // case 2: [23.2.4.1 (2)] forward iterator, distance(first, last) <= size()
406 // case 3: [23.2.4.1 (2)]
407 //         forward iterator, size() < distance(first, last) <= capacity()
408 // case 4: [23.2.4.1 (2)] forward iterator, distance(first, last) > capacity()
409 // case 5: [23.2.4.1 (2)]
410 //         forward iterator, distance(first, last) > capacity(),
411 //         exception guarantees
412 void
test_range_assign_1()413 test_range_assign_1()
414 {
415   // @TODO
416 }
417 
418 void
test_range_assign_2()419 test_range_assign_2()
420 {
421   // setup
422   typedef copy_tracker T;
423   typedef std::vector<T, tracker_allocator<T> > X;
424 
425   X a(7);
426   X b(3);
427 
428   copy_tracker::reset();
429   tracker_allocator_counter::reset();
430 
431   // assert preconditions
432   VERIFY(b.size() < a.capacity());
433 
434   // run test
435   a.assign(b.begin(), b.end());
436 
437   // assert postconditions
438   VERIFY(a.size() == b.size());
439   VERIFY(a == b);
440   VERIFY(tracker_allocator_counter::get_allocation_count() == 0);
441 
442   // teardown
443   copy_tracker::reset();
444   tracker_allocator_counter::reset();
445 }
446 
447 void
test_range_assign_3()448 test_range_assign_3()
449 {
450   // setup
451   typedef copy_tracker T;
452   typedef std::vector<T, tracker_allocator<T> > X;
453 
454   X a(7);
455   a.reserve(a.size() + 7);
456   X b(a.size() + 3);
457 
458   copy_tracker::reset();
459   tracker_allocator_counter::reset();
460 
461   // assert preconditions
462   VERIFY(a.size() < b.size());
463   VERIFY(b.size() < a.capacity());
464 
465   // run test
466   a.assign(b.begin(), b.end());
467 
468   // assert postconditions
469   VERIFY(a.size() == b.size());
470   VERIFY(a == b);
471   VERIFY(tracker_allocator_counter::get_allocation_count() == 0);
472 
473   // teardown
474   copy_tracker::reset();
475   tracker_allocator_counter::reset();
476 }
477 
478 void
test_range_assign_4()479 test_range_assign_4()
480 {
481   // setup
482   typedef copy_tracker T;
483   typedef std::vector<T, tracker_allocator<T> > X;
484 
485   tracker_allocator_counter::reset();
486   {
487     X a(7);
488     X b(a.capacity() + 7);
489 
490     copy_tracker::reset();
491 
492     // assert preconditions
493     VERIFY(b.size() > a.capacity());
494 
495     // run test
496     a.assign(b.begin(), b.end());
497 
498     // assert postconditions
499     VERIFY(a.size() == b.size());
500     VERIFY(a == b);
501   }
502   VERIFY(tracker_allocator_counter::get_allocation_count() > 0);
503   VERIFY(tracker_allocator_counter::get_allocation_count() == tracker_allocator_counter::get_deallocation_count());
504 
505   // teardown
506   copy_tracker::reset();
507   tracker_allocator_counter::reset();
508 }
509 
510 void
test_range_assign_4_exception_guarantee()511 test_range_assign_4_exception_guarantee()
512 {
513   // setup
514   typedef copy_tracker T;
515   typedef std::vector<T, tracker_allocator<T> > X;
516 
517   tracker_allocator_counter::reset();
518   {
519     X a(7);
520     X b(a.capacity() + 7);
521 
522     copy_tracker::reset();
523     copy_constructor::throw_on(3);
524 
525     // assert preconditions
526     VERIFY(b.size() > a.capacity());
527 
528     // run test
529     try
530     {
531       a.assign(b.begin(), b.end());
532       VERIFY(false);
533     }
534     catch (...)
535     {
536     }
537   }
538 
539   // assert postconditions
540   VERIFY(tracker_allocator_counter::get_allocation_count() > 0);
541   VERIFY(tracker_allocator_counter::get_allocation_count() == tracker_allocator_counter::get_deallocation_count());
542 
543   // teardown
544   copy_tracker::reset();
545   tracker_allocator_counter::reset();
546 }
547 
548 
main()549 int main()
550 {
551   test_default_ctor_exception_gurantee();
552   test_copy_ctor_exception_gurantee();
553   test_assignment_operator_1();
554   test_assignment_operator_2();
555   test_assignment_operator_3();
556   test_assignment_operator_3_exception_guarantee();
557   test_fill_assign_1();
558   test_fill_assign_2();
559   test_fill_assign_3();
560   test_fill_assign_3_exception_guarantee();
561   test_fill_assign_4();
562   test_range_assign_1();
563   test_range_assign_2();
564   test_range_assign_3();
565   test_range_assign_4();
566   test_range_assign_4_exception_guarantee();
567 
568   return 0;
569 }
570