1// 2001-12-27 pme
2//
3// Copyright (C) 2001, 2002, 2003, 2004, 2005 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 2, 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 COPYING.  If not, write to the Free
18// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19// USA.
20
21// 23.2.1.1 deque constructors, copy, and assignment
22
23#include <deque>
24#include <iterator>
25#include <sstream>
26#include <testsuite_allocator.h>
27#include <testsuite_hooks.h>
28
29using __gnu_test::copy_tracker;
30using __gnu_test::allocation_tracker;
31using __gnu_test::tracker_alloc;
32using __gnu_test::copy_constructor;
33using __gnu_test::assignment_operator;
34using __gnu_test::counter;
35using __gnu_test::destructor;
36
37typedef std::deque<counter>   gdeque;
38
39bool test __attribute__((unused)) = true;
40
41// 23.2.1     required types
42//
43// A missing required type will cause a compile failure.
44//
45void
46requiredTypesCheck()
47{
48  typedef int             T;
49  typedef std::deque<T>   X;
50
51  typedef X::reference              reference;
52  typedef X::const_reference        const_reference;
53  typedef X::iterator               iterator;
54  typedef X::const_iterator         const_iterator;
55  typedef X::size_type              size_type;
56  typedef X::difference_type        difference_type;
57  typedef X::value_type             value_type;
58  typedef X::allocator_type         allocator_type;
59  typedef X::pointer                pointer;
60  typedef X::const_pointer          const_pointer;
61  typedef X::reverse_iterator       reverse_iterator;
62  typedef X::const_reverse_iterator const_reverse_iterator;
63}
64
65
66// @fn defaultConstructorCheck
67// Explicitly checks the default deque constructor and destructor for both
68// trivial and non-trivial types.  In addition, the size() and empty()
69// member functions are explicitly checked here since it should be their
70// first use. Checking those functions means checking the begin() and
71// end() and their const brethren functions as well.
72//
73// @verbatim
74// 23.2.1.1   default ctor/dtor
75//  effects:
76//    23.2.1.1        constructs an empty deque using the specified allocator
77//  postconditions:
78//    23.1 table 65   u.size() == 0
79//  throws:
80//  complexity:
81//    23.1 table 65   constant
82//
83// 23.2.1.2   bool empty() const
84//  semantics:
85//    23.1 table 65   a.size() == 0
86//    23.1 (7)        a.begin() == a.end()
87//  throws:
88//  complexity:
89//    23.1 table 65   constant
90//
91// 23.2.1.2   size_type size() const
92//  semantics:
93//    23.1 table 65   a.end() - a.begin()
94//  throws:
95//  complexity:
96//    23.1 table 65(A) should be constant
97//
98// 23.2.1     iterator begin()
99//            const_iterator begin() const
100//            iterator end()
101//            const_iterator end() const
102//  throws:
103//    23.1 (10) pt. 4 does not throw
104//  complexity:
105//    23.1 table 65   constant
106// @endverbatim
107void
108defaultConstructorCheckPOD()
109{
110  // setup
111  typedef int             T;
112  typedef std::deque<T>   X;
113
114  // run test
115  X u;
116
117  // assert postconditions
118  VERIFY(u.empty());
119  VERIFY(0 == u.size());
120  VERIFY(u.begin() == u.end());
121  VERIFY(0 == std::distance(u.begin(), u.end()));
122
123  // teardown
124}
125
126
127void
128defaultConstructorCheck()
129{
130  // setup
131  typedef copy_tracker  T;
132  typedef std::deque<T>     X;
133
134  copy_tracker::reset();
135
136  // run test
137  const X u;
138
139  // assert postconditions
140  VERIFY(u.empty());
141  VERIFY(0 == u.size());
142  VERIFY(u.begin() == u.end());
143  VERIFY(0 == std::distance(u.begin(), u.end()));
144
145  // teardown
146}
147
148
149// @fn copyConstructorCheck()
150// Explicitly checks the deque copy constructor.  Continues verificaton of
151// ancillary member functions documented under defaultConstructorCheck().
152//
153// This check also tests the push_back() member function.
154//
155// @verbatim
156// 23.2.1     copy constructor
157//  effects:
158//  postconditions:
159//    22.1.1 table 65 a == X(a)
160//                    u == a
161//  throws:
162//  complexity:
163//    22.1.1 table 65 linear
164// @endverbatim
165void
166copyConstructorCheck()
167{
168  // setup
169  typedef copy_tracker  T;
170  typedef std::deque<T>     X;
171
172  const std::size_t copyBaseSize = 17;  // arbitrary
173
174  X a;
175  for (std::size_t i = 0; i < copyBaseSize; ++i)
176    a.push_back(i);
177  copy_tracker::reset();
178
179  // assert preconditions
180  VERIFY(!a.empty());
181  VERIFY(copyBaseSize == a.size());
182  VERIFY(a.begin() != a.end());
183  VERIFY( copyBaseSize == static_cast<std::size_t>(std::distance(a.begin(), a.end())) );
184
185  // run test
186  X u = a;
187
188  // assert postconditions
189  VERIFY(u == a);
190  VERIFY(copyBaseSize == copy_constructor::count());
191
192  // teardown
193}
194
195
196// @fn fillConstructorCheck()
197// This test explicitly verifies the basic fill constructor.  Like the default
198// constructor, later tests depend on the fill constructor working correctly.
199// That means this explicit test should preceed the later tests so the error
200// message given on assertion failure can be more helpful n tracking the
201// problem.
202//
203// 23.2.1.1   fill constructor
204//  complexity:
205//    23.2.1.1        linear in N
206void
207fillConstructorCheck()
208{
209  // setup
210  typedef copy_tracker  T;
211  typedef std::deque<T>   X;
212
213  const X::size_type  n(23);
214  const X::value_type t(111);
215
216  copy_tracker::reset();
217
218  // run test
219  X a(n, t);
220
221  // assert postconditions
222  VERIFY(n == a.size());
223  VERIFY(n == copy_constructor::count());
224
225  // teardown
226}
227
228
229// @fn fillConstructorCheck2()
230// Explicit check for fill constructors masqueraded as range constructors as
231// elucidated in clause 23.1.1 paragraph 9 of the standard.
232//
233// 23.1.1 (9) fill constructor looking like a range constructor
234void
235fillConstructorCheck2()
236{
237  typedef copy_tracker  T;
238  typedef std::deque<T>   X;
239
240  const std::size_t f = 23;
241  const std::size_t l = 111;
242
243  copy_tracker::reset();
244
245  X a(f, l);
246
247  VERIFY(f == a.size());
248  VERIFY(f == copy_constructor::count());
249}
250
251
252// @fn rangeConstructorCheckForwardIterator()
253// This test copies from one deque to another to force the copy
254// constructor for T to be used because the compiler will kindly
255// elide copies if the default constructor can be used with
256// type conversions.  Trust me.
257//
258// 23.2.1.1   range constructor, forward iterators
259void
260rangeConstructorCheckForwardIterator()
261{
262  // setup
263  typedef copy_tracker  T;
264  typedef std::deque<T>   X;
265
266  const X::size_type  n(726);
267  const X::value_type t(307);
268  X source(n, t);
269  X::iterator i = source.begin();
270  X::iterator j = source.end();
271  X::size_type rangeSize = std::distance(i, j);
272
273  copy_tracker::reset();
274
275  // test
276  X a(i, j);
277
278  // assert postconditions
279  VERIFY(rangeSize == a.size());
280  VERIFY(copy_constructor::count() <= rangeSize);
281}
282
283
284// @fn rangeConstructorCheckInputIterator()
285// An explicit check for range construction on an input iterator
286// range, which the standard expounds upon as having a different
287// complexity than forward iterators.
288//
289// 23.2.1.1   range constructor, input iterators
290void
291rangeConstructorCheckInputIterator()
292{
293  typedef copy_tracker  T;
294  typedef std::deque<T>     X;
295
296  std::istringstream ibuf("1234567890123456789");
297  const X::size_type rangeSize = ibuf.str().size();
298  std::istream_iterator<char>  i(ibuf);
299  std::istream_iterator<char>  j;
300
301  copy_tracker::reset();
302
303  X a(i, j);
304
305  VERIFY(rangeSize == a.size());
306  VERIFY(copy_constructor::count() <= (2 * rangeSize));
307}
308
309
310// 23.2.1     copy assignment
311void
312copyAssignmentCheck()
313{
314  typedef copy_tracker  T;
315  typedef std::deque<T>     X;
316
317  const X::size_type  n(18);
318  const X::value_type t(1023);
319  X a(n, t);
320  X r;
321
322  copy_tracker::reset();
323
324  r = a;
325
326  VERIFY(r == a);
327  VERIFY(n == copy_constructor::count());
328}
329
330
331// 23.2.1.1   fill assignment
332//
333// The complexity check must check dtors+copyAssign and
334// copyCtor+copyAssign because that's the way the SGI implementation
335// works.  Dunno if it's true standard compliant (which specifies fill
336// assignment in terms of erase and insert only), but it should work
337// as (most) users expect and is more efficient.
338void
339fillAssignmentCheck()
340{
341  typedef copy_tracker  T;
342  typedef std::deque<T>   X;
343
344  const X::size_type  starting_size(10);
345  const X::value_type starting_value(66);
346  const X::size_type  n(23);
347  const X::value_type t(111);
348
349  X a(starting_size, starting_value);
350  copy_tracker::reset();
351
352  // preconditions
353  VERIFY(starting_size == a.size());
354
355  // test
356  a.assign(n, t);
357
358  // postconditions
359  VERIFY(n == a.size());
360  VERIFY(n == (copy_constructor::count() + assignment_operator::count()));
361  VERIFY(starting_size == (destructor::count() + assignment_operator::count()));
362}
363
364
365// @verbatim
366// 23.2.1     range assignment
367// 23.2.1.1   deque constructors, copy, and assignment
368//  effects:
369//  Constructs a deque equal to the range [first, last), using the
370//  specified allocator.
371//
372//      template<typename InputIterator>
373//        assign(InputIterator first, InputIterator last);
374//
375//    is equivalent to
376//
377//      erase(begin(), end());
378//      insert(begin(), first, last);
379//
380//  postconditions:
381//  throws:
382//  complexity:
383//    forward iterators: N calls to the copy constructor, 0 reallocations
384//    input iterators:   2N calls to the copy constructor, log(N) reallocations
385// @endverbatim
386void
387rangeAssignmentCheck()
388{
389  typedef copy_tracker  T;
390  typedef std::deque<T>   X;
391
392  const X::size_type  source_size(726);
393  const X::value_type source_value(307);
394  const X::size_type  starting_size(10);
395  const X::value_type starting_value(66);
396
397  X source(source_size, source_value);
398  X::iterator i = source.begin();
399  X::iterator j = source.end();
400  X::size_type rangeSize = std::distance(i, j);
401
402  X a(starting_size, starting_value);
403  VERIFY(starting_size == a.size());
404
405  copy_tracker::reset();
406
407  a.assign(i, j);
408
409  VERIFY(source == a);
410  VERIFY(rangeSize == (copy_constructor::count() + assignment_operator::count()));
411  VERIFY(starting_size == (destructor::count() + assignment_operator::count()));
412}
413
414
415// 23.1 (10)  range assignment
416// 23.2.1.3   with exception
417void
418rangeAssignmentCheckWithException()
419{
420  // setup
421  typedef copy_tracker T;
422  typedef std::deque<T>    X;
423
424  // test
425  // What does "no effects" mean?
426}
427
428
429// 23.1.1 (9) fill assignment looking like a range assignment
430void
431fillAssignmentCheck2()
432{
433  // setup
434  typedef copy_tracker T;
435  typedef std::deque<T>    X;
436
437  // test
438  // What does "no effects" mean?
439}
440
441// Verify that the default deque constructor offers the basic exception
442// guarantee.
443void
444test_default_ctor_exception_safety()
445{
446  // setup
447  typedef copy_tracker T;
448  typedef std::deque<T, tracker_alloc<T> > X;
449
450  T::reset();
451  copy_constructor::throw_on(3);
452  allocation_tracker::resetCounts();
453
454  // test
455  try
456  {
457    X a(7);
458    VERIFY( false );
459  }
460  catch (...)
461  {
462  }
463
464  // assert postconditions
465  VERIFY(allocation_tracker::allocationTotal() == allocation_tracker::deallocationTotal());
466
467  // teardown
468}
469
470// Verify that the copy constructor offers the basic exception guarantee.
471void
472test_copy_ctor_exception_safety()
473{
474  // setup
475  typedef copy_tracker T;
476  typedef std::deque<T, tracker_alloc<T> > X;
477
478  allocation_tracker::resetCounts();
479  {
480    X a(7);
481    T::reset();
482    copy_constructor::throw_on(3);
483
484
485    // test
486    try
487    {
488      X u(a);
489      VERIFY(false);
490    }
491    catch (...)
492    {
493    }
494  }
495
496  // assert postconditions
497  VERIFY(allocation_tracker::allocationTotal() == allocation_tracker::deallocationTotal());
498
499  // teardown
500}
501
502int main()
503{
504  // basic functionality and standard conformance checks
505  requiredTypesCheck();
506  defaultConstructorCheckPOD();
507  defaultConstructorCheck();
508  test_default_ctor_exception_safety();
509  copyConstructorCheck();
510  test_copy_ctor_exception_safety();
511  fillConstructorCheck();
512  fillConstructorCheck2();
513  rangeConstructorCheckInputIterator();
514  rangeConstructorCheckForwardIterator();
515  copyAssignmentCheck();
516  fillAssignmentCheck();
517  fillAssignmentCheck2();
518  rangeAssignmentCheck();
519  rangeAssignmentCheckWithException();
520  return 0;
521}
522