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 
9 #include "gear_config.h"
10 #include <libtest/test.hpp>
11 
12 using namespace libtest;
13 
14 #include <cassert>
15 #include <cerrno>
16 #include <cstdio>
17 #include <cstdlib>
18 #include <cstring>
19 
20 #include <libgearman/gearman.h>
21 
22 #include <libtest/test.hpp>
23 
24 #include "libgearman/client.hpp"
25 using namespace org::gearmand;
26 
27 #include <tests/start_worker.h>
28 
29 #define DEFAULT_WORKER_NAME "burnin"
30 
worker_fn(gearman_job_st *,void *)31 static gearman_return_t worker_fn(gearman_job_st*, void*)
32 {
33   return GEARMAN_SUCCESS;
34 }
35 
36 struct client_test_st {
37   libgearman::Client _client;
38   worker_handle_st *handle;
39 
client_test_stclient_test_st40   client_test_st():
41     _client(libtest::default_port()),
42     handle(NULL)
43   {
44     gearman_function_t func_arg= gearman_function_create(worker_fn);
45     handle= test_worker_start(libtest::default_port(), NULL, DEFAULT_WORKER_NAME, func_arg, NULL, gearman_worker_options_t());
46   }
47 
~client_test_stclient_test_st48   ~client_test_st()
49   {
50     delete handle;
51   }
52 
clientclient_test_st53   gearman_client_st* client()
54   {
55     return &_client;
56   }
57 };
58 
59 struct client_context_st {
60   int latch;
61   size_t min_size;
62   size_t max_size;
63   size_t num_tasks;
64   size_t count;
65   char *blob;
66 
client_context_stclient_context_st67   client_context_st():
68     latch(0),
69     min_size(1024),
70     max_size(1024 *2),
71     num_tasks(20),
72     count(2000),
73     blob(NULL)
74   { }
75 
~client_context_stclient_context_st76   ~client_context_st()
77   {
78     if (blob)
79     {
80       free(blob);
81     }
82   }
83 };
84 
85 #ifndef __INTEL_COMPILER
86 #pragma GCC diagnostic ignored "-Wold-style-cast"
87 #endif
88 
89 static client_test_st *test_client_context= NULL;
burnin_TEST(void *)90 static test_return_t burnin_TEST(void*)
91 {
92   gearman_client_st *client= test_client_context->client();
93   fatal_assert(client);
94 
95   client_context_st *context= (client_context_st *)gearman_client_context(client);
96   fatal_assert(context);
97 
98   // This sketchy, don't do this in your own code.
99   test_true(context->num_tasks > 0);
100   std::vector<gearman_task_st> tasks;
101   try {
102     tasks.resize(context->num_tasks);
103   }
104   catch (...)
105   { }
106   ASSERT_EQ(tasks.size(), context->num_tasks);
107 
108   ASSERT_EQ(gearman_client_echo(client, test_literal_param("echo_test")), GEARMAN_SUCCESS);
109 
110   do
111   {
112     for (uint32_t x= 0; x < context->num_tasks; x++)
113     {
114       size_t blob_size= 0;
115 
116       if (context->min_size == context->max_size)
117       {
118         blob_size= context->max_size;
119       }
120       else
121       {
122         blob_size= (size_t)rand();
123 
124         if (context->max_size > RAND_MAX)
125         {
126           blob_size*= (size_t)(rand() + 1);
127         }
128 
129         blob_size= (blob_size % (context->max_size - context->min_size)) + context->min_size;
130       }
131 
132       gearman_task_st *task_ptr;
133       gearman_return_t ret;
134       if (context->latch)
135       {
136         task_ptr= gearman_client_add_task_background(client, &(tasks[x]),
137                                                      NULL, DEFAULT_WORKER_NAME, NULL,
138                                                      (void *)context->blob, blob_size, &ret);
139       }
140       else
141       {
142         task_ptr= gearman_client_add_task(client, &(tasks[x]), NULL,
143                                           DEFAULT_WORKER_NAME, NULL, (void *)context->blob, blob_size,
144                                           &ret);
145       }
146 
147       ASSERT_EQ(ret, GEARMAN_SUCCESS);
148       test_truth(task_ptr);
149     }
150 
151     gearman_return_t ret= gearman_client_run_tasks(client);
152     for (uint32_t x= 0; x < context->num_tasks; x++)
153     {
154       ASSERT_EQ(GEARMAN_TASK_STATE_FINISHED, tasks[x].state);
155       ASSERT_EQ(GEARMAN_SUCCESS, tasks[x].result_rc);
156     }
157     test_zero(client->new_tasks);
158 
159     ASSERT_EQ(ret, GEARMAN_SUCCESS);
160 
161     for (uint32_t x= 0; x < context->num_tasks; x++)
162     {
163       gearman_task_free(&(tasks[x]));
164     }
165   } while (context->count--);
166 
167   context->latch++;
168 
169   return TEST_SUCCESS;
170 }
171 
burnin_setup(void *)172 static test_return_t burnin_setup(void*)
173 {
174   test_client_context= new client_test_st;
175   client_context_st *context= new client_context_st;
176 
177   context->blob= (char *)malloc(context->max_size);
178   test_true(context->blob);
179   memset(context->blob, 'x', context->max_size);
180 
181   gearman_client_set_context(test_client_context->client(), context);
182 
183   return TEST_SUCCESS;
184 }
185 
burnin_cleanup(void *)186 static test_return_t burnin_cleanup(void*)
187 {
188   client_context_st *context= (struct client_context_st *)gearman_client_context(test_client_context->client());
189 
190   delete context;
191   delete test_client_context;
192   test_client_context= NULL;
193 
194   return TEST_SUCCESS;
195 }
196 
197 /*********************** World functions **************************************/
198 
world_create(server_startup_st & servers,test_return_t & error)199 static void *world_create(server_startup_st& servers, test_return_t& error)
200 {
201   if (server_startup(servers, "gearmand", libtest::default_port(), NULL) == false)
202   {
203     error= TEST_SKIPPED;
204     return NULL;
205   }
206 
207   worker_handles_st *handle= new worker_handles_st;
208   if (handle == NULL)
209   {
210     error= TEST_FAILURE;
211     return NULL;
212   }
213 
214   return handle;
215 }
216 
world_destroy(void * object)217 static bool world_destroy(void *object)
218 {
219   worker_handles_st *handles= (worker_handles_st *)object;
220   delete handles;
221 
222   return TEST_SUCCESS;
223 }
224 
225 test_st burnin_TESTS[] ={
226   {"burnin", 0, burnin_TEST },
227   {0, 0, 0}
228 };
229 
230 collection_st collection[] ={
231   {"burnin", burnin_setup, burnin_cleanup, burnin_TESTS },
232   {0, 0, 0, 0}
233 };
234 
get_world(libtest::Framework * world)235 void get_world(libtest::Framework *world)
236 {
237   world->collections(collection);
238   world->create(world_create);
239   world->destroy(world_destroy);
240 }
241