2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
33 /* $Id: tag_report.c,v 1.2 2006/12/13 22:55:22 vapier Exp $ */
34 #include "tag_report.h"
39 static char * worst_case(char *, char *);
41 /************************************************************************
43 ************************************************************************/
46 * printf format statement for standard reports
47 * 5 fields with max/min widths
49 #define FORMAT "%-20.20s %-15.15s %10.10s %-20.20s %s\n"
52 * This is the central results reporting function. All standard report
53 * format results are printed thru test_result.
56 test_result(tag
, tcid
, tc
, result
, tags
)
57 char *tag
, *tcid
, *tc
;
61 char *expert
, expkey
[KEYSIZE
];
64 const char **cont_save
;
71 tag
= "test_result: no tag";
73 result
= "(RESULT IS NULL)";
75 strcpy(expkey
, "contacts");
76 /* note: the sym_get here does _not_ change the "cursor" */
77 if((expert
= (char *)sym_get(tags
, expkey
)) == NULL
) {
82 for(c
= result
; *c
; c
++) {
90 /* split contacts on "," and print out a line for each */
91 cont_save
= splitstr(expert
, ",", NULL
);
92 for(cont
=(char **)cont_save
;*cont
!= NULL
; cont
++) {
93 printf(FORMAT
, tag
, tcid
, tc
, result
, *cont
);
95 splitstr_free(cont_save
);
102 * CUTS test reporting.
104 * (1) make a list (2d char array) of all TCIDs (see above for why)
105 * (2) look thru the list:
106 * (a) keep track of the "worst case" in this *TAG*
107 * (b) report each testcase's results
108 * (c) if the testcase number is != 0, count it
109 * (3) report tag's results
110 * (4) check the number of expected results with the actual results,
111 * report an error if they don't match.
115 cuts_report(tags
, keys
, at
, tag
)
116 SYM tags
, keys
; char *at
, *tag
;
120 /* analysis type: count of CUTS test cases */
122 char *dat
; /* strdup(at) */
123 int tccount
; /* expected count of testcases */
124 int tcnum
; /* seen count of testcases */
126 /* a list of tcids */
127 char **taglist
, **tl
;
132 char *result
= "", *worst_case(); /* overall result */
134 /* parse analysis type: cuts:tc-count */
135 ant
= splitstr((dat
=strdup(at
)), ":",NULL
);
137 tccount
=atoi(ant
[1]);
145 taglist
= (char **)malloc(sizeof(char *) * ntags
);
149 sym_seq(tags
, &Key
, &Data
, R_FIRST
);
151 if(tagcount
== ntags
) {
152 /* exceeded tag array size -- realloc */
153 ntags
+= NTCID_START
;
154 taglist
= (char **)realloc(taglist
, sizeof(char *) * ntags
);
155 tl
= taglist
+tagcount
;
158 if(strcmp((char *)Key
.data
, "_keys")==0)
161 printf("cuts_report: tcid %s\n", (char *)Key
.data
);
164 } while(sym_seq(tags
, &Key
, &Data
, R_NEXT
)==0);
166 if(tagcount
== ntags
) {
167 /* exceeded tag array size -- realloc */
168 ntags
++; /* need just one more */
169 taglist
= (char **)realloc(taglist
, sizeof(char *) * ntags
);
170 tl
= taglist
+tagcount
;
177 /* dump all found records */
179 for(tl
=taglist
; *tl
!= NULL
; tl
++) {
181 strcpy(key_get
, *tl
);
182 Key
.data
= (void *) key_get
;
184 /*sym_dump_s(sym_get(tags, key_get), 0);*/
186 sym_seq(tags
, &Key
, &Data
, R_CURSOR
);
189 printf("cuts_report: tc %s = %s\n", (char *)Key
.data
,
191 result
= worst_case(result
, (char *)Data
.data
);
192 test_result(tag
, *tl
, (char *)Key
.data
, (char *)Data
.data
, keys
);
193 if(atoi((char *)Key
.data
))
195 } while(sym_seq(tags
, &Key
, &Data
, R_NEXT
)==0);
198 test_result(tag
, "*", "*", result
, keys
);
200 if(tccount
!= 0 && tccount
!= tcnum
)
201 test_result(tag
, "-", "-", "TC count wrong", keys
);
209 * Do the report generation.
211 * A problem: I really need multiple cursors. I'd rather not look into
212 * the depths of the current symbol table implimentation (there are the
213 * cursors there that I could use) so that a different (faster!) symbol
214 * table can be used in the future.
216 * I could get a key (tag), get it's sub-keys (TCIDs), then get the key
217 * again to reset to the top level, _then_ get the next key. That would
218 * be very inefficient.
220 * The solution I chose is to extract all tags into a list (char array),
221 * then go thru that list with the cursor free for other levels to use.
223 * (1) make a list (2d char array) of all Tags
224 * (2) search for the first tag that has a "stime" record, and use that as
225 * the date (MMDDYY) that the tests were run.
226 * (3) print the report header
227 * (4) go thru all tags and report each as described at the beginning of
231 tag_report(alltags
, ctag
, keys
)
232 SYM alltags
, ctag
, keys
;
237 char key_get
[KEYSIZE
];
240 /* retrieved _keys values: initation status, start time, duration,
241 * termination type, termination id, start line, end line. */
242 char *tag
, *contact
, *is
, *mystime
, *duration
, *tt
, *ti
, *sl
, *el
;
244 /* Check all driver-level status first */
245 strcpy(key_get
, "tag");
246 if((tag
= (char *)sym_get(keys
, key_get
)) == NULL
) {
250 /* Check all driver-level status first */
251 strcpy(key_get
, "initiation_status");
252 if((is
= (char *)sym_get(keys
, key_get
)) == NULL
) {
253 test_result(tag
, NULL
, NULL
, "no init status", keys
);
257 if(strcmp(is
, "ok")) {
258 test_result(tag
, NULL
, NULL
, is
, keys
);
261 strcpy(key_get
, "corefile");
262 if((info
= (char *)sym_get(keys
, key_get
)) != NULL
)
263 if(strcmp(info
, "no") != 0) {
264 test_result(tag
, NULL
, NULL
, "coredump", keys
);
267 strcpy(key_get
, "termination_type");
268 if((tt
= (char *)sym_get(keys
, key_get
))==NULL
) {
269 test_result(tag
, NULL
, NULL
, "no Term Type", keys
);
273 if(strcmp(tt
, "exited")) {
274 test_result(tag
, NULL
, NULL
, tt
, keys
);
277 strcpy(key_get
, "analysis");
278 if((info
= (char *)sym_get(keys
, key_get
)) == NULL
) {
279 test_result(tag
, NULL
, NULL
, "no Analysis Type", keys
);
283 /* Getting here indicates that there were no fatal driver-level
284 * errors. Do the kind of reporting requested by the test.
287 if(strncmp(info
, "none", 4) == 0 ) {
289 * If analysis is 'none', alway report the test as
290 * a pass regardless of output or exit status.
292 test_result(tag
, NULL
, NULL
, "pass", keys
);
294 } else if(strncmp(info
, "cuts", 4)) {
297 * If analysis is not cuts, assume it is 'exit', thus
298 * the termination_id is used to determine pass/fail result.
300 if ( strcmp(tt
, "timeout") ) {
301 strcpy(key_get
, "termination_id");
302 if((info
= (char *)sym_get(keys
, key_get
)) == NULL
) {
303 test_result(tag
, NULL
, NULL
, "no_Term_Id", keys
);
305 if(strcmp(info
, "0")) {
306 test_result(tag
, NULL
, NULL
, "fail", keys
);
308 test_result(tag
, NULL
, NULL
, "pass", keys
);
313 cuts_report(ctag
, keys
, info
, tag
);
320 * - tab separated fields
322 * - fields 6 - ~ are:
323 * start-time (time_t)
327 * Start Line (of test results in output file)
333 strcpy(key_get
, "termination_id");
334 if((ti
= (char *)sym_get(keys
, key_get
)) == NULL
) {
335 ti
= "No_Termination_ID";
338 strcpy(key_get
, "termination_type");
339 if((tt
= (char *)sym_get(keys
, key_get
)) == NULL
) {
340 tt
= "No_Termination_Type";
343 strcpy(key_get
, "duration");
344 if((duration
= (char *)sym_get(keys
, key_get
)) == NULL
) {
345 duration
= "No_Duration";
348 strcpy(key_get
, "_Start_line");
349 if((sl
= (char *)sym_get(keys
, key_get
)) == NULL
) {
350 sl
= "No_Start_line";
353 strcpy(key_get
, "_End_line");
354 if((el
= (char *)sym_get(keys
, key_get
)) == NULL
) {
358 strcpy(key_get
, "contacts");
359 if((contact
= (char *)sym_get(keys
, key_get
)) == NULL
) {
360 contact
= "No_Contacts";
363 strcpy(key_get
, "stime");
364 if((mystime
= (char *)sym_get(keys
, key_get
)) == NULL
) {
365 mystime
= "No_stime";
368 printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
369 tag
, "!", "!", is
, contact
, mystime
, duration
,
377 * Print a header made up of the RTS keywords
378 * In "extended" mode, print the header to stderr.
396 fprintf(out
, "System Configuration:\n");
397 /* build header out of RTS keywords */
398 sprintf(key_get
, "_RTS");
399 Key
.data
= (void *) key_get
;
400 if(sym_seq(tags
, &Key
, &Data
, R_CURSOR
) == 0) {
402 if(strcmp((char *)Key
.data
, "PATH")==0)
404 fprintf(out
, "%-20.20s %s\n", (char *)Key
.data
, (char *)Data
.data
);
405 } while(sym_seq(tags
, &Key
, &Data
, R_NEXT
)==0);
409 fprintf(out
, FORMAT
, "tag", "tcid", "testcase", "status", "contact");
410 fprintf(out
, "-------------------------------------------------------------------------------\n");
416 * CUTS testcase record
418 * This is passed s SYM for the current tag and the initiation keys.
419 * The text seen by lex is in yytext (global).
422 cuts_testcase(tag
, keys
)
427 char *oldresult
, *newresult
, *worst_case();
429 extern char yytext
[];
431 cuts_info
[tok_num
] = strtok(yytext
, "\t ");
433 (cuts_info
[++tok_num
] = strtok(NULL
, "\t ")) != NULL
)
436 strcpy(key
, cuts_info
[0]);
438 strcat(key
, cuts_info
[1]);
441 DEBUG(D_SCAN_CUTS
, 1) {
442 printf("cuts_testcase: TCID=%s TC=%s Result=%s\n", cuts_info
[0],
443 cuts_info
[1], cuts_info
[2]);
444 printf("cuts_testcase: %d %s\n", tok_num
, key
);
448 if((oldresult
=(char *)sym_get(tag
, key
)) != NULL
) {
449 /* Duplicate -- assume mulitple runs */
450 /* keep "worst case" */
451 newresult
= worst_case(oldresult
, cuts_info
[2]);
452 sym_put(tag
, key
, strdup(newresult
), PUT_REPLACE
);
453 free(oldresult
); /* remove the "data" portion of the key */
455 sym_put(tag
, key
, strdup(cuts_info
[2]), 0);
461 * Determine a "worst case" status from two given statuses.
467 /* NULL-terminated table, ordered from worst-case to best-case */
468 static char *worst
[] = {
469 "FAIL", "BROK", "PASS", "CONF",
470 "WARN", "INFO", NULL
,
475 /* Search the table for each status, then use the index to determine
476 which has a lower precedence */
477 for(w1
=worst
; *w1
!= NULL
&& strcmp(t1
,*w1
); w1
++)
480 for(w2
=worst
; *w2
!= NULL
&& strcmp(t2
,*w2
); w2
++)