libamxo  4.3.4
Object Definition Language (ODL) parsing
test_events.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 #include <sys/time.h>
55 #include <sys/resource.h>
56 #include <sys/types.h>
57 #include <sys/stat.h>
58 
59 #include <string.h>
60 #include <stdlib.h>
61 #include <stdio.h>
62 #include <stdarg.h>
63 #include <stddef.h>
64 #include <setjmp.h>
65 #include <inttypes.h>
66 #include <limits.h>
67 #include <unistd.h>
68 #include <fcntl.h>
69 #include <cmocka.h>
70 
71 #include <amxc/amxc.h>
72 #include <amxp/amxp_signal.h>
73 #include <amxp/amxp_slot.h>
74 #include <amxd/amxd_dm.h>
75 #include <amxd/amxd_object.h>
76 #include <amxd/amxd_parameter.h>
77 #include <amxd/amxd_transaction.h>
78 #include <amxo/amxo.h>
79 #include <amxo/amxo_hooks.h>
80 
81 #include "test_events.h"
82 
83 typedef struct _expected_events {
84  const char* path;
85  const char* signame;
87 
88 #include <amxc/amxc_macros.h>
89 static uint32_t event_counter = 0;
90 static uint32_t instance_add_counter = 0;
91 static uint32_t object_changed_counter = 0;
92 static amxc_var_t events;
93 
94 static void _print_event(const char* const sig_name,
95  const amxc_var_t* const data,
96  void* const priv) {
97 
98  amxc_string_t* fn_name = (amxc_string_t*) priv;
99  assert_non_null(priv);
100  assert_string_equal(amxc_string_get(fn_name, 0), "print_event");
101  printf("Event received %s\n", sig_name);
102  amxc_var_dump(data, STDOUT_FILENO);
103  event_counter++;
104 }
105 
106 static void _check_event(const char* const sig_name,
107  const amxc_var_t* const data,
108  UNUSED void* const priv) {
109 
110  amxc_var_t* event = NULL;
111  printf("Event received %s\n", sig_name);
112  event = amxc_var_add(amxc_htable_t, &events, NULL);
113  amxc_var_copy(event, data);
114  amxc_var_add_key(cstring_t, event, "signame", sig_name);
115  event_counter++;
116 }
117 
118 static void _instance_added(const char* const sig_name,
119  const amxc_var_t* const data,
120  UNUSED void* const priv) {
121 
122  printf("Event received %s\n", sig_name);
123  amxc_var_dump(data, STDOUT_FILENO);
125 }
126 
127 static void _object_changed(const char* const sig_name,
128  const amxc_var_t* const data,
129  UNUSED void* const priv) {
130 
131  printf("Event received %s\n", sig_name);
132  amxc_var_dump(data, STDOUT_FILENO);
134 }
135 
136 void test_event_subscription(UNUSED void** state) {
137  amxd_dm_t dm;
138  amxo_parser_t parser;
139  amxd_trans_t transaction;
140 
141  const char* odl = "%define {"
142  " object Test[] { string text = \"Hallo\"; }"
143  "}"
144  "%populate {"
145  " on event regexp(\".*\") call print_event;"
146  "}";
147  const char* odl_2 = "%populate {"
148  " on event regexp(\"dm:instance-.*\") of \"Test\" call print_event;"
149  "}";
150 
151  amxd_dm_init(&dm);
152  amxo_parser_init(&parser);
153 
154  amxo_resolver_ftab_add(&parser, "print_event", AMXO_FUNC(_print_event));
155  assert_int_equal(amxo_parser_parse_string(&parser, odl, amxd_dm_get_root(&dm)), 0);
156  assert_int_equal(amxo_parser_get_status(&parser), amxd_status_ok);
157 
158  while(amxp_signal_read() == 0) {
159  }
160  assert_int_equal(event_counter, 1);
161 
162  amxp_slot_disconnect_all(_print_event);
163  assert_int_equal(amxo_parser_parse_string(&parser, odl_2, amxd_dm_get_root(&dm)), 0);
164  assert_int_equal(amxo_parser_get_status(&parser), amxd_status_ok);
165 
166  amxd_trans_init(&transaction);
167  amxd_trans_select_pathf(&transaction, "Test");
168  amxd_trans_add_inst(&transaction, 0, NULL);
169  amxd_trans_select_pathf(&transaction, ".^");
170  amxd_trans_add_inst(&transaction, 0, NULL);
171  amxd_trans_select_pathf(&transaction, ".^");
172  amxd_trans_add_inst(&transaction, 0, NULL);
173  assert_int_equal(amxd_trans_apply(&transaction, &dm), 0);
174  amxd_trans_clean(&transaction);
175 
176  event_counter = 0;
177  while(amxp_signal_read() == 0) {
178  }
179  assert_int_equal(event_counter, 3);
180 
181  amxo_parser_clean(&parser);
182  amxd_dm_clean(&dm);
183 }
184 
186  amxd_dm_t dm;
187  amxo_parser_t parser;
188  amxd_trans_t transaction;
189 
190  const char* odl =
191  "%define {"
192  " object Root {"
193  " object Test[] { "
194  " on event '*' call print_event;"
195  " string text = \"Hallo\";"
196  " }"
197  " }"
198  "}";
199 
200  amxd_dm_init(&dm);
201  amxo_parser_init(&parser);
202 
203  amxo_resolver_ftab_add(&parser, "print_event", AMXO_FUNC(_print_event));
204  assert_int_equal(amxo_parser_parse_string(&parser, odl, amxd_dm_get_root(&dm)), 0);
205  assert_int_equal(amxo_parser_get_status(&parser), amxd_status_ok);
206 
207  event_counter = 0;
208  while(amxp_signal_read() == 0) {
209  }
210  assert_int_equal(event_counter, 1);
211 
212  amxd_trans_init(&transaction);
213  amxd_trans_select_pathf(&transaction, "Root.Test");
214  amxd_trans_add_inst(&transaction, 0, NULL);
215  amxd_trans_select_pathf(&transaction, ".^");
216  amxd_trans_add_inst(&transaction, 0, NULL);
217  assert_int_equal(amxd_trans_apply(&transaction, &dm), 0);
218  amxd_trans_clean(&transaction);
219 
220  event_counter = 0;
221  while(amxp_signal_read() == 0) {
222  }
223  assert_int_equal(event_counter, 2);
224 
225  amxd_trans_init(&transaction);
226  amxd_trans_select_pathf(&transaction, "Root.Test.1.");
227  amxd_trans_set_value(cstring_t, &transaction, "text", "Testing");
228  assert_int_equal(amxd_trans_apply(&transaction, &dm), 0);
229  amxd_trans_clean(&transaction);
230 
231  event_counter = 0;
232  while(amxp_signal_read() == 0) {
233  }
234  assert_int_equal(event_counter, 1);
235 
236  amxp_slot_disconnect_all(_print_event);
237  amxo_parser_clean(&parser);
238  amxd_dm_clean(&dm);
239 }
240 
242  amxd_dm_t dm;
243  amxo_parser_t parser;
244  amxd_trans_t transaction;
245 
246  const char* odl =
247  "%define {\n"
248  " object Test { string text = \"Hallo\"; }\n"
249  "}\n"
250  "%populate {\n"
251  " on event regexp(\".*\") call print_event \n"
252  " filter 'object == \"Test.\" && parameters.text.from == \"Hallo\"';\n"
253  "}\n";
254 
255  amxd_dm_init(&dm);
256  amxo_parser_init(&parser);
257 
258  amxo_resolver_ftab_add(&parser, "print_event", AMXO_FUNC(_print_event));
259  printf("%s\n", odl);
260  fflush(stdout);
261  assert_int_equal(amxo_parser_parse_string(&parser, odl, amxd_dm_get_root(&dm)), 0);
262  assert_int_equal(amxo_parser_get_status(&parser), amxd_status_ok);
263 
264  event_counter = 0;
265  while(amxp_signal_read() == 0) {
266  }
267  assert_int_equal(event_counter, 0);
268 
269  amxd_trans_init(&transaction);
270  amxd_trans_select_pathf(&transaction, "Test");
271  amxd_trans_set_value(cstring_t, &transaction, "text", "Test Text");
272  assert_int_equal(amxd_trans_apply(&transaction, &dm), 0);
273 
274  amxd_trans_clean(&transaction);
275  amxd_trans_select_pathf(&transaction, "Test");
276  amxd_trans_set_value(cstring_t, &transaction, "text", "Test Text2");
277  assert_int_equal(amxd_trans_apply(&transaction, &dm), 0);
278 
279  amxd_trans_clean(&transaction);
280  amxd_trans_select_pathf(&transaction, "Test");
281  amxd_trans_set_value(cstring_t, &transaction, "text", "Hallo");
282  assert_int_equal(amxd_trans_apply(&transaction, &dm), 0);
283 
284  amxd_trans_clean(&transaction);
285  amxd_trans_select_pathf(&transaction, "Test");
286  amxd_trans_set_value(cstring_t, &transaction, "text", "YAT");
287  assert_int_equal(amxd_trans_apply(&transaction, &dm), 0);
288  amxd_trans_clean(&transaction);
289 
290  event_counter = 0;
291  while(amxp_signal_read() == 0) {
292  }
293  assert_int_equal(event_counter, 2);
294 
295  amxo_parser_clean(&parser);
296  amxd_dm_clean(&dm);
297 }
298 
300  amxd_dm_t dm;
301  amxo_parser_t parser;
302 
303  const char* odl = "%define {"
304  " object Test[] { string text = \"Hallo\"; }"
305  "}"
306  "%populate {"
307  " on event regexp(\".*\") call print_event;"
308  "}";
309 
310  amxd_dm_init(&dm);
311  amxo_parser_init(&parser);
312 
313  assert_int_equal(amxo_parser_parse_string(&parser, odl, amxd_dm_get_root(&dm)), 0);
314  assert_int_equal(amxo_parser_get_status(&parser), amxd_status_ok);
315 
316  amxo_parser_clean(&parser);
317  amxd_dm_clean(&dm);
318 }
319 
321  amxd_dm_t dm;
322  amxo_parser_t parser;
323 
324  const char* odl =
325  "%define {"
326  " object Test {"
327  " object MiTest[] {"
328  " string Text;"
329  " %unique %key string Alias;"
330  " }"
331  " }"
332  "}"
333  "%populate {"
334  " object Test.MiTest {"
335  " instance add (0,\"welcome\") {"
336  " parameter Text = \"1234\";"
337  " }"
338  " }"
339  " object Test.MiTest.welcome {"
340  " parameter Text = \"ABCD\";"
341  " }"
342  " on event \"*\" call print_event;"
343  " on event \"dm:instance-added\" call instance_added;"
344  " on event \"dm:object-changed\" call object_changed;"
345  "}";
346 
347  const char* odl_dot =
348  "%populate {"
349  " object Test.MiTest {"
350  " instance add (0,\"welcome.again\") {"
351  " parameter Text = \"I like dots in Aliases\";"
352  " }"
353  " }"
354  "}";
355 
356  amxd_dm_init(&dm);
357  amxo_parser_init(&parser);
358 
359  amxo_resolver_ftab_add(&parser, "instance_added", AMXO_FUNC(_instance_added));
360  amxo_resolver_ftab_add(&parser, "object_changed", AMXO_FUNC(_object_changed));
361  amxo_resolver_ftab_add(&parser, "print_event", AMXO_FUNC(_print_event));
362 
363  assert_int_equal(amxo_parser_parse_string(&parser, odl, amxd_dm_get_root(&dm)), 0);
364  assert_int_equal(amxo_parser_get_status(&parser), amxd_status_ok);
365 
366  event_counter = 0;
367  while(amxp_signal_read() == 0) {
368  }
369  assert_int_equal(event_counter, 4);
370  assert_int_equal(instance_add_counter, 1);
371  assert_int_equal(object_changed_counter, 1);
372 
373  assert_int_equal(amxo_parser_parse_string(&parser, odl_dot, amxd_dm_get_root(&dm)), 0);
374  assert_int_equal(amxo_parser_get_status(&parser), amxd_status_ok);
375 
376  while(amxp_signal_read() == 0) {
377  }
378  assert_int_equal(event_counter, 5);
379  assert_int_equal(instance_add_counter, 2);
380 
381  amxo_parser_clean(&parser);
382  amxd_dm_clean(&dm);
383 }
384 
386  amxd_dm_t dm;
387  amxo_parser_t parser;
388  const char* file = "./odl/greeter.odl";
389  const amxc_llist_t* levents = NULL;
390 
391  expected_events_t eevents[] = {
392  { "Greeter.", "dm:object-added" },
393  { "Greeter.History.", "dm:object-added" },
394  { "Greeter.History.Info.", "dm:object-added" },
395  { "Greeter.", "dm:object-changed" },
396  { "Greeter.History.1.", "dm:object-changed" },
397  { "Greeter.History.1.", "dm:object-changed" },
398  { "Greeter.History.1.", "dm:object-changed" },
399  { "Greeter.History.1.", "dm:object-changed" },
400  { "Greeter.History.", "dm:instance-added" },
401  { "Greeter.History.1.Info.", "dm:object-added" },
402  { "Greeter.History.1.Info.", "dm:instance-added" },
403  { "Greeter.History.1.Info.", "dm:instance-added" },
404  { "Greeter.History.1.Info.", "dm:instance-added" },
405  { "Greeter.History.1.Info.", "dm:instance-added" },
406  };
407 
408  amxd_dm_init(&dm);
409  amxo_parser_init(&parser);
410 
411  amxc_var_init(&events);
412  amxc_var_set_type(&events, AMXC_VAR_ID_LIST);
413  amxo_resolver_ftab_add(&parser, "check_event", AMXO_FUNC(_check_event));
414  assert_int_equal(amxo_parser_parse_file(&parser, file, amxd_dm_get_root(&dm)), 0);
415 
416  event_counter = 0;
417  while(amxp_signal_read() == 0) {
418  }
419 
420  printf("\n\n");
421  fflush(stdout);
422  amxc_var_dump(&events, STDOUT_FILENO);
423  levents = amxc_var_constcast(amxc_llist_t, &events);
424  assert_int_equal(sizeof(eevents) / sizeof(expected_events_t), amxc_llist_size(levents));
425  for(uint32_t i = 0; i < sizeof(eevents) / sizeof(expected_events_t); i++) {
426  amxc_llist_it_t* it = amxc_llist_get_first(levents);
427  assert_non_null(it);
428  amxc_var_t* event = amxc_var_from_llist_it(it);
429 
430  assert_string_equal(eevents[i].path, GET_CHAR(event, "path"));
431  assert_string_equal(eevents[i].signame, GET_CHAR(event, "signame"));
432 
433  amxc_var_delete(&event);
434  }
435 
436  amxc_var_clean(&events);
437  amxo_parser_clean(&parser);
438  amxd_dm_clean(&dm);
439 }
Ambiorix ODL parser header file.
include test_include odl
Definition: test_valid.odl:66
int amxo_parser_parse_string(amxo_parser_t *parser, const char *text, amxd_object_t *object)
Parses a string containing a valid ODL part.
void amxo_parser_clean(amxo_parser_t *parser)
Cleans up the odl parser instance.
int amxo_parser_parse_file(amxo_parser_t *parser, const char *file_path, amxd_object_t *object)
Parses an odl file.
static amxd_status_t amxo_parser_get_status(amxo_parser_t *parser)
Get the status of the odl parser.
Definition: amxo.h:414
int amxo_parser_init(amxo_parser_t *parser)
Initializes a new odl parser instance.
int amxo_resolver_ftab_add(amxo_parser_t *parser, const char *fn_name, amxo_fn_ptr_t fn)
Adds a C function to the function table.
#define AMXO_FUNC(x)
Function ponter caster macro.
Definition: amxo_types.h:80
The ODL parser structure.
Definition: amxo_types.h:245
const char * signame
Definition: test_events.c:85
const char * path
Definition: test_events.c:84
static void _print_event(const char *const sig_name, const amxc_var_t *const data, void *const priv)
Definition: test_events.c:94
static void _object_changed(const char *const sig_name, const amxc_var_t *const data, UNUSED void *const priv)
Definition: test_events.c:127
void test_event_subscription_filter(UNUSED void **state)
Definition: test_events.c:241
static amxc_var_t events
Definition: test_events.c:92
void test_event_subscription(UNUSED void **state)
Definition: test_events.c:136
static void _instance_added(const char *const sig_name, const amxc_var_t *const data, UNUSED void *const priv)
Definition: test_events.c:118
void test_event_subscription_in_object_def(UNUSED void **state)
Definition: test_events.c:185
static uint32_t event_counter
Definition: test_events.c:89
static uint32_t instance_add_counter
Definition: test_events.c:90
static uint32_t object_changed_counter
Definition: test_events.c:91
struct _expected_events expected_events_t
void test_events_are_in_correct_order(UNUSED void **state)
Definition: test_events.c:385
static void _check_event(const char *const sig_name, const amxc_var_t *const data, UNUSED void *const priv)
Definition: test_events.c:106
void test_populate_section_generates_events(UNUSED void **state)
Definition: test_events.c:320
void test_subscription_warns_if_function_not_resolved(UNUSED void **state)
Definition: test_events.c:299
#define UNUSED
Definition: test_issue_48.c:84