Use a saner variant for computing the number of groups in cpuctl tests
[ltp-debian.git] / pan / tag_report.c
blob0389e715dcd47a07470ec781ab417724f721699a
1 /*
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:
26 * http://www.sgi.com
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"
35 #include "debug.h"
36 #include "reporter.h"
37 #include "splitstr.h"
39 static char * worst_case(char *, char *);
41 /************************************************************************
42 * Report Generation *
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.
55 int
56 test_result(tag, tcid, tc, result, tags)
57 char *tag, *tcid, *tc;
58 char *result;
59 SYM tags;
61 char *expert, expkey[KEYSIZE];
62 register char *c;
63 char **cont;
64 const char **cont_save;
66 if(tcid == NULL)
67 tcid = "-";
68 if(tc == NULL)
69 tc = "-";
70 if(tag == NULL)
71 tag = "test_result: no tag";
72 if(result == NULL)
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) {
78 expert = "UNKNOWN";
81 /* ' tr " " "_" ' */
82 for(c = result; *c; c++) {
83 if(*c == ' ') {
84 *c = '_';
87 if(*result == '\0')
88 result = "?";
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);
97 return 0;
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;
118 DBT Key, Data;
120 /* analysis type: count of CUTS test cases */
121 const char **ant;
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;
128 int ntags, tagcount;
130 char key_get[255];
132 char *result = "", *worst_case(); /* overall result */
134 /* parse analysis type: cuts:tc-count */
135 ant = splitstr((dat=strdup(at)), ":",NULL);
136 if(ant[1] != NULL)
137 tccount=atoi(ant[1]);
138 else
139 tccount=0;
140 free(dat);
141 splitstr_free(ant);
143 /* extract tcids */
144 ntags=NTCID_START;
145 taglist= (char **)malloc(sizeof(char *) * ntags);
146 tagcount=0;
148 tl = taglist;
149 sym_seq(tags, &Key, &Data, R_FIRST);
150 do {
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)
159 continue;
160 DEBUG(D_REPORT, 10)
161 printf("cuts_report: tcid %s\n", (char *)Key.data);
162 *tl++ = Key.data;
163 tagcount++;
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;
173 *tl++ = NULL;
175 ntags = tagcount;
177 /* dump all found records */
178 tcnum=0;
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);
187 do {
188 DEBUG(D_REPORT, 10)
189 printf("cuts_report: tc %s = %s\n", (char *)Key.data,
190 (char *)Data.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))
194 tcnum++;
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);
203 free(taglist);
205 return 0;
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
228 * this file
231 tag_report(alltags, ctag, keys)
232 SYM alltags, ctag, keys;
235 extern int extended;
237 char key_get[KEYSIZE];
238 char *info;
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) {
247 return -1;
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);
254 return -1;
257 if(strcmp(is, "ok")) {
258 test_result(tag, NULL, NULL, is, keys);
259 } else {
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);
270 return -1;
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);
280 return -1;
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);
304 } else {
305 if(strcmp(info, "0")) {
306 test_result(tag, NULL, NULL, "fail", keys);
307 } else {
308 test_result(tag, NULL, NULL, "pass", keys);
312 } else {
313 cuts_report(ctag, keys, info, tag);
318 * Extended Format:
319 * - tcid+tc = "!"
320 * - tab separated fields
321 * - no field widths
322 * - fields 6 - ~ are:
323 * start-time (time_t)
324 * duration
325 * termination_id
326 * termination_type
327 * Start Line (of test results in output file)
328 * End Line
331 if(extended) {
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) {
355 el = "No_End_line";
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,
370 ti, tt, sl, el);
373 return 0;
377 * Print a header made up of the RTS keywords
378 * In "extended" mode, print the header to stderr.
381 print_header(tags)
382 SYM tags;
384 DBT Key, Data;
385 char key_get[255];
387 FILE *out;
389 extern int extended;
391 if(extended)
392 out = stderr;
393 else
394 out = stdout;
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) {
401 do {
402 if(strcmp((char *)Key.data, "PATH")==0)
403 continue;
404 fprintf(out, "%-20.20s %s\n", (char *)Key.data, (char *)Data.data);
405 } while(sym_seq(tags, &Key, &Data, R_NEXT)==0);
408 fprintf(out, "\n");
409 fprintf(out, FORMAT, "tag", "tcid", "testcase", "status", "contact");
410 fprintf(out, "-------------------------------------------------------------------------------\n");
412 return 0;
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)
423 SYM tag, keys;
425 char *cuts_info[5];
426 char key[KEYSIZE];
427 char *oldresult, *newresult, *worst_case();
428 int tok_num=0;
429 extern char yytext[];
431 cuts_info[tok_num] = strtok(yytext, "\t ");
432 while(tok_num < 5 &&
433 (cuts_info[++tok_num] = strtok(NULL, "\t ")) != NULL )
436 strcpy(key, cuts_info[0]);
437 strcat(key, ",");
438 strcat(key, cuts_info[1]);
440 #ifdef DEBUGGING
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);
446 #endif
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 */
454 } else {
455 sym_put(tag, key, strdup(cuts_info[2]), 0);
457 return 0;
461 * Determine a "worst case" status from two given statuses.
463 static char *
464 worst_case(t1, t2)
465 char *t1, *t2;
467 /* NULL-terminated table, ordered from worst-case to best-case */
468 static char *worst[] = {
469 "FAIL", "BROK", "PASS", "CONF",
470 "WARN", "INFO", NULL,
473 char **w1, **w2;
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++)
483 if(w1 < w2)
484 return(t1);
485 else
486 return(t2);