test.c 5.6 KB

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