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