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