2 * src/runner.c - type representing the runner.
\r
4 * Copyright 2008,2009 Martin Quinson, Malek Cherier All right reserved.
\r
6 * This program is free software; you can redistribute it and/or modify it
\r
7 * under the terms of the license (GNU LGPL) which comes with this package.
\r
10 * This file contains all the definitions of the functions related with
\r
11 * the tesh runner type.
\r
19 #include <variable.h>
\r
21 #include <errno.h> /* for error code */
\r
22 #include <stdlib.h> /* for calloc() */
\r
26 #include <sys/resource.h>
\r
29 #define _RUNNER_HASHCODE 0xFEFEAAAA
\r
31 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
\r
38 /* the unique tesh runner */
\r
42 /* wait for the tesh runner terminaison */
\r
47 runner_start_routine(void* p);
\r
50 /* check the syntax of the tesh files if
\r
51 * the check_syntax_flag is specified. Returns
\r
52 * 0 if the syntax is clean.
\r
60 timer_handle = NULL;
\r
63 runner_start_routine(void* p)
\r
68 li.QuadPart=- runner->timeout * 10000000; /* 10000000 = 10 000 000 * 100 nanoseconds = 1 second */
\r
70 /* create the waitable timer */
\r
71 timer_handle = CreateWaitableTimer(NULL, TRUE, NULL);
\r
73 /* set a timer to wait for timeout seconds */
\r
74 SetWaitableTimer(timer_handle, &li, 0, NULL, NULL, 0);
\r
76 /* wait for the timer */
\r
77 WaitForSingleObject(timer_handle, INFINITE);
\r
81 exit_code = ELEADTIME;
\r
82 runner->timeouted = 1;
\r
83 xbt_os_sem_release(units_sem);
\r
91 runner_start_routine(void* p)
\r
95 ts.tv_sec = runner->timeout;
\r
100 nanosleep(&ts, &ts);
\r
101 }while(EINTR == errno);
\r
105 /* TODO process the error */
\r
109 if(runner->waiting)
\r
111 exit_code = ELEADTIME;
\r
112 runner->timeouted = 1;
\r
113 xbt_os_sem_release(units_sem);
\r
123 runner_init(int check_syntax_flag, int timeout, fstreams_t fstreams)
\r
128 char buffer[PATH_MAX + 1] = {0};
\r
131 variable_t variable;
\r
136 runner = xbt_new0(s_runner_t, 1);
\r
138 if(!(runner->units = units_new(runner, fstreams)))
\r
145 runner->timeout = timeout;
\r
146 runner->timeouted = 0;
\r
147 runner->interrupted = 0;
\r
148 runner->number_of_ended_units = 0;
\r
149 runner->number_of_runned_units = 0;
\r
150 runner->waiting = 0;
\r
152 runner->total_of_tests = 0;
\r
153 runner->total_of_successeded_tests = 0;
\r
154 runner->total_of_failed_tests = 0;
\r
155 runner->total_of_interrupted_tests = 0;
\r
157 runner->total_of_units = 0;
\r
158 runner->total_of_successeded_units = 0;
\r
159 runner->total_of_failed_units = 0;
\r
160 runner->total_of_interrupted_units = 0;
\r
162 runner->total_of_suites = 0;
\r
163 runner->total_of_successeded_suites = 0;
\r
164 runner->total_of_failed_suites = 0;
\r
165 runner->total_of_interrupted_suites = 0;
\r
167 /* initialize the vector of variables */
\r
168 runner->variables = xbt_dynar_new(sizeof(variable_t), (void_f_pvoid_t)variable_free);
\r
170 /* add the environment variables in the vector */
\r
171 for(i = 0; environ[i] != NULL; i++)
\r
173 val = strchr(environ[i], '=');
\r
180 strncpy(buffer, environ[i], (val - environ[i] -1));
\r
182 if(!strcmp("TESH_PPID", buffer))
\r
185 variable = variable_new(buffer, val);
\r
187 xbt_dynar_push(runner->variables, &variable);
\r
193 sprintf(buffer,"%d",getpid());
\r
196 setenv("TESH_PPID", buffer, 0);
\r
198 SetEnvironmentVariable("TESH_PPID", buffer);
\r
201 variable = variable_new("TESH_PPID", buffer);
\r
204 xbt_dynar_push(runner->variables, &variable);
\r
209 /* add the errors variables */
\r
210 while((cstr = error_get_at(i++, &code)))
\r
212 sprintf(buffer,"%d",code);
\r
213 variable = variable_new(cstr, buffer);
\r
215 xbt_dynar_push(runner->variables, &variable);
\r
218 /* if the user want check the syntax, check it */
\r
219 if(check_syntax_flag)
\r
222 return exit_code ? -1 : 0;
\r
227 runner_destroy(void)
\r
229 units_free((void**)(&(runner->units)));
\r
231 xbt_dynar_free(&runner->variables);
\r
234 CloseHandle(timer_handle);
\r
238 xbt_os_thread_join(runner->thread, NULL);
\r
249 /* allocate the mutex used by the units to asynchronously access
\r
250 * to the properties of the runner.
\r
252 xbt_os_mutex_t mutex = xbt_os_mutex_init();
\r
254 /* run all the units */
\r
255 units_run_all(runner->units, mutex);
\r
260 /* if the runner is timeouted or receive a interruption request
\r
261 * , interrupt all the active units.
\r
263 if(runner->timeouted || interrupted)
\r
264 runner_interrupt();
\r
266 /* joins all the units */
\r
267 units_join_all(runner->units);
\r
269 /* release the mutex resource */
\r
270 xbt_os_mutex_destroy(mutex);
\r
277 if(runner->timeout > 0)
\r
278 runner->thread = xbt_os_thread_create("", runner_start_routine, NULL);
\r
280 /* signal that the runner is waiting */
\r
281 runner->waiting = 1;
\r
283 /* wait for the end of all the units */
\r
284 xbt_os_sem_acquire(units_sem);
\r
286 runner->waiting = 0;
\r
292 * interrupt all the active units.
\r
293 * this function is called when the lead time of the execution is reached
\r
294 * or when a failed unit requests an interruption of the execution.
\r
297 runner_interrupt(void)
\r
299 units_interrupt_all(runner->units);
\r
303 runner_summarize(void)
\r
309 struct rusage r_usage;
\r
311 FILETIME start_time;
\r
312 FILETIME exit_time;
\r
313 FILETIME kernel_time;
\r
314 FILETIME user_time;
\r
318 printf("\n TEst SHell utility - mini shell specialized in running test units.\n");
\r
319 printf(" =============================================================================\n");
\r
321 units_summuarize(runner->units);
\r
323 printf(" =====================================================================%s\n",
\r
324 runner->total_of_failed_tests ? "== FAILED": (runner->total_of_interrupted_tests || runner->total_of_interrupted_units) ? "==== INTR" : "====== OK");
\r
326 printf(" TOTAL : Suite(s): %.0f%% ok (%d suite(s): %d ok",
\r
327 (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),
\r
328 runner->total_of_suites, runner->total_of_successeded_suites);
\r
330 if(runner->total_of_failed_suites > 0)
\r
331 printf(", %d failed", runner->total_of_failed_suites);
\r
333 if(runner->total_of_interrupted_suites > 0)
\r
334 printf(", %d interrupted)", runner->total_of_interrupted_suites);
\r
338 printf(" Unit(s): %.0f%% ok (%d unit(s): %d ok",
\r
339 (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),
\r
340 runner->total_of_units, runner->total_of_successeded_units);
\r
342 if(runner->total_of_failed_units > 0)
\r
343 printf(", %d failed", runner->total_of_failed_units);
\r
345 if(runner->total_of_interrupted_units > 0)
\r
346 printf(", %d interrupted)", runner->total_of_interrupted_units);
\r
350 printf(" Test(s): %.0f%% ok (%d test(s): %d ok",
\r
351 (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),
\r
352 runner->total_of_tests, runner->total_of_successeded_tests);
\r
354 if(runner->total_of_failed_tests > 0)
\r
355 printf(", %d failed", runner->total_of_failed_tests);
\r
357 if(runner->total_of_interrupted_tests > 0)
\r
358 printf(", %d interrupted)", runner->total_of_interrupted_tests);
\r
363 if(!getrusage(RUSAGE_SELF, &r_usage))
\r
366 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);
\r
367 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);
\r
369 if(!getrusage(RUSAGE_CHILDREN, &r_usage))
\r
371 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);
\r
372 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);
\r
378 if(GetProcessTimes(GetCurrentProcess(), &start_time, &exit_time, &kernel_time, &user_time))
\r
380 FileTimeToSystemTime(&user_time, &si);
\r
382 printf(" Total tesh user time used: %uhour(s) %uminute(s) %usecond(s) %millisecond(s)\n", si.wHour, si.wMinute, si.wSecond, si.wMilliseconds );
\r
384 FileTimeToSystemTime(&kernel_time, &si);
\r
386 printf(" Total tesh kernel time used: %uhour(s) %uminute(s) %usecond(s) %millisecond(s)\n", si.wHour, si.wMinute, si.wSecond, si.wMilliseconds );
\r
396 ERROR0("Syntax error detected");
\r
397 else if(!exit_code)
\r
398 INFO0("Syntax 0K");
\r
416 INFO0("syntax checked (OK)");
\r
418 units_reset_all(runner->units);
\r
427 WARN0("mismatch in the syntax : --just-check-syntax and --check-syntax options at same time");
\r