client_test.cc 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091
  1. /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
  2. *
  3. * Gearmand client and server library.
  4. *
  5. * Copyright (C) 2011 Data Differential, http://datadifferential.com/
  6. * Copyright (C) 2008 Brian Aker, Eric Day
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions are
  11. * met:
  12. *
  13. * * Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. *
  16. * * Redistributions in binary form must reproduce the above
  17. * copyright notice, this list of conditions and the following disclaimer
  18. * in the documentation and/or other materials provided with the
  19. * distribution.
  20. *
  21. * * The names of its contributors may not be used to endorse or
  22. * promote products derived from this software without specific prior
  23. * written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  26. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  27. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  28. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  29. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  30. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  31. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  32. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  33. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  34. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  35. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  36. *
  37. */
  38. #include "config.h"
  39. #if defined(NDEBUG)
  40. # undef NDEBUG
  41. #endif
  42. #include <cassert>
  43. #include <cstdio>
  44. #include <cstdlib>
  45. #include <cstring>
  46. #include <ctime>
  47. #define GEARMAN_CORE
  48. #include <libgearman/gearman.h>
  49. #include <libtest/server.h>
  50. #include <libtest/test.h>
  51. #include <libtest/worker.h>
  52. #define CLIENT_TEST_PORT 32123
  53. #define NAMESPACE_KEY "foo123"
  54. #define WORKER_FUNCTION_NAME "client_test"
  55. #define WORKER_CHUNKED_FUNCTION_NAME "reverse_test"
  56. #define WORKER_UNIQUE_FUNCTION_NAME "unique_test"
  57. #define WORKER_SPLIT_FUNCTION_NAME "split_worker"
  58. #include <tests/do.h>
  59. #include <tests/server_options.h>
  60. #include <tests/do_background.h>
  61. #include <tests/execute.h>
  62. #include <tests/gearman_client_do_job_handle.h>
  63. #include <tests/gearman_execute_map_reduce.h>
  64. #include <tests/protocol.h>
  65. #include <tests/task.h>
  66. #include <tests/unique.h>
  67. #include <tests/workers.h>
  68. #ifndef __INTEL_COMPILER
  69. #pragma GCC diagnostic ignored "-Wold-style-cast"
  70. #endif
  71. struct client_test_st
  72. {
  73. gearman_client_st *_client;
  74. bool _clone;
  75. pid_t gearmand_pid;
  76. struct worker_handle_st *completion_worker;
  77. struct worker_handle_st *chunky_worker;
  78. struct worker_handle_st *unique_check;
  79. struct worker_handle_st *split_worker;
  80. struct worker_handle_st *namespace_completion_worker;
  81. struct worker_handle_st *namespace_chunky_worker;
  82. struct worker_handle_st *namespace_split_worker;
  83. const char *_worker_name;
  84. client_test_st() :
  85. _clone(true),
  86. gearmand_pid(-1),
  87. completion_worker(NULL),
  88. chunky_worker(NULL),
  89. unique_check(NULL),
  90. split_worker(NULL),
  91. namespace_completion_worker(NULL),
  92. _worker_name(WORKER_FUNCTION_NAME)
  93. {
  94. if (not (_client= gearman_client_create(NULL)))
  95. {
  96. abort(); // This would only happen from a programming error
  97. }
  98. }
  99. ~client_test_st()
  100. {
  101. test_gearmand_stop(gearmand_pid);
  102. test_worker_stop(completion_worker);
  103. test_worker_stop(chunky_worker);
  104. test_worker_stop(unique_check);
  105. test_worker_stop(split_worker);
  106. test_worker_stop(namespace_completion_worker);
  107. test_worker_stop(namespace_chunky_worker);
  108. test_worker_stop(namespace_split_worker);
  109. gearman_client_free(_client);
  110. }
  111. const char *worker_name() const
  112. {
  113. return _worker_name;
  114. }
  115. void set_worker_name(const char *arg)
  116. {
  117. _worker_name= arg;
  118. }
  119. void set_clone(bool arg)
  120. {
  121. _clone= arg;
  122. }
  123. bool clone() const
  124. {
  125. return _clone;
  126. }
  127. gearman_client_st *client()
  128. {
  129. return _client;
  130. }
  131. void reset_client()
  132. {
  133. gearman_client_free(_client);
  134. _client= gearman_client_create(NULL);
  135. }
  136. };
  137. #ifndef __INTEL_COMPILER
  138. #pragma GCC diagnostic ignored "-Wold-style-cast"
  139. #endif
  140. /**
  141. @note Just here until I fix libhashkit.
  142. */
  143. static uint32_t internal_generate_hash(const char *key, size_t key_length)
  144. {
  145. const char *ptr= key;
  146. uint32_t value= 0;
  147. while (key_length--)
  148. {
  149. uint32_t val= (uint32_t) *ptr++;
  150. value += val;
  151. value += (value << 10);
  152. value ^= (value >> 6);
  153. }
  154. value += (value << 3);
  155. value ^= (value >> 11);
  156. value += (value << 15);
  157. return value == 0 ? 1 : (uint32_t) value;
  158. }
  159. /* Prototypes */
  160. void *client_test_temp_worker(gearman_job_st *job, void *context,
  161. size_t *result_size, gearman_return_t *ret_ptr);
  162. void *world_create(test_return_t *error);
  163. test_return_t world_destroy(void *object);
  164. static void *client_thread(void *object)
  165. {
  166. (void)object;
  167. gearman_client_st client;
  168. gearman_client_st *client_ptr;
  169. size_t result_size;
  170. client_ptr= gearman_client_create(&client);
  171. if (client_ptr == NULL)
  172. abort(); // This would be pretty bad.
  173. gearman_return_t rc= gearman_client_add_server(&client, NULL, CLIENT_TEST_PORT);
  174. if (gearman_failed(rc))
  175. {
  176. pthread_exit(0);
  177. }
  178. gearman_client_set_timeout(&client, 400);
  179. for (size_t x= 0; x < 5; x++)
  180. {
  181. (void) gearman_client_do(&client, "client_test_temp", NULL, NULL, 0,
  182. &result_size, &rc);
  183. }
  184. gearman_client_free(client_ptr);
  185. pthread_exit(0);
  186. }
  187. static test_return_t init_test(void *)
  188. {
  189. gearman_client_st client;
  190. test_truth(gearman_client_create(&client));
  191. gearman_client_free(&client);
  192. return TEST_SUCCESS;
  193. }
  194. static test_return_t allocation_test(void *)
  195. {
  196. gearman_client_st *client;
  197. test_truth(client= gearman_client_create(NULL));
  198. gearman_client_free(client);
  199. return TEST_SUCCESS;
  200. }
  201. static test_return_t clone_test(void *object)
  202. {
  203. const gearman_client_st *from= (gearman_client_st *)object;
  204. gearman_client_st *from_with_host;
  205. gearman_client_st *client;
  206. client= gearman_client_clone(NULL, NULL);
  207. test_truth(client);
  208. test_truth(client->options.allocated);
  209. gearman_client_free(client);
  210. client= gearman_client_clone(NULL, from);
  211. test_truth(client);
  212. gearman_client_free(client);
  213. from_with_host= gearman_client_create(NULL);
  214. test_truth(from_with_host);
  215. gearman_client_add_server(from_with_host, "127.0.0.1", 12345);
  216. client= gearman_client_clone(NULL, from_with_host);
  217. test_truth(client);
  218. test_truth(client->universal.con_list);
  219. test_truth(gearman_client_compare(client, from_with_host));
  220. gearman_client_free(client);
  221. gearman_client_free(from_with_host);
  222. return TEST_SUCCESS;
  223. }
  224. static test_return_t option_test(void *)
  225. {
  226. gearman_client_st *gear;
  227. gearman_client_options_t default_options;
  228. gear= gearman_client_create(NULL);
  229. test_truth(gear);
  230. { // Initial Allocated, no changes
  231. test_truth(gear->options.allocated);
  232. test_false(gear->options.non_blocking);
  233. test_false(gear->options.unbuffered_result);
  234. test_false(gear->options.no_new);
  235. test_false(gear->options.free_tasks);
  236. }
  237. /* Set up for default options */
  238. default_options= gearman_client_options(gear);
  239. /*
  240. We take the basic options, and push
  241. them back in. See if we change anything.
  242. */
  243. gearman_client_set_options(gear, default_options);
  244. { // Initial Allocated, no changes
  245. test_truth(gear->options.allocated);
  246. test_false(gear->options.non_blocking);
  247. test_false(gear->options.unbuffered_result);
  248. test_false(gear->options.no_new);
  249. test_false(gear->options.free_tasks);
  250. }
  251. /*
  252. We will trying to modify non-mutable options (which should not be allowed)
  253. */
  254. {
  255. gearman_client_remove_options(gear, GEARMAN_CLIENT_ALLOCATED);
  256. { // Initial Allocated, no changes
  257. test_truth(gear->options.allocated);
  258. test_false(gear->options.non_blocking);
  259. test_false(gear->options.unbuffered_result);
  260. test_false(gear->options.no_new);
  261. test_false(gear->options.free_tasks);
  262. }
  263. gearman_client_remove_options(gear, GEARMAN_CLIENT_NO_NEW);
  264. { // Initial Allocated, no changes
  265. test_truth(gear->options.allocated);
  266. test_false(gear->options.non_blocking);
  267. test_false(gear->options.unbuffered_result);
  268. test_false(gear->options.no_new);
  269. test_false(gear->options.free_tasks);
  270. }
  271. }
  272. /*
  273. We will test modifying GEARMAN_CLIENT_NON_BLOCKING in several manners.
  274. */
  275. {
  276. gearman_client_remove_options(gear, GEARMAN_CLIENT_NON_BLOCKING);
  277. { // GEARMAN_CLIENT_NON_BLOCKING set to default, by default.
  278. test_truth(gear->options.allocated);
  279. test_false(gear->options.non_blocking);
  280. test_false(gear->options.unbuffered_result);
  281. test_false(gear->options.no_new);
  282. test_false(gear->options.free_tasks);
  283. }
  284. gearman_client_add_options(gear, GEARMAN_CLIENT_NON_BLOCKING);
  285. { // GEARMAN_CLIENT_NON_BLOCKING set to default, by default.
  286. test_truth(gear->options.allocated);
  287. test_truth(gear->options.non_blocking);
  288. test_false(gear->options.unbuffered_result);
  289. test_false(gear->options.no_new);
  290. test_false(gear->options.free_tasks);
  291. }
  292. gearman_client_set_options(gear, GEARMAN_CLIENT_NON_BLOCKING);
  293. { // GEARMAN_CLIENT_NON_BLOCKING set to default, by default.
  294. test_truth(gear->options.allocated);
  295. test_truth(gear->options.non_blocking);
  296. test_false(gear->options.unbuffered_result);
  297. test_false(gear->options.no_new);
  298. test_false(gear->options.free_tasks);
  299. }
  300. gearman_client_set_options(gear, GEARMAN_CLIENT_UNBUFFERED_RESULT);
  301. { // Everything is now set to false except GEARMAN_CLIENT_UNBUFFERED_RESULT, and non-mutable options
  302. test_truth(gear->options.allocated);
  303. test_false(gear->options.non_blocking);
  304. test_truth(gear->options.unbuffered_result);
  305. test_false(gear->options.no_new);
  306. test_false(gear->options.free_tasks);
  307. }
  308. /*
  309. Reset options to default. Then add an option, and then add more options. Make sure
  310. the options are all additive.
  311. */
  312. {
  313. gearman_client_set_options(gear, default_options);
  314. { // See if we return to defaults
  315. test_truth(gear->options.allocated);
  316. test_false(gear->options.non_blocking);
  317. test_false(gear->options.unbuffered_result);
  318. test_false(gear->options.no_new);
  319. test_false(gear->options.free_tasks);
  320. }
  321. gearman_client_add_options(gear, GEARMAN_CLIENT_FREE_TASKS);
  322. { // All defaults, except timeout_return
  323. test_truth(gear->options.allocated);
  324. test_false(gear->options.non_blocking);
  325. test_false(gear->options.unbuffered_result);
  326. test_false(gear->options.no_new);
  327. test_truth(gear->options.free_tasks);
  328. }
  329. gearman_client_add_options(gear, (gearman_client_options_t)(GEARMAN_CLIENT_NON_BLOCKING|GEARMAN_CLIENT_UNBUFFERED_RESULT));
  330. { // GEARMAN_CLIENT_NON_BLOCKING set to default, by default.
  331. test_truth(gear->options.allocated);
  332. test_truth(gear->options.non_blocking);
  333. test_truth(gear->options.unbuffered_result);
  334. test_false(gear->options.no_new);
  335. test_truth(gear->options.free_tasks);
  336. }
  337. }
  338. /*
  339. Add an option, and then replace with that option plus a new option.
  340. */
  341. {
  342. gearman_client_set_options(gear, default_options);
  343. { // See if we return to defaults
  344. test_truth(gear->options.allocated);
  345. test_false(gear->options.non_blocking);
  346. test_false(gear->options.unbuffered_result);
  347. test_false(gear->options.no_new);
  348. test_false(gear->options.free_tasks);
  349. }
  350. gearman_client_add_options(gear, GEARMAN_CLIENT_FREE_TASKS);
  351. { // All defaults, except timeout_return
  352. test_truth(gear->options.allocated);
  353. test_false(gear->options.non_blocking);
  354. test_false(gear->options.unbuffered_result);
  355. test_false(gear->options.no_new);
  356. test_truth(gear->options.free_tasks);
  357. }
  358. gearman_client_add_options(gear, (gearman_client_options_t)(GEARMAN_CLIENT_FREE_TASKS|GEARMAN_CLIENT_UNBUFFERED_RESULT));
  359. { // GEARMAN_CLIENT_NON_BLOCKING set to default, by default.
  360. test_truth(gear->options.allocated);
  361. test_false(gear->options.non_blocking);
  362. test_truth(gear->options.unbuffered_result);
  363. test_false(gear->options.no_new);
  364. test_truth(gear->options.free_tasks);
  365. }
  366. }
  367. }
  368. gearman_client_free(gear);
  369. return TEST_SUCCESS;
  370. }
  371. static test_return_t echo_test(void *object)
  372. {
  373. gearman_client_st *client= (gearman_client_st *)object;
  374. test_truth(client);
  375. gearman_string_t value= { gearman_literal_param("This is my echo test") };
  376. test_true_got(gearman_success(gearman_client_echo(client, gearman_string_param(value))), gearman_client_error(client));
  377. return TEST_SUCCESS;
  378. }
  379. static test_return_t submit_job_test(void *object)
  380. {
  381. gearman_client_st *client= (gearman_client_st *)object;
  382. const char *worker_function= (const char *)gearman_client_context(client);
  383. gearman_string_t value= { gearman_literal_param("submit_job_test") };
  384. size_t result_length;
  385. gearman_return_t rc;
  386. void *job_result= gearman_client_do(client, worker_function, NULL, gearman_string_param(value), &result_length, &rc);
  387. test_true_got(rc == GEARMAN_SUCCESS, gearman_client_error(client) ? gearman_client_error(client) : gearman_strerror(rc));
  388. test_truth(job_result);
  389. test_compare(gearman_size(value), result_length);
  390. test_memcmp(gearman_c_str(value), job_result, gearman_size(value));
  391. free(job_result);
  392. return TEST_SUCCESS;
  393. }
  394. static test_return_t submit_null_job_test(void *object)
  395. {
  396. gearman_client_st *client= (gearman_client_st *)object;
  397. test_truth(client);
  398. const char *worker_function= (const char *)gearman_client_context(client);
  399. test_truth(worker_function);
  400. size_t result_length;
  401. gearman_return_t rc;
  402. void *job_result= gearman_client_do(client, worker_function, NULL, NULL, 0,
  403. &result_length, &rc);
  404. test_true_got(rc == GEARMAN_SUCCESS, gearman_client_error(client));
  405. test_compare(0, result_length);
  406. test_truth(not job_result);
  407. return TEST_SUCCESS;
  408. }
  409. static test_return_t submit_exception_job_test(void *object)
  410. {
  411. gearman_client_st *client= (gearman_client_st *)object;
  412. test_truth(client);
  413. const char *worker_function= (const char *)gearman_client_context(client);
  414. test_truth(worker_function);
  415. size_t result_length;
  416. gearman_return_t rc;
  417. void *job_result= gearman_client_do(client, worker_function, NULL,
  418. gearman_literal_param("exception"),
  419. &result_length, &rc);
  420. test_true_got(rc == GEARMAN_SUCCESS, gearman_client_error(client) ? gearman_client_error(client) : gearman_strerror(rc));
  421. test_memcmp("exception", job_result, result_length);
  422. free(job_result);
  423. return TEST_SUCCESS;
  424. }
  425. static test_return_t submit_warning_job_test(void *object)
  426. {
  427. gearman_client_st *client= (gearman_client_st *)object;
  428. test_truth(client);
  429. const char *worker_function= (const char *)gearman_client_context(client);
  430. test_truth(worker_function);
  431. size_t result_length;
  432. gearman_return_t rc;
  433. void *job_result= gearman_client_do(client, worker_function, NULL,
  434. gearman_literal_param("warning"),
  435. &result_length, &rc);
  436. test_true_got(rc == GEARMAN_SUCCESS, gearman_client_error(client) ? gearman_client_error(client) : gearman_strerror(rc));
  437. test_memcmp("warning", job_result, result_length);
  438. free(job_result);
  439. return TEST_SUCCESS;
  440. }
  441. static test_return_t submit_fail_job_test(void *object)
  442. {
  443. gearman_client_st *client= (gearman_client_st *)object;
  444. test_truth(client);
  445. const char *worker_function= (const char *)gearman_client_context(client);
  446. test_truth(worker_function);
  447. size_t result_length;
  448. gearman_return_t rc;
  449. void *job_result= gearman_client_do(client, worker_function, NULL, "fail", 4,
  450. &result_length, &rc);
  451. test_true_got(rc == GEARMAN_WORK_FAIL, gearman_client_error(client));
  452. test_false(job_result);
  453. test_false(result_length);
  454. return TEST_SUCCESS;
  455. }
  456. static test_return_t submit_multiple_do(void *object)
  457. {
  458. for (uint32_t x= 0; x < 100 /* arbitrary */; x++)
  459. {
  460. uint32_t option= random() %3;
  461. switch (option)
  462. {
  463. case 0:
  464. test_compare(TEST_SUCCESS, submit_null_job_test(object));
  465. break;
  466. case 1:
  467. test_compare(TEST_SUCCESS, submit_job_test(object));
  468. break;
  469. default:
  470. case 2:
  471. test_compare(TEST_SUCCESS, submit_fail_job_test(object));
  472. break;
  473. }
  474. }
  475. return TEST_SUCCESS;
  476. }
  477. static test_return_t background_test(void *object)
  478. {
  479. gearman_client_st *client= (gearman_client_st *)object;
  480. test_truth(client);
  481. gearman_string_t value= { gearman_literal_param("background_test") };
  482. const char *worker_function= (const char *)gearman_client_context(client);
  483. test_truth(worker_function);
  484. char job_handle[GEARMAN_JOB_HANDLE_SIZE];
  485. test_compare_got(GEARMAN_SUCCESS,
  486. gearman_client_do_background(client, worker_function, NULL, gearman_string_param(value), job_handle),
  487. gearman_client_error(client));
  488. while (1)
  489. {
  490. bool is_known;
  491. bool is_running;
  492. uint32_t numerator;
  493. uint32_t denominator;
  494. test_true_got(gearman_success(gearman_client_job_status(client, job_handle, &is_known, &is_running, &numerator, &denominator)),
  495. gearman_client_error(client));
  496. if (not is_known)
  497. break;
  498. }
  499. return TEST_SUCCESS;
  500. }
  501. static test_return_t background_failure_test(void *object)
  502. {
  503. gearman_client_st *client= (gearman_client_st *)object;
  504. char job_handle[GEARMAN_JOB_HANDLE_SIZE];
  505. bool is_known;
  506. bool is_running;
  507. uint32_t numerator;
  508. uint32_t denominator;
  509. gearman_return_t rc= gearman_client_do_background(client, "does_not_exist", NULL,
  510. gearman_literal_param("background_failure_test"),
  511. job_handle);
  512. test_compare_got(GEARMAN_SUCCESS, rc, gearman_client_error(client));
  513. rc= gearman_client_job_status(client, job_handle, &is_known, &is_running,
  514. &numerator, &denominator);
  515. if (rc != GEARMAN_SUCCESS || is_known != true || is_running != false ||
  516. numerator != 0 || denominator != 0)
  517. {
  518. printf("background_failure_test:%s\n", gearman_client_error(client));
  519. return TEST_FAILURE;
  520. }
  521. return TEST_SUCCESS;
  522. }
  523. static test_return_t add_servers_test(void *)
  524. {
  525. gearman_client_st client, *client_ptr;
  526. client_ptr= gearman_client_create(&client);
  527. test_truth(client_ptr);
  528. gearman_return_t rc;
  529. rc= gearman_client_add_servers(&client, "127.0.0.1:4730,localhost");
  530. test_true_got(rc == GEARMAN_SUCCESS, gearman_strerror(rc));
  531. rc= gearman_client_add_servers(&client, "old_jobserver:7003,broken:12345");
  532. test_true_got(rc == GEARMAN_SUCCESS, gearman_strerror(rc));
  533. gearman_client_free(&client);
  534. return TEST_SUCCESS;
  535. }
  536. static test_return_t bug_518512_test(void *)
  537. {
  538. gearman_client_st client;
  539. size_t result_size;
  540. test_truth(gearman_client_create(&client));
  541. gearman_return_t rc;
  542. rc= gearman_client_add_server(&client, NULL, CLIENT_TEST_PORT);
  543. test_true_got(rc == GEARMAN_SUCCESS, gearman_strerror(rc));
  544. gearman_client_set_timeout(&client, 100);
  545. void *result= gearman_client_do(&client, "client_test_temp", NULL, NULL, 0,
  546. &result_size, &rc);
  547. test_true_got(rc == GEARMAN_TIMEOUT, gearman_strerror(rc));
  548. test_false(result);
  549. test_compare(0, result_size);
  550. struct worker_handle_st *completion_worker= test_worker_start(CLIENT_TEST_PORT, "client_test_temp",
  551. client_test_temp_worker, NULL, gearman_worker_options_t());
  552. gearman_client_set_timeout(&client, -1);
  553. result= gearman_client_do(&client, "client_test_temp", NULL, NULL, 0,
  554. &result_size, &rc);
  555. test_true_got(rc != GEARMAN_TIMEOUT, gearman_strerror(rc));
  556. (void)result;
  557. test_worker_stop(completion_worker);
  558. gearman_client_free(&client);
  559. return TEST_SUCCESS;
  560. }
  561. #define NUMBER_OF_WORKERS 2
  562. static test_return_t loop_test(void *)
  563. {
  564. void *unused;
  565. pthread_attr_t attr;
  566. pthread_t one;
  567. pthread_t two;
  568. pthread_attr_init(&attr);
  569. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  570. struct worker_handle_st *handles[NUMBER_OF_WORKERS];
  571. for (size_t x= 0; x < NUMBER_OF_WORKERS; x++)
  572. {
  573. handles[x]= test_worker_start(CLIENT_TEST_PORT, "client_test_temp",
  574. client_test_temp_worker, NULL, gearman_worker_options_t());
  575. }
  576. pthread_create(&one, &attr, client_thread, NULL);
  577. pthread_create(&two, &attr, client_thread, NULL);
  578. pthread_join(one, &unused);
  579. pthread_join(two, &unused);
  580. for (size_t x= 0; x < NUMBER_OF_WORKERS; x++)
  581. {
  582. test_worker_stop(handles[x]);
  583. }
  584. pthread_attr_destroy(&attr);
  585. return TEST_SUCCESS;
  586. }
  587. static test_return_t submit_log_failure(void *object)
  588. {
  589. gearman_client_st *client= (gearman_client_st *)object;
  590. test_truth(client);
  591. gearman_string_t value= { gearman_literal_param("submit_log_failure") };
  592. const char *worker_function= (const char *)gearman_client_context(client);
  593. test_truth(worker_function);
  594. size_t result_length;
  595. gearman_return_t rc;
  596. void *job_result= gearman_client_do(client, worker_function, NULL,
  597. gearman_string_param(value),
  598. &result_length, &rc);
  599. test_true_got(rc == GEARMAN_NO_SERVERS, gearman_strerror(rc));
  600. test_false(job_result);
  601. test_compare(0, result_length);
  602. return TEST_SUCCESS;
  603. }
  604. static void log_counter(const char *line, gearman_verbose_t verbose,
  605. void *context)
  606. {
  607. uint32_t *counter= (uint32_t *)context;
  608. (void)verbose;
  609. (void)line;
  610. *counter= *counter + 1;
  611. }
  612. static test_return_t strerror_count(void *)
  613. {
  614. test_compare((int)GEARMAN_MAX_RETURN, 50);
  615. return TEST_SUCCESS;
  616. }
  617. #undef MAKE_NEW_STRERROR
  618. static char * make_number(uint32_t expected, uint32_t got)
  619. {
  620. char buffer[1024];
  621. snprintf(buffer, sizeof(buffer), "Expected %uU, got %uU", expected, got);
  622. return strdup(buffer);
  623. }
  624. static test_return_t strerror_strings(void *object __attribute__((unused)))
  625. {
  626. uint32_t values[] = { 324335284U, 1940666259U, 4156775927U, 18028287U,
  627. 1834995715U, 1009419836U, 1038124396U, 3050095617U,
  628. 4004269877U, 2913489720U, 1389266665U, 1374361090U,
  629. 3775104989U, 1158738795U, 2490507301U, 426780991U,
  630. 2421852085U, 426121997U, 3669711613U, 2620567638U,
  631. 48094985U, 4052600452U, 2697110207U, 4260329382U,
  632. 3706494438U, 1765339649U, 1176029865U, 2899482444U,
  633. 2255507756U, 1844534215U, 1685626311U, 3134591697U,
  634. 1469920452U, 2236059486U, 1693700353U, 1173962212U,
  635. 2491943732U, 1864825729U, 523632457U, 1342225548U,
  636. 245155833U, 3999913926U, 2789053153U, 2576033598U,
  637. 463490826U, 1983660343U, 2268979717U, 1656388188U,
  638. 1558344702U, 3577742799U};
  639. for (int rc= GEARMAN_SUCCESS; rc < GEARMAN_MAX_RETURN; rc++)
  640. {
  641. uint32_t hash_val;
  642. const char *msg= gearman_strerror((gearman_return_t)rc);
  643. hash_val= internal_generate_hash(msg, strlen(msg));
  644. test_true_got(values[rc] == hash_val, make_number(values[rc], hash_val));
  645. }
  646. return TEST_SUCCESS;
  647. }
  648. static uint32_t global_counter;
  649. static test_return_t pre_chunk(void *object)
  650. {
  651. client_test_st *all= (client_test_st *)object;
  652. all->set_worker_name(WORKER_CHUNKED_FUNCTION_NAME);
  653. return TEST_SUCCESS;
  654. }
  655. static test_return_t pre_namespace(void *object)
  656. {
  657. client_test_st *all= (client_test_st *)object;
  658. gearman_client_set_namespace(all->client(), NAMESPACE_KEY, strlen(NAMESPACE_KEY));
  659. return TEST_SUCCESS;
  660. }
  661. static test_return_t pre_unique(void *object)
  662. {
  663. client_test_st *all= (client_test_st *)object;
  664. all->set_worker_name(WORKER_UNIQUE_FUNCTION_NAME);
  665. return TEST_SUCCESS;
  666. }
  667. static test_return_t post_function_reset(void *object)
  668. {
  669. client_test_st *all= (client_test_st *)object;
  670. all->set_worker_name(WORKER_FUNCTION_NAME);
  671. gearman_client_set_namespace(all->client(), 0, 0);
  672. return TEST_SUCCESS;
  673. }
  674. static test_return_t pre_logging(void *object)
  675. {
  676. client_test_st *all= (client_test_st *)object;
  677. gearman_log_fn *func= log_counter;
  678. global_counter= 0;
  679. all->reset_client();
  680. all->set_clone(false);
  681. gearman_client_set_log_fn(all->client(), func, &global_counter, GEARMAN_VERBOSE_MAX);
  682. return TEST_SUCCESS;
  683. }
  684. static test_return_t post_logging(void *)
  685. {
  686. test_truth(global_counter);
  687. return TEST_SUCCESS;
  688. }
  689. void *client_test_temp_worker(gearman_job_st *, void *,
  690. size_t *result_size, gearman_return_t *ret_ptr)
  691. {
  692. *result_size= 0;
  693. *ret_ptr= GEARMAN_SUCCESS;
  694. return NULL;
  695. }
  696. void *world_create(test_return_t *error)
  697. {
  698. client_test_st *test= new client_test_st();
  699. pid_t gearmand_pid;
  700. /**
  701. * @TODO We cast this to char ** below, which is evil. We need to do the
  702. * right thing
  703. */
  704. const char *argv[1]= { "client_gearmand" };
  705. if (not test)
  706. {
  707. *error= TEST_MEMORY_ALLOCATION_FAILURE;
  708. return NULL;
  709. }
  710. /**
  711. We start up everything before we allocate so that we don't have to track memory in the forked process.
  712. */
  713. gearmand_pid= test_gearmand_start(CLIENT_TEST_PORT, 1, argv);
  714. if (gearmand_pid == -1)
  715. {
  716. *error= TEST_FAILURE;
  717. return NULL;
  718. }
  719. test->completion_worker= test_worker_start(CLIENT_TEST_PORT, WORKER_FUNCTION_NAME, echo_or_react_worker, NULL, gearman_worker_options_t());
  720. test->chunky_worker= test_worker_start(CLIENT_TEST_PORT, WORKER_CHUNKED_FUNCTION_NAME, echo_or_react_chunk_worker, NULL, gearman_worker_options_t());
  721. test->unique_check= test_worker_start(CLIENT_TEST_PORT, WORKER_UNIQUE_FUNCTION_NAME, unique_worker, NULL, GEARMAN_WORKER_GRAB_UNIQ);
  722. test->split_worker= test_worker_start_with_reducer(CLIENT_TEST_PORT, NULL, WORKER_SPLIT_FUNCTION_NAME, split_worker, cat_aggregator_fn, NULL, GEARMAN_WORKER_GRAB_ALL);
  723. test->namespace_completion_worker= test_worker_start_with_namespace(CLIENT_TEST_PORT, WORKER_FUNCTION_NAME, echo_or_react_worker, NULL, NAMESPACE_KEY, gearman_worker_options_t());
  724. test->namespace_chunky_worker= test_worker_start_with_namespace(CLIENT_TEST_PORT, WORKER_CHUNKED_FUNCTION_NAME, echo_or_react_worker, NULL, NAMESPACE_KEY, gearman_worker_options_t());
  725. test->namespace_split_worker= test_worker_start_with_reducer(CLIENT_TEST_PORT, NAMESPACE_KEY, WORKER_SPLIT_FUNCTION_NAME, split_worker, cat_aggregator_fn, NULL, GEARMAN_WORKER_GRAB_ALL);
  726. test->gearmand_pid= gearmand_pid;
  727. if (gearman_failed(gearman_client_add_server(test->client(), NULL, CLIENT_TEST_PORT)))
  728. {
  729. *error= TEST_FAILURE;
  730. return NULL;
  731. }
  732. *error= TEST_SUCCESS;
  733. return (void *)test;
  734. }
  735. test_return_t world_destroy(void *object)
  736. {
  737. client_test_st *test= (client_test_st *)object;
  738. delete test;
  739. return TEST_SUCCESS;
  740. }
  741. test_st tests[] ={
  742. {"init", 0, init_test },
  743. {"allocation", 0, allocation_test },
  744. {"clone_test", 0, clone_test },
  745. {"echo", 0, echo_test },
  746. {"options", 0, option_test },
  747. {"submit_job", 0, submit_job_test },
  748. {"submit_null_job", 0, submit_null_job_test },
  749. {"submit_fail_job", 0, submit_fail_job_test },
  750. {"exception", 0, submit_exception_job_test },
  751. {"warning", 0, submit_warning_job_test },
  752. {"submit_multiple_do", 0, submit_multiple_do },
  753. {"background", 0, background_test },
  754. {"background_failure", 0, background_failure_test },
  755. {"add_servers", 0, add_servers_test },
  756. {"bug_518512_test", 0, bug_518512_test },
  757. {"loop_test", 0, loop_test },
  758. {0, 0, 0}
  759. };
  760. test_st gearman_command_t_tests[] ={
  761. {"gearman_command_t", 0, check_gearman_command_t },
  762. {0, 0, 0}
  763. };
  764. test_st tests_log[] ={
  765. {"submit_log_failure", 0, submit_log_failure },
  766. {0, 0, 0}
  767. };
  768. test_st gearman_strerror_tests[] ={
  769. {"count", 0, strerror_count },
  770. {"strings", 0, strerror_strings },
  771. {0, 0, 0}
  772. };
  773. test_st unique_tests[] ={
  774. {"compare sent unique", 0, unique_compare_test },
  775. {0, 0, 0}
  776. };
  777. test_st gearman_client_do_tests[] ={
  778. {"gearman_client_do() fail huge unique", 0, gearman_client_do_huge_unique },
  779. {"gearman_client_do() with active background task", 0, gearman_client_do_with_active_background_task },
  780. {0, 0, 0}
  781. };
  782. test_st gearman_execute_tests[] ={
  783. {"gearman_execute()", 0, gearman_execute_test },
  784. {"gearman_execute(GEARMAN_WORK_FAIL)", 0, gearman_execute_fail_test },
  785. {"gearman_execute() epoch", 0, gearman_execute_epoch_test },
  786. {"gearman_execute() timeout", 0, gearman_execute_timeout_test },
  787. {"gearman_execute() background", 0, gearman_execute_bg_test },
  788. {"gearman_execute() multiple background", 0, gearman_execute_multile_bg_test },
  789. {0, 0, 0}
  790. };
  791. test_st gearman_client_do_background_tests[] ={
  792. {"gearman_client_do_background()", 0, gearman_client_do_background_basic },
  793. {"gearman_client_do_high_background()", 0, gearman_client_do_high_background_basic },
  794. {"gearman_client_do_low_background()", 0, gearman_client_do_low_background_basic },
  795. {0, 0, 0}
  796. };
  797. test_st gearman_client_do_job_handle_tests[] ={
  798. {"gearman_client_do_job_handle() no active tasks", 0, gearman_client_do_job_handle_no_active_task },
  799. {"gearman_client_do_job_handle() follow do command", 0, gearman_client_do_job_handle_follow_do },
  800. {0, 0, 0}
  801. };
  802. test_st gearman_execute_map_reduce_tests[] ={
  803. {"gearman_execute_map_reduce()", 0, gearman_execute_map_reduce_basic },
  804. {"gearman_execute_map_reduce(GEARMAN_ARGUMENT_TOO_LARGE)", 0, gearman_execute_map_reduce_check_parameters },
  805. {"gearman_execute_map_reduce(GEARMAN_WORK_FAIL)", 0, gearman_execute_map_reduce_workfail },
  806. {"gearman_execute_map_reduce() fail in reduction", 0, gearman_execute_map_reduce_fail_in_reduction },
  807. {0, 0, 0}
  808. };
  809. test_st gearman_client_set_server_option_tests[] ={
  810. {"gearman_client_set_server_option(exceptions)", 0, gearman_client_set_server_option_exception},
  811. {"gearman_client_set_server_option(bad)", 0, gearman_client_set_server_option_bad},
  812. {0, 0, 0}
  813. };
  814. test_st gearman_task_tests[] ={
  815. {"gearman_client_add_task() ", 0, gearman_client_add_task_test},
  816. {"gearman_client_add_task() fail", 0, gearman_client_add_task_test_fail},
  817. {"gearman_client_add_task() bad workload", 0, gearman_client_add_task_test_bad_workload},
  818. {"gearman_client_add_task_background()", 0, gearman_client_add_task_background_test},
  819. {"gearman_client_add_task_low_background()", 0, gearman_client_add_task_low_background_test},
  820. {"gearman_client_add_task_high_background()", 0, gearman_client_add_task_high_background_test},
  821. {"gearman_client_add_task() exception", 0, gearman_client_add_task_exception},
  822. {"gearman_client_add_task() warning", 0, gearman_client_add_task_warning},
  823. {0, 0, 0}
  824. };
  825. collection_st collection[] ={
  826. {"gearman_client_st", 0, 0, tests},
  827. {"gearman_client_st chunky", pre_chunk, post_function_reset, tests}, // Test with a worker that will respond in part
  828. {"gearman_strerror", 0, 0, gearman_strerror_tests},
  829. {"gearman_task", 0, 0, gearman_task_tests},
  830. {"gearman_task chunky", pre_chunk, post_function_reset, gearman_task_tests},
  831. {"gearman_task namespace", pre_namespace, post_function_reset, gearman_task_tests},
  832. {"unique", pre_unique, post_function_reset, unique_tests},
  833. {"gearman_client_do()", 0, 0, gearman_client_do_tests},
  834. {"gearman_client_do() namespace", pre_namespace, post_function_reset, gearman_client_do_tests},
  835. {"gearman_execute chunky", pre_chunk, post_function_reset, gearman_execute_tests},
  836. {"gearman_client_do_job_handle", 0, 0, gearman_client_do_job_handle_tests},
  837. {"gearman_client_do_job_handle namespace", pre_namespace, post_function_reset, gearman_client_do_job_handle_tests},
  838. {"gearman_client_do_background", 0, 0, gearman_client_do_background_tests},
  839. {"gearman_client_set_server_option", 0, 0, gearman_client_set_server_option_tests},
  840. {"gearman_execute", 0, 0, gearman_execute_tests},
  841. {"gearman_execute_map_reduce()", 0, 0, gearman_execute_map_reduce_tests},
  842. {"gearman_command_t", 0, 0, gearman_command_t_tests},
  843. {"client-logging", pre_logging, post_logging, tests_log},
  844. {0, 0, 0, 0}
  845. };
  846. typedef test_return_t (*libgearman_test_prepost_callback_fn)(client_test_st *);
  847. typedef test_return_t (*libgearman_test_callback_fn)(gearman_client_st *);
  848. static test_return_t _runner_prepost_default(libgearman_test_prepost_callback_fn func, client_test_st *container)
  849. {
  850. if (func)
  851. {
  852. return func(container);
  853. }
  854. return TEST_SUCCESS;
  855. }
  856. static test_return_t _runner_default(libgearman_test_callback_fn func, client_test_st *container)
  857. {
  858. if (func)
  859. {
  860. test_return_t rc;
  861. if (container->clone())
  862. {
  863. gearman_client_st *client= gearman_client_clone(NULL, container->client());
  864. test_truth(client);
  865. gearman_client_set_context(client, (void *)container->worker_name());
  866. rc= func(client);
  867. if (rc == TEST_SUCCESS)
  868. test_truth(not client->task_list);
  869. gearman_client_free(client);
  870. }
  871. else
  872. {
  873. gearman_client_set_context(container->client(), (void *)container->worker_name());
  874. rc= func(container->client());
  875. assert(not container->client()->task_list);
  876. }
  877. return rc;
  878. }
  879. return TEST_SUCCESS;
  880. }
  881. static world_runner_st runner= {
  882. (test_callback_runner_fn)_runner_prepost_default,
  883. (test_callback_runner_fn)_runner_default,
  884. (test_callback_runner_fn)_runner_prepost_default
  885. };
  886. void get_world(world_st *world)
  887. {
  888. world->collections= collection;
  889. world->create= world_create;
  890. world->destroy= world_destroy;
  891. world->runner= &runner;
  892. }