* the tesh runner type.\r
*\r
*/\r
- \r
#include <runner.h>\r
#include <units.h>\r
#include <unit.h>\r
#include <stdlib.h> /* for calloc() */\r
#include <stdio.h>\r
\r
+#include <readline.h>\r
+#include <explode.h>\r
+\r
#ifndef WIN32\r
#include <sys/resource.h>\r
#endif\r
\r
+\r
+\r
+\r
+\r
#define _RUNNER_HASHCODE 0xFEFEAAAA \r
\r
XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);\r
\r
+#if (!defined(__BUILTIN) && defined(__CHKCMD) && !defined(WIN32))\r
+static const char* builtin[] =\r
+{\r
+ "alias",\r
+ "bind",\r
+ "builtin",\r
+ "caller",\r
+ "cd",\r
+ "command",\r
+ "compgen",\r
+ "complete",\r
+ "declare",\r
+ "disown",\r
+ "echo",\r
+ "enable",\r
+ "eval",\r
+ "exec",\r
+ "export",\r
+ "false",\r
+ "fc",\r
+ "function",\r
+ "getopts",\r
+ "hash",\r
+ "history",\r
+ "jobs",\r
+ "let",\r
+ "logout",\r
+ "printf",\r
+ "pwd",\r
+ "readonly",\r
+ "shift",\r
+ "shopt",\r
+ "source",\r
+ "suspend",\r
+ "test",\r
+ "time",\r
+ "times",\r
+ "trap",\r
+ "true",\r
+ "type",\r
+ "typeset",\r
+ "ulimit",\r
+ "umask",\r
+ "unalias",\r
+ "unset",\r
+ NULL\r
+};\r
+\r
+#define __BUILTIN_MAX ((size_t)42)\r
+#endif\r
+\r
+\r
+# ifdef __APPLE__\r
+/* under darwin, the environment gets added to the process at startup time. So, it's not defined at library link time, forcing us to extra tricks */\r
+# include <crt_externs.h>\r
+# define environ (*_NSGetEnviron())\r
+# elif !defined(WIN32)\r
+ /* the environment, as specified by the opengroup, used to initialize the process properties */\r
+ extern char **environ;\r
+# endif\r
+\r
#ifndef WIN32\r
extern char**\r
environ;\r
* the check_syntax_flag is specified. Returns\r
* 0 if the syntax is clean.\r
*/\r
-static void\r
-check_syntax(void);\r
+/*static void\r
+check_syntax(void);*/\r
\r
#ifdef WIN32\r
\r
static HANDLE \r
timer_handle = NULL;\r
\r
+\r
static void*\r
runner_start_routine(void* p)\r
{\r
\r
/* wait for the timer */\r
WaitForSingleObject(timer_handle, INFINITE);\r
- \r
+\r
if(runner->waiting)\r
{\r
exit_code = ELEADTIME;\r
+ err_kind = 1;\r
runner->timeouted = 1;\r
xbt_os_sem_release(units_sem);\r
}\r
runner_start_routine(void* p)\r
{\r
struct timespec ts;\r
-\r
- ts.tv_sec = runner->timeout;\r
- ts.tv_nsec = 0L;\r
-\r
- do\r
+ int timeout = runner->timeout;\r
+ \r
+ \r
+ while(timeout-- && runner->waiting)\r
{\r
- nanosleep(&ts, &ts);\r
- }while(EINTR == errno);\r
+ ts.tv_sec = 1;\r
+ ts.tv_nsec = 0L;\r
+\r
+ do\r
+ {\r
+ nanosleep(&ts, &ts);\r
+ }while(EINTR == errno);\r
+ }\r
\r
if(errno)\r
{\r
if(runner->waiting)\r
{\r
exit_code = ELEADTIME;\r
+ err_kind = 1;\r
runner->timeouted = 1;\r
xbt_os_sem_release(units_sem);\r
}\r
\r
\r
int\r
-runner_init(int check_syntax_flag, int timeout, fstreams_t fstreams)\r
+runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams)\r
{\r
\r
int i;\r
char* val;\r
char buffer[PATH_MAX + 1] = {0};\r
+\r
int code;\r
const char* cstr;\r
variable_t variable;\r
\r
+ #if (defined(__CHKCMD) && defined(__BUILTIN) && !defined(WIN32))\r
+ FILE* s;\r
+ int n = 0;\r
+ size_t len;\r
+ char* line = NULL;\r
+ int is_blank;\r
+ #endif\r
+ \r
+ \r
if(runner)\r
- return EALREADY;\r
+ {\r
+ ERROR0("The runner is already initialized");\r
+ return -1;\r
+ }\r
\r
runner = xbt_new0(s_runner_t, 1);\r
\r
+ runner->path = NULL;\r
+ runner->builtin = NULL;\r
+ \r
if(!(runner->units = units_new(runner, fstreams)))\r
{\r
free(runner);\r
variable = variable_new(buffer, val);\r
variable->env = 1;\r
xbt_dynar_push(runner->variables, &variable);\r
+ \r
+ #ifndef WIN32\r
+ if(!strcmp("PATH", buffer))\r
+ #else\r
+ if(!strcmp("Path", buffer) || !strcmp("PATH", buffer))\r
+ #endif\r
+ {\r
+ char* p;\r
+ size_t j,k, len;\r
+ \r
+ /* get the list of paths */\r
+ \r
+ #ifdef WIN32\r
+ runner->path = explode(';', val);\r
+ #else\r
+ runner->path = explode(':', val);\r
+ #endif\r
+\r
+ /* remove spaces and backslahes at the end of the path */\r
+ for (k = 0; runner->path[k] != NULL; k++)\r
+ {\r
+ p = runner->path[k];\r
+ \r
+ len = strlen(p);\r
+ \r
+ #ifndef WIN32\r
+ for(j = len - 1; p[j] == '/' || p[j] == ' '; j--)\r
+ #else\r
+ for(j = len - 1; p[j] == '\\' || p[j] == ' '; j--)\r
+ #endif\r
+ p[j] = '\0';\r
+ }\r
+ }\r
+ \r
+ \r
+ memset(buffer, 0, PATH_MAX + 1);\r
}\r
}\r
\r
if(is_tesh_root)\r
{\r
+ char* tesh_dir = getcwd(NULL, 0);\r
+ \r
sprintf(buffer,"%d",getpid());\r
\r
#ifndef WIN32\r
setenv("TESH_PPID", buffer, 0);\r
+ setenv("TESH_DIR", tesh_dir, 0);\r
#else\r
SetEnvironmentVariable("TESH_PPID", buffer);\r
+ SetEnvironmentVariable("TESH_DIR", tesh_dir);\r
#endif\r
\r
variable = variable_new("TESH_PPID", buffer);\r
- variable->env = 1;\r
+ variable->err = 1;\r
+ \r
+ xbt_dynar_push(runner->variables, &variable);\r
+\r
+ variable = variable_new("TESH_DIR", tesh_dir);\r
+ variable->err = 1;\r
\r
xbt_dynar_push(runner->variables, &variable);\r
+ \r
+ free(tesh_dir);\r
}\r
\r
+ variable = variable_new("EXIT_SUCCESS", "0");\r
+ variable->err = 1;\r
+ \r
+ xbt_dynar_push(runner->variables, &variable);\r
+\r
+ variable = variable_new("EXIT_FAILURE", "1");\r
+ variable->err = 1;\r
+ \r
+ xbt_dynar_push(runner->variables, &variable);\r
+\r
+ variable = variable_new("TRUE", "0");\r
+ variable->err = 1;\r
+ \r
+ xbt_dynar_push(runner->variables, &variable);\r
+\r
+ variable = variable_new("FALSE", "1");\r
+ variable->err = 1;\r
+ \r
+ xbt_dynar_push(runner->variables, &variable);\r
+\r
i = 0;\r
\r
/* add the errors variables */\r
}\r
\r
/* if the user want check the syntax, check it */\r
- if(check_syntax_flag)\r
+ /*if(check_syntax_flag)\r
check_syntax();\r
+ */\r
+ \r
+ #if (!defined(WIN32) && defined(__CHKCMD))\r
+ #if defined(__BUILTIN)\r
+ \r
+ if(!is_tesh_root)\r
+ {\r
+ /* compute the full path the builtin.def file */\r
+ sprintf(buffer,"%s/builtin.def",getenv("TESH_DIR"));\r
\r
- return exit_code ? -1 : 0;\r
+ if(!(s = fopen(buffer, "r"))) \r
+ {\r
+ ERROR1("File `(%s)' not found", buffer);\r
+ return -1;\r
+ }\r
+ \r
+ }\r
+ else\r
+ {\r
+ if(!(s = fopen("builtin.def", "r"))) \r
+ {\r
+ ERROR0("File `(builtin.def)' not found");\r
+ return -1;\r
+ }\r
+ }\r
+ \r
+ if(s)\r
+ {\r
+ fpos_t begin;\r
+\r
+ fgetpos(s, &begin);\r
+\r
+ while(readline(s, &line, &len) != -1)\r
+ {\r
+ i = 0;\r
+ is_blank = 1;\r
+ \r
+\r
+ while(line[i] != '\0') \r
+ {\r
+ if (line[i] != ' ' && line[i] != '\t' && line[i]!='\n' && line[i]!='\r')\r
+ {\r
+ is_blank = 0;\r
+ break;\r
+ }\r
+ \r
+ i++;\r
+ }\r
+\r
+ if(!is_blank)\r
+ n++;\r
+ }\r
+\r
+ fsetpos(s, &begin);\r
+ free(line);\r
+ line = NULL;\r
+\r
+ if(n)\r
+ {\r
+ char* l;\r
+ \r
+ runner->builtin = xbt_new0(char*, n + 1); /* (char**) calloc(n + 1, sizeof(char*));*/\r
+ \r
+ n = 0;\r
+ \r
+ while(readline(s, &line, &len) != -1)\r
+ {\r
+ i = 0;\r
+ is_blank = 1;\r
+\r
+ while(line[i] != '\0') \r
+ {\r
+ if (line[i] != ' ' && line[i] != '\t' && line[i]!='\n' && line[i]!='\r')\r
+ {\r
+ is_blank = 0;\r
+ break;\r
+ }\r
+ \r
+ i++;\r
+ }\r
+\r
+ if(!is_blank)\r
+ {\r
+ l = strdup(line);\r
+\r
+ l[strlen(l) - 1] = '\0';\r
+\r
+ (runner->builtin)[n++] = l;\r
+ \r
+ }\r
+ }\r
+ \r
+ }\r
+ else\r
+ {\r
+ WARN0("The file `(builtin.def)' is empty");\r
+ free(runner->builtin);\r
+ runner->builtin = NULL;\r
+ }\r
+ \r
+\r
+ fclose(s);\r
+ \r
+ if(line)\r
+ free(line);\r
+ \r
+ }\r
+ \r
+ #else\r
+ runner->builtin = xbt_new0(char*, __BUILTIN_MAX + 1); /* (char**) calloc(__BUILTIN_MAX + 1, sizeof(char*));*/\r
\r
+ for(i = 0; i < __BUILTIN_MAX; i++)\r
+ runner->builtin[i] = strdup(builtin[i]); \r
+ #endif\r
+ #endif\r
+\r
+ return exit_code ? -1 : 0;\r
}\r
\r
void\r
runner_destroy(void)\r
{\r
- units_free((void**)(&(runner->units)));\r
-\r
- xbt_dynar_free(&runner->variables);\r
+ int i;\r
+ \r
+ if(runner->units)\r
+ units_free((void**)(&(runner->units)));\r
+ \r
+ if(runner->variables)\r
+ xbt_dynar_free(&runner->variables);\r
\r
#ifdef WIN32\r
CloseHandle(timer_handle);\r
\r
if(runner->thread)\r
xbt_os_thread_join(runner->thread, NULL);\r
+ \r
+ if(runner->path)\r
+ {\r
+ for (i = 0; runner->path[i] != NULL; i++)\r
+ free(runner->path[i]);\r
+ \r
+ free(runner->path);\r
+ }\r
+\r
+ if(runner->builtin)\r
+ {\r
+ for (i = 0; runner->builtin[i] != NULL; i++)\r
+ free(runner->builtin[i]);\r
+ \r
+ free(runner->builtin);\r
+ }\r
\r
free(runner);\r
\r
/* run all the units */\r
units_run_all(runner->units, mutex);\r
\r
+ \r
if(!interrupted)\r
runner_wait();\r
+\r
\r
/* if the runner is timeouted or receive a interruption request\r
* , interrupt all the active units.\r
\r
/* wait for the end of all the units */\r
xbt_os_sem_acquire(units_sem);\r
+\r
\r
runner->waiting = 0;\r
}\r
\r
printf(" Test(s): %.0f%% ok (%d test(s): %d ok",\r
(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
- runner->total_of_tests, runner->total_of_successeded_tests); \r
+ runner->total_of_tests, runner->total_of_successeded_tests);\r
\r
if(runner->total_of_failed_tests > 0)\r
printf(", %d failed", runner->total_of_failed_tests);\r
{\r
FileTimeToSystemTime(&user_time, &si);\r
\r
- printf(" Total tesh user time used: %uhour(s) %uminute(s) %usecond(s) %millisecond(s)\n", si.wHour, si.wMinute, si.wSecond, si.wMilliseconds );\r
+ printf(" User time used: %2u Hour(s) %2u Minute(s) %2u Second(s) %3u Millisecond(s)\n", si.wHour, si.wMinute, si.wSecond, si.wMilliseconds );\r
\r
FileTimeToSystemTime(&kernel_time, &si);\r
\r
- printf(" Total tesh kernel time used: %uhour(s) %uminute(s) %usecond(s) %millisecond(s)\n", si.wHour, si.wMinute, si.wSecond, si.wMilliseconds );\r
+ printf(" Kernel time used: %2u Hour(s) %2u Minute(s) %2u Second(s) %3u Millisecond(s)\n", si.wHour, si.wMinute, si.wSecond, si.wMilliseconds );\r
}\r
\r
\r
else\r
{\r
if(exit_code)\r
- ERROR0("Syntax error detected");\r
+ ERROR0("Syntax NOK");\r
else if(!exit_code)\r
INFO0("Syntax 0K");\r
}\r
}\r
\r
-static void\r
-check_syntax(void)\r
+int\r
+runner_is_timedout(void)\r
{\r
- if(!dry_run_flag)\r
- {\r
- dry_run_flag = 1;\r
- \r
- runner_run();\r
- \r
- dry_run_flag = 0;\r
- \r
- if(!exit_code)\r
- {\r
- if(!silent_flag)\r
- INFO0("syntax checked (OK)");\r
- \r
- units_reset_all(runner->units);\r
- \r
- }\r
- else\r
- errno = exit_code;\r
- \r
- }\r
- else\r
- {\r
- WARN0("mismatch in the syntax : --just-check-syntax and --check-syntax options at same time");\r
- }\r
-\r
+ return runner->timeouted;\r
}\r
+\r