1// -*- C++ -*-
2// Utility subroutines for the C++ library testsuite.
3//
4// Copyright (C) 2000-2015 Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library.  This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 3, or (at your option)
10// any later version.
11//
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License along
18// with this library; see the file COPYING3.  If not see
19// <http://www.gnu.org/licenses/>.
20//
21
22// This file provides the following:
23//
24// 1)  VERIFY(), via _GLIBCXX_ASSERT, from Brent Verner <brent@rcfile.org>.
25//   This file is included in the various testsuite programs to provide
26//   #define(able) assert() behavior for debugging/testing. It may be
27//   a suitable location for other furry woodland creatures as well.
28//
29// 2)  set_memory_limits()
30//   set_memory_limits() uses setrlimit() to restrict dynamic memory
31//   allocation.  We provide a default memory limit if none is passed by the
32//   calling application.  The argument to set_memory_limits() is the
33//   limit in megabytes (a floating-point number).  If _GLIBCXX_RES_LIMITS is
34//   not #defined before including this header, then no limiting is attempted.
35//
36// 3)  object_counter
37//   This is a POD with a static data member, object_counter::count,
38//   which starts at zero, increments on instance construction, and decrements
39//   on instance destruction.  "assert_count(n)" can be called to VERIFY()
40//   that the count equals N.
41//
42// 4)  copy_tracker, from Stephen M. Webb <stephen@bregmasoft.com>.
43//   A class with nontrivial ctor/dtor that provides the ability to track the
44//   number of copy ctors and dtors, and will throw on demand during copy.
45
46#ifndef _GLIBCXX_TESTSUITE_HOOKS_H
47#define _GLIBCXX_TESTSUITE_HOOKS_H
48
49#include <bits/c++config.h>
50#include <bits/functexcept.h>
51#include <ctime>
52
53#ifdef _GLIBCXX_HAVE_SYS_STAT_H
54#include <sys/stat.h>
55#endif
56
57#ifdef _GLIBCXX_ASSERT
58# include <cassert>
59# define VERIFY(fn) assert(fn)
60#else
61# define VERIFY(fn) test &= bool(fn)
62#endif
63
64#ifdef _GLIBCXX_HAVE_UNISTD_H
65# include <unistd.h>
66#else
67# define unlink(x)
68#endif
69
70namespace __gnu_test
71{
72  // All macros are defined in GLIBCXX_CONFIGURE_TESTSUITE and imported
73  // from c++config.h
74
75  // Set memory limits if possible, if not set to 0.
76#ifndef _GLIBCXX_RES_LIMITS
77#  define MEMLIMIT_MB 0
78#else
79# ifndef MEMLIMIT_MB
80#  define MEMLIMIT_MB 16.0
81# endif
82#endif
83  extern void
84  set_memory_limits(float __size = MEMLIMIT_MB);
85
86  extern void
87  set_file_limit(unsigned long __size);
88
89  // Check mangled name demangles (using __cxa_demangle) as expected.
90  void
91  verify_demangle(const char* mangled, const char* wanted);
92
93  // Simple callback structure for variable numbers of tests (all with
94  // same signature).  Assume all unit tests are of the signature
95  // void test01();
96  class func_callback
97  {
98  public:
99    typedef void (*test_type) (void);
100
101  private:
102    int		_M_size;
103    test_type	_M_tests[15];
104
105    func_callback&
106    operator=(const func_callback&);
107
108    func_callback(const func_callback&);
109
110  public:
111    func_callback(): _M_size(0) { }
112
113    int
114    size() const { return _M_size; }
115
116    const test_type*
117    tests() const { return _M_tests; }
118
119    void
120    push_back(test_type test)
121    {
122      _M_tests[_M_size] = test;
123      ++_M_size;
124    }
125  };
126
127
128  // Run select unit tests after setting global locale.
129  void
130  run_tests_wrapped_locale(const char*, const func_callback&);
131
132  // Run select unit tests after setting environment variables.
133  void
134  run_tests_wrapped_env(const char*, const char*, const func_callback&);
135
136  // Counting.
137  struct object_counter
138  {
139    // Specifically and glaringly-obviously marked 'signed' so that
140    // when COUNT mistakenly goes negative, we can track the patterns
141    // of deletions more easily.
142    typedef  signed int     size_type;
143    static size_type   count;
144    object_counter() { ++count; }
145    object_counter (const object_counter&) { ++count; }
146    ~object_counter() { --count; }
147  };
148
149#define assert_count(n)   VERIFY(__gnu_test::object_counter::count == n)
150
151  // A (static) class for counting copy constructors and possibly throwing an
152  // exception on a desired count.
153  class copy_constructor
154  {
155  public:
156    static unsigned int
157    count() { return count_; }
158
159    static void
160    mark_call()
161    {
162      count_++;
163      if (count_ == throw_on_)
164	std::__throw_runtime_error("copy_constructor::mark_call");
165    }
166
167    static void
168    reset()
169    {
170      count_ = 0;
171      throw_on_ = 0;
172    }
173
174    static void
175    throw_on(unsigned int count) { throw_on_ = count; }
176
177  private:
178    static unsigned int count_;
179    static unsigned int throw_on_;
180  };
181
182  // A (static) class for counting assignment operator calls and
183  // possibly throwing an exception on a desired count.
184  class assignment_operator
185  {
186  public:
187    static unsigned int
188    count() { return count_; }
189
190    static void
191    mark_call()
192    {
193      count_++;
194      if (count_ == throw_on_)
195	std::__throw_runtime_error("assignment_operator::mark_call");
196    }
197
198    static void
199    reset()
200    {
201      count_ = 0;
202      throw_on_ = 0;
203    }
204
205    static void
206    throw_on(unsigned int count) { throw_on_ = count; }
207
208  private:
209    static unsigned int count_;
210    static unsigned int throw_on_;
211  };
212
213  // A (static) class for tracking calls to an object's destructor.
214  class destructor
215  {
216  public:
217    static unsigned int
218    count() { return _M_count; }
219
220    static void
221    mark_call() { _M_count++; }
222
223    static void
224    reset() { _M_count = 0; }
225
226  private:
227    static unsigned int _M_count;
228  };
229
230  // An class of objects that can be used for validating various
231  // behaviours and guarantees of containers and algorithms defined in
232  // the standard library.
233  class copy_tracker
234  {
235  public:
236    // Creates a copy-tracking object with the given ID number.  If
237    // "throw_on_copy" is set, an exception will be thrown if an
238    // attempt is made to copy this object.
239    copy_tracker(int id = next_id_--, bool throw_on_copy = false)
240    : id_(id) , throw_on_copy_(throw_on_copy) { }
241
242    // Copy-constructs the object, marking a call to the copy
243    // constructor and forcing an exception if indicated.
244    copy_tracker(const copy_tracker& rhs)
245    : id_(rhs.id()), throw_on_copy_(rhs.throw_on_copy_)
246    {
247      if (throw_on_copy_)
248	copy_constructor::throw_on(copy_constructor::count() + 1);
249      copy_constructor::mark_call();
250    }
251
252    // Assigns the value of another object to this one, tracking the
253    // number of times this member function has been called and if the
254    // other object is supposed to throw an exception when it is
255    // copied, well, make it so.
256    copy_tracker&
257    operator=(const copy_tracker& rhs)
258    {
259      id_ = rhs.id();
260      if (rhs.throw_on_copy_)
261        assignment_operator::throw_on(assignment_operator::count() + 1);
262      assignment_operator::mark_call();
263      return *this;
264    }
265
266    ~copy_tracker()
267    { destructor::mark_call(); }
268
269    int
270    id() const { return id_; }
271
272    static void
273    reset()
274    {
275      copy_constructor::reset();
276      assignment_operator::reset();
277      destructor::reset();
278    }
279
280  private:
281    int   id_;
282    const bool  throw_on_copy_;
283    static int next_id_;
284  };
285
286  inline bool
287  operator==(const copy_tracker& lhs, const copy_tracker& rhs)
288  { return lhs.id() == rhs.id(); }
289
290  inline bool
291  operator<(const copy_tracker& lhs, const copy_tracker& rhs)
292  { return lhs.id() < rhs.id(); }
293
294  // Class for checking required type conversions, implicit and
295  // explicit for given library data structures.
296  template<typename _Container>
297    struct conversion
298    {
299      typedef typename _Container::const_iterator const_iterator;
300
301      // Implicit conversion iterator to const_iterator.
302      static const_iterator
303      iterator_to_const_iterator()
304      {
305	_Container v;
306	const_iterator it = v.begin();
307	const_iterator end = v.end();
308	return it == end ? v.end() : it;
309      }
310    };
311
312  // A binary semaphore for use across multiple processes.
313  class semaphore
314  {
315  public:
316    // Creates a binary semaphore.  The semaphore is initially in the
317    // unsignaled state.
318    semaphore();
319
320    // Destroy the semaphore.
321    ~semaphore();
322
323    // Signal the semaphore.  If there are processes blocked in
324    // "wait", exactly one will be permitted to proceed.
325    void signal();
326
327    // Wait until the semaphore is signaled.
328    void wait();
329
330  private:
331    int sem_set_;
332
333    pid_t pid_;
334  };
335
336  // For use in 22_locale/time_get and time_put.
337  std::tm test_tm(int sec, int min, int hour, int mday, int mon,
338		  int year, int wday, int yday, int isdst);
339
340} // namespace __gnu_test
341
342#endif // _GLIBCXX_TESTSUITE_HOOKS_H
343
344