Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
last version of tesh
[simgrid.git] / tools / tesh2 / src / runner.c
1 #include <runner.h>
2 #include <units.h>
3 #include <unit.h>
4 #include <error.h>
5 #include <variable.h>
6
7 #include <errno.h>      /* for error code       */
8 #include <stdlib.h>     /* for calloc()         */
9 #include <stdio.h>
10
11 #include <sys/resource.h>       
12
13 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
14
15 extern char**
16 environ;
17
18 /* the unique tesh runner */
19 static runner_t
20 runner = NULL;
21
22 /* wait for the tesh runner terminaison */
23 static void
24 runner_wait(void);
25
26 static void*
27 runner_start_routine(void* p);
28
29
30 /* check the syntax of the tesh files if 
31  * the want_check_syntax is specified. Returns
32  * 0 if the syntax is clean.
33  */
34 static void
35 check_syntax(void);
36
37 #ifdef WIN32
38
39 static HANDLE 
40 timer_handle = NULL;
41
42 static void*
43 runner_start_routine(void* p)
44 {
45         
46     LARGE_INTEGER li;
47
48     li.QuadPart=- runner->timeout * 10000000;   /* 10000000 = 10 000 000 * 100 nanoseconds = 1 second */
49
50     /* create the waitable timer */
51     timer_handle = CreateWaitableTimer(NULL, TRUE, NULL);
52
53     /* set a timer to wait for timeout seconds */
54     SetWaitableTimer(timer_handle, &li, 0, NULL, NULL, 0);
55     
56     /* wait for the timer */
57     WaitForSingleObject(timer_handle, INFINITE);
58         
59         if(runner->waiting)
60         {
61                 exit_code = ELEADTIME;
62                 runner->timeouted = 1;
63                 xbt_os_sem_release(units_sem);
64         }
65
66         return NULL;
67 }
68
69 #else
70 static void*
71 runner_start_routine(void* p)
72 {
73         struct timespec ts;
74
75         ts.tv_sec = runner->timeout;
76         ts.tv_nsec = 0L;
77
78         do
79         {
80                 nanosleep(&ts, &ts);
81         }while(EINTR == errno);
82         
83         if(errno)
84         {
85                 /* TODO process the error */
86         }
87         else
88         {
89                 if(runner->waiting)
90                 {
91                         exit_code = ELEADTIME;
92                         runner->timeouted = 1;
93                         xbt_os_sem_release(units_sem);
94                 }
95         }
96         
97         return NULL;
98 }
99 #endif
100
101
102 int
103 runner_init(int want_check_syntax, int timeout, fstreams_t fstreams)
104 {
105         
106         int i;
107         char* val;
108         char buffer[MAX_PATH + 1] = {0};
109         int code;
110         const char* cstr;
111         variable_t variable;
112                 
113         if(!(runner = (runner_t)calloc(1, sizeof(s_runner_t))))
114                 return errno;
115         
116         
117         if(!(runner->units = units_new(runner, fstreams)))
118         {
119                 free(runner);
120                 runner = NULL;
121                 return errno;
122         }
123
124         runner->timeout = timeout;
125         runner->timeouted = 0;
126         runner->interrupted = 0;
127         runner->number_of_ended_units = 0;
128         runner->number_of_runned_units = 0;
129         runner->waiting = 0;
130         
131         runner->total_of_tests = 0;
132         runner->total_of_successeded_tests = 0;
133         runner->total_of_failed_tests = 0;
134         runner->total_of_interrupted_tests = 0;
135         
136         runner->total_of_units = 0;
137         runner->total_of_successeded_units = 0;
138         runner->total_of_failed_units = 0;
139         runner->total_of_interrupted_units = 0;
140         
141         runner->total_of_suites = 0;
142         runner->total_of_successeded_suites = 0;
143         runner->total_of_failed_suites = 0;
144         runner->total_of_interrupted_suites = 0;
145         
146         /* initialize the vector of variables */
147         runner->variables = vector_new(32, (fn_finalize_t)variable_free);
148         
149         
150         for(i = 0; environ[i] != NULL; i++)
151         {
152                 val = strchr(environ[i], '=');
153                 
154                 if(val)
155                 {
156                         val++;
157                                 
158                         if(val[0] != '\0')
159                                 strncpy(buffer, environ[i], (val - environ[i] -1));
160                         
161                         variable = variable_new(buffer, val);
162                         variable->env = 1;
163                         
164                         /*printf("Add the environment variable %s %s\n", variable->name, variable->val);*/
165                         
166                         vector_push_back(runner->variables, variable);
167                 }
168         }
169         
170         i = 0;
171         
172         while((cstr = error_get_at(i++, &code)))
173         {
174                 sprintf(buffer,"%d",code);
175                 variable = variable_new(cstr, buffer);
176                 variable->err = 1;
177                 vector_push_back(runner->variables, variable);
178         }
179         
180         
181         if(want_check_syntax)
182                 check_syntax();
183                 
184         return exit_code;
185                 
186 }
187
188 void
189 runner_destroy(void)
190 {
191         units_free((void**)(&(runner->units)));
192         vector_free(&runner->variables);
193         
194
195         #ifdef WIN32
196         CloseHandle(timer_handle);
197         #endif
198
199         if(runner->thread)
200                 xbt_os_thread_join(runner->thread, NULL);
201
202         free(runner);
203
204         runner = NULL;
205 }
206
207 void
208 runner_run(void)
209 {
210         xbt_os_mutex_t mutex;
211
212         mutex = xbt_os_mutex_init();
213         
214         units_run_all(runner->units, mutex);
215         
216         if(!interrupted)
217                 runner_wait();
218         
219         /* if the runner is timeouted or receive a interruption request
220          * , interrupt all the active units.
221          */
222         if(runner->timeouted || interrupted)
223                 runner_interrupt();
224         
225         units_join_all(runner->units);
226
227         xbt_os_mutex_destroy(mutex);
228
229 }
230
231 static void
232 runner_wait(void)
233 {
234         if(runner->timeout > 0)
235                 runner->thread = xbt_os_thread_create("", runner_start_routine, NULL);
236         /* signal that the runner is waiting */
237         runner->waiting = 1;
238         
239         /* wait for the end of all the units */
240         xbt_os_sem_acquire(units_sem);
241         
242         runner->waiting = 0;
243 }
244
245
246
247 /*
248  * interrupt all the active units.
249  * this function is called when the lead time of the execution is reached
250  * or when a failed unit requests an interruption of the execution.
251  */
252 void
253 runner_interrupt(void)
254 {
255         units_interrupt_all(runner->units);
256 }
257
258 void
259 runner_display_status(void)
260 {
261         
262         if(!want_dry_run)
263         {
264                 struct rusage r_usage;
265                 
266                 /*printf("\033[1m");*/
267                 printf("\n  TEst SHell utility - mini shell specialized in running test units.\n");
268                 printf(" =============================================================================\n");
269                 /*printf("\033[0m");*/
270                 
271                 units_verbose(runner->units);
272                 
273                 /*printf("\033[1m");*/
274                 printf(" =====================================================================%s\n",
275                 runner->total_of_failed_tests ? "== FAILED": (runner->total_of_interrupted_tests || runner->total_of_interrupted_units) ? "==== INTR" : "====== OK");
276                 
277                 printf(" TOTAL : Suite(s): %.0f%% ok (%d suite(s): %d ok",
278                 (runner->total_of_suites ? (1-((double)runner->total_of_failed_suites + (double)runner->total_of_interrupted_suites)/(double)runner->total_of_suites)*100.0 : 100.0),
279                 runner->total_of_suites, runner->total_of_successeded_suites);
280                 
281                 if(runner->total_of_failed_suites > 0)
282                         printf(", %d failed", runner->total_of_failed_suites);
283                 
284                 if(runner->total_of_interrupted_suites > 0)
285                         printf(", %d interrupted)", runner->total_of_interrupted_suites);
286                 
287                 printf(")\n");  
288                 
289                 printf("         Unit(s):  %.0f%% ok (%d unit(s): %d ok",
290                 (runner->total_of_units ? (1-((double)runner->total_of_failed_units + (double)runner->total_of_interrupted_units)/(double)runner->total_of_units)*100.0 : 100.0),
291                 runner->total_of_units, runner->total_of_successeded_units);
292                 
293                 if(runner->total_of_failed_units > 0)
294                         printf(", %d failed", runner->total_of_failed_units);
295                 
296                 if(runner->total_of_interrupted_units > 0)
297                         printf(", %d interrupted)", runner->total_of_interrupted_units);
298                 
299                 printf(")\n");
300                 
301                 printf("         Test(s):  %.0f%% ok (%d test(s): %d ok",
302                 (runner->total_of_tests ? (1-((double)runner->total_of_failed_tests + (double)runner->total_of_interrupted_tests)/(double)runner->total_of_tests)*100.0 : 100.0),
303                 runner->total_of_tests, runner->total_of_successeded_tests); 
304                 
305                 if(runner->total_of_failed_tests > 0)
306                         printf(", %d failed", runner->total_of_failed_tests);
307                 
308                 if(runner->total_of_interrupted_tests > 0)
309                         printf(", %d interrupted)", runner->total_of_interrupted_tests);
310                 
311                 printf(")\n\n");
312                 
313                 
314                 if(!getrusage(RUSAGE_SELF, &r_usage))
315                 {
316                 
317                         printf("         Total tesh user time used:       %ld second(s) %ld microsecond(s)\n", r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec);
318                         printf("         Total tesh system time used:     %ld second(s) %ld microsecond(s)\n\n", r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec);
319                 
320                         if(!getrusage(RUSAGE_CHILDREN, &r_usage))
321                         {
322                                 printf("         Total children user time used:   %ld second(s) %ld microsecond(s)\n", r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec);
323                                 printf("         Total children system time used: %ld second(s) %ld microsecond(s)\n\n", r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec);
324                 
325                         }       
326                 }
327                 
328                 /*printf("\033[0m");*/
329         }
330         else
331         {
332                 if(exit_code)
333                         ERROR0("Syntax error detected");
334                 else if(!exit_code)
335                         INFO0("Syntax 0K");
336         }
337 }
338
339 static void
340 check_syntax(void)
341 {
342         if(!want_dry_run)
343         {
344                 want_dry_run = 1;
345                 
346                 runner_run();
347         
348                 want_dry_run = 0;
349                 
350                 if(!exit_code)
351                 {
352                         if(!want_silent)
353                                 INFO0("syntax checked (OK)");
354                         
355                         units_reset_all(runner->units);
356                 
357                 }
358                 
359         }
360         else
361         {
362                 WARN0("mismatch in the syntax : --just-check-syntax and --check-syntax options at same time");
363         }
364
365 }