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