Update copyright to LGPL on all files
[dyninst.git] / testsuite / src / StdOutputDriver.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31 // StdOutputDriver.C
32 // Implements the standard test_driver output system
33
34 #include "TestOutputDriver.h"
35 #include "StdOutputDriver.h"
36 #include "test_info_new.h"
37
38 #include <map>
39 #include <string>
40
41 #include <string.h>
42 #include <stdarg.h>
43 #include <stdio.h>
44 #include <assert.h>
45 #include <stdlib.h>
46
47 StdOutputDriver::StdOutputDriver(void * data) : attributes(NULL), streams() {
48   streams[STDOUT] = std::string("-");
49   streams[STDERR] = std::string("-");
50   streams[LOGINFO] = std::string("-");
51   streams[LOGERR] = std::string("-");
52   streams[HUMAN] = std::string("-");
53   last_test = NULL;
54   last_group = NULL;
55 }
56
57 StdOutputDriver::~StdOutputDriver() {
58   if (attributes != NULL) {
59     delete attributes;
60   }
61 }
62
63 void StdOutputDriver::startNewTest(std::map<std::string, std::string> &attrs, TestInfo *test, RunGroup *group) {
64   if (attributes != NULL) {
65     delete attributes;
66     attributes = NULL;
67   }
68   last_test = test;
69   last_group = group;
70
71   attributes = new std::map<std::string, std::string>(attrs);
72 }
73
74 void StdOutputDriver::redirectStream(TestOutputStream stream, const char *filename) {
75   if (streams.find(stream) == streams.end()) {
76     fprintf(stderr, "[%s:%u] - StdOutputDriver::redirectStream called with unexpected stream value %d\n", __FILE__, __LINE__, stream);
77   } else {
78     streams[stream] = std::string(filename);
79   }
80 }
81
82 void StdOutputDriver::logResult(test_results_t result, int stage) {
83    // TODO Finish me.  I can probably copy the final output stuff from
84    // test_driver.C into here.
85    
86    // I think this just has to print out the human log results
87    bool print_stage = false;
88    const char *outfn = streams[HUMAN].c_str();
89    FILE *out;
90    if (strcmp(outfn, "-") == 0) {
91       out = stdout;
92    } else {
93       out = fopen(outfn, "a");
94       if (NULL == out) {
95          out = stdout;
96       }
97    }
98    
99    // Now print out a summary results line
100    const char *run_mode_str;
101    const char *orig_run_mode_str = (*attributes)["run_mode"].c_str();
102    if (strcmp(orig_run_mode_str, "createProcess") == 0)
103       run_mode_str = "create";
104    else if (strcmp(orig_run_mode_str, "useAttach") == 0)
105       run_mode_str = "attach";
106    else if (strcmp(orig_run_mode_str, "binary") == 0)
107       run_mode_str = "rewriter";
108    else
109       run_mode_str = orig_run_mode_str;
110    assert(last_test && last_group);
111
112    int max_name_len = TestInfo::getMaxTestNameLength();
113    if (!max_name_len)
114            max_name_len = strlen(last_test->name);
115    char *name_align_buffer = (char *) malloc(max_name_len);
116    //  fill name_align_buffer with max_length - test_name->length() spaces.
117    unsigned int i = 0;
118    for (; i < (max_name_len - strlen(last_test->name)); ++i)
119    {
120            name_align_buffer[i] = ' ';
121    }
122    name_align_buffer[i] = '\0';
123 #if defined(cap_32_64_test)
124    fprintf(out, "%s:%s compiler: %s\topt: %s\tabi: %s\tmode: %-10s\tresult: ",
125            last_test->name, name_align_buffer, last_group->compiler, last_group->optlevel, last_group->abi, run_mode_str);
126 #else
127    fprintf(out, "%s:%s compiler: %s\topt: %s\tmode: %-10s\tresult: ",
128            last_test->name, name_align_buffer, last_group->compiler, last_group->optlevel, run_mode_str);
129 #endif
130    free(name_align_buffer);
131    switch(result) {
132       case PASSED:
133          fprintf(out, "PASSED");
134          break;
135          
136       case FAILED:
137          fprintf(out, "FAILED");
138          print_stage = true;
139          break;
140          
141       case SKIPPED:
142          fprintf(out, "SKIPPED");
143          break;
144          
145       case CRASHED:
146          fprintf(out, "CRASHED");
147          print_stage = true;
148          break;
149
150       default:
151          fprintf(out, "UNKNOWN");
152    }
153    
154    if (print_stage && stage != -1)
155    {
156      switch ( (test_runstate_t) stage)
157      {
158      case program_setup_rs:
159        fprintf(out, " (Module Setup)");
160        break;
161      case group_setup_rs:
162        fprintf(out, " (Group Setup)");
163        break;
164      case group_teardown_rs:
165        fprintf(out, " (Group Teardown)");
166        break;
167      case test_init_rs:
168        fprintf(out, " (Test Init)");
169        break;
170      case test_setup_rs:
171        fprintf(out, " (Test Setup)");
172        break;
173      case test_execute_rs:
174        fprintf(out, " (Running Test)");
175        break;
176      case test_teardown_rs:
177        fprintf(out, " (Test Teardown)");
178        break;
179      default:
180        fprintf(out, "\nUnknown test state: %d\n", stage);
181        assert(0);
182        break;
183      }
184    }
185
186    fprintf(out, "\n");
187    
188    if ((out != stdout) && (out != stderr)) {
189       fclose(out);
190    } else {
191       fflush(out);
192    }
193    last_group = NULL;
194    last_test = NULL;
195 }
196
197 void StdOutputDriver::logCrash(std::string testname) {
198   // TODO Do something here
199 }
200
201 void StdOutputDriver::log(TestOutputStream stream, const char *fmt, ...) {
202   va_list args;
203   va_start(args, fmt);
204   vlog(stream, fmt, args);
205   va_end(args);
206 }
207
208 void StdOutputDriver::vlog(TestOutputStream stream, const char *fmt, va_list args) {
209   // If stream is an invalid stream, return
210   if (streams.find(stream) == streams.end()) {
211     fprintf(stderr, "[%s:%u] - StdOutputDriver::log called with unexpected stream value %d\n", __FILE__, __LINE__, stream);
212     return;
213   }
214
215   // If the stream has been redirected to NULL, ignore this output
216   if (NULL == streams[stream].c_str()) {
217     return;
218   }
219
220   const char *fn = streams[stream].c_str();
221   FILE *out;
222   if (strcmp(fn, "-") == 0) {
223     // We're printing to the default file
224     switch(stream) {
225     case STDOUT:
226     case LOGINFO:
227     case HUMAN:
228       out = stdout;
229       break;
230
231     case STDERR:
232     case LOGERR:
233       out = stderr;
234       break;
235     }
236   } else {
237     // Open the file
238     out = fopen(fn, "a");
239     if (NULL == out) {
240       // TODO Handle this error
241       return;
242     }
243   }
244
245   vfprintf(out, fmt, args);
246
247   if ((out != stdout) && (out != stderr)) {
248     fclose(out);
249   }
250 }
251
252 void StdOutputDriver::finalizeOutput() {
253   // I don't think this method needs to do anything for StdOutputDriver
254 }