libamxb  4.8.2
Bus Agnostic C API
test_amxb_ba_subscribe.c
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** SPDX-License-Identifier: BSD-2-Clause-Patent
4 **
5 ** SPDX-FileCopyrightText: Copyright (c) 2023 SoftAtHome
6 **
7 ** Redistribution and use in source and binary forms, with or without modification,
8 ** are permitted provided that the following conditions are met:
9 **
10 ** 1. Redistributions of source code must retain the above copyright notice,
11 ** this list of conditions and the following disclaimer.
12 **
13 ** 2. Redistributions in binary form must reproduce the above copyright notice,
14 ** this list of conditions and the following disclaimer in the documentation
15 ** and/or other materials provided with the distribution.
16 **
17 ** Subject to the terms and conditions of this license, each copyright holder
18 ** and contributor hereby grants to those receiving rights under this license
19 ** a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
20 ** (except for failure to satisfy the conditions of this license) patent license
21 ** to make, have made, use, offer to sell, sell, import, and otherwise transfer
22 ** this software, where such license applies only to those patent claims, already
23 ** acquired or hereafter acquired, licensable by such copyright holder or contributor
24 ** that are necessarily infringed by:
25 **
26 ** (a) their Contribution(s) (the licensed copyrights of copyright holders and
27 ** non-copyrightable additions of contributors, in source or binary form) alone;
28 ** or
29 **
30 ** (b) combination of their Contribution(s) with the work of authorship to which
31 ** such Contribution(s) was added by such copyright holder or contributor, if,
32 ** at the time the Contribution is added, such addition causes such combination
33 ** to be necessarily infringed. The patent license shall not apply to any other
34 ** combinations which include the Contribution.
35 **
36 ** Except as expressly stated above, no rights or licenses from any copyright
37 ** holder or contributor is granted under this license, whether expressly, by
38 ** implication, estoppel or otherwise.
39 **
40 ** DISCLAIMER
41 **
42 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
46 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
49 ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
51 ** USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 **
53 ****************************************************************************/
54 
55 #include <stdlib.h>
56 #include <stdio.h>
57 #include <stdarg.h>
58 #include <stddef.h>
59 #include <string.h>
60 #include <unistd.h>
61 #include <setjmp.h>
62 #include <cmocka.h>
63 
64 #include <amxc/amxc_variant.h>
65 #include <amxc/amxc_htable.h>
66 #include <amxc/amxc_lqueue.h>
67 
68 #include <amxp/amxp_signal.h>
69 #include <amxp/amxp_slot.h>
70 
71 #include <amxd/amxd_dm.h>
72 
73 #include <amxb/amxb_be.h>
74 #include <amxb/amxb.h>
75 
76 #include "test_amxb_ba_subscribe.h"
77 
78 #include <amxc/amxc_macros.h>
79 static char* dummy_ctx = "xbus";
80 static char verify_host[64];
81 static char verify_port[64];
82 static char verify_path[64];
83 static int return_val;
84 static const char* sub_obj = NULL;
85 
86 int __wrap_dlclose(void* handle);
87 
88 static void handle_events(void) {
89  printf("Handling events ");
90  while(amxp_signal_read() == 0) {
91  printf(".");
92  }
93  printf("\n");
94 }
95 
96 static void* dummy_connect(const char* host,
97  const char* port,
98  const char* path,
99  UNUSED amxp_signal_mngr_t* sigmngr) {
100  strcpy(verify_host, host);
101  strcpy(verify_port, port);
102  strcpy(verify_path, path);
103 
104  return dummy_ctx;
105 }
106 
107 static int dummy_disconnect(void* ctx) {
108  assert_ptr_equal(ctx, dummy_ctx);
109  return return_val;
110 }
111 
112 static int dummy_get_fd(void* ctx) {
113  assert_ptr_equal(ctx, dummy_ctx);
114  return return_val;
115 }
116 
117 static void dummy_free(void* ctx) {
118  assert_ptr_equal(ctx, dummy_ctx);
119 }
120 
121 static int dummy_read(void* const ctx) {
122  assert_ptr_equal(ctx, dummy_ctx);
123  return return_val;
124 }
125 
126 static int dummy_describe(void* const ctx,
127  const char* object,
128  UNUSED const char* search_path,
129  UNUSED uint32_t flags,
130  UNUSED uint32_t access,
131  amxc_var_t* values,
132  UNUSED int timeout) {
133  assert_ptr_equal(ctx, dummy_ctx);
134  amxc_var_set_type(values, AMXC_VAR_ID_LIST);
135  amxc_var_t* obj_data = amxc_var_add(amxc_htable_t, values, NULL);
136 
137  amxc_string_t path;
138  amxc_string_init(&path, 0);
139  amxc_string_setf(&path, "%s%s", object, search_path);
140 
141  amxc_var_add_key(cstring_t, obj_data, "path", amxc_string_get(&path, 0));
142  amxc_var_dump(values, STDOUT_FILENO);
143  fflush(stdout);
144 
145  amxc_string_clean(&path);
146  return 0;
147 }
148 
149 static int dummy_subscribe(void* const ctx,
150  UNUSED const char* object) {
151  assert_ptr_equal(ctx, dummy_ctx);
152  return return_val;
153 }
154 
155 static int dummy_unsubscribe(void* const ctx,
156  UNUSED const char* object) {
157  assert_ptr_equal(ctx, dummy_ctx);
158  return return_val;
159 }
160 
163  .disconnect = dummy_disconnect,
164  .get_fd = dummy_get_fd,
165  .read = dummy_read,
166  .subscribe = dummy_subscribe,
167  .unsubscribe = dummy_unsubscribe,
168  .describe = dummy_describe,
169  .free = dummy_free,
170  .name = "xbus",
171  .size = sizeof(amxb_be_funcs_t),
172 };
173 
176  .name = "zbus",
177  .size = sizeof(amxb_be_funcs_t),
178 };
179 
182  .subscribe = dummy_subscribe,
183  .describe = dummy_describe,
184  .name = "ybus",
185  .size = sizeof(amxb_be_funcs_t),
186 };
187 
188 int __wrap_dlclose(UNUSED void* handle) {
189  return 0;
190 }
191 
192 static void dummy_notify_handler(UNUSED const char* const sig_name,
193  UNUSED const amxc_var_t* const data,
194  UNUSED void* const priv) {
195  return;
196 }
197 
198 static void dummy_notify_handler2(UNUSED const char* const sig_name,
199  UNUSED const amxc_var_t* const data,
200  UNUSED void* const priv) {
201  return;
202 }
203 
204 void test_amxb_subscribe(UNUSED void** state) {
205  amxb_bus_ctx_t* ctx = NULL;
206 
207  assert_int_equal(amxb_be_register(&dummy_be1), 0);
208  assert_int_equal(amxb_be_register(&dummy_be3), 0);
209 
210  return_val = 0;
211  sub_obj = "object";
212  assert_int_equal(amxb_connect(&ctx, "xbus://test:80/var/run/xbus.sock"), 0);
213  assert_int_not_equal(amxb_subscribe(ctx, "object", NULL, NULL, NULL), return_val);
214  assert_int_not_equal(amxb_subscribe(ctx, NULL, NULL, NULL, NULL), return_val);
215  assert_int_not_equal(amxb_subscribe(NULL, NULL, NULL, NULL, NULL), return_val);
216  assert_int_equal(amxb_subscribe(ctx, "object", NULL, dummy_notify_handler, NULL), return_val);
217  assert_int_equal(amxb_subscribe(ctx, "object", NULL, dummy_notify_handler, NULL), return_val);
218  assert_int_equal(amxb_unsubscribe(ctx, "object", dummy_notify_handler, NULL), return_val);
219  assert_int_equal(amxb_subscribe(ctx, "object.*.", NULL, dummy_notify_handler, NULL), return_val);
220  assert_int_equal(amxb_unsubscribe(ctx, "object.*.", dummy_notify_handler, NULL), return_val);
221  return_val = -1;
222  sub_obj = "other_object";
223  assert_int_equal(amxb_subscribe(ctx, "other_object", NULL, dummy_notify_handler, NULL), return_val);
224  return_val = 0;
225  assert_int_equal(amxb_disconnect(ctx), return_val);
226  assert_int_not_equal(amxb_subscribe(ctx, "other_object", NULL, dummy_notify_handler, NULL), return_val);
227  amxb_free(&ctx);
228 
229  return_val = 0;
230  assert_int_not_equal(amxb_subscribe(ctx, "other_object", NULL, dummy_notify_handler, NULL), return_val);
231 
232  assert_int_equal(amxb_connect(&ctx, "zbus://test:80/var/run/zbus.sock"), 0);
233  assert_int_equal(amxb_subscribe(ctx, "object", NULL, dummy_notify_handler, NULL), AMXB_ERROR_NOT_SUPPORTED_OP);
234  amxb_free(&ctx);
235 
236  assert_int_equal(amxb_be_unregister(&dummy_be1), 0);
237  assert_int_equal(amxb_be_unregister(&dummy_be3), 0);
238 }
239 
240 void test_amxb_subscribe_invalid_path(UNUSED void** state) {
241  amxb_bus_ctx_t* ctx = NULL;
242 
243  assert_int_equal(amxb_be_register(&dummy_be1), 0);
244  assert_int_equal(amxb_be_register(&dummy_be3), 0);
245 
246  return_val = 0;
247  sub_obj = "object";
248  assert_int_equal(amxb_connect(&ctx, "xbus://test:80/var/run/xbus.sock"), 0);
249  assert_int_not_equal(amxb_subscribe(ctx, "object.parameter+", NULL, dummy_notify_handler, NULL), return_val);
250  assert_int_not_equal(amxb_subscribe(ctx, "object.parameter[testing].", NULL, dummy_notify_handler, NULL), return_val);
251  assert_int_not_equal(amxb_subscribe(ctx, "object.{i}.", NULL, dummy_notify_handler, NULL), return_val);
252  assert_int_not_equal(amxb_unsubscribe(ctx, "object.parameter+", dummy_notify_handler, NULL), return_val);
253  assert_int_not_equal(amxb_unsubscribe(ctx, "object.parameter[testing].", dummy_notify_handler, NULL), return_val);
254  assert_int_not_equal(amxb_unsubscribe(ctx, "object.{i}.", dummy_notify_handler, NULL), return_val);
255  assert_int_equal(amxb_disconnect(ctx), return_val);
256  amxb_free(&ctx);
257 
258  assert_int_equal(amxb_be_unregister(&dummy_be1), 0);
259  assert_int_equal(amxb_be_unregister(&dummy_be3), 0);
260 }
261 
262 void test_amxb_subscribe_should_not_segfault(UNUSED void** state) {
263  amxb_bus_ctx_t* ctx = NULL;
264 
265  assert_int_equal(amxb_be_register(&dummy_be1), 0);
266 
267  assert_int_equal(amxb_connect(&ctx, "xbus://test:80/var/run/xbus.sock"), 0);
268  sub_obj = "myroot.some_object.some_other";
269  return_val = 0;
270  assert_int_equal(amxb_subscribe(ctx, "myroot.some_object.some_other.", NULL, dummy_notify_handler, NULL), return_val);
271  assert_int_equal(amxb_unsubscribe(ctx, "myroot.some_object.some_other.", dummy_notify_handler, NULL), return_val);
272 
273  amxb_free(&ctx);
274 
275  assert_int_equal(amxb_be_unregister(&dummy_be1), 0);
276 }
277 
278 void test_amxb_unsubscribe(UNUSED void** state) {
279  amxb_bus_ctx_t* ctx = NULL;
280 
281  assert_int_equal(amxb_be_register(&dummy_be1), 0);
282  assert_int_equal(amxb_be_register(&dummy_be3), 0);
283  assert_int_equal(amxb_be_register(&dummy_be4), 0);
284 
285  return_val = 0;
286  sub_obj = "object";
287  assert_int_equal(amxb_connect(&ctx, "xbus://test:80/var/run/xbus.sock"), 0);
288  assert_int_not_equal(amxb_unsubscribe(ctx, "object", NULL, NULL), return_val);
289  assert_int_not_equal(amxb_unsubscribe(ctx, NULL, NULL, NULL), return_val);
290  assert_int_not_equal(amxb_unsubscribe(NULL, NULL, NULL, NULL), return_val);
291  assert_int_equal(amxb_subscribe(ctx, "object", NULL, dummy_notify_handler, NULL), return_val);
292  assert_int_equal(amxb_subscribe(ctx, "object", NULL, dummy_notify_handler, NULL), return_val);
293  assert_int_equal(amxb_subscribe(ctx, "object", NULL, dummy_notify_handler2, NULL), return_val);
294  assert_int_equal(amxb_unsubscribe(ctx, "object", dummy_notify_handler2, NULL), return_val);
295  assert_int_equal(amxb_unsubscribe(ctx, "object", dummy_notify_handler, NULL), return_val);
296  return_val = -1;
297  sub_obj = "other_object";
298  assert_int_equal(amxb_subscribe(ctx, "other_object", NULL, dummy_notify_handler, NULL), return_val);
299  return_val = 0;
300  assert_int_not_equal(amxb_unsubscribe(ctx, "other_object", dummy_notify_handler, NULL), return_val);
301  assert_int_equal(amxb_subscribe(ctx, "other_object", NULL, dummy_notify_handler, NULL), return_val);
302  assert_int_equal(amxb_disconnect(ctx), return_val);
303  assert_int_not_equal(amxb_unsubscribe(ctx, "other_object", dummy_notify_handler, NULL), return_val);
304  amxb_free(&ctx);
305 
306  return_val = 0;
307  assert_int_not_equal(amxb_unsubscribe(ctx, "other_object", dummy_notify_handler, NULL), return_val);
308 
309  sub_obj = "test_object";
310  assert_int_equal(amxb_connect(&ctx, "ybus://test:80/var/run/ybus.sock"), 0);
311  assert_int_equal(amxb_subscribe(ctx, "test_object", NULL, dummy_notify_handler, NULL), return_val);
312  assert_int_equal(amxb_unsubscribe(ctx, "test_object", dummy_notify_handler, NULL), return_val);
313  amxb_free(&ctx);
314 
315  assert_int_equal(amxb_be_unregister(&dummy_be1), 0);
316  assert_int_equal(amxb_be_unregister(&dummy_be3), 0);
317  assert_int_equal(amxb_be_unregister(&dummy_be4), 0);
318 }
319 
320 
321 void test_amxb_subscription_new(UNUSED void** state) {
322  amxb_bus_ctx_t* ctx = NULL;
323  amxb_subscription_t* sub = NULL;
324  amxb_subscription_t* fsub = NULL;
325 
326  assert_int_equal(amxb_be_register(&dummy_be1), 0);
327  assert_int_equal(amxb_be_register(&dummy_be3), 0);
328 
329  return_val = 0;
330  sub_obj = "object";
331  assert_int_equal(amxb_connect(&ctx, "xbus://test:80/var/run/xbus.sock"), 0);
332  assert_int_equal(amxb_subscription_new(&sub, ctx, "object", NULL, dummy_notify_handler, NULL), return_val);
333  assert_non_null(sub);
334 
335  fsub = amxb_subscription_find(ctx, "object", dummy_notify_handler, NULL);
336  assert_non_null(fsub);
337  assert_ptr_equal(fsub, sub);
338 
339  assert_int_equal(amxb_subscription_delete(&sub), return_val);
340  assert_null(sub);
341 
342  assert_int_equal(amxb_subscription_new(&sub, ctx, "object", NULL, dummy_notify_handler, NULL), return_val);
343  assert_non_null(sub);
344 
345  assert_int_equal(amxb_disconnect(ctx), return_val);
346  amxb_free(&ctx);
347 
348  assert_int_equal(amxb_subscription_delete(&sub), return_val);
349  assert_null(sub);
350 
351  assert_int_equal(amxb_be_unregister(&dummy_be1), 0);
352  assert_int_equal(amxb_be_unregister(&dummy_be3), 0);
353 }
354 
355 static void test_wait_done(UNUSED const char* const sig_name,
356  UNUSED const amxc_var_t* const data,
357  void* const priv) {
358  uint32_t* counter = (uint32_t*) priv;
359  (*counter)++;
360 }
361 
362 void test_amxb_wait_for(UNUSED void** state) {
363  amxb_bus_ctx_t* ctx = NULL;
364  uint32_t counter = 0;
365 
366  amxp_sigmngr_add_signal(NULL, "wait:done");
367  amxp_slot_connect(NULL, "wait:done", NULL, test_wait_done, &counter);
368 
369  assert_int_equal(amxb_be_register(&dummy_be1), 0);
370  assert_int_equal(amxb_be_register(&dummy_be3), 0);
371 
372  assert_int_equal(amxb_connect(&ctx, "xbus://test:80/var/run/xbus.sock"), 0);
373  assert_int_equal(amxb_wait_for_object("MyObject"), 0);
374  handle_events();
375  assert_int_equal(counter, 1);
376 
377  assert_int_equal(amxb_wait_for_object("MyObject."), 0);
378  assert_int_equal(amxb_wait_for_object("YetAnotherObject."), 0);
379  assert_int_equal(amxb_wait_for_object("YetAnotherObject.SubObject."), 0);
380  handle_events();
381  assert_int_equal(counter, 2);
382 
383  amxb_free(&ctx);
384 
385  assert_int_equal(amxb_connect(&ctx, "zbus://test:80/var/run/zbus.sock"), 0);
386  assert_int_equal(amxb_wait_for_object("MyObject."), 0);
387  assert_int_equal(amxb_wait_for_object("YetAnotherObject."), 0);
388  assert_int_equal(amxb_wait_for_object("YetAnotherObject.SubObject."), 0);
389  handle_events();
390  assert_int_equal(counter, 2);
391 
392  assert_int_equal(amxb_be_unregister(&dummy_be1), 0);
393  assert_int_equal(amxb_be_unregister(&dummy_be3), 0);
394 }
395 
396 void test_amxb_subscription_find(UNUSED void** state) {
397  amxb_bus_ctx_t* ctx = NULL;
398  amxb_subscription_t* sub1 = NULL;
399  amxb_subscription_t* sub2 = NULL;
400  amxb_subscription_t* fsub = NULL;
401 
402  assert_int_equal(amxb_be_register(&dummy_be1), 0);
403 
404  return_val = 0;
405  sub_obj = "object";
406  assert_int_equal(amxb_connect(&ctx, "xbus://test:80/var/run/xbus.sock"), 0);
407 
408  assert_int_equal(amxb_subscription_new(&sub1, ctx, "object.", NULL, dummy_notify_handler, NULL), return_val);
409  assert_non_null(sub1);
410  assert_int_equal(amxb_subscription_new(&sub2, ctx, "object.subobject.", NULL, dummy_notify_handler, NULL), return_val);
411  assert_non_null(sub2);
412 
413  fsub = amxb_subscription_find_child(ctx, "object.");
414  assert_non_null(fsub);
415  assert_ptr_equal(sub2, fsub);
416 
417  fsub = amxb_subscription_find_parent(ctx, "object.subobject.");
418  assert_non_null(fsub);
419  assert_ptr_equal(sub1, fsub);
420 
421  fsub = amxb_subscription_find_parent(ctx, "test.subobject.");
422  assert_null(fsub);
423 
424  fsub = amxb_subscription_find_child(ctx, "test.");
425  assert_null(fsub);
426 
427  fsub = amxb_subscription_find_child(ctx, NULL);
428  assert_null(fsub);
429 
430  fsub = amxb_subscription_find_parent(ctx, "");
431  assert_null(fsub);
432 
433  assert_int_equal(amxb_subscription_delete(&sub1), 0);
434  assert_int_equal(amxb_subscription_delete(&sub2), 0);
435 
436  assert_int_equal(amxb_disconnect(ctx), return_val);
437  amxb_free(&ctx);
438 
439  assert_int_equal(amxb_be_unregister(&dummy_be1), 0);
440 }
Ambiorix bus agnostic API header file.
Ambiorix bus agnostic API header file.
struct _amxb_be_funcs amxb_be_funcs_t
Definition: amxb_types.h:79
int amxb_be_unregister(amxb_be_funcs_t *const funcs)
Unregisters a backend interface.
int amxb_be_register(amxb_be_funcs_t *const funcs)
Registers backend interface.
int amxb_connect(amxb_bus_ctx_t **ctx, const char *uri)
Create a bus connection.
void amxb_free(amxb_bus_ctx_t **ctx)
Frees allocated memory.
int amxb_disconnect(amxb_bus_ctx_t *ctx)
Disconnects a bus connection.
#define AMXB_ERROR_NOT_SUPPORTED_OP
Function/operation not supported.
Definition: amxb_error.h:110
int amxb_unsubscribe(amxb_bus_ctx_t *const ctx, const char *object, amxp_slot_fn_t slot_cb, void *priv)
Removes an event subscription.
amxb_subscription_t * amxb_subscription_find_child(amxb_bus_ctx_t *bus_ctx, const char *object)
Find a child subscription.
int amxb_subscription_delete(amxb_subscription_t **subscription)
Deletes a subscription object and unsubscribe for events of a object tree.
amxb_subscription_t * amxb_subscription_find_parent(amxb_bus_ctx_t *bus_ctx, const char *object)
Find a parent subscription.
int amxb_subscribe(amxb_bus_ctx_t *const ctx, const char *object, const char *expression, amxp_slot_fn_t slot_cb, void *priv)
Subscribes for events of a object tree.
amxb_subscription_t * amxb_subscription_find(amxb_bus_ctx_t *bus_ctx, const char *object, amxp_slot_fn_t slot_cb, void *priv)
Find an exact subscription.
int amxb_wait_for_object(const char *object)
Checks if an object is available, if not waits for it.
int amxb_subscription_new(amxb_subscription_t **subscription, amxb_bus_ctx_t *bus_ctx, const char *object, const char *expression, amxp_slot_fn_t slot_cb, void *priv)
Creates a subscription object and subscribes for events of a object tree.
The back-end interface structure.
amxb_be_connect_fn_t connect
void test_amxb_subscription_find(UNUSED void **state)
static int dummy_describe(void *const ctx, const char *object, UNUSED const char *search_path, UNUSED uint32_t flags, UNUSED uint32_t access, amxc_var_t *values, UNUSED int timeout)
static amxb_be_funcs_t dummy_be1
static int return_val
static int dummy_unsubscribe(void *const ctx, UNUSED const char *object)
static void * dummy_connect(const char *host, const char *port, const char *path, UNUSED amxp_signal_mngr_t *sigmngr)
static char verify_port[64]
static int dummy_subscribe(void *const ctx, UNUSED const char *object)
static int dummy_get_fd(void *ctx)
void test_amxb_subscribe_invalid_path(UNUSED void **state)
static char verify_host[64]
static amxb_be_funcs_t dummy_be4
int __wrap_dlclose(void *handle)
static int dummy_disconnect(void *ctx)
static void test_wait_done(UNUSED const char *const sig_name, UNUSED const amxc_var_t *const data, void *const priv)
void test_amxb_subscribe(UNUSED void **state)
static void dummy_free(void *ctx)
void test_amxb_subscription_new(UNUSED void **state)
void test_amxb_unsubscribe(UNUSED void **state)
static amxb_be_funcs_t dummy_be3
static char verify_path[64]
static const char * sub_obj
void test_amxb_subscribe_should_not_segfault(UNUSED void **state)
static void dummy_notify_handler2(UNUSED const char *const sig_name, UNUSED const amxc_var_t *const data, UNUSED void *const priv)
static int dummy_read(void *const ctx)
static char * dummy_ctx
static void dummy_notify_handler(UNUSED const char *const sig_name, UNUSED const amxc_var_t *const data, UNUSED void *const priv)
void test_amxb_wait_for(UNUSED void **state)
static void handle_events(void)