New tests, updates
[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 #include <config.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdarg.h>
34 #include <glib.h>
35 #ifdef HAVE_SYS_TIME_H
36 #include <sys/time.h>
37 #endif
38 #ifdef G_OS_WIN32
39 #include <winsock2.h>
40 #endif
41
42 #include "test.h"
43
44 extern gint global_passed, global_tests;
45
46 static gchar *last_result = NULL;
47
48 gboolean 
49 run_test(Test *test, gchar **result_out)
50 {
51         gchar *result; 
52
53         if((result = test->handler()) == NULL) {
54                 *result_out = NULL;
55                 return TRUE;
56         } else {
57                 *result_out = result;   
58                 return FALSE;
59         }
60 }
61
62 gboolean
63 run_group(Group *group, gint iterations, gboolean quiet, 
64         gboolean time, gchar *tests_to_run_s)
65 {
66         Test *tests = group->handler();
67         gint i, j, passed = 0, total = 0;
68         gdouble start_time_group, start_time_test;
69         gchar **tests_to_run = NULL;
70
71         if(!quiet) {
72                 if(iterations > 1) {
73                         printf("[%s] (%dx)\n", group->name, iterations);
74                 } else {
75                         printf("[%s]\n", group->name);
76                 }
77         }
78
79         if(tests_to_run_s != NULL) {
80                 tests_to_run = eg_strsplit(tests_to_run_s, ",", -1);
81         }
82
83         start_time_group = get_timestamp();
84
85         for(i = 0; tests[i].name != NULL; i++) {
86                 gchar *result = "";
87                 gboolean iter_pass, run;
88         
89                 iter_pass = FALSE;
90                 if(tests_to_run != NULL) {
91                         gint j;
92                         run = FALSE;
93                         for(j = 0; tests_to_run[j] != NULL; j++) {
94                                 if(strcmp(tests_to_run[j], tests[i].name) == 0) {
95                                         run = TRUE;
96                                         break;
97                                 }
98                         }
99                 } else {
100                         run = TRUE;
101                 }
102
103                 if(!run) {
104                         continue;
105                 }
106         
107                 total++;
108         
109                 if(!quiet) {
110                         printf("  %s: ", tests[i].name);
111                 }
112
113                 start_time_test = get_timestamp();
114                 
115                 for(j = 0; j < iterations; j++) {
116                         iter_pass = run_test(&(tests[i]), &result);
117                         if(!iter_pass) {
118                                 break;
119                         }
120                 }
121
122                 if(iter_pass) {
123                         passed++;
124                         if(!quiet) {
125                                 if(time) {
126                                         printf("OK (%g)\n", get_timestamp() - start_time_test);
127                                 } else {
128                                         printf("OK\n");
129                                 }
130                         }
131                 } else  {                       
132                         if(!quiet) {
133                                 printf("FAILED (%s)\n", result);
134                         }
135                         
136                         if(last_result == result) {
137                                 last_result = NULL;
138                                 g_free(result);
139                         }
140                 }
141         }
142
143         global_passed += passed;
144         global_tests += total;
145
146         if(!quiet) {
147                 gdouble pass_percentage = ((gdouble)passed / (gdouble)total) * 100.0;
148                 if(time) {
149                         printf("  %d / %d (%g%%, %g)\n", passed, total,
150                                 pass_percentage, get_timestamp() - start_time_group);
151                 } else {
152                         printf("  %d / %d (%g%%)\n", passed, total, pass_percentage);
153                 }
154         }
155
156         if(tests_to_run != NULL) {
157                 eg_strfreev(tests_to_run);
158         }
159
160         return passed == total;
161 }
162
163 RESULT
164 FAILED(const gchar *format, ...)
165 {
166         gchar *ret;
167         va_list args;
168         gint n;
169
170         va_start(args, format);
171         n = vasprintf(&ret, format, args);
172         va_end(args);
173
174         if(n == -1) {
175                 last_result = NULL;
176                 return NULL;
177         }
178
179         last_result = ret;
180         return ret;
181 }
182
183 gdouble
184 get_timestamp()
185 {
186         /* FIXME: We should use g_get_current_time here */
187         GTimeVal res;
188         g_get_current_time (&res);
189         return res.tv_sec + (1.e-6) * res.tv_usec;
190 }
191
192 /* 
193  * Duplicating code here from EGlib to avoid g_strsplit skew between
194  * EGLib and GLib
195  */
196  
197 gchar ** 
198 eg_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens)
199 {
200         gchar *string_c;
201         gchar *strtok_save, **vector;
202         gchar *token, *token_c;
203         gint size = 1;
204         size_t token_length;
205
206         g_return_val_if_fail(string != NULL, NULL);
207         g_return_val_if_fail(delimiter != NULL, NULL);
208         g_return_val_if_fail(delimiter[0] != 0, NULL);
209         
210         token_length = strlen(string);
211         string_c = (gchar *)g_malloc(token_length + 1);
212         memcpy(string_c, string, token_length);
213         string_c[token_length] = 0;
214         
215         vector = NULL;
216         token = (gchar *)strtok_r(string_c, delimiter, &strtok_save);
217
218         while(token != NULL) {
219                 token_length = strlen(token);
220                 token_c = (gchar *)g_malloc(token_length + 1);
221                 memcpy(token_c, token, token_length);
222                 token_c[token_length] = 0;
223
224                 vector = vector == NULL ? 
225                         (gchar **)g_malloc(2 * sizeof(vector)) :
226                         (gchar **)g_realloc(vector, (size + 1) * sizeof(vector));
227         
228                 vector[size - 1] = token_c;     
229                 size++;
230
231                 if(max_tokens > 0 && size >= max_tokens) {
232                         if(size > max_tokens) {
233                                 break;
234                         }
235
236                         token = strtok_save;
237                 } else {
238                         token = (gchar *)strtok_r(NULL, delimiter, &strtok_save);
239                 }
240         }
241
242         if(vector != NULL && size > 0) {
243                 vector[size - 1] = NULL;
244         }
245         
246         g_free(string_c);
247         string_c = NULL;
248
249         return vector;
250 }
251
252 void
253 eg_strfreev (gchar **str_array)
254 {
255         gchar **orig = str_array;
256         if (str_array == NULL)
257                 return;
258         while (*str_array != NULL){
259                 g_free (*str_array);
260                 str_array++;
261         }
262         g_free (orig);
263 }
264
265
266