copied mono-api-diff.cs from mono-2-2 branch so new patch can be applied and history...
[mono.git] / eglib / test / test.c
1 /*
2  * EGLib Unit Group/Test Runners
3  *
4  * Author:
5  *   Aaron Bockover (abockover@novell.com)
6  *
7  * (C) 2006 Novell, Inc.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining
10  * a copy of this software and associated documentation files (the
11  * "Software"), to deal in the Software without restriction, including
12  * without limitation the rights to use, copy, modify, merge, publish,
13  * distribute, sublicense, and/or sell copies of the Software, and to
14  * permit persons to whom the Software is furnished to do so, subject to
15  * the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be
18  * included in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27  */
28
29 #ifndef _GNU_SOURCE
30 #define _GNU_SOURCE
31 #endif
32
33 #include <config.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <stdarg.h>
38 #include <glib.h>
39 #ifdef HAVE_SYS_TIME_H
40 #include <sys/time.h>
41 #endif
42 #ifdef G_OS_WIN32
43 #include <winsock2.h>
44 #endif
45
46 #include "test.h"
47
48 extern gint global_passed, global_tests;
49
50 static gchar *last_result = NULL;
51
52 gboolean 
53 run_test(Test *test, gchar **result_out)
54 {
55         gchar *result; 
56
57         if((result = test->handler()) == NULL) {
58                 *result_out = NULL;
59                 return TRUE;
60         } else {
61                 *result_out = result;   
62                 return FALSE;
63         }
64 }
65
66 gboolean
67 run_group(Group *group, gint iterations, gboolean quiet, 
68         gboolean time, gchar *tests_to_run_s)
69 {
70         Test *tests = group->handler();
71         gint i, j, passed = 0, total = 0;
72         gdouble start_time_group, start_time_test;
73         gchar **tests_to_run = NULL;
74
75         if(!quiet) {
76                 if(iterations > 1) {
77                         printf("[%s] (%dx)\n", group->name, iterations);
78                 } else {
79                         printf("[%s]\n", group->name);
80                 }
81         }
82
83         if(tests_to_run_s != NULL) {
84                 tests_to_run = eg_strsplit(tests_to_run_s, ",", -1);
85         }
86
87         start_time_group = get_timestamp();
88
89         for(i = 0; tests[i].name != NULL; i++) {
90                 gchar *result = "";
91                 gboolean iter_pass, run;
92         
93                 iter_pass = FALSE;
94                 if(tests_to_run != NULL) {
95                         gint j;
96                         run = FALSE;
97                         for(j = 0; tests_to_run[j] != NULL; j++) {
98                                 if(strcmp(tests_to_run[j], tests[i].name) == 0) {
99                                         run = TRUE;
100                                         break;
101                                 }
102                         }
103                 } else {
104                         run = TRUE;
105                 }
106
107                 if(!run) {
108                         continue;
109                 }
110         
111                 total++;
112         
113                 if(!quiet) {
114                         printf("  %s: ", tests[i].name);
115                 }
116
117                 start_time_test = get_timestamp();
118                 
119                 for(j = 0; j < iterations; j++) {
120                         iter_pass = run_test(&(tests[i]), &result);
121                         if(!iter_pass) {
122                                 break;
123                         }
124                 }
125
126                 if(iter_pass) {
127                         passed++;
128                         if(!quiet) {
129                                 if(time) {
130                                         printf("OK (%g)\n", get_timestamp() - start_time_test);
131                                 } else {
132                                         printf("OK\n");
133                                 }
134                         }
135                 } else  {                       
136                         if(!quiet) {
137                                 printf("FAILED (%s)\n", result);
138                         }
139                         
140                         if(last_result == result) {
141                                 last_result = NULL;
142                                 g_free(result);
143                         }
144                 }
145         }
146
147         global_passed += passed;
148         global_tests += total;
149
150         if(!quiet) {
151                 gdouble pass_percentage = ((gdouble)passed / (gdouble)total) * 100.0;
152                 if(time) {
153                         printf("  %d / %d (%g%%, %g)\n", passed, total,
154                                 pass_percentage, get_timestamp() - start_time_group);
155                 } else {
156                         printf("  %d / %d (%g%%)\n", passed, total, pass_percentage);
157                 }
158         }
159
160         if(tests_to_run != NULL) {
161                 eg_strfreev(tests_to_run);
162         }
163
164         return passed == total;
165 }
166
167 RESULT
168 FAILED(const gchar *format, ...)
169 {
170         gchar *ret;
171         va_list args;
172         gint n;
173
174         va_start(args, format);
175         n = vasprintf(&ret, format, args);
176         va_end(args);
177
178         if(n == -1) {
179                 last_result = NULL;
180                 return NULL;
181         }
182
183         last_result = ret;
184         return ret;
185 }
186
187 gdouble
188 get_timestamp()
189 {
190         /* FIXME: We should use g_get_current_time here */
191         GTimeVal res;
192         g_get_current_time (&res);
193         return res.tv_sec + (1.e-6) * res.tv_usec;
194 }
195
196 /* 
197  * Duplicating code here from EGlib to avoid g_strsplit skew between
198  * EGLib and GLib
199  */
200  
201 gchar ** 
202 eg_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens)
203 {
204         gchar *string_c;
205         gchar *strtok_save, **vector;
206         gchar *token, *token_c;
207         gint size = 1;
208         size_t token_length;
209
210         g_return_val_if_fail(string != NULL, NULL);
211         g_return_val_if_fail(delimiter != NULL, NULL);
212         g_return_val_if_fail(delimiter[0] != 0, NULL);
213         
214         token_length = strlen(string);
215         string_c = (gchar *)g_malloc(token_length + 1);
216         memcpy(string_c, string, token_length);
217         string_c[token_length] = 0;
218         
219         vector = NULL;
220         token = (gchar *)strtok_r(string_c, delimiter, &strtok_save);
221
222         while(token != NULL) {
223                 token_length = strlen(token);
224                 token_c = (gchar *)g_malloc(token_length + 1);
225                 memcpy(token_c, token, token_length);
226                 token_c[token_length] = 0;
227
228                 vector = vector == NULL ? 
229                         (gchar **)g_malloc(2 * sizeof(vector)) :
230                         (gchar **)g_realloc(vector, (size + 1) * sizeof(vector));
231         
232                 vector[size - 1] = token_c;     
233                 size++;
234
235                 if(max_tokens > 0 && size >= max_tokens) {
236                         if(size > max_tokens) {
237                                 break;
238                         }
239
240                         token = strtok_save;
241                 } else {
242                         token = (gchar *)strtok_r(NULL, delimiter, &strtok_save);
243                 }
244         }
245
246         if(vector != NULL && size > 0) {
247                 vector[size - 1] = NULL;
248         }
249         
250         g_free(string_c);
251         string_c = NULL;
252
253         return vector;
254 }
255
256 void
257 eg_strfreev (gchar **str_array)
258 {
259         gchar **orig = str_array;
260         if (str_array == NULL)
261                 return;
262         while (*str_array != NULL){
263                 g_free (*str_array);
264                 str_array++;
265         }
266         g_free (orig);
267 }
268
269
270