]>
Commit | Line | Data |
---|---|---|
8d59b230 BK |
1 | // -*- C++ -*- |
2 | // Utility subroutines for the C++ library testsuite. | |
fe413112 | 3 | // |
261e5b9e | 4 | // Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. |
fe413112 PE |
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 2, 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 COPYING. If not, write to the Free | |
19 | // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
20 | // USA. | |
21 | // | |
22 | // As a special exception, you may use this file as part of a free software | |
23 | // library without restriction. Specifically, if other files instantiate | |
24 | // templates or use macros or inline functions from this file, or you compile | |
25 | // this file and link it with other files to produce an executable, this | |
26 | // file does not by itself cause the resulting executable to be covered by | |
27 | // the GNU General Public License. This exception does not however | |
28 | // invalidate any other reasons why the executable file might be covered by | |
29 | // the GNU General Public License. | |
30 | ||
31 | // This file provides the following: | |
32 | // | |
cb584bcf | 33 | // 1) VERIFY(), via _GLIBCXX_ASSERT, from Brent Verner <brent@rcfile.org>. |
fe413112 PE |
34 | // This file is included in the various testsuite programs to provide |
35 | // #define(able) assert() behavior for debugging/testing. It may be | |
36 | // a suitable location for other furry woodland creatures as well. | |
37 | // | |
8d59b230 BK |
38 | // 2) set_memory_limits() |
39 | // set_memory_limits() uses setrlimit() to restrict dynamic memory | |
fe413112 | 40 | // allocation. We provide a default memory limit if none is passed by the |
8d59b230 | 41 | // calling application. The argument to set_memory_limits() is the |
2ae6e982 | 42 | // limit in megabytes (a floating-point number). If _GLIBCXX_RES_LIMITS is |
c4297522 | 43 | // not #defined before including this header, then no limiting is attempted. |
bb2ae697 | 44 | // |
8d59b230 | 45 | // 3) counter |
bb2ae697 PE |
46 | // This is a POD with a static data member, gnu_counting_struct::count, |
47 | // which starts at zero, increments on instance construction, and decrements | |
48 | // on instance destruction. "assert_count(n)" can be called to VERIFY() | |
49 | // that the count equals N. | |
8ea08b7d | 50 | // |
8d59b230 | 51 | // 4) copy_tracker, from Stephen M. Webb <stephen@bregmasoft.com>. |
8ea08b7d PE |
52 | // A class with nontrivial ctor/dtor that provides the ability to track the |
53 | // number of copy ctors and dtors, and will throw on demand during copy. | |
f13a69ec | 54 | // |
8d59b230 BK |
55 | // 5) pod_char, pod_int, , abstract character classes and |
56 | // char_traits specializations for testing instantiations. | |
fe413112 | 57 | |
3d7c150e BK |
58 | #ifndef _GLIBCXX_TESTSUITE_HOOKS_H |
59 | #define _GLIBCXX_TESTSUITE_HOOKS_H | |
fe413112 | 60 | |
f13a69ec | 61 | #include <bits/c++config.h> |
49bc23b7 | 62 | #include <bits/functexcept.h> |
f13a69ec | 63 | #include <cstddef> |
9540958e BK |
64 | #include <locale> |
65 | #include <ext/pod_char_traits.h> | |
ea1ea21a MM |
66 | #ifdef _GLIBCXX_HAVE_SYS_STAT_H |
67 | #include <sys/stat.h> | |
68 | #endif | |
9540958e | 69 | |
cb584bcf | 70 | #ifdef _GLIBCXX_ASSERT |
fe413112 PE |
71 | # include <cassert> |
72 | # define VERIFY(fn) assert(fn) | |
fe413112 | 73 | #else |
fe413112 | 74 | # define VERIFY(fn) test &= (fn) |
fe413112 | 75 | #endif |
9540958e | 76 | |
aaa4a229 PE |
77 | #ifdef _GLIBCXX_HAVE_UNISTD_H |
78 | # include <unistd.h> | |
79 | #else | |
80 | # define unlink(x) | |
81 | #endif | |
fe413112 | 82 | |
aecf642c | 83 | namespace __gnu_test |
8d59b230 | 84 | { |
3d7c150e | 85 | // All macros are defined in GLIBCXX_CONFIGURE_TESTSUITE and imported |
8d59b230 | 86 | // from c++config.h |
fe413112 | 87 | |
8d59b230 | 88 | // Set memory limits if possible, if not set to 0. |
2ae6e982 | 89 | #ifndef _GLIBCXX_RES_LIMITS |
8d59b230 | 90 | # define MEMLIMIT_MB 0 |
58b08ac3 | 91 | #else |
8d59b230 BK |
92 | # ifndef MEMLIMIT_MB |
93 | # define MEMLIMIT_MB 16.0 | |
94 | # endif | |
fe413112 | 95 | #endif |
8d59b230 BK |
96 | extern void |
97 | set_memory_limits(float __size = MEMLIMIT_MB); | |
fe413112 | 98 | |
2ae6e982 PC |
99 | extern void |
100 | set_file_limit(unsigned long __size); | |
4ffbd077 BK |
101 | |
102 | // Check mangled name demangles (using __cxa_demangle) as expected. | |
103 | void | |
104 | verify_demangle(const char* mangled, const char* wanted); | |
105 | ||
8d59b230 BK |
106 | // Simple callback structure for variable numbers of tests (all with |
107 | // same signature). Assume all unit tests are of the signature | |
108 | // void test01(); | |
cb584bcf BK |
109 | class func_callback |
110 | { | |
111 | public: | |
112 | typedef void (*test_type) (void); | |
113 | ||
114 | private: | |
115 | int _M_size; | |
116 | test_type _M_tests[15]; | |
117 | ||
118 | public: | |
119 | func_callback(): _M_size(0) { }; | |
120 | ||
121 | int | |
122 | size() const { return _M_size; } | |
123 | ||
124 | const test_type* | |
125 | tests() const { return _M_tests; } | |
126 | ||
127 | void | |
128 | push_back(test_type test) | |
129 | { | |
130 | _M_tests[_M_size] = test; | |
131 | ++_M_size; | |
132 | } | |
133 | }; | |
134 | ||
fe413112 | 135 | |
8d59b230 BK |
136 | // Run select unit tests after setting global locale. |
137 | void | |
138 | run_tests_wrapped_locale(const char*, const func_callback&); | |
bb2ae697 | 139 | |
8d59b230 BK |
140 | // Run select unit tests after setting environment variables. |
141 | void | |
142 | run_tests_wrapped_env(const char*, const char*, const func_callback&); | |
143 | ||
3d838e28 BK |
144 | // Try to create a locale with the given name. If it fails, bail. |
145 | std::locale | |
146 | try_named_locale(const char* name); | |
4ffbd077 | 147 | |
ea1ea21a MM |
148 | int |
149 | try_mkfifo (const char* filename, mode_t mode); | |
46c4e5d6 | 150 | |
8d59b230 BK |
151 | // Test data types. |
152 | struct pod_char | |
153 | { | |
154 | unsigned char c; | |
155 | }; | |
ce345590 PC |
156 | |
157 | inline bool | |
158 | operator==(const pod_char& lhs, const pod_char& rhs) | |
159 | { return lhs.c == rhs.c; } | |
8d59b230 BK |
160 | |
161 | struct pod_int | |
162 | { | |
163 | int i; | |
164 | }; | |
165 | ||
8d59b230 BK |
166 | struct state |
167 | { | |
168 | unsigned long l; | |
169 | unsigned long l2; | |
170 | }; | |
171 | ||
9540958e BK |
172 | typedef unsigned short value_type; |
173 | typedef unsigned int int_type; | |
174 | typedef __gnu_cxx::character<value_type, int_type> pod_type; | |
175 | ||
46c4e5d6 | 176 | |
8d59b230 BK |
177 | // Counting. |
178 | struct counter | |
179 | { | |
bb2ae697 | 180 | // Specifically and glaringly-obviously marked 'signed' so that when |
8ea08b7d PE |
181 | // COUNT mistakenly goes negative, we can track the patterns of |
182 | // deletions more easily. | |
bb2ae697 PE |
183 | typedef signed int size_type; |
184 | static size_type count; | |
8d59b230 BK |
185 | counter() { ++count; } |
186 | counter (const counter&) { ++count; } | |
187 | ~counter() { --count; } | |
188 | }; | |
189 | ||
aecf642c | 190 | #define assert_count(n) VERIFY(__gnu_test::counter::count == n) |
8d59b230 BK |
191 | |
192 | // A (static) class for counting copy constructors and possibly throwing an | |
193 | // exception on a desired count. | |
194 | class copy_constructor | |
162c7cd9 | 195 | { |
8d59b230 BK |
196 | public: |
197 | static unsigned int | |
198 | count() { return count_; } | |
199 | ||
200 | static void | |
201 | mark_call() | |
162c7cd9 | 202 | { |
8d59b230 BK |
203 | count_++; |
204 | if (count_ == throw_on_) | |
205 | __throw_exception_again "copy constructor exception"; | |
162c7cd9 | 206 | } |
8d59b230 BK |
207 | |
208 | static void | |
209 | reset() | |
162c7cd9 | 210 | { |
8d59b230 BK |
211 | count_ = 0; |
212 | throw_on_ = 0; | |
162c7cd9 | 213 | } |
8d59b230 BK |
214 | |
215 | static void | |
216 | throw_on(unsigned int count) { throw_on_ = count; } | |
162c7cd9 | 217 | |
8d59b230 BK |
218 | private: |
219 | static unsigned int count_; | |
220 | static unsigned int throw_on_; | |
221 | }; | |
222 | ||
223 | // A (static) class for counting assignment operator calls and | |
224 | // possibly throwing an exception on a desired count. | |
225 | class assignment_operator | |
162c7cd9 | 226 | { |
8d59b230 BK |
227 | public: |
228 | static unsigned int | |
229 | count() { return count_; } | |
230 | ||
231 | static void | |
232 | mark_call() | |
233 | { | |
234 | count_++; | |
235 | if (count_ == throw_on_) | |
236 | __throw_exception_again "assignment operator exception"; | |
237 | } | |
162c7cd9 | 238 | |
8d59b230 BK |
239 | static void |
240 | reset() | |
241 | { | |
242 | count_ = 0; | |
243 | throw_on_ = 0; | |
244 | } | |
162c7cd9 | 245 | |
8d59b230 BK |
246 | static void |
247 | throw_on(unsigned int count) { throw_on_ = count; } | |
162c7cd9 | 248 | |
8d59b230 BK |
249 | private: |
250 | static unsigned int count_; | |
251 | static unsigned int throw_on_; | |
252 | }; | |
253 | ||
254 | // A (static) class for tracking calls to an object's destructor. | |
255 | class destructor | |
256 | { | |
257 | public: | |
258 | static unsigned int | |
259 | count() { return _M_count; } | |
260 | ||
261 | static void | |
262 | mark_call() { _M_count++; } | |
162c7cd9 | 263 | |
8d59b230 BK |
264 | static void |
265 | reset() { _M_count = 0; } | |
162c7cd9 | 266 | |
8d59b230 BK |
267 | private: |
268 | static unsigned int _M_count; | |
269 | }; | |
270 | ||
271 | // An class of objects that can be used for validating various | |
272 | // behaviours and guarantees of containers and algorithms defined in | |
273 | // the standard library. | |
274 | class copy_tracker | |
275 | { | |
8ea08b7d | 276 | public: |
8d59b230 BK |
277 | // Creates a copy-tracking object with the given ID number. If |
278 | // "throw_on_copy" is set, an exception will be thrown if an | |
279 | // attempt is made to copy this object. | |
280 | copy_tracker(int id = next_id_--, bool throw_on_copy = false) | |
281 | : id_(id) , throw_on_copy_(throw_on_copy) { } | |
8ea08b7d | 282 | |
162c7cd9 SW |
283 | // Copy-constructs the object, marking a call to the copy |
284 | // constructor and forcing an exception if indicated. | |
8d59b230 | 285 | copy_tracker(const copy_tracker& rhs) |
162c7cd9 | 286 | : id_(rhs.id()), throw_on_copy_(rhs.throw_on_copy_) |
8ea08b7d | 287 | { |
162c7cd9 | 288 | if (throw_on_copy_) |
8d59b230 BK |
289 | copy_constructor::throw_on(copy_constructor::count() + 1); |
290 | copy_constructor::mark_call(); | |
162c7cd9 SW |
291 | } |
292 | ||
293 | // Assigns the value of another object to this one, tracking the | |
294 | // number of times this member function has been called and if the | |
295 | // other object is supposed to throw an exception when it is | |
296 | // copied, well, make it so. | |
8d59b230 BK |
297 | copy_tracker& |
298 | operator=(const copy_tracker& rhs) | |
162c7cd9 SW |
299 | { |
300 | id_ = rhs.id(); | |
301 | if (rhs.throw_on_copy_) | |
8d59b230 BK |
302 | assignment_operator::throw_on(assignment_operator::count() + 1); |
303 | assignment_operator::mark_call(); | |
532722be | 304 | return *this; |
8ea08b7d PE |
305 | } |
306 | ||
8d59b230 BK |
307 | ~copy_tracker() |
308 | { destructor::mark_call(); } | |
8ea08b7d PE |
309 | |
310 | int | |
8d59b230 | 311 | id() const { return id_; } |
8ea08b7d PE |
312 | |
313 | private: | |
162c7cd9 SW |
314 | int id_; |
315 | const bool throw_on_copy_; | |
8ea08b7d PE |
316 | |
317 | public: | |
318 | static void | |
319 | reset() | |
162c7cd9 | 320 | { |
8d59b230 BK |
321 | copy_constructor::reset(); |
322 | assignment_operator::reset(); | |
323 | destructor::reset(); | |
162c7cd9 | 324 | } |
8ea08b7d | 325 | |
162c7cd9 | 326 | // for backwards-compatibility |
8ea08b7d PE |
327 | static int |
328 | copyCount() | |
8d59b230 | 329 | { return copy_constructor::count(); } |
8ea08b7d | 330 | |
162c7cd9 | 331 | // for backwards-compatibility |
8ea08b7d PE |
332 | static int |
333 | dtorCount() | |
8d59b230 | 334 | { return destructor::count(); } |
8ea08b7d PE |
335 | |
336 | private: | |
162c7cd9 | 337 | static int next_id_; |
8d59b230 | 338 | }; |
f13a69ec | 339 | |
8d59b230 BK |
340 | inline bool |
341 | operator==(const copy_tracker& lhs, const copy_tracker& rhs) | |
342 | { return lhs.id() == rhs.id(); } | |
261e5b9e BK |
343 | |
344 | // Class for checking required type conversions, implicit and | |
345 | // explicit for given library data structures. | |
346 | template<typename _Container> | |
347 | struct conversion | |
348 | { | |
349 | typedef typename _Container::const_iterator const_iterator; | |
350 | ||
351 | // Implicit conversion iterator to const_iterator. | |
352 | static const_iterator | |
353 | iterator_to_const_iterator() | |
354 | { | |
355 | _Container v; | |
356 | const_iterator it = v.begin(); | |
357 | const_iterator end = v.end(); | |
358 | return it == end ? v.end() : it; | |
359 | } | |
360 | }; | |
aecf642c | 361 | } // namespace __gnu_test |
f13a69ec | 362 | |
f13a69ec BK |
363 | namespace std |
364 | { | |
365 | template<class _CharT> | |
366 | struct char_traits; | |
367 | ||
8d59b230 | 368 | // char_traits specialization |
f13a69ec | 369 | template<> |
aecf642c | 370 | struct char_traits<__gnu_test::pod_char> |
f13a69ec | 371 | { |
aecf642c BK |
372 | typedef __gnu_test::pod_char char_type; |
373 | typedef __gnu_test::pod_int int_type; | |
aecf642c | 374 | typedef __gnu_test::state state_type; |
9540958e BK |
375 | typedef fpos<state_type> pos_type; |
376 | typedef streamoff off_type; | |
f13a69ec BK |
377 | |
378 | static void | |
9540958e BK |
379 | assign(char_type& c1, const char_type& c2) |
380 | { c1.c = c2.c; } | |
f13a69ec BK |
381 | |
382 | static bool | |
9540958e BK |
383 | eq(const char_type& c1, const char_type& c2) |
384 | { return c1.c == c2.c; } | |
f13a69ec BK |
385 | |
386 | static bool | |
9540958e BK |
387 | lt(const char_type& c1, const char_type& c2) |
388 | { return c1.c < c2.c; } | |
f13a69ec BK |
389 | |
390 | static int | |
9540958e BK |
391 | compare(const char_type* s1, const char_type* s2, size_t n) |
392 | { return memcmp(s1, s2, n); } | |
f13a69ec BK |
393 | |
394 | static size_t | |
9540958e BK |
395 | length(const char_type* s) |
396 | { return strlen(reinterpret_cast<const char*>(s)); } | |
f13a69ec BK |
397 | |
398 | static const char_type* | |
9540958e BK |
399 | find(const char_type* s, size_t n, const char_type& a) |
400 | { return static_cast<const char_type*>(memchr(s, a.c, n)); } | |
f13a69ec BK |
401 | |
402 | static char_type* | |
9540958e BK |
403 | move(char_type* s1, const char_type* s2, size_t n) |
404 | { | |
405 | memmove(s1, s2, n); | |
406 | return s1; | |
407 | } | |
f13a69ec BK |
408 | |
409 | static char_type* | |
9540958e BK |
410 | copy(char_type* s1, const char_type* s2, size_t n) |
411 | { | |
412 | memcpy(s1, s2, n); | |
413 | return s1; | |
414 | } | |
f13a69ec BK |
415 | |
416 | static char_type* | |
9540958e BK |
417 | assign(char_type* s, size_t n, char_type a) |
418 | { | |
419 | memset(s, a.c, n); | |
420 | return s; | |
421 | } | |
f13a69ec BK |
422 | |
423 | static char_type | |
9540958e BK |
424 | to_char_type(const int_type& c) |
425 | { | |
426 | char_type ret; | |
427 | ret.c = static_cast<unsigned char>(c.i); | |
428 | return ret; | |
429 | } | |
f13a69ec BK |
430 | |
431 | static int_type | |
9540958e BK |
432 | to_int_type(const char_type& c) |
433 | { | |
434 | int_type ret; | |
435 | ret.i = c.c; | |
436 | return ret; | |
437 | } | |
f13a69ec BK |
438 | |
439 | static bool | |
9540958e BK |
440 | eq_int_type(const int_type& c1, const int_type& c2) |
441 | { return c1.i == c2.i; } | |
f13a69ec BK |
442 | |
443 | static int_type | |
9540958e BK |
444 | eof() |
445 | { | |
446 | int_type n; | |
447 | n.i = -10; | |
448 | return n; | |
449 | } | |
f13a69ec BK |
450 | |
451 | static int_type | |
9540958e BK |
452 | not_eof(const int_type& c) |
453 | { | |
454 | if (eq_int_type(c, eof())) | |
455 | return int_type(); | |
456 | return c; | |
457 | } | |
f13a69ec BK |
458 | }; |
459 | } // namespace std | |
bb2ae697 | 460 | |
3d7c150e | 461 | #endif // _GLIBCXX_TESTSUITE_HOOKS_H |
fe413112 | 462 |