5 * Copyright (c) 2001-2002 Samuel A. Falvo II, William D. Tanksley
6 * See CUT-LICENSE.TXT for details.
8 * Based on WDT's 'TestAssert' package.
25 #ifndef BOOL /* Just in case -- helps in portability */
37 typedef struct test_output
*test_output
;
43 const char *group_name
;
44 const char *test_name
;
48 static int breakpoint
= 0;
49 static int count
= 0, count_failures
= 0, count_errors
= 0;
50 static cut_fn cur_takedown
= 0;
51 static test_output problem_reports
= 0;
52 static const char *program
;
55 die(int code
, const char *fmt
, ...)
62 vfprintf(stderr
, fmt
, v
);
65 if (fmt
&& *fmt
) fputs(": ", stderr
);
66 fprintf(stderr
, "%s\n", strerror(errno
));
72 static void print_string( char *string
)
74 printf( "%s", string
);
78 static void print_string_as_error( char *filename
, int lineNumber
, char *string
)
80 printf( " %s:%d: %s", filename
, lineNumber
, string
);
84 static void print_integer( int i
)
90 static void print_integer_in_field( int i
, int width
)
92 printf( "%*d", width
, i
);
96 static void new_line( void )
102 static void print_character( char ch
)
108 /* CUT Initialization and Takedown Functions */
110 void cut_init(const char *prog_name
, int brkpoint
)
112 breakpoint
= brkpoint
;
118 print_string( "Breakpoint at test " );
119 print_integer( brkpoint
);
124 void cut_exit( void )
131 for (to
= problem_reports
; to
; to
= to
->next
) {
132 printf("\n%s in %s/%s", to
->desc
, to
->group_name
, to
->test_name
);
133 if (!WIFEXITED(to
->status
) || (WEXITSTATUS(to
->status
) != 255)) {
134 if (WIFEXITED(to
->status
)) {
135 printf(" (Exit Status %d)", WEXITSTATUS(to
->status
));
137 if (WIFSIGNALED(to
->status
)) {
138 printf(" (Signal %d)", WTERMSIG(to
->status
));
143 while ((r
= fread(buf
, 1, BUF_SIZE
, to
->file
))) {
144 s
= fwrite(buf
, 1, r
, stdout
);
145 if (r
!= s
) die(3, "fwrite");
149 printf("\n%d tests; %d failures; %d errors.\n", count
, count_failures
,
151 exit(!!(count_failures
+ count_errors
));
154 /* Test Progress Accounting functions */
157 cut_mark_point(char out
, char *filename
, int lineNumber
)
159 if ((count
% 10) == 0) {
160 if ((count
% 50) == 0) new_line();
161 print_integer_in_field( count
, 5 );
164 print_character(out
);
167 if( count
== breakpoint
)
169 print_string_as_error( filename
, lineNumber
, "Breakpoint hit" );
186 print_string_as_error( filename
, lineNumber
, "(" );
187 print_string( expression
);
189 print_string( message
);
192 if (cur_takedown
) cur_takedown();
198 typedef void(*collect_fn
)(void *);
201 collect(pid_t
*pid
, collect_fn fn
, void *data
)
212 if ((*pid
= fork())) {
213 if (*pid
< 0) return 0;
216 r
= dup2(fileno(out
), fileno(stdout
));
217 if (r
< 0) die(3, "dup2");
219 if (r
) die(3, "fclose");
228 run_in_child(void *data
)
231 cut_fn
*fns
= data
, bringup
= fns
[0], test
= fns
[1], takedown
= fns
[2];
233 r
= dup2(fileno(stdout
), fileno(stderr
));
234 if (r
< 0) die(3, "dup2");
236 cur_takedown
= takedown
;
244 __cut_run(char *group_name
, cut_fn bringup
, cut_fn takedown
, char *test_name
,
245 cut_fn test
, char *filename
, int lineno
)
251 char *problem_desc
= 0;
252 cut_fn fns
[3] = { bringup
, test
, takedown
};
254 out
= collect(&pid
, run_in_child
, fns
);
255 if (!out
) die(1, " %s:%d: collect", filename
, lineno
);
256 if (pid
< 0) die(3, "fork");
258 r
= waitpid(pid
, &status
, 0);
259 if (r
!= pid
) die(3, "wait");
262 cut_mark_point('.', filename
, lineno
);
263 } else if (WIFEXITED(status
) && (WEXITSTATUS(status
) == 255)) {
264 cut_mark_point('F', filename
, lineno
);
266 problem_desc
= "Failure";
268 cut_mark_point('E', filename
, lineno
);
270 problem_desc
= "Error";
278 /* collect the output */
279 to
= malloc(sizeof(struct test_output
));
280 if (!to
) die(3, "malloc");
282 to
->desc
= problem_desc
;
284 to
->group_name
= group_name
;
285 to
->test_name
= test_name
;
287 to
->next
= problem_reports
;
288 problem_reports
= to
;