OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [libstdc++-v3/] [testsuite/] [util/] [exception/] [safety.h] - Blame information for rev 424

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 424 jeremybenn
// -*- C++ -*-
2
 
3
// Copyright (C) 2009, 2010 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 terms
7
// of the GNU General Public License as published by the Free Software
8
// Foundation; either version 3, or (at your option) any later
9
// version.
10
 
11
// This library is distributed in the hope that it will be useful, but
12
// WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
// 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
#ifndef _GLIBCXX_EXCEPTION_SAFETY_H
21
#define _GLIBCXX_EXCEPTION_SAFETY_H
22
 
23
#include <testsuite_container_traits.h>
24
#include <ext/throw_allocator.h>
25
 
26
// Container requirement testing.
27
namespace __gnu_test
28
{
29
  // Base class for exception testing, contains utilities.
30
  struct setup_base
31
  {
32
    typedef std::size_t                                 size_type;
33
    typedef std::uniform_int_distribution<size_type>    distribution_type;
34
    typedef std::mt19937                                engine_type;
35
 
36
    // Return randomly generated integer on range [0, __max_size].
37
    static size_type
38
    generate(size_type __max_size)
39
    {
40
      // Make the generator static...
41
      const engine_type engine;
42
      const distribution_type distribution;
43
      static auto generator = std::bind(distribution, engine,
44
                                        std::placeholders::_1);
45
 
46
      // ... but set the range for this particular invocation here.
47
      const typename distribution_type::param_type p(0, __max_size);
48
      size_type random = generator(p);
49
      if (random < distribution.min() || random > distribution.max())
50
        {
51
          std::string __s("setup_base::generate");
52
          __s += "\n";
53
          __s += "random number generated is: ";
54
          char buf[40];
55
          __builtin_sprintf(buf, "%lu", random);
56
          __s += buf;
57
          __s += " on range [";
58
          __builtin_sprintf(buf, "%lu", distribution.min());
59
          __s += buf;
60
          __s += ", ";
61
          __builtin_sprintf(buf, "%lu", distribution.max());
62
          __s += buf;
63
          __s += "]\n";
64
          std::__throw_out_of_range(__s.c_str());
65
        }
66
      return random;
67
    }
68
 
69
    // Given an instantiating type, return a unique value.
70
    template<typename _Tp>
71
      struct generate_unique
72
      {
73
        typedef _Tp value_type;
74
 
75
        operator value_type()
76
        {
77
          static value_type __ret;
78
          ++__ret;
79
          return __ret;
80
        }
81
      };
82
 
83
    // Partial specialization for pair.
84
    template<typename _Tp1, typename _Tp2>
85
      struct generate_unique<std::pair<const _Tp1, _Tp2>>
86
      {
87
        typedef _Tp1 first_type;
88
        typedef _Tp2 second_type;
89
        typedef std::pair<const _Tp1, _Tp2> pair_type;
90
 
91
        operator pair_type()
92
        {
93
          static first_type _S_1;
94
          static second_type _S_2;
95
          ++_S_1;
96
          ++_S_2;
97
          return pair_type(_S_1, _S_2);
98
        }
99
      };
100
 
101
    // Partial specialization for throw_value
102
    template<typename _Cond>
103
      struct generate_unique<__gnu_cxx::throw_value_base<_Cond>>
104
      {
105
        typedef __gnu_cxx::throw_value_base<_Cond> value_type;
106
 
107
        operator value_type()
108
        {
109
          static size_t _S_i(0);
110
          return value_type(_S_i++);
111
        }
112
      };
113
 
114
 
115
    // Construct container of size n directly. _Tp == container type.
116
    template<typename _Tp>
117
      struct make_container_base
118
      {
119
        _Tp _M_container;
120
 
121
        make_container_base() = default;
122
        make_container_base(const size_type n): _M_container(n) { }
123
 
124
        operator _Tp&() { return _M_container; }
125
      };
126
 
127
    // Construct container of size n, via multiple insertions. For
128
    // associated and unordered types, unique value_type elements are
129
    // necessary.
130
    template<typename _Tp, bool = traits<_Tp>::is_mapped::value>
131
      struct make_insert_container_base
132
      : public make_container_base<_Tp>
133
      {
134
        using make_container_base<_Tp>::_M_container;
135
        typedef typename _Tp::value_type value_type;
136
 
137
        make_insert_container_base(const size_type n)
138
        {
139
          for (size_type i = 0; i < n; ++i)
140
            {
141
              value_type v = generate_unique<value_type>();
142
              _M_container.insert(v);
143
            }
144
          assert(_M_container.size() == n);
145
        }
146
      };
147
 
148
    template<typename _Tp>
149
      struct make_insert_container_base<_Tp, false>
150
      : public make_container_base<_Tp>
151
      {
152
        using make_container_base<_Tp>::_M_container;
153
        typedef typename _Tp::value_type value_type;
154
 
155
        make_insert_container_base(const size_type n)
156
        {
157
          for (size_type i = 0; i < n; ++i)
158
            {
159
              value_type v = generate_unique<value_type>();
160
              _M_container.insert(_M_container.end(), v);
161
            }
162
          assert(_M_container.size() == n);
163
        }
164
      };
165
 
166
    template<typename _Tp, bool = traits<_Tp>::has_size_type_constructor::value>
167
      struct make_container_n;
168
 
169
    // Specialization for non-associative types that have a constructor with
170
    // a size argument.
171
    template<typename _Tp>
172
      struct make_container_n<_Tp, true>
173
      : public make_container_base<_Tp>
174
      {
175
        make_container_n(const size_type n) : make_container_base<_Tp>(n) { }
176
      };
177
 
178
    template<typename _Tp>
179
      struct make_container_n<_Tp, false>
180
      : public make_insert_container_base<_Tp>
181
      {
182
        make_container_n(const size_type n)
183
        : make_insert_container_base<_Tp>(n) { }
184
      };
185
 
186
 
187
    // Randomly size and populate a given container reference.
188
    // NB: Responsibility for turning off exceptions lies with caller.
189
    template<typename _Tp, bool = traits<_Tp>::is_allocator_aware::value>
190
      struct populate
191
      {
192
        typedef _Tp                                     container_type;
193
        typedef typename container_type::allocator_type allocator_type;
194
        typedef typename container_type::value_type     value_type;
195
 
196
        populate(_Tp& __container)
197
        {
198
          const allocator_type a = __container.get_allocator();
199
 
200
          // Size test container.
201
          const size_type max_elements = 100;
202
          size_type n = generate(max_elements);
203
 
204
          // Construct new container.
205
          make_container_n<container_type> made(n);
206
          container_type& tmp = made;
207
          std::swap(tmp, __container);
208
        }
209
      };
210
 
211
    // Partial specialization, empty.
212
    template<typename _Tp>
213
      struct populate<_Tp, false>
214
      {
215
        populate(_Tp&) { }
216
      };
217
 
218
    // Compare two containers for equivalence.
219
    // Right now, that means size.
220
    // Returns true if equal, throws if not.
221
    template<typename _Tp>
222
      static bool
223
      compare(const _Tp& __control, const _Tp& __test)
224
      {
225
        // Make sure test container is in a consistent state, as
226
        // compared to the control container.
227
        // NB: Should be equivalent to __test != __control, but
228
        // computed without equivalence operators
229
        const size_type szt = std::distance(__test.begin(), __test.end());
230
        const size_type szc = std::distance(__control.begin(),
231
                                            __control.end());
232
        bool __equal_size = szt == szc;
233
 
234
        // Should test iterator validity before and after exception.
235
        bool __equal_it = std::equal(__test.begin(), __test.end(),
236
                                     __control.begin());
237
 
238
        if (!__equal_size || !__equal_it)
239
          throw std::logic_error("setup_base::compare containers not equal");
240
 
241
        return true;
242
      }
243
  };
244
 
245
 
246
  // Containing structure holding functors.
247
  struct functor_base : public setup_base
248
  {
249
    // Abstract the erase function.
250
    template<typename _Tp>
251
      struct erase_base
252
      {
253
        typedef typename _Tp::iterator                  iterator;
254
 
255
        iterator (_Tp::* _F_erase_point)(iterator);
256
        iterator (_Tp::* _F_erase_range)(iterator, iterator);
257
 
258
        erase_base()
259
        : _F_erase_point(&_Tp::erase), _F_erase_range(&_Tp::erase) { }
260
      };
261
 
262
    // Specialization, as forward_list has erase_after.
263
    template<typename _Tp1, typename _Tp2>
264
      struct erase_base<std::forward_list<_Tp1, _Tp2>>
265
      {
266
        typedef std::forward_list<_Tp1, _Tp2>           container_type;
267
        typedef typename container_type::iterator       iterator;
268
        typedef typename container_type::const_iterator         const_iterator;
269
 
270
        void (container_type::* _F_erase_point)(const_iterator);
271
        void (container_type::* _F_erase_range)(const_iterator, const_iterator);
272
 
273
        erase_base()
274
        : _F_erase_point(&container_type::erase_after),
275
          _F_erase_range(&container_type::erase_after) { }
276
      };
277
 
278
    // Specializations for the unordered containers.
279
    template<typename _Tp1, typename _Tp2, typename _Tp3,
280
             typename _Tp4, typename _Tp5>
281
      struct erase_base<std::unordered_map<_Tp1, _Tp2, _Tp3, _Tp4, _Tp5>>
282
      {
283
        typedef std::unordered_map<_Tp1, _Tp2, _Tp3, _Tp4, _Tp5>
284
                                                        container_type;
285
        typedef typename container_type::iterator       iterator;
286
        typedef typename container_type::const_iterator const_iterator;
287
 
288
        iterator (container_type::* _F_erase_point)(const_iterator);
289
        iterator (container_type::* _F_erase_range)(const_iterator,
290
                                                    const_iterator);
291
 
292
        erase_base()
293
        : _F_erase_point(&container_type::erase),
294
          _F_erase_range(&container_type::erase) { }
295
      };
296
 
297
    template<typename _Tp1, typename _Tp2, typename _Tp3,
298
             typename _Tp4, typename _Tp5>
299
      struct erase_base<std::unordered_multimap<_Tp1, _Tp2, _Tp3,
300
                                                _Tp4, _Tp5>>
301
      {
302
        typedef std::unordered_multimap<_Tp1, _Tp2, _Tp3, _Tp4, _Tp5>
303
                                                        container_type;
304
        typedef typename container_type::iterator       iterator;
305
        typedef typename container_type::const_iterator const_iterator;
306
 
307
        iterator (container_type::* _F_erase_point)(const_iterator);
308
        iterator (container_type::* _F_erase_range)(const_iterator,
309
                                                    const_iterator);
310
 
311
        erase_base()
312
        : _F_erase_point(&container_type::erase),
313
          _F_erase_range(&container_type::erase) { }
314
      };
315
 
316
    template<typename _Tp1, typename _Tp2, typename _Tp3, typename _Tp4>
317
      struct erase_base<std::unordered_set<_Tp1, _Tp2, _Tp3, _Tp4>>
318
      {
319
        typedef std::unordered_set<_Tp1, _Tp2, _Tp3, _Tp4>
320
                                                        container_type;
321
        typedef typename container_type::iterator       iterator;
322
        typedef typename container_type::const_iterator const_iterator;
323
 
324
        iterator (container_type::* _F_erase_point)(const_iterator);
325
        iterator (container_type::* _F_erase_range)(const_iterator,
326
                                                    const_iterator);
327
 
328
        erase_base()
329
        : _F_erase_point(&container_type::erase),
330
          _F_erase_range(&container_type::erase) { }
331
      };
332
 
333
    template<typename _Tp1, typename _Tp2, typename _Tp3, typename _Tp4>
334
      struct erase_base<std::unordered_multiset<_Tp1, _Tp2, _Tp3, _Tp4>>
335
      {
336
        typedef std::unordered_multiset<_Tp1, _Tp2, _Tp3, _Tp4>
337
                                                        container_type;
338
        typedef typename container_type::iterator       iterator;
339
        typedef typename container_type::const_iterator const_iterator;
340
 
341
        iterator (container_type::* _F_erase_point)(const_iterator);
342
        iterator (container_type::* _F_erase_range)(const_iterator,
343
                                                    const_iterator);
344
 
345
        erase_base()
346
        : _F_erase_point(&container_type::erase),
347
          _F_erase_range(&container_type::erase) { }
348
      };
349
 
350
    template<typename _Tp, bool = traits<_Tp>::has_erase::value>
351
      struct erase_point : public erase_base<_Tp>
352
      {
353
        using erase_base<_Tp>::_F_erase_point;
354
 
355
        void
356
        operator()(_Tp& __container)
357
        {
358
          try
359
            {
360
              // NB: Should be equivalent to size() member function, but
361
              // computed with begin() and end().
362
              const size_type sz = std::distance(__container.begin(),
363
                                                 __container.end());
364
 
365
              // NB: Lowest common denominator: use forward iterator operations.
366
              auto i = __container.begin();
367
              std::advance(i, generate(sz));
368
 
369
              // Makes it easier to think of this as __container.erase(i)
370
              (__container.*_F_erase_point)(i);
371
            }
372
          catch(const __gnu_cxx::forced_error&)
373
            { throw; }
374
        }
375
      };
376
 
377
    // Specialization, empty.
378
    template<typename _Tp>
379
      struct erase_point<_Tp, false>
380
      {
381
        void
382
        operator()(_Tp&) { }
383
      };
384
 
385
 
386
    template<typename _Tp, bool = traits<_Tp>::has_erase::value>
387
      struct erase_range : public erase_base<_Tp>
388
      {
389
        using erase_base<_Tp>::_F_erase_range;
390
 
391
        void
392
        operator()(_Tp& __container)
393
        {
394
          try
395
            {
396
              const size_type sz = std::distance(__container.begin(),
397
                                                 __container.end());
398
              size_type s1 = generate(sz);
399
              size_type s2 = generate(sz);
400
              auto i1 = __container.begin();
401
              auto i2 = __container.begin();
402
              std::advance(i1, std::min(s1, s2));
403
              std::advance(i2, std::max(s1, s2));
404
 
405
              // Makes it easier to think of this as __container.erase(i1, i2).
406
              (__container.*_F_erase_range)(i1, i2);
407
            }
408
          catch(const __gnu_cxx::forced_error&)
409
            { throw; }
410
        }
411
      };
412
 
413
    // Specialization, empty.
414
    template<typename _Tp>
415
      struct erase_range<_Tp, false>
416
      {
417
        void
418
        operator()(_Tp&) { }
419
      };
420
 
421
 
422
    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value>
423
      struct pop_front
424
      {
425
        void
426
        operator()(_Tp& __container)
427
        {
428
          try
429
            {
430
              __container.pop_front();
431
            }
432
          catch(const __gnu_cxx::forced_error&)
433
            { throw; }
434
        }
435
      };
436
 
437
    // Specialization, empty.
438
    template<typename _Tp>
439
      struct pop_front<_Tp, false>
440
      {
441
        void
442
        operator()(_Tp&) { }
443
      };
444
 
445
 
446
    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
447
                                  && traits<_Tp>::is_reversible::value>
448
      struct pop_back
449
      {
450
        void
451
        operator()(_Tp& __container)
452
        {
453
          try
454
            {
455
              __container.pop_back();
456
            }
457
          catch(const __gnu_cxx::forced_error&)
458
            { throw; }
459
        }
460
      };
461
 
462
    // Specialization, empty.
463
    template<typename _Tp>
464
      struct pop_back<_Tp, false>
465
      {
466
        void
467
        operator()(_Tp&) { }
468
      };
469
 
470
 
471
    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value>
472
      struct push_front
473
      {
474
        typedef _Tp                                     container_type;
475
        typedef typename container_type::value_type     value_type;
476
 
477
        void
478
        operator()(_Tp& __test)
479
        {
480
          try
481
            {
482
              const value_type cv = generate_unique<value_type>();
483
              __test.push_front(cv);
484
            }
485
          catch(const __gnu_cxx::forced_error&)
486
            { throw; }
487
        }
488
 
489
        // Assumes containers start out equivalent.
490
        void
491
        operator()(_Tp& __control, _Tp& __test)
492
        {
493
          try
494
            {
495
              const value_type cv = generate_unique<value_type>();
496
              __test.push_front(cv);
497
            }
498
          catch(const __gnu_cxx::forced_error&)
499
            { throw; }
500
        }
501
    };
502
 
503
    // Specialization, empty.
504
    template<typename _Tp>
505
      struct push_front<_Tp, false>
506
      {
507
        void
508
        operator()(_Tp&) { }
509
 
510
        void
511
        operator()(_Tp&, _Tp&) { }
512
      };
513
 
514
 
515
    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
516
                                  && traits<_Tp>::is_reversible::value>
517
      struct push_back
518
      {
519
        typedef _Tp                                     container_type;
520
        typedef typename container_type::value_type     value_type;
521
 
522
        void
523
        operator()(_Tp& __test)
524
        {
525
          try
526
            {
527
              const value_type cv = generate_unique<value_type>();
528
              __test.push_back(cv);
529
            }
530
          catch(const __gnu_cxx::forced_error&)
531
            { throw; }
532
        }
533
 
534
        // Assumes containers start out equivalent.
535
        void
536
        operator()(_Tp& __control, _Tp& __test)
537
        {
538
          try
539
            {
540
              const value_type cv = generate_unique<value_type>();
541
              __test.push_back(cv);
542
            }
543
          catch(const __gnu_cxx::forced_error&)
544
            { throw; }
545
        }
546
    };
547
 
548
    // Specialization, empty.
549
    template<typename _Tp>
550
      struct push_back<_Tp, false>
551
      {
552
        void
553
        operator()(_Tp&) { }
554
 
555
        void
556
        operator()(_Tp&, _Tp&) { }
557
      };
558
 
559
 
560
    // Abstract the insert function into two parts:
561
    // 1, insert_base_functions == holds function pointer
562
    // 2, insert_base == links function pointer to class insert method
563
    template<typename _Tp>
564
      struct insert_base
565
      {
566
        typedef typename _Tp::iterator                  iterator;
567
        typedef typename _Tp::value_type                value_type;
568
 
569
        iterator (_Tp::* _F_insert_point)(iterator, const value_type&);
570
 
571
        insert_base() : _F_insert_point(&_Tp::insert) { }
572
      };
573
 
574
    // Specialization, as string insertion has a different signature.
575
    template<typename _Tp1, typename _Tp2, typename _Tp3>
576
      struct insert_base<std::basic_string<_Tp1, _Tp2, _Tp3>>
577
      {
578
        typedef std::basic_string<_Tp1, _Tp2, _Tp3>     container_type;
579
        typedef typename container_type::iterator       iterator;
580
        typedef typename container_type::value_type     value_type;
581
 
582
        iterator (container_type::* _F_insert_point)(iterator, value_type);
583
 
584
        insert_base() : _F_insert_point(&container_type::insert) { }
585
      };
586
 
587
    template<typename _Tp1, typename _Tp2, typename _Tp3,
588
             template <typename, typename, typename> class _Tp4>
589
      struct insert_base<__gnu_cxx::__versa_string<_Tp1, _Tp2, _Tp3, _Tp4>>
590
      {
591
        typedef __gnu_cxx::__versa_string<_Tp1, _Tp2, _Tp3, _Tp4>
592
                                                        container_type;
593
        typedef typename container_type::iterator       iterator;
594
        typedef typename container_type::value_type     value_type;
595
 
596
        iterator (container_type::* _F_insert_point)(iterator, value_type);
597
 
598
        insert_base() : _F_insert_point(&container_type::insert) { }
599
      };
600
 
601
    // Specialization, as forward_list insertion has a different signature.
602
    template<typename _Tp1, typename _Tp2>
603
      struct insert_base<std::forward_list<_Tp1, _Tp2>>
604
      {
605
        typedef std::forward_list<_Tp1, _Tp2> container_type;
606
        typedef typename container_type::iterator       iterator;
607
        typedef typename container_type::const_iterator const_iterator;
608
        typedef typename container_type::value_type     value_type;
609
 
610
        iterator (container_type::* _F_insert_point)(const_iterator,
611
                                                     const value_type&);
612
 
613
        insert_base() : _F_insert_point(&container_type::insert_after) { }
614
      };
615
 
616
    // Likewise for the unordered containers.
617
    template<typename _Tp1, typename _Tp2, typename _Tp3,
618
             typename _Tp4, typename _Tp5>
619
      struct insert_base<std::unordered_map<_Tp1, _Tp2, _Tp3, _Tp4, _Tp5>>
620
      {
621
        typedef std::unordered_map<_Tp1, _Tp2, _Tp3, _Tp4, _Tp5>
622
                                                        container_type;
623
        typedef typename container_type::iterator       iterator;
624
        typedef typename container_type::const_iterator const_iterator;
625
        typedef typename container_type::value_type     value_type;
626
 
627
        iterator (container_type::* _F_insert_point)(const_iterator,
628
                                                     const value_type&);
629
 
630
        insert_base() : _F_insert_point(&container_type::insert) { }
631
      };
632
 
633
    template<typename _Tp1, typename _Tp2, typename _Tp3,
634
             typename _Tp4, typename _Tp5>
635
      struct insert_base<std::unordered_multimap<_Tp1, _Tp2, _Tp3,
636
                                                 _Tp4, _Tp5>>
637
      {
638
        typedef std::unordered_multimap<_Tp1, _Tp2, _Tp3, _Tp4, _Tp5>
639
                                                        container_type;
640
        typedef typename container_type::iterator       iterator;
641
        typedef typename container_type::const_iterator const_iterator;
642
        typedef typename container_type::value_type     value_type;
643
 
644
        iterator (container_type::* _F_insert_point)(const_iterator,
645
                                                     const value_type&);
646
 
647
        insert_base() : _F_insert_point(&container_type::insert) { }
648
      };
649
 
650
    template<typename _Tp1, typename _Tp2, typename _Tp3, typename _Tp4>
651
      struct insert_base<std::unordered_set<_Tp1, _Tp2, _Tp3, _Tp4>>
652
      {
653
        typedef std::unordered_set<_Tp1, _Tp2, _Tp3, _Tp4>
654
                                                        container_type;
655
        typedef typename container_type::iterator       iterator;
656
        typedef typename container_type::const_iterator const_iterator;
657
        typedef typename container_type::value_type     value_type;
658
 
659
        iterator (container_type::* _F_insert_point)(const_iterator,
660
                                                     const value_type&);
661
 
662
        insert_base() : _F_insert_point(&container_type::insert) { }
663
      };
664
 
665
    template<typename _Tp1, typename _Tp2, typename _Tp3, typename _Tp4>
666
      struct insert_base<std::unordered_multiset<_Tp1, _Tp2, _Tp3, _Tp4>>
667
      {
668
        typedef std::unordered_multiset<_Tp1, _Tp2, _Tp3, _Tp4>
669
                                                        container_type;
670
        typedef typename container_type::iterator       iterator;
671
        typedef typename container_type::const_iterator const_iterator;
672
        typedef typename container_type::value_type     value_type;
673
 
674
        iterator (container_type::* _F_insert_point)(const_iterator,
675
                                                     const value_type&);
676
 
677
        insert_base() : _F_insert_point(&container_type::insert) { }
678
      };
679
 
680
    template<typename _Tp, bool = traits<_Tp>::has_insert::value>
681
      struct insert_point : public insert_base<_Tp>
682
      {
683
        typedef _Tp                                     container_type;
684
        typedef typename container_type::value_type     value_type;
685
        using insert_base<_Tp>::_F_insert_point;
686
 
687
        void
688
        operator()(_Tp& __test)
689
        {
690
          try
691
            {
692
              const value_type cv = generate_unique<value_type>();
693
              const size_type sz = std::distance(__test.begin(), __test.end());
694
              size_type s = generate(sz);
695
              auto i = __test.begin();
696
              std::advance(i, s);
697
              (__test.*_F_insert_point)(i, cv);
698
            }
699
          catch(const __gnu_cxx::forced_error&)
700
            { throw; }
701
        }
702
 
703
        // Assumes containers start out equivalent.
704
        void
705
        operator()(_Tp& __control, _Tp& __test)
706
        {
707
          try
708
            {
709
              const value_type cv = generate_unique<value_type>();
710
              const size_type sz = std::distance(__test.begin(), __test.end());
711
              size_type s = generate(sz);
712
              auto i = __test.begin();
713
              std::advance(i, s);
714
              (__test.*_F_insert_point)(i, cv);
715
            }
716
          catch(const __gnu_cxx::forced_error&)
717
            { throw; }
718
        }
719
      };
720
 
721
    // Specialization, empty.
722
    template<typename _Tp>
723
      struct insert_point<_Tp, false>
724
      {
725
        void
726
        operator()(_Tp&) { }
727
 
728
        void
729
        operator()(_Tp&, _Tp&) { }
730
      };
731
 
732
 
733
    template<typename _Tp, bool = traits<_Tp>::is_associative::value
734
                                  || traits<_Tp>::is_unordered::value>
735
      struct clear
736
      {
737
        void
738
        operator()(_Tp& __container)
739
        {
740
          try
741
            {
742
              __container.clear();
743
            }
744
          catch(const __gnu_cxx::forced_error&)
745
            { throw; }
746
        }
747
      };
748
 
749
    // Specialization, empty.
750
    template<typename _Tp>
751
      struct clear<_Tp, false>
752
      {
753
        void
754
        operator()(_Tp&) { }
755
      };
756
 
757
 
758
    template<typename _Tp, bool = traits<_Tp>::is_unordered::value>
759
      struct rehash
760
      {
761
        void
762
        operator()(_Tp& __test)
763
        {
764
          try
765
            {
766
              size_type s = generate(__test.bucket_count());
767
              __test.rehash(s);
768
            }
769
          catch(const __gnu_cxx::forced_error&)
770
            { throw; }
771
        }
772
 
773
        void
774
        operator()(_Tp& __control, _Tp& __test)
775
        {
776
          try
777
            {
778
              size_type s = generate(__test.bucket_count());
779
              __test.rehash(s);
780
            }
781
          catch(const __gnu_cxx::forced_error&)
782
            {
783
              // Also check hash status.
784
              bool fail(false);
785
              if (__control.load_factor() != __test.load_factor())
786
                fail = true;
787
              if (__control.max_load_factor() != __test.max_load_factor())
788
                fail = true;
789
              if (__control.bucket_count() != __test.bucket_count())
790
                fail = true;
791
              if (__control.max_bucket_count() != __test.max_bucket_count())
792
                fail = true;
793
 
794
              if (fail)
795
                {
796
                  char buf[40];
797
                  std::string __s("setup_base::rehash "
798
                                  "containers not equal");
799
                  __s += "\n";
800
                  __s += "\n";
801
                  __s += "\t\t\tcontrol : test";
802
                  __s += "\n";
803
                  __s += "load_factor\t\t";
804
                  __builtin_sprintf(buf, "%lu", __control.load_factor());
805
                  __s += buf;
806
                  __s += " : ";
807
                  __builtin_sprintf(buf, "%lu", __test.load_factor());
808
                  __s += buf;
809
                  __s += "\n";
810
 
811
                  __s += "max_load_factor\t\t";
812
                  __builtin_sprintf(buf, "%lu", __control.max_load_factor());
813
                  __s += buf;
814
                  __s += " : ";
815
                  __builtin_sprintf(buf, "%lu", __test.max_load_factor());
816
                  __s += buf;
817
                  __s += "\n";
818
 
819
                  __s += "bucket_count\t\t";
820
                  __builtin_sprintf(buf, "%lu", __control.bucket_count());
821
                  __s += buf;
822
                  __s += " : ";
823
                  __builtin_sprintf(buf, "%lu", __test.bucket_count());
824
                  __s += buf;
825
                  __s += "\n";
826
 
827
                  __s += "max_bucket_count\t";
828
                  __builtin_sprintf(buf, "%lu", __control.max_bucket_count());
829
                  __s += buf;
830
                  __s += " : ";
831
                  __builtin_sprintf(buf, "%lu", __test.max_bucket_count());
832
                  __s += buf;
833
                  __s += "\n";
834
 
835
                  std::__throw_logic_error(__s.c_str());
836
                }
837
            }
838
        }
839
      };
840
 
841
    // Specialization, empty.
842
    template<typename _Tp>
843
      struct rehash<_Tp, false>
844
      {
845
        void
846
        operator()(_Tp&) { }
847
 
848
        void
849
        operator()(_Tp&, _Tp&) { }
850
      };
851
 
852
 
853
    template<typename _Tp>
854
      struct swap
855
      {
856
        _Tp _M_other;
857
 
858
        void
859
        operator()(_Tp& __container)
860
        {
861
          try
862
            {
863
              __container.swap(_M_other);
864
            }
865
          catch(const __gnu_cxx::forced_error&)
866
            { throw; }
867
        }
868
      };
869
 
870
 
871
    template<typename _Tp>
872
      struct iterator_operations
873
      {
874
        typedef _Tp                                     container_type;
875
        typedef typename container_type::iterator       iterator;
876
 
877
        void
878
        operator()(_Tp& __container)
879
        {
880
          try
881
            {
882
              // Any will do.
883
              iterator i = __container.begin();
884
              iterator __attribute__((unused)) icopy(i);
885
              iterator __attribute__((unused)) iassign = i;
886
            }
887
          catch(const __gnu_cxx::forced_error&)
888
            { throw; }
889
        }
890
      };
891
 
892
 
893
    template<typename _Tp>
894
      struct const_iterator_operations
895
      {
896
        typedef _Tp                                     container_type;
897
        typedef typename container_type::const_iterator const_iterator;
898
 
899
        void
900
        operator()(_Tp& __container)
901
        {
902
          try
903
            {
904
              // Any will do.
905
              const_iterator i = __container.begin();
906
              const_iterator __attribute__((unused)) icopy(i);
907
              const_iterator __attribute__((unused)) iassign = i;
908
            }
909
          catch(const __gnu_cxx::forced_error&)
910
            { throw; }
911
        }
912
      };
913
  };
914
 
915
  // Base class for exception tests.
916
  template<typename _Tp>
917
    struct test_base: public functor_base
918
    {
919
      typedef _Tp                                       container_type;
920
 
921
      typedef functor_base                              base_type;
922
      typedef populate<container_type>                  populate;
923
      typedef make_container_n<container_type>          make_container_n;
924
 
925
      typedef clear<container_type>                     clear;
926
      typedef erase_point<container_type>               erase_point;
927
      typedef erase_range<container_type>               erase_range;
928
      typedef insert_point<container_type>              insert_point;
929
      typedef pop_front<container_type>                 pop_front;
930
      typedef pop_back<container_type>                  pop_back;
931
      typedef push_front<container_type>                push_front;
932
      typedef push_back<container_type>                 push_back;
933
      typedef rehash<container_type>                    rehash;
934
      typedef swap<container_type>                      swap;
935
      typedef iterator_operations<container_type>       iterator_ops;
936
      typedef const_iterator_operations<container_type> const_iterator_ops;
937
 
938
      using base_type::compare;
939
 
940
      // Functor objects.
941
      clear                     _M_clear;
942
      erase_point               _M_erasep;
943
      erase_range               _M_eraser;
944
      insert_point              _M_insertp;
945
      pop_front                 _M_popf;
946
      pop_back                  _M_popb;
947
      push_front                _M_pushf;
948
      push_back                 _M_pushb;
949
      rehash                    _M_rehash;
950
      swap                      _M_swap;
951
 
952
      iterator_ops              _M_iops;
953
      const_iterator_ops        _M_ciops;
954
    };
955
 
956
 
957
  // Run through all member functions for basic exception safety
958
  // guarantee: no resource leaks when exceptions are thrown.
959
  //
960
  // Types of resources checked: memory.
961
  //
962
  // For each member function, use throw_value and throw_allocator as
963
  // value_type and allocator_type to force potential exception safety
964
  // errors.
965
  //
966
  // NB: Assumes
967
  // _Tp::value_type is __gnu_cxx::throw_value_*
968
  // _Tp::allocator_type is __gnu_cxx::throw_allocator_*
969
  // And that the _Cond template parameter for them both is
970
  // __gnu_cxx::limit_condition.
971
  template<typename _Tp>
972
    struct basic_safety : public test_base<_Tp>
973
    {
974
      typedef _Tp                                       container_type;
975
      typedef test_base<container_type>                 base_type;
976
      typedef typename base_type::populate              populate;
977
      typedef std::function<void(container_type&)>      function_type;
978
      typedef __gnu_cxx::limit_condition                condition_type;
979
 
980
      using base_type::generate;
981
 
982
      container_type                                    _M_container;
983
      std::vector<function_type>                        _M_functions;
984
 
985
      basic_safety() { run(); }
986
 
987
      void
988
      run()
989
      {
990
        // Setup.
991
        condition_type::never_adjustor off;
992
 
993
        // Construct containers.
994
        populate p1(_M_container);
995
        populate p2(base_type::_M_swap._M_other);
996
 
997
        // Construct list of member functions to exercise.
998
        _M_functions.push_back(function_type(base_type::_M_iops));
999
        _M_functions.push_back(function_type(base_type::_M_ciops));
1000
 
1001
        _M_functions.push_back(function_type(base_type::_M_erasep));
1002
        _M_functions.push_back(function_type(base_type::_M_eraser));
1003
        _M_functions.push_back(function_type(base_type::_M_insertp));
1004
        _M_functions.push_back(function_type(base_type::_M_popf));
1005
        _M_functions.push_back(function_type(base_type::_M_popb));
1006
        _M_functions.push_back(function_type(base_type::_M_pushf));
1007
        _M_functions.push_back(function_type(base_type::_M_pushb));
1008
        _M_functions.push_back(function_type(base_type::_M_rehash));
1009
        _M_functions.push_back(function_type(base_type::_M_swap));
1010
 
1011
        // Last.
1012
        _M_functions.push_back(function_type(base_type::_M_clear));
1013
 
1014
        // Run tests.
1015
        auto i = _M_functions.begin();
1016
        for (auto i = _M_functions.begin(); i != _M_functions.end(); ++i)
1017
          {
1018
            function_type& f = *i;
1019
            run_steps_to_limit(f);
1020
          }
1021
      }
1022
 
1023
      template<typename _Funct>
1024
        void
1025
        run_steps_to_limit(const _Funct& __f)
1026
        {
1027
          size_t i(1);
1028
          bool exit(false);
1029
          auto a = _M_container.get_allocator();
1030
 
1031
          do
1032
            {
1033
              // Use the current step as an allocator label.
1034
              a.set_label(i);
1035
 
1036
              try
1037
                {
1038
                  condition_type::limit_adjustor limit(i);
1039
                  __f(_M_container);
1040
 
1041
                  // If we get here, done.
1042
                  exit = true;
1043
                }
1044
              catch(const __gnu_cxx::forced_error&)
1045
                {
1046
                  // Check this step for allocations.
1047
                  // NB: Will throw std::logic_error if allocations.
1048
                  a.check_allocated(i);
1049
 
1050
                  // Check memory allocated with operator new.
1051
 
1052
                  ++i;
1053
                }
1054
            }
1055
          while (!exit);
1056
 
1057
          // Log count info.
1058
          std::cout << __f.target_type().name() << std::endl;
1059
          std::cout << "end count " << i << std::endl;
1060
        }
1061
  };
1062
 
1063
 
1064
  // Run through all member functions with a no throw requirement, sudden death.
1065
  // all: member functions erase, pop_back, pop_front, swap
1066
  //      iterator copy ctor, assignment operator
1067
  // unordered and associative: clear
1068
  // NB: Assumes _Tp::allocator_type is __gnu_cxx::throw_allocator_random.
1069
  template<typename _Tp>
1070
    struct generation_prohibited : public test_base<_Tp>
1071
    {
1072
      typedef _Tp                                       container_type;
1073
      typedef test_base<container_type>                 base_type;
1074
      typedef typename base_type::populate              populate;
1075
      typedef __gnu_cxx::random_condition               condition_type;
1076
 
1077
      container_type                                    _M_container;
1078
 
1079
      generation_prohibited()  { run(); }
1080
 
1081
      void
1082
      run()
1083
      {
1084
        // Furthermore, assumes that the test functor will throw
1085
        // forced_exception via throw_allocator, that all errors are
1086
        // propagated and in error. Sudden death!
1087
 
1088
        // Setup.
1089
        {
1090
          condition_type::never_adjustor off;
1091
          populate p1(_M_container);
1092
          populate p2(base_type::_M_swap._M_other);
1093
        }
1094
 
1095
        // Run tests.
1096
        {
1097
          condition_type::always_adjustor on;
1098
 
1099
          // NB: Vector and deque are special, erase can throw if the copy
1100
          // constructor or assignment operator of value_type throws.
1101
          if (!traits<container_type>::has_throwing_erase::value)
1102
            {
1103
              _M_erasep(_M_container);
1104
              _M_eraser(_M_container);
1105
            }
1106
 
1107
          _M_popf(_M_container);
1108
          _M_popb(_M_container);
1109
 
1110
          _M_iops(_M_container);
1111
          _M_ciops(_M_container);
1112
 
1113
          _M_swap(_M_container);
1114
 
1115
          // Last.
1116
          _M_clear(_M_container);
1117
        }
1118
      }
1119
    };
1120
 
1121
 
1122
  // Test strong exception guarantee.
1123
  // Run through all member functions with a roll-back, consistent
1124
  // coherent requirement.
1125
  // all: member functions insert of a single element, push_back, push_front
1126
  // unordered: rehash
1127
  template<typename _Tp>
1128
    struct propagation_consistent : public test_base<_Tp>
1129
    {
1130
      typedef _Tp                                       container_type;
1131
      typedef test_base<container_type>                 base_type;
1132
      typedef typename base_type::populate              populate;
1133
      typedef std::function<void(container_type&)>      function_type;
1134
      typedef __gnu_cxx::limit_condition                condition_type;
1135
 
1136
      using base_type::compare;
1137
 
1138
      container_type                                    _M_container_test;
1139
      container_type                                    _M_container_control;
1140
      std::vector<function_type>                        _M_functions;
1141
 
1142
      propagation_consistent() { run(); }
1143
 
1144
      void
1145
      sync()
1146
      { _M_container_test = _M_container_control; }
1147
 
1148
      // Run test.
1149
      void
1150
      run()
1151
      {
1152
        // Setup.
1153
        condition_type::never_adjustor off;
1154
 
1155
        // Construct containers.
1156
        populate p(_M_container_control);
1157
        sync();
1158
 
1159
        // Construct list of member functions to exercise.
1160
        _M_functions.push_back(function_type(base_type::_M_pushf));
1161
        _M_functions.push_back(function_type(base_type::_M_pushb));
1162
        _M_functions.push_back(function_type(base_type::_M_insertp));
1163
        _M_functions.push_back(function_type(base_type::_M_rehash));
1164
 
1165
        // Run tests.
1166
        auto i = _M_functions.begin();
1167
        for (auto i = _M_functions.begin(); i != _M_functions.end(); ++i)
1168
          {
1169
            function_type& f = *i;
1170
            run_steps_to_limit(f);
1171
          }
1172
      }
1173
 
1174
      template<typename _Funct>
1175
        void
1176
        run_steps_to_limit(const _Funct& __f)
1177
        {
1178
          size_t i(1);
1179
          bool exit(false);
1180
 
1181
          do
1182
            {
1183
              sync();
1184
 
1185
              try
1186
                {
1187
                  condition_type::limit_adjustor limit(i);
1188
                  __f(_M_container_test);
1189
 
1190
                  // If we get here, done.
1191
                  exit = true;
1192
                }
1193
              catch(const __gnu_cxx::forced_error&)
1194
                {
1195
                  compare(_M_container_control, _M_container_test);
1196
                  ++i;
1197
                }
1198
            }
1199
          while (!exit);
1200
 
1201
          // Log count info.
1202
          std::cout << __f.target_type().name() << std::endl;
1203
          std::cout << "end count " << i << std::endl;
1204
        }
1205
    };
1206
 
1207
} // namespace __gnu_test
1208
 
1209
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.