HomePort
daemon_api_test.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011 Aalborg University. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are
5  * permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this list of
8  * conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11  * of conditions and the following disclaimer in the documentation and/or other materials
12  * provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY Aalborg University ''AS IS'' AND ANY EXPRESS OR IMPLIED
15  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Aalborg University OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  * The views and conclusions contained in the software and documentation are those of the
25  * authors and should not be interpreted as representing official policies, either expressed
26  */
27 
28 #include <gtest/gtest.h>
29 #include "hpd/hpd_api.h"
30 #include "daemon.h"
31 
32 #define CASE hpd_daemon_api
33 
34 typedef struct {
35  int next;
45  int option_errors[21];
49 
51 
52 static hpd_error_t on_create(void **data, const hpd_module_t *)
53 {
54  module_data_t *module_data = (module_data_t *) calloc(1, sizeof(module_data_t));
55  if (!module_data) return HPD_E_ALLOC;
56  module_data->create_called = ++module_data->next;
57  *data = module_data;
58  last_module_data = module_data;
59  return HPD_E_SUCCESS;
60 }
61 
62 static hpd_error_t on_create_add_options(void **data, const hpd_module_t *context)
63 {
64  hpd_t *hpd = context->hpd;
65  hpd_argp_option_t *option;
66  hpd_error_t rc;
67  if ((rc = on_create(data, context)) != HPD_E_SUCCESS) return rc;
68 
69  module_data_t *module_data = (module_data_t *) *data;
70  if ((module_data->add_option1 = hpd_module_add_option(context, "opt1", NULL, 0, "Option 1")) != HPD_E_SUCCESS)
71  return module_data->add_option1;
72  if ((module_data->add_option2 = hpd_module_add_option(context, "opt2", NULL, 0, "Option 2")) != HPD_E_SUCCESS)
73  return module_data->add_option2;
74 
75  if (hpd->module_options_count != 2) module_data->option_errors[0] = 1;
76  option = &hpd->options[0];
77  if (strcmp(option->name, "mod-opt1")) module_data->option_errors[1] = 1;
78  if (option->key != 0xff+0) module_data->option_errors[2] = 1;
79  if (option->arg != nullptr) module_data->option_errors[3] = 1;
80  if (option->flags != 0) module_data->option_errors[4] = 1;
81  if (strcmp(option->doc, "Option 1")) module_data->option_errors[5] = 1;
82  if (option->group != 0) module_data->option_errors[6] = 1;
83  option = &hpd->options[1];
84  if (strcmp(option->name, "mod-opt2")) module_data->option_errors[7] = 1;
85  if (option->key != 0xff+1) module_data->option_errors[8] = 1;
86  if (option->arg != nullptr) module_data->option_errors[9] = 1;
87  if (option->flags != 0) module_data->option_errors[10] = 1;
88  if (strcmp(option->doc, "Option 2")) module_data->option_errors[11] = 1;
89  if (option->group != 0) module_data->option_errors[12] = 1;
90  option = &hpd->options[2];
91  if (option->name != nullptr) module_data->option_errors[13] = 1;
92  if (option->key != 0) module_data->option_errors[14] = 1;
93  if (option->arg != nullptr) module_data->option_errors[15] = 1;
94  if (option->flags != 0) module_data->option_errors[16] = 1;
95  if (option->doc != nullptr) module_data->option_errors[17] = 1;
96  if (option->group != 0) module_data->option_errors[18] = 1;
97  if (hpd->option2module[0] != context) module_data->option_errors[19] = 1;
98  if (hpd->option2module[1] != context) module_data->option_errors[20] = 1;
99 
100  return HPD_E_SUCCESS;
101 }
102 
104 {
105  module_data_t *module_data = (module_data_t *) data;
106  module_data->destroy_called = ++module_data->next;
107  return HPD_E_SUCCESS;
108 }
109 
111 {
112  module_data_t *module_data = (module_data_t *) data;
113  module_data->start_called = ++module_data->next;
114  module_data->start_loop = hpd->loop;
115  return HPD_E_SUCCESS;
116 }
117 
119 {
120  module_data_t *module_data = (module_data_t *) data;
121  module_data->stop_called = ++module_data->next;
122  module_data->stop_loop = hpd->loop;
123  return HPD_E_SUCCESS;
124 }
125 
126 static hpd_error_t on_parse_opt(void *data, const char *name, const char *)
127 {
128  module_data_t *module_data = (module_data_t *) data;
129  if (strcmp(name, "opt1") == 0) module_data->opt1_called = ++module_data->next;
130  else if (strcmp(name, "opt2") == 0) module_data->opt2_called = ++module_data->next;
131  else module_data->parse_opt_called = ++module_data->next;
132  return HPD_E_SUCCESS;
133 }
134 
135 static void stop_hpd(hpd_ev_loop_t *loop, ev_timer *w, int revents)
136 {
137  hpd_t *hpd = (hpd_t *) w->data;
138  hpd_stop(hpd);
139 }
140 
141 TEST(CASE, hpd_allocation) {
142  hpd_t *hpd;
143 
144  ASSERT_EQ(hpd_alloc(&hpd), HPD_E_SUCCESS);
145  ASSERT_EQ(hpd->loop, nullptr);
146  ASSERT_EQ(hpd->configuration, nullptr);
147  ASSERT_TRUE(TAILQ_EMPTY(&hpd->modules));
148  ASSERT_EQ(hpd->module_options_count, 0);
149  ASSERT_EQ(hpd->options, nullptr);
150  ASSERT_EQ(hpd->option2module, nullptr);
151  ASSERT_EQ(hpd_free(hpd), HPD_E_SUCCESS);
152 }
153 
155  hpd_t *hpd;
157 
158  ASSERT_EQ(hpd_alloc(&hpd), HPD_E_SUCCESS);
159  ASSERT_EQ(hpd_get_loop(hpd, &loop), HPD_E_SUCCESS);
160  ASSERT_EQ(loop, hpd->loop);
161  ASSERT_EQ(hpd_free(hpd), HPD_E_SUCCESS);
162 }
163 
164 TEST(CASE, hpd_run_1sec) {
165  hpd_t *hpd;
166  ev_timer timer;
167  int argc = 0;
168  char *argv[] = {
169  (char *) "/usr/local/bin/hpd",
170  nullptr
171  };
172 
173  ASSERT_EQ(hpd_alloc(&hpd), HPD_E_SUCCESS);
174  hpd_ev_loop_t *loop = hpd->loop;
175 
176  ev_init(&timer, stop_hpd);
177  timer.repeat = 0.250;
178  timer.data = hpd;
179  // TODO Test broken: loop no longer available before start()
180  ev_timer_again(loop, &timer);
181 
182  ASSERT_EQ(hpd_start(hpd, argc, argv), HPD_E_SUCCESS);
183 
184  ASSERT_EQ(hpd_free(hpd), HPD_E_SUCCESS);
185 }
186 
187 TEST(CASE, module_allocation) {
188  hpd_t *hpd;
189  hpd_module_t *module;
190  const char *id = "mod";
192 
193  ASSERT_EQ(hpd_alloc(&hpd), HPD_E_SUCCESS);
194 
195  ASSERT_EQ(hpd_module(hpd, id, &module_def), HPD_E_SUCCESS);
196  ASSERT_FALSE(TAILQ_EMPTY(&hpd->modules));
197  ASSERT_NE((module = TAILQ_FIRST(&hpd->modules)), nullptr);
198  ASSERT_EQ(module->hpd, hpd);
199  ASSERT_EQ(TAILQ_NEXT(module, HPD_TAILQ_FIELD), nullptr);
200  ASSERT_EQ(TAILQ_PREV(module, hpd_modules, HPD_TAILQ_FIELD), nullptr);
201  ASSERT_EQ(module->def.on_create, module_def.on_create);
202  ASSERT_EQ(module->def.on_destroy, module_def.on_destroy);
203  ASSERT_EQ(module->def.on_start, module_def.on_start);
204  ASSERT_EQ(module->def.on_stop, module_def.on_stop);
205  ASSERT_EQ(module->def.on_parse_opt, module_def.on_parse_opt);
206  ASSERT_EQ(strcmp(module->id, id), 0);
207  ASSERT_EQ(module->data, nullptr);
208  ASSERT_EQ(last_module_data, nullptr);
209 
210  ASSERT_EQ(hpd_free(hpd), HPD_E_SUCCESS);
211 }
212 
213 TEST(CASE, module_run_1sec) {
214  hpd_t *hpd;
215  ev_timer timer;
216  int argc = 0;
217  char *argv[] = {
218  (char *) "/usr/local/bin/hpd",
219  nullptr
220  };
221  const char *id = "mod";
223 
224  ASSERT_EQ(hpd_alloc(&hpd), HPD_E_SUCCESS);
225  hpd_ev_loop_t *loop = hpd->loop;
226  ASSERT_EQ(hpd_module(hpd, id, &module_def), HPD_E_SUCCESS);
227 
228  ev_init(&timer, stop_hpd);
229  timer.repeat = 0.250;
230  timer.data = hpd;
231  ev_timer_again(loop, &timer);
232 
233  ASSERT_EQ(last_module_data, nullptr);
234  ASSERT_EQ(hpd_start(hpd, argc, argv), HPD_E_SUCCESS);
235  ASSERT_NE(hpd->loop, nullptr);
236  ASSERT_NE(last_module_data, nullptr);
237  ASSERT_EQ(last_module_data->create_called, 1);
238  ASSERT_EQ(last_module_data->start_called, 2);
239  ASSERT_EQ(last_module_data->stop_called, 3);
240  ASSERT_EQ(last_module_data->destroy_called, 4);
241  ASSERT_EQ(last_module_data->parse_opt_called, 0);
242  ASSERT_EQ(last_module_data->start_loop, loop);
243  ASSERT_EQ(last_module_data->stop_loop, loop);
244  free(last_module_data);
245  last_module_data = nullptr;
246 
247  ASSERT_EQ(hpd_free(hpd), HPD_E_SUCCESS);
248 }
249 
250 TEST(CASE, option_no_call_1sec) {
251  hpd_t *hpd;
252  ev_timer timer;
253  int argc = 1;
254  char *argv[] = {
255  (char *) "/usr/local/bin/hpd",
256  nullptr
257  };
258  const char *id = "mod";
260 
261  ASSERT_EQ(hpd_alloc(&hpd), HPD_E_SUCCESS);
262  hpd_ev_loop_t *loop = hpd->loop;
263  ASSERT_EQ(hpd_module(hpd, id, &module_def), HPD_E_SUCCESS);
264 
265  ev_init(&timer, stop_hpd);
266  timer.repeat = 0.250;
267  timer.data = hpd;
268  ev_timer_again(loop, &timer);
269 
270  ASSERT_EQ(last_module_data, nullptr);
271  ASSERT_EQ(hpd_start(hpd, argc, argv), HPD_E_SUCCESS);
272  ASSERT_NE(hpd->loop, nullptr);
273  ASSERT_NE(last_module_data, nullptr);
274  ASSERT_EQ(last_module_data->create_called, 1);
275  ASSERT_EQ(last_module_data->start_called, 2);
276  ASSERT_EQ(last_module_data->stop_called, 3);
277  ASSERT_EQ(last_module_data->destroy_called, 4);
278  ASSERT_EQ(last_module_data->parse_opt_called, 0);
279  ASSERT_EQ(last_module_data->start_loop, loop);
280  ASSERT_EQ(last_module_data->stop_loop, loop);
281  ASSERT_EQ(last_module_data->add_option1, HPD_E_SUCCESS);
282  ASSERT_EQ(last_module_data->add_option2, HPD_E_SUCCESS);
283  for (int i = 0; i < 21; i++)
284  ASSERT_EQ(last_module_data->option_errors[i], 0);
285  free(last_module_data);
286  last_module_data = nullptr;
287 
288  ASSERT_EQ(hpd_free(hpd), HPD_E_SUCCESS);
289 }
290 
291 TEST(CASE, option_call1_1sec) {
292  hpd_t *hpd;
293  ev_timer timer;
294  int argc = 2;
295  char *argv[] = {
296  (char *) "/usr/local/bin/hpd",
297  (char *) "--mod-opt1",
298  nullptr
299  };
300  const char *id = "mod";
302 
303  ASSERT_EQ(hpd_alloc(&hpd), HPD_E_SUCCESS);
304  hpd_ev_loop_t *loop = hpd->loop;
305  ASSERT_EQ(hpd_module(hpd, id, &module_def), HPD_E_SUCCESS);
306 
307  ev_init(&timer, stop_hpd);
308  timer.repeat = 0.250;
309  timer.data = hpd;
310  ev_timer_again(loop, &timer);
311 
312  ASSERT_EQ(last_module_data, nullptr);
313  ASSERT_EQ(hpd_start(hpd, argc, argv), HPD_E_SUCCESS);
314  ASSERT_NE(hpd->loop, nullptr);
315  ASSERT_NE(last_module_data, nullptr);
316  ASSERT_EQ(last_module_data->create_called, 1);
317  ASSERT_EQ(last_module_data->opt1_called, 2);
318  ASSERT_EQ(last_module_data->opt2_called, 0);
319  ASSERT_EQ(last_module_data->parse_opt_called, 0);
320  ASSERT_EQ(last_module_data->start_called, 3);
321  ASSERT_EQ(last_module_data->stop_called, 4);
322  ASSERT_EQ(last_module_data->destroy_called, 5);
323  ASSERT_EQ(last_module_data->start_loop, loop);
324  ASSERT_EQ(last_module_data->stop_loop, loop);
325  ASSERT_EQ(last_module_data->add_option1, HPD_E_SUCCESS);
326  ASSERT_EQ(last_module_data->add_option2, HPD_E_SUCCESS);
327  for (int i = 0; i < 21; i++)
328  ASSERT_EQ(last_module_data->option_errors[i], 0);
329  free(last_module_data);
330  last_module_data = nullptr;
331 
332  ASSERT_EQ(hpd_free(hpd), HPD_E_SUCCESS);
333 }
334 
335 TEST(CASE, option_call2_1sec) {
336  hpd_t *hpd;
337  ev_timer timer;
338  int argc = 3;
339  char *argv[] = {
340  (char *) "/usr/local/bin/hpd",
341  (char *) "--mod-opt1",
342  (char *) "--mod-opt2",
343  nullptr
344  };
345  const char *id = "mod";
347 
348  ASSERT_EQ(hpd_alloc(&hpd), HPD_E_SUCCESS);
349  hpd_ev_loop_t *loop = hpd->loop;
350  ASSERT_EQ(hpd_module(hpd, id, &module_def), HPD_E_SUCCESS);
351 
352  ev_init(&timer, stop_hpd);
353  timer.repeat = 0.250;
354  timer.data = hpd;
355  ev_timer_again(loop, &timer);
356 
357  ASSERT_EQ(last_module_data, nullptr);
358  ASSERT_EQ(hpd_start(hpd, argc, argv), HPD_E_SUCCESS);
359  ASSERT_NE(hpd->loop, nullptr);
360  ASSERT_NE(last_module_data, nullptr);
361  ASSERT_EQ(last_module_data->create_called, 1);
362  ASSERT_EQ(last_module_data->opt1_called, 2);
363  ASSERT_EQ(last_module_data->opt2_called, 3);
364  ASSERT_EQ(last_module_data->parse_opt_called, 0);
365  ASSERT_EQ(last_module_data->start_called, 4);
366  ASSERT_EQ(last_module_data->stop_called, 5);
367  ASSERT_EQ(last_module_data->destroy_called, 6);
368  ASSERT_EQ(last_module_data->start_loop, loop);
369  ASSERT_EQ(last_module_data->stop_loop, loop);
370  ASSERT_EQ(last_module_data->add_option1, HPD_E_SUCCESS);
371  ASSERT_EQ(last_module_data->add_option2, HPD_E_SUCCESS);
372  for (int i = 0; i < 21; i++)
373  ASSERT_EQ(last_module_data->option_errors[i], 0);
374  free(last_module_data);
375  last_module_data = nullptr;
376 
377  ASSERT_EQ(hpd_free(hpd), HPD_E_SUCCESS);
378 }
379 
const hpd_module_t ** option2module
Definition: daemon.h:59
hpd_ev_loop_t * loop
Definition: daemon.h:51
void * data
Definition: daemon.h:94
hpd_error_t hpd_start(hpd_t *hpd, int argc, char *argv[])
Definition: daemon_api.c:85
hpd_parse_opt_f on_parse_opt
Definition: hpd_types.h:205
hpd_modules_t modules
Definition: daemon.h:55
char * id
Definition: daemon.h:93
struct argp_option hpd_argp_option_t
Definition: daemon.h:43
static hpd_error_t on_stop(void *data, hpd_t *hpd)
hpd_error_t hpd_module_add_option(const hpd_module_t *context, const char *name, const char *arg, int flags, const char *doc)
[hpd_t functions]
Definition: daemon_api.c:65
TEST(CASE, hpd_allocation)
free(data.url)
static hpd_error_t on_parse_opt(void *data, const char *name, const char *)
#define HPD_TAILQ_FIELD
Definition: hpd_queue.h:37
hpd_argp_option_t * options
Definition: daemon.h:58
hpd_error_t add_option2
hpd_configuration_t * configuration
Definition: daemon.h:52
hpd_create_f on_create
Definition: hpd_types.h:201
enum hpd_error hpd_error_t
Definition: hpd_types.h:167
[Application API Callbacks]
Definition: hpd_types.h:200
static hpd_error_t on_start(void *data, hpd_t *hpd)
static hpd_error_t on_create_add_options(void **data, const hpd_module_t *context)
hpd_error_t add_option1
static module_data_t * last_module_data
hpd_error_t hpd_module(hpd_t *hpd, const char *id, const hpd_module_def_t *module_def)
Definition: daemon_api.c:50
hpd_start_f on_start
Definition: hpd_types.h:203
Definition: daemon.h:50
static void stop_hpd(hpd_ev_loop_t *loop, ev_timer *w, int revents)
hpd_error_t hpd_stop(hpd_t *hpd)
Definition: daemon_api.c:91
static struct ev_loop * loop
hpd_t * hpd
Definition: daemon.h:90
#define CASE
static hpd_error_t on_destroy(void *data)
hpd_error_t hpd_alloc(hpd_t **hpd)
[hpd_t functions]
Definition: daemon_api.c:33
hpd_ev_loop_t * stop_loop
hpd_ev_loop_t * start_loop
hpd_stop_f on_stop
Definition: hpd_types.h:204
struct ev_loop hpd_ev_loop_t
Definition: hpd_types.h:51
hpd_destroy_f on_destroy
Definition: hpd_types.h:202
static hpd_error_t on_create(void **data, const hpd_module_t *)
int module_options_count
Definition: daemon.h:56
hpd_module_def_t def
Definition: daemon.h:92
hpd_error_t hpd_get_loop(hpd_t *hpd, hpd_ev_loop_t **loop)
Definition: daemon_api.c:44
hpd_error_t hpd_free(hpd_t *hpd)
Definition: daemon_api.c:38