burnin.cc 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /* Gearman server and library
  2. * Copyright (C) 2008 Brian Aker, Eric Day
  3. * All rights reserved.
  4. *
  5. * Use and distribution licensed under the BSD license. See
  6. * the COPYING file in the parent directory for full text.
  7. */
  8. #include "config.h"
  9. #if defined(NDEBUG)
  10. # undef NDEBUG
  11. #endif
  12. #include <cassert>
  13. #include <cerrno>
  14. #include <cstdio>
  15. #include <cstdlib>
  16. #include <cstring>
  17. #include <libgearman/gearman.h>
  18. #include <libtest/test.h>
  19. #include <libtest/server.h>
  20. #include <libtest/worker.h>
  21. #define CLIENT_TEST_PORT 32143
  22. #define DEFAULT_WORKER_NAME "burnin"
  23. struct client_test_st {
  24. gearman_client_st client;
  25. pid_t gearmand_pid;
  26. struct worker_handle_st *handle;
  27. client_test_st():
  28. gearmand_pid(-1),
  29. handle(NULL)
  30. { }
  31. };
  32. struct client_context_st {
  33. int latch;
  34. size_t min_size;
  35. size_t max_size;
  36. size_t num_tasks;
  37. size_t count;
  38. char *blob;
  39. client_context_st():
  40. latch(0),
  41. min_size(1024),
  42. max_size(1024 *2),
  43. num_tasks(20),
  44. count(2000),
  45. blob(NULL)
  46. { }
  47. };
  48. void *world_create(test_return_t *error);
  49. test_return_t world_destroy(void *object);
  50. #ifndef __INTEL_COMPILER
  51. #pragma GCC diagnostic ignored "-Wold-style-cast"
  52. #endif
  53. static test_return_t burnin_test(void *object)
  54. {
  55. gearman_client_st *client= (gearman_client_st *)object;
  56. struct client_context_st *context= (struct client_context_st *)gearman_client_context(client);
  57. // This sketchy, don't do this in your own code.
  58. gearman_task_st *tasks= (gearman_task_st *)calloc(context->num_tasks, sizeof(gearman_task_st));
  59. test_true_got(tasks, strerror(errno));
  60. test_true_got(gearman_success(gearman_client_echo(client, gearman_literal_param("echo_test"))), gearman_client_error(client));
  61. do
  62. {
  63. for (uint32_t x= 0; x < context->num_tasks; x++)
  64. {
  65. size_t blob_size= 0;
  66. if (context->min_size == context->max_size)
  67. {
  68. blob_size= context->max_size;
  69. }
  70. else
  71. {
  72. blob_size= (size_t)rand();
  73. if (context->max_size > RAND_MAX)
  74. blob_size*= (size_t)(rand() + 1);
  75. blob_size= (blob_size % (context->max_size - context->min_size)) + context->min_size;
  76. }
  77. gearman_task_st *task_ptr;
  78. gearman_return_t ret;
  79. if (context->latch)
  80. {
  81. task_ptr= gearman_client_add_task_background(client, &(tasks[x]),
  82. NULL, DEFAULT_WORKER_NAME, NULL,
  83. (void *)context->blob, blob_size, &ret);
  84. }
  85. else
  86. {
  87. task_ptr= gearman_client_add_task(client, &(tasks[x]), NULL,
  88. DEFAULT_WORKER_NAME, NULL, (void *)context->blob, blob_size,
  89. &ret);
  90. }
  91. test_true_got(gearman_success(ret), gearman_client_error(client));
  92. test_truth(task_ptr);
  93. }
  94. gearman_return_t ret= gearman_client_run_tasks(client);
  95. for (uint32_t x= 0; x < context->num_tasks; x++)
  96. {
  97. test_compare(GEARMAN_TASK_STATE_FINISHED, tasks[x].state);
  98. test_compare(GEARMAN_SUCCESS, tasks[x].result_rc);
  99. }
  100. test_compare(0, client->new_tasks);
  101. test_true_got(gearman_success(ret), gearman_client_error(client));
  102. for (uint32_t x= 0; x < context->num_tasks; x++)
  103. {
  104. gearman_task_free(&(tasks[x]));
  105. }
  106. } while (context->count--);
  107. free(tasks);
  108. context->latch++;
  109. return TEST_SUCCESS;
  110. }
  111. static test_return_t setup(void *object)
  112. {
  113. gearman_client_st *client= (gearman_client_st *)object;
  114. struct client_context_st *context= new client_context_st;
  115. test_true_got(context, strerror(errno));
  116. context->blob= (char *)malloc(context->max_size);
  117. test_true_got(context->blob, strerror(errno));
  118. memset(context->blob, 'x', context->max_size);
  119. gearman_client_set_context(client, context);
  120. return TEST_SUCCESS;
  121. }
  122. static test_return_t cleanup(void *object)
  123. {
  124. gearman_client_st *client= (gearman_client_st *)object;
  125. struct client_context_st *context= (struct client_context_st *)gearman_client_context(client);
  126. free(context->blob);
  127. delete(context);
  128. return TEST_SUCCESS;
  129. }
  130. static void *worker_fn(gearman_job_st *, void *,
  131. size_t *result_size, gearman_return_t *ret_ptr)
  132. {
  133. result_size= 0;
  134. *ret_ptr= GEARMAN_SUCCESS;
  135. return NULL;
  136. }
  137. void *world_create(test_return_t *error)
  138. {
  139. pid_t gearmand_pid;
  140. /**
  141. * @TODO We cast this to char ** below, which is evil. We need to do the
  142. * right thing
  143. */
  144. const char *argv[1]= { "client_gearmand" };
  145. client_test_st *test= new client_test_st;
  146. if (not test)
  147. {
  148. *error= TEST_MEMORY_ALLOCATION_FAILURE;
  149. return NULL;
  150. }
  151. /**
  152. We start up everything before we allocate so that we don't have to track memory in the forked process.
  153. */
  154. test->gearmand_pid= gearmand_pid= test_gearmand_start(CLIENT_TEST_PORT, 1, argv);
  155. if (test->gearmand_pid == -1)
  156. {
  157. *error= TEST_FAILURE;
  158. return NULL;
  159. }
  160. test->handle= test_worker_start(CLIENT_TEST_PORT, DEFAULT_WORKER_NAME, worker_fn, NULL, gearman_worker_options_t());
  161. if (not test->handle)
  162. {
  163. *error= TEST_FAILURE;
  164. return NULL;
  165. }
  166. if (not gearman_client_create(&(test->client)))
  167. {
  168. *error= TEST_FAILURE;
  169. return NULL;
  170. }
  171. if (gearman_failed(gearman_client_add_server(&(test->client), NULL, CLIENT_TEST_PORT)))
  172. {
  173. *error= TEST_FAILURE;
  174. return NULL;
  175. }
  176. *error= TEST_SUCCESS;
  177. return (void *)test;
  178. }
  179. test_return_t world_destroy(void *object)
  180. {
  181. client_test_st *test= (client_test_st *)object;
  182. gearman_client_free(&(test->client));
  183. test_gearmand_stop(test->gearmand_pid);
  184. test_worker_stop(test->handle);
  185. delete test;
  186. return TEST_SUCCESS;
  187. }
  188. test_st tests[] ={
  189. {"burnin", 0, burnin_test },
  190. // {"burnin_background", 0, burnin_test },
  191. {0, 0, 0}
  192. };
  193. collection_st collection[] ={
  194. {"burnin", setup, cleanup, tests},
  195. {0, 0, 0, 0}
  196. };
  197. typedef test_return_t (*libgearman_test_callback_fn)(gearman_client_st *);
  198. static test_return_t _runner_default(libgearman_test_callback_fn func, client_test_st *container)
  199. {
  200. if (func)
  201. {
  202. return func(&container->client);
  203. }
  204. else
  205. {
  206. return TEST_SUCCESS;
  207. }
  208. }
  209. static world_runner_st runner= {
  210. (test_callback_runner_fn)_runner_default,
  211. (test_callback_runner_fn)_runner_default,
  212. (test_callback_runner_fn)_runner_default
  213. };
  214. void get_world(world_st *world)
  215. {
  216. world->collections= collection;
  217. world->create= world_create;
  218. world->destroy= world_destroy;
  219. world->runner= &runner;
  220. }