1 static const char version[] = "$Id: test.c,v 1.18 2013/10/03 21:18:36 valtri Exp $";
2
3 /*
4 * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
5 *
6 * See the COPYING file for the terms of usage and distribution.
7 */
8
9 #ifdef HAVE_CONFIG_H
10 # include "config.h"
11 #endif
12 #include <sd/test.h>
13 #include <sd/malloc.h>
14 #include <sd/sprintf.h>
15 #include <sd/sd_xplatform.h>
16
17 #include <stdlib.h>
18 #include <string.h>
19 #if !defined(_WIN32) || defined(__MINGW32__) || defined(__MINGW32__)
20 #include <sys/time.h>
21 #endif
22
23 typedef XP_UINT64 usec_t;
24
25 #define MAX_NFUNC 100
26
27 struct __sd_test
28 {
29 char* name;
30 char in_filename[128];
31 char ref_filename[128];
32 char out_filename[128];
33 FILE* in;
34 FILE* out;
35 FILE* err;
36 int verbose;
37 int timed;
38 sd_test_func_t** funcs;
39 int size;
40 int argc;
41 char** argv;
42 void* udata;
43 };
44
45
46 /******************************************************************************/
now(void)47 static usec_t now(void)
48 {
49
50 #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__)
51 FILETIME tv;
52 ULARGE_INTEGER li;
53 #else
54 struct timeval tv;
55 #endif
56
57 SD_GETTIMEOFDAY(&tv, NULL);
58
59 #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__)
60 memcpy(&li, &tv, sizeof(FILETIME));
61 li.QuadPart /= 10; /* In microseconds */
62 /* printf("timestampstamp usec %I64u\n", li.QuadPart);*/
63 return li.QuadPart;
64 #else
65 return (usec_t) (tv.tv_sec * 1000000 + tv.tv_usec);
66 #endif
67 }
68
69 /******************************************************************************/
sd_test_new(int a_argc,char * a_argv[])70 extern sd_test_t* sd_test_new(int a_argc, char* a_argv[])
71 {
72 sd_test_t* this;
73 int c;
74 char* ptr;
75
76 this = sd_calloc(1, sizeof(sd_test_t));
77 this->funcs = sd_calloc(MAX_NFUNC, sizeof(sd_test_func_t *));
78
79 /*
80 * Get rid of libtool frontend script. It is not always there (for example
81 * on FreeBSD) ==> get the basename first.
82 */
83 ptr = strrchr(a_argv[0], '/');
84 this->name = ptr ? ptr + 1 : a_argv[0];
85 ptr = strstr(this->name, "lt-");
86 if (ptr) this->name = ptr + 3;
87 this->name = strdup(this->name);
88 #ifdef _WIN32
89 /* strip .exe extension if found */
90 if (strlen(this->name) > 4) {
91 ptr = this->name + strlen(this->name) - 4;
92 if (strcasecmp(ptr, ".exe") == 0) ptr[0] = '\x0';
93 }
94 #endif
95
96 snprintf(this->ref_filename, sizeof(this->ref_filename), "%s.ref",
97 this->name);
98 snprintf(this->in_filename, sizeof(this->in_filename), "%s.in",
99 this->name);
100 snprintf(this->out_filename, sizeof(this->out_filename), "%s.out",
101 this->name);
102
103 this->in = fopen(this->in_filename, "r");
104 this->out = fopen(this->out_filename, "w");
105 this->err = 0;
106 this->verbose= 0;
107 this->size = 0;
108
109 while ((c = SD_GETOPT(a_argc, a_argv, "vt")) != EOF) {
110 switch(c) {
111 case 'v': this->verbose = 1; break;
112 case 't': this->timed = 1; break;
113 default: break;
114 }
115 }
116
117 this->argc = a_argc - (SD_OPTIND - 1);
118 this->argv = a_argv + (SD_OPTIND - 1);
119 return this;
120 }
121
122 /******************************************************************************/
sd_test_delete(sd_test_t * this)123 extern void sd_test_delete(sd_test_t* this)
124 {
125 if (!this)
126 return;
127
128 if (this->in) fclose(this->in);
129 if (this->out) fclose(this->out);
130 free(this->name);
131 free(this->funcs);
132 free(this);
133 }
134
135 /******************************************************************************/
sd_test_get_name(const sd_test_t * this)136 extern const char* sd_test_get_name(const sd_test_t* this)
137 {
138 return this ? this->name : NULL;
139 }
140
141 /******************************************************************************/
sd_test_get_verbose(const sd_test_t * this)142 extern int sd_test_get_verbose(const sd_test_t* this)
143 {
144 return this ? this->verbose: 0;
145 }
146
147 /******************************************************************************/
sd_test_set_verbose(sd_test_t * this,int a_verbose)148 extern int sd_test_set_verbose(sd_test_t* this, int a_verbose)
149 {
150 if (!this)
151 return 0;
152
153 return this->verbose = a_verbose;
154 }
155
156 /******************************************************************************/
sd_test_in(sd_test_t * this)157 extern FILE* sd_test_in(sd_test_t* this)
158 {
159 if (!this)
160 return NULL;
161
162 return this->in ? this->in : stdin;
163 }
164
165 /******************************************************************************/
sd_test_out(sd_test_t * this)166 extern FILE* sd_test_out(sd_test_t* this)
167 {
168 if (!this)
169 return NULL;
170
171 if (this->verbose)
172 return stdout;
173
174 return this->out ? this->out : stdout;
175 }
176
177 /******************************************************************************/
sd_test_err(sd_test_t * this)178 extern FILE* sd_test_err(sd_test_t* this)
179 {
180 if (!this)
181 return NULL;
182
183 return this->err ? this->err : stderr;
184 }
185
186 /******************************************************************************/
sd_test_run(sd_test_t * this,int argc,char * argv[])187 extern int sd_test_run(sd_test_t* this, int argc, char* argv[])
188 {
189 int i, passed = 0;
190
191 if (!this)
192 return -1;
193
194 fprintf(sd_test_err(this), "%s: ", this->name);
195
196 for (i = 0; i < this->size; i++) {
197 int t;
198 usec_t elapsed;
199
200 fprintf(sd_test_out(this), "=> test #%d :\n", i);
201
202 elapsed = now();
203 t = (*this->funcs[i])(this, this->argc, this->argv);
204 elapsed = now() - elapsed;
205
206 fprintf(sd_test_out(this), "=> test #%d : %s\n", i, t ? " passed" : " failed");
207 fflush(sd_test_out(this));
208
209 passed += (t != 0);
210
211 fprintf(sd_test_err(this), "%c", t ? '+' : '-');
212 if (this->timed)
213 #ifdef _WIN32
214 fprintf(sd_test_err(this), "%I64u ", elapsed);
215 #else
216 fprintf(sd_test_err(this), "%llu ", elapsed);
217 #endif
218 }
219
220 fprintf(sd_test_err(this), " %d/%d %s.\n", passed, this->size,
221 passed == this->size ? " passed" : " failed");
222
223 return passed == this->size;
224 }
225
226 /******************************************************************************/
sd_test_add(sd_test_t * this,sd_test_func_t a_func)227 extern int sd_test_add(sd_test_t* this, sd_test_func_t a_func)
228 {
229 if (!this)
230 return -1;
231
232 if (this->size == MAX_NFUNC)
233 return this->size;
234
235 this->funcs[this->size] = a_func;
236
237 return this->size++;
238 }
239
240 /******************************************************************************/
sd_test_get_udata(sd_test_t * this)241 extern void* sd_test_get_udata(sd_test_t* this)
242 {
243 return this->udata;
244 }
245
246 /******************************************************************************/
sd_test_set_udata(sd_test_t * this,void * a_udata)247 extern void sd_test_set_udata(sd_test_t* this, void* a_udata)
248 {
249 this->udata = a_udata;
250 }
251