]>
Commit | Line | Data |
---|---|---|
8d59b230 BK |
1 | // -*- C++ -*- |
2 | // Utility subroutines for the C++ library testsuite. | |
fe413112 | 3 | // |
8d59b230 | 4 | // Copyright (C) 2000, 2001, 2002, 2003 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 | // | |
33 | // 1) VERIFY(), via DEBUG_ASSERT, from Brent Verner <brent@rcfile.org>. | |
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 |
3d7c150e | 42 | // limit in megabytes (a floating-point number). If _GLIBCXX_MEM_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> |
fe413112 PE |
64 | #ifdef DEBUG_ASSERT |
65 | # include <cassert> | |
66 | # define VERIFY(fn) assert(fn) | |
fe413112 | 67 | #else |
fe413112 | 68 | # define VERIFY(fn) test &= (fn) |
fe413112 | 69 | #endif |
8d59b230 | 70 | #include <list> |
3d838e28 | 71 | #include <locale> |
fe413112 | 72 | |
8d59b230 BK |
73 | namespace __gnu_cxx_test |
74 | { | |
3d7c150e | 75 | // All macros are defined in GLIBCXX_CONFIGURE_TESTSUITE and imported |
8d59b230 | 76 | // from c++config.h |
fe413112 | 77 | |
8d59b230 | 78 | // Set memory limits if possible, if not set to 0. |
3d7c150e | 79 | #ifndef _GLIBCXX_MEM_LIMITS |
8d59b230 | 80 | # define MEMLIMIT_MB 0 |
58b08ac3 | 81 | #else |
8d59b230 BK |
82 | # ifndef MEMLIMIT_MB |
83 | # define MEMLIMIT_MB 16.0 | |
84 | # endif | |
fe413112 | 85 | #endif |
8d59b230 BK |
86 | extern void |
87 | set_memory_limits(float __size = MEMLIMIT_MB); | |
fe413112 | 88 | |
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 | ||
94 | ||
8d59b230 BK |
95 | // Simple callback structure for variable numbers of tests (all with |
96 | // same signature). Assume all unit tests are of the signature | |
97 | // void test01(); | |
98 | typedef void (*test_func) (void); | |
99 | typedef std::list<test_func> func_callback; | |
fe413112 | 100 | |
8d59b230 BK |
101 | // Run select unit tests after setting global locale. |
102 | void | |
103 | run_tests_wrapped_locale(const char*, const func_callback&); | |
bb2ae697 | 104 | |
8d59b230 BK |
105 | // Run select unit tests after setting environment variables. |
106 | void | |
107 | run_tests_wrapped_env(const char*, const char*, const func_callback&); | |
108 | ||
3d838e28 BK |
109 | // Try to create a locale with the given name. If it fails, bail. |
110 | std::locale | |
111 | try_named_locale(const char* name); | |
4ffbd077 | 112 | |
46c4e5d6 | 113 | |
8d59b230 BK |
114 | // Test data types. |
115 | struct pod_char | |
116 | { | |
117 | unsigned char c; | |
118 | }; | |
119 | ||
120 | struct pod_int | |
121 | { | |
122 | int i; | |
123 | }; | |
124 | ||
125 | struct pod_unsigned_int | |
126 | { | |
127 | unsigned int i; | |
128 | }; | |
129 | ||
130 | struct pod_long | |
131 | { | |
132 | unsigned long i; | |
133 | }; | |
134 | ||
135 | struct state | |
136 | { | |
137 | unsigned long l; | |
138 | unsigned long l2; | |
139 | }; | |
140 | ||
46c4e5d6 | 141 | |
8d59b230 BK |
142 | // Counting. |
143 | struct counter | |
144 | { | |
bb2ae697 | 145 | // Specifically and glaringly-obviously marked 'signed' so that when |
8ea08b7d PE |
146 | // COUNT mistakenly goes negative, we can track the patterns of |
147 | // deletions more easily. | |
bb2ae697 PE |
148 | typedef signed int size_type; |
149 | static size_type count; | |
8d59b230 BK |
150 | counter() { ++count; } |
151 | counter (const counter&) { ++count; } | |
152 | ~counter() { --count; } | |
153 | }; | |
154 | ||
155 | #define assert_count(n) VERIFY(__gnu_cxx_test::counter::count == n) | |
156 | ||
157 | // A (static) class for counting copy constructors and possibly throwing an | |
158 | // exception on a desired count. | |
159 | class copy_constructor | |
162c7cd9 | 160 | { |
8d59b230 BK |
161 | public: |
162 | static unsigned int | |
163 | count() { return count_; } | |
164 | ||
165 | static void | |
166 | mark_call() | |
162c7cd9 | 167 | { |
8d59b230 BK |
168 | count_++; |
169 | if (count_ == throw_on_) | |
170 | __throw_exception_again "copy constructor exception"; | |
162c7cd9 | 171 | } |
8d59b230 BK |
172 | |
173 | static void | |
174 | reset() | |
162c7cd9 | 175 | { |
8d59b230 BK |
176 | count_ = 0; |
177 | throw_on_ = 0; | |
162c7cd9 | 178 | } |
8d59b230 BK |
179 | |
180 | static void | |
181 | throw_on(unsigned int count) { throw_on_ = count; } | |
162c7cd9 | 182 | |
8d59b230 BK |
183 | private: |
184 | static unsigned int count_; | |
185 | static unsigned int throw_on_; | |
186 | }; | |
187 | ||
188 | // A (static) class for counting assignment operator calls and | |
189 | // possibly throwing an exception on a desired count. | |
190 | class assignment_operator | |
162c7cd9 | 191 | { |
8d59b230 BK |
192 | public: |
193 | static unsigned int | |
194 | count() { return count_; } | |
195 | ||
196 | static void | |
197 | mark_call() | |
198 | { | |
199 | count_++; | |
200 | if (count_ == throw_on_) | |
201 | __throw_exception_again "assignment operator exception"; | |
202 | } | |
162c7cd9 | 203 | |
8d59b230 BK |
204 | static void |
205 | reset() | |
206 | { | |
207 | count_ = 0; | |
208 | throw_on_ = 0; | |
209 | } | |
162c7cd9 | 210 | |
8d59b230 BK |
211 | static void |
212 | throw_on(unsigned int count) { throw_on_ = count; } | |
162c7cd9 | 213 | |
8d59b230 BK |
214 | private: |
215 | static unsigned int count_; | |
216 | static unsigned int throw_on_; | |
217 | }; | |
218 | ||
219 | // A (static) class for tracking calls to an object's destructor. | |
220 | class destructor | |
221 | { | |
222 | public: | |
223 | static unsigned int | |
224 | count() { return _M_count; } | |
225 | ||
226 | static void | |
227 | mark_call() { _M_count++; } | |
162c7cd9 | 228 | |
8d59b230 BK |
229 | static void |
230 | reset() { _M_count = 0; } | |
162c7cd9 | 231 | |
8d59b230 BK |
232 | private: |
233 | static unsigned int _M_count; | |
234 | }; | |
235 | ||
236 | // An class of objects that can be used for validating various | |
237 | // behaviours and guarantees of containers and algorithms defined in | |
238 | // the standard library. | |
239 | class copy_tracker | |
240 | { | |
8ea08b7d | 241 | public: |
8d59b230 BK |
242 | // Creates a copy-tracking object with the given ID number. If |
243 | // "throw_on_copy" is set, an exception will be thrown if an | |
244 | // attempt is made to copy this object. | |
245 | copy_tracker(int id = next_id_--, bool throw_on_copy = false) | |
246 | : id_(id) , throw_on_copy_(throw_on_copy) { } | |
8ea08b7d | 247 | |
162c7cd9 SW |
248 | // Copy-constructs the object, marking a call to the copy |
249 | // constructor and forcing an exception if indicated. | |
8d59b230 | 250 | copy_tracker(const copy_tracker& rhs) |
162c7cd9 | 251 | : id_(rhs.id()), throw_on_copy_(rhs.throw_on_copy_) |
8ea08b7d | 252 | { |
162c7cd9 | 253 | if (throw_on_copy_) |
8d59b230 BK |
254 | copy_constructor::throw_on(copy_constructor::count() + 1); |
255 | copy_constructor::mark_call(); | |
162c7cd9 SW |
256 | } |
257 | ||
258 | // Assigns the value of another object to this one, tracking the | |
259 | // number of times this member function has been called and if the | |
260 | // other object is supposed to throw an exception when it is | |
261 | // copied, well, make it so. | |
8d59b230 BK |
262 | copy_tracker& |
263 | operator=(const copy_tracker& rhs) | |
162c7cd9 SW |
264 | { |
265 | id_ = rhs.id(); | |
266 | if (rhs.throw_on_copy_) | |
8d59b230 BK |
267 | assignment_operator::throw_on(assignment_operator::count() + 1); |
268 | assignment_operator::mark_call(); | |
532722be | 269 | return *this; |
8ea08b7d PE |
270 | } |
271 | ||
8d59b230 BK |
272 | ~copy_tracker() |
273 | { destructor::mark_call(); } | |
8ea08b7d PE |
274 | |
275 | int | |
8d59b230 | 276 | id() const { return id_; } |
8ea08b7d PE |
277 | |
278 | private: | |
162c7cd9 SW |
279 | int id_; |
280 | const bool throw_on_copy_; | |
8ea08b7d PE |
281 | |
282 | public: | |
283 | static void | |
284 | reset() | |
162c7cd9 | 285 | { |
8d59b230 BK |
286 | copy_constructor::reset(); |
287 | assignment_operator::reset(); | |
288 | destructor::reset(); | |
162c7cd9 | 289 | } |
8ea08b7d | 290 | |
162c7cd9 | 291 | // for backwards-compatibility |
8ea08b7d PE |
292 | static int |
293 | copyCount() | |
8d59b230 | 294 | { return copy_constructor::count(); } |
8ea08b7d | 295 | |
162c7cd9 | 296 | // for backwards-compatibility |
8ea08b7d PE |
297 | static int |
298 | dtorCount() | |
8d59b230 | 299 | { return destructor::count(); } |
8ea08b7d PE |
300 | |
301 | private: | |
162c7cd9 | 302 | static int next_id_; |
8d59b230 | 303 | }; |
f13a69ec | 304 | |
8d59b230 BK |
305 | inline bool |
306 | operator==(const copy_tracker& lhs, const copy_tracker& rhs) | |
307 | { return lhs.id() == rhs.id(); } | |
532722be | 308 | } // namespace __gnu_cxx_test |
f13a69ec | 309 | |
f13a69ec BK |
310 | namespace std |
311 | { | |
312 | template<class _CharT> | |
313 | struct char_traits; | |
314 | ||
8d59b230 | 315 | // char_traits specialization |
f13a69ec | 316 | template<> |
8d59b230 | 317 | struct char_traits<__gnu_cxx_test::pod_char> |
f13a69ec | 318 | { |
8d59b230 BK |
319 | typedef __gnu_cxx_test::pod_char char_type; |
320 | typedef __gnu_cxx_test::pod_int int_type; | |
321 | typedef long pos_type; | |
322 | typedef unsigned long off_type; | |
323 | typedef __gnu_cxx_test::state state_type; | |
f13a69ec BK |
324 | |
325 | static void | |
326 | assign(char_type& __c1, const char_type& __c2); | |
327 | ||
328 | static bool | |
329 | eq(const char_type& __c1, const char_type& __c2); | |
330 | ||
331 | static bool | |
332 | lt(const char_type& __c1, const char_type& __c2); | |
333 | ||
334 | static int | |
335 | compare(const char_type* __s1, const char_type* __s2, size_t __n); | |
336 | ||
337 | static size_t | |
338 | length(const char_type* __s); | |
339 | ||
340 | static const char_type* | |
341 | find(const char_type* __s, size_t __n, const char_type& __a); | |
342 | ||
343 | static char_type* | |
344 | move(char_type* __s1, const char_type* __s2, size_t __n); | |
345 | ||
346 | static char_type* | |
347 | copy(char_type* __s1, const char_type* __s2, size_t __n); | |
348 | ||
349 | static char_type* | |
350 | assign(char_type* __s, size_t __n, char_type __a); | |
351 | ||
352 | static char_type | |
353 | to_char_type(const int_type& __c); | |
354 | ||
355 | static int_type | |
356 | to_int_type(const char_type& __c); | |
357 | ||
358 | static bool | |
359 | eq_int_type(const int_type& __c1, const int_type& __c2); | |
360 | ||
361 | static int_type | |
362 | eof(); | |
363 | ||
364 | static int_type | |
365 | not_eof(const int_type& __c); | |
366 | }; | |
367 | } // namespace std | |
bb2ae697 | 368 | |
3d7c150e | 369 | #endif // _GLIBCXX_TESTSUITE_HOOKS_H |
fe413112 | 370 |