]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/infra/testsuite/cyginfra/tassert3.cxx
Initial revision
[karo-tx-redboot.git] / tools / src / infra / testsuite / cyginfra / tassert3.cxx
1 //==========================================================================
2 //
3 //      tassert3.cxx
4 //
5 //      Assertion test case                                                                
6 //
7 //==========================================================================
8 //####COPYRIGHTBEGIN####
9 //                                                                          
10 // ----------------------------------------------------------------------------
11 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
12 //
13 // This file is part of the eCos host tools.
14 //
15 // This program is free software; you can redistribute it and/or modify it 
16 // under the terms of the GNU General Public License as published by the Free 
17 // Software Foundation; either version 2 of the License, or (at your option) 
18 // any later version.
19 // 
20 // This program is distributed in the hope that it will be useful, but WITHOUT 
21 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
22 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
23 // more details.
24 // 
25 // You should have received a copy of the GNU General Public License along with
26 // this program; if not, write to the Free Software Foundation, Inc., 
27 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28 //
29 // ----------------------------------------------------------------------------
30 //                                                                          
31 //####COPYRIGHTEND####
32 //==========================================================================
33 //#####DESCRIPTIONBEGIN####                                             
34 //
35 // Author(s):           bartv
36 // Contributors:        bartv
37 // Date:                1998-12-21
38 // Purpose:
39 // Description:         Check the host extensions.
40 //
41 //####DESCRIPTIONEND####
42 //==========================================================================
43
44 // -------------------------------------------------------------------------
45 // The host-side assertion support has three extensions to the generic
46 // assertion support:
47 //
48 // 1) cyg_assert_install_failure_handler()
49 //    Provide an alternative handler that gets invoked when an
50 //    assertion fails.
51 //
52 // 2) cyg_assert_install_failure_callback()
53 //    Provide an additional callback that should get invoked when an
54 //    assertion triggers to provide additional information.
55 //
56 // 3) cyg_assert_failure_invoke_callbacks()
57 //    Used by (1) to call the functions installed via (2).
58 //
59 // The tests make use of setjmp()/longjmp() buffer to avoid having to
60 // do lots of output parsing in the DejaGnu driver.
61
62 #define CYG_DECLARE_HOST_ASSERTION_SUPPORT
63 #define CYGDBG_USE_ASSERTS
64 #define CYGDBG_INFRA_DEBUG_PRECONDITIONS
65 #define CYGDBG_INFRA_DEBUG_POSTCONDITIONS
66 #define CYGDBG_INFRA_DEBUG_LOOP_INVARIANTS
67 #define CYGDBG_INFRA_DEBUG_INVARIANTS
68
69 #include <cyg/infra/testcase.h>
70 #include <cyg/infra/cyg_ass.h>
71 #include <cstdlib>
72 #include <csetjmp>
73 #include <cstring>
74
75 // Forward declarations of some integers to allow the line number to be
76 // checked.
77 extern cyg_uint32 main_start, main_end;
78
79 // This is used to "recover" from an assertion failure
80 static jmp_buf setjmp_buffer;
81
82 // A constant string useful for comparisons.
83 static const char message[] = "fail";
84
85 // Some state information to make sure that the world is in the expected
86 // state
87 bool expecting_failure1         = false;
88 bool expecting_failure2         = false;
89 bool expecting_failure3         = false;
90
91 // -------------------------------------------------------------------------
92 // The first assertion handler. This is used to check that the arguments
93 // make sense.
94
95 extern "C"
96 bool
97 failure_handler1(const char* fn, const char* file, cyg_uint32 line, const char* msg)
98 {
99     if (!expecting_failure1) {
100         CYG_TEST_FAIL("assertion failure handler1 invoked unexpectedly");
101     }
102     expecting_failure1 = false;
103     // The function should be 0 or contain main
104     if (0 != fn) {
105         if (0 == strstr(fn, "main")) {
106             CYG_TEST_FAIL("invalid function name passed to assertion failure handler");
107         }
108     }
109     // The file name should always be valid and contain tassert3.cxx.
110     // It may contain path information as well.
111     if ( (0 == file) || (0 == strstr(file, "tassert3.cxx"))) {
112         CYG_TEST_FAIL("invalid file name passed to assertion failure handler");
113     }
114     // The line number can be validated against some globals.
115     if ((line <= main_start) || (line >= main_end)) {
116         CYG_TEST_FAIL("invalid line number passed to assertion failure handler");
117     }
118     // The message passed is known.
119     if (0 != strcmp(msg, message)) {
120         CYG_TEST_FAIL("invalid message passed to assertion failure handler");
121     }
122     CYG_TEST_PASS("application-specific assertion failure handler");
123     
124     // Everything OK, back to main()
125     longjmp(setjmp_buffer, 1);
126     CYG_TEST_FAIL_FINISH("longjmp() is not functional");
127     return false;
128 }
129
130 // -------------------------------------------------------------------------
131 // A second assertion handler. This is used to make sure that assertion
132 // failure handlers can be overwritten.
133
134 extern "C"
135 bool
136 failure_handler2(const char* fn, const char* file, cyg_uint32 line, const char* msg)
137 {
138     if (!expecting_failure2) {
139         CYG_TEST_FAIL("assertion failure handler2 invoked incorrectly");
140     }
141     expecting_failure2 = false;
142     CYG_TEST_PASS("assertion failure handlers can be replaced");
143     longjmp(setjmp_buffer, 1);
144     CYG_TEST_FAIL_FINISH("longjmp() is not functional");
145     return false;
146 }
147 // -------------------------------------------------------------------------
148 // The third assertion handler. This time a couple of output callbacks are
149 // installed and the main failure handler has to invoke the output callbacks.
150 // A number of statics are used to make sure everything works ok.
151
152 static const char callback1_title[] = "callback1_header";
153 static const char callback2_title[] = "callback2_header";
154 static const char callback2_data[]  = "callback2 data\n";
155 static bool seen_callback1_title    = false;
156 static bool seen_callback2_title    = false;
157 static bool callback1_done          = false;
158 static bool callback2_done          = false;
159 static int  number_of_headers       = 0;
160 static bool callback1_invoked       = false;
161 static bool callback2_invoked       = false;
162 static int  number_of_lines_seen    = 0;
163 const  int  callback2_lines         = 16;
164 static int  callback2_lines_seen    = 0;
165 static int  number_of_trailers      = 0;
166
167 extern "C"
168 void
169 callback1(void (*outputfn)(const char*))
170 {
171     if (callback1_invoked) {
172         CYG_TEST_FAIL("callback1 invoked multiple times");
173     }
174     callback1_invoked = true;
175
176     // This callback does nothing.
177 }
178
179 extern "C"
180 void
181 callback2(void (*outputfn)(const char*))
182 {
183     if (callback2_invoked) {
184         CYG_TEST_FAIL("callback2 invoked multiple times");
185     }
186     callback2_invoked = true;
187     for (int i = 0; i < callback2_lines; i++) {
188         (*outputfn)(callback2_data);
189     }
190 }
191
192 // handle_callback_header() should be invoked at least twice,
193 // once with callback1_header and once with callback2_header
194 extern "C"
195 void
196 handle_callback_header(const char* name)
197 {
198     number_of_headers++;
199     if (0 == strcmp(name, callback1_title)) {
200         if (seen_callback1_title) {
201             CYG_TEST_FAIL("callback1 title seen multiple times");
202         } else {
203             seen_callback1_title = true;
204         }
205     }
206     if (0 == strcmp(name, callback2_title)) {
207         if (seen_callback2_title) {
208             CYG_TEST_FAIL("callback2 title seen multiple times");
209         } else {
210             seen_callback2_title = true;
211         }
212     }
213 }
214
215 // The body output function should be invoked zero times for
216 // callback1 and a fixed number of times for callback2.
217 extern "C"
218 void
219 handle_callback_body(const char* data)
220 {
221     number_of_lines_seen++;
222     
223     if (seen_callback1_title && !callback1_done) {
224         CYG_TEST_FAIL("callback1 should not perform any output");
225     }
226     if (seen_callback2_title && !callback2_done) {
227         callback2_lines_seen++;
228         if (0 != strcmp(data, callback2_data)) {
229             CYG_TEST_FAIL("callback2 has generated incorrect data");
230         }
231     }
232 }
233
234 // The trailer output function should be invoked at least twice, once
235 // for each callback.
236 extern "C"
237 void
238 handle_callback_trailer(void)
239 {
240     if (0 == number_of_headers) {
241         CYG_TEST_FAIL("callback trailer seen before header");
242     }
243     number_of_trailers++;
244     if (seen_callback1_title && !callback1_done) {
245         callback1_done = true;
246     }
247     if (seen_callback2_title && !callback2_done) {
248         callback2_done = true;
249     }
250 }
251
252 // This is the failure handler. It causes the various callbacks to run, then
253 // checks the resulting values of the statics.
254 extern "C"
255 bool
256 failure_handler3(const char* fn, const char* file, cyg_uint32 line, const char* msg)
257 {
258     if (!expecting_failure3) {
259         CYG_TEST_FAIL("assertion failure handler3 invoked incorrectly");
260     }
261     expecting_failure3 = false;
262
263     cyg_assert_failure_invoke_callbacks(
264         &handle_callback_header,
265         &handle_callback_body,
266         &handle_callback_trailer);
267
268     bool all_ok = true;
269     if (!seen_callback1_title) {
270         CYG_TEST_FAIL("callback1's title not seen");
271         all_ok = false;
272     }
273     if (!seen_callback2_title) {
274         CYG_TEST_FAIL("callback2's title not seen");
275         all_ok = false;
276     }
277     if (number_of_headers != number_of_trailers) {
278         CYG_TEST_FAIL("headers and trailers do not match up");
279         all_ok = false;
280     }
281     if (!callback1_done) {
282         CYG_TEST_FAIL("callback1 did not finish");
283         all_ok = false;
284     }
285     if (!callback2_done) {
286         CYG_TEST_FAIL("callback2 did not finish");
287         all_ok = false;
288     }
289     if (number_of_lines_seen < callback2_lines) {
290         CYG_TEST_FAIL("total number of output lines is less than expected");
291         all_ok = false;
292     }
293     if (callback2_lines_seen != callback2_lines) {
294         CYG_TEST_FAIL("callback2 generated the wrong number of lines");
295         all_ok = false;
296     }
297     
298     if (all_ok) {
299         CYG_TEST_PASS("assertion callbacks");
300     }
301         
302     longjmp(setjmp_buffer, 1);
303     CYG_TEST_FAIL_FINISH("longjmp() is not functional");
304     return false;
305 }
306
307 // ----------------------------------------------------------------------------
308 // main(). Perform the various assertion tests in order.
309
310 cyg_uint32 main_start = (cyg_uint32) __LINE__;
311 int
312 main(int argc, char** argv)
313 {
314     expecting_failure1 = true;
315     // First check, a very basic assertion invocation.
316     if (setjmp(setjmp_buffer) == 0) {
317         cyg_assert_install_failure_handler(&failure_handler1);
318         CYG_FAIL(message);
319         CYG_TEST_FAIL("assertion did not trigger");
320     }
321     expecting_failure1 = false;
322     expecting_failure2 = true;
323
324     // Now try installing a different assertion handler.
325     if (setjmp(setjmp_buffer) == 0) {
326         cyg_assert_install_failure_handler(&failure_handler2);
327         CYG_FAIL(message);
328         CYG_TEST_FAIL("assertion did not trigger");
329     }
330     expecting_failure2 = false;
331     expecting_failure3 = true;
332
333     if (setjmp(setjmp_buffer) == 0) {
334         cyg_assert_install_failure_callback(callback1_title, &callback1);
335         cyg_assert_install_failure_callback(callback2_title, &callback2);
336         cyg_assert_install_failure_handler(&failure_handler3);
337         CYG_FAIL(message);
338         CYG_TEST_FAIL("assertion did not trigger");
339     }
340     expecting_failure3 = false;
341     
342     return 0;
343 }
344 cyg_uint32 main_end = (cyg_uint32) __LINE__;
345