Asterisk - The Open Source Telephony Project  18.5.0
test_vector.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2015, Fairview 5 Engineering, LLC
5  *
6  * George Joseph <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*!
20  * \file
21  * \brief Vector tests
22  *
23  * \author George Joseph <[email protected]>
24  *
25  * This module will run some vector tests.
26  *
27  * \ingroup tests
28  */
29 
30 /*** MODULEINFO
31  <depend>TEST_FRAMEWORK</depend>
32  <support_level>core</support_level>
33  ***/
34 
35 #include "asterisk.h"
36 
37 #include "asterisk/test.h"
38 #include "asterisk/utils.h"
39 #include "asterisk/strings.h"
40 #include "asterisk/module.h"
41 #include "asterisk/vector.h"
42 
43 static int cleanup_count;
44 
45 static void cleanup(char *element)
46 {
47  cleanup_count++;
48 }
49 
50 #define STRING_CMP(a, b) ({ \
51  ((a) == NULL || (b) == NULL) ? -1 : (strcmp((a), (b)) == 0); \
52 })
53 
54 AST_TEST_DEFINE(basic_ops)
55 {
56  AST_VECTOR(test_struct, char *) sv1;
57  int rc = AST_TEST_PASS;
58 
59  char *AAA = "AAA";
60  char *BBB = "BBB";
61  char *CCC = "CCC";
62  char *YYY = "YYY";
63  char *ZZZ = "ZZZ";
64  char CCC2[4];
65 
66  strcpy(CCC2, "CCC");
67  switch (cmd) {
68  case TEST_INIT:
69  info->name = "basic";
70  info->category = "/main/vector/";
71  info->summary = "Test vector basic ops";
72  info->description = "Test vector basic ops";
73  return AST_TEST_NOT_RUN;
74  case TEST_EXECUTE:
75  break;
76  }
77 
78  ast_test_validate(test, AST_VECTOR_INIT(&sv1, 3) == 0);
79  ast_test_validate_cleanup(test, sv1.max == 3, rc, cleanup);
80  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 0, rc, cleanup);
81  /* there should be no vector growth for the 3 appends */
82  ast_test_validate_cleanup(test, AST_VECTOR_APPEND(&sv1, AAA) == 0, rc, cleanup);
83  ast_test_validate_cleanup(test, sv1.max == 3, rc, cleanup);
84  ast_test_validate_cleanup(test, AST_VECTOR_APPEND(&sv1, BBB) == 0, rc, cleanup);
85  ast_test_validate_cleanup(test, sv1.max == 3, rc, cleanup);
86  ast_test_validate_cleanup(test, AST_VECTOR_APPEND(&sv1, CCC) == 0, rc, cleanup);
87  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 3, rc, cleanup);
88  ast_test_validate_cleanup(test, sv1.max >= 3, rc, cleanup);
89  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
90  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == BBB, rc, cleanup);
91  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 2) == CCC, rc, cleanup);
92  ast_test_validate_cleanup(test, sv1.max == sv1.current, rc, cleanup);
93 
94  ast_test_validate_cleanup(test, AST_VECTOR_INSERT_AT(&sv1, 1, ZZZ) == 0, rc, cleanup);
95  /* The vector should have grown */
96  ast_test_validate_cleanup(test, sv1.max == 8, rc, cleanup);
97  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 4, rc, cleanup);
98  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
99  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == ZZZ, rc, cleanup);
100  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 2) == BBB, rc, cleanup);
101  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 3) == CCC, rc, cleanup);
102 
103  /* Test inserting > current but < max */
104  ast_test_validate_cleanup(test, AST_VECTOR_INSERT_AT(&sv1, 6, YYY) == 0, rc, cleanup);
105  ast_test_validate_cleanup(test, sv1.current == 7, rc, cleanup);
106  /* The vector should not have grown */
107  ast_test_validate_cleanup(test, sv1.max == 8, rc, cleanup);
108  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 6) == YYY, rc, cleanup);
109  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 4) == NULL, rc, cleanup);
110  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 5) == NULL, rc, cleanup);
111  ast_test_validate_cleanup(test, *(char **)AST_VECTOR_GET_CMP(&sv1, "AAA", STRING_CMP) == AAA, rc, cleanup);
112  ast_test_validate_cleanup(test, *(char **)AST_VECTOR_GET_CMP(&sv1, "ZZZ", STRING_CMP) == ZZZ, rc, cleanup);
113 
114  /* Test inserting > max */
115  ast_test_validate_cleanup(test, AST_VECTOR_INSERT_AT(&sv1, 12, AAA) == 0, rc, cleanup);
116  ast_test_validate_cleanup(test, sv1.current == 13, rc, cleanup);
117  /* The vector should have grown */
118  ast_test_validate_cleanup(test, sv1.max == 26, rc, cleanup);
119 
120  /* RESET */
121  AST_VECTOR_FREE(&sv1);
122  ast_test_validate(test, sv1.elems == NULL);
123  ast_test_validate(test, sv1.current == 0);
124  ast_test_validate(test, sv1.max == 0);
125 
126  /* Test with initial size = 0 */
127  ast_test_validate(test, AST_VECTOR_INIT(&sv1, 0) == 0);
128  ast_test_validate_cleanup(test, sv1.max == 0, rc, cleanup);
129  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 0, rc, cleanup);
130 
131  ast_test_validate_cleanup(test, AST_VECTOR_APPEND(&sv1, AAA) == 0, rc, cleanup);
132  ast_test_validate_cleanup(test, AST_VECTOR_APPEND(&sv1, BBB) == 0, rc, cleanup);
133  ast_test_validate_cleanup(test, AST_VECTOR_APPEND(&sv1, CCC) == 0, rc, cleanup);
134  ast_test_validate_cleanup(test, sv1.max >= 3, rc, cleanup);
135  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 3, rc, cleanup);
136 
137  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
138  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == BBB, rc, cleanup);
139  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 2) == CCC, rc, cleanup);
140 
141  /* Overwrite index 1 */
142  ast_test_validate_cleanup(test, AST_VECTOR_REPLACE(&sv1, 1, ZZZ) == 0, rc, cleanup);
143  ast_test_validate_cleanup(test, sv1.current == 3, rc, cleanup);
144  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
145  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == ZZZ, rc, cleanup);
146  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 2) == CCC, rc, cleanup);
147 
148  /* Replace beyond current */
149  ast_test_validate_cleanup(test, AST_VECTOR_REPLACE(&sv1, 10, YYY) == 0, rc, cleanup);
150  ast_test_validate_cleanup(test, sv1.current == 11, rc, cleanup);
151  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
152  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == ZZZ, rc, cleanup);
153  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 2) == CCC, rc, cleanup);
154  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 5) == NULL, rc, cleanup);
155  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 10) == YYY, rc, cleanup);
156 
157  /* Replace beyond max */
158  ast_test_validate_cleanup(test, AST_VECTOR_REPLACE(&sv1, 100, YYY) == 0, rc, cleanup);
159  ast_test_validate_cleanup(test, sv1.current == 101, rc, cleanup);
160  ast_test_validate_cleanup(test, sv1.max >= 101, rc, cleanup);
161 
162  /* Remove index 0 and bring the last entry (10/YYY) into it's empty slot */
163  ast_test_validate_cleanup(test, AST_VECTOR_REMOVE_UNORDERED(&sv1, 0) == AAA, rc, cleanup);
164  ast_test_validate_cleanup(test, sv1.current == 100, rc, cleanup);
165  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == YYY, rc, cleanup);
166  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == ZZZ, rc, cleanup);
167 
168  /* Replace 0 and 2 leaving 1 alone */
169  ast_test_validate_cleanup(test, AST_VECTOR_REPLACE(&sv1, 0, AAA) == 0, rc, cleanup);
170  ast_test_validate_cleanup(test, AST_VECTOR_REPLACE(&sv1, 2, CCC) == 0, rc, cleanup);
171  ast_test_validate_cleanup(test, sv1.current == 100, rc, cleanup);
172  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
173  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == ZZZ, rc, cleanup);
174  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 2) == CCC, rc, cleanup);
175 
176  /* Remove 1 and compact preserving order */
177  ast_test_validate_cleanup(test, AST_VECTOR_REMOVE_ORDERED(&sv1, 1) == ZZZ, rc, cleanup);
178  ast_test_validate_cleanup(test, sv1.current == 99, rc, cleanup);
179  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
180  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == CCC, rc, cleanup);
181 
182  ast_test_validate_cleanup(test, AST_VECTOR_INSERT_AT(&sv1, 0, ZZZ) == 0, rc, cleanup);
183  ast_test_validate_cleanup(test, sv1.current == 100, rc, cleanup);
184 
185  /* This should fail because comparison is by pointer */
186  ast_test_validate_cleanup(test, AST_VECTOR_REMOVE_ELEM_ORDERED(&sv1, "ZZZ", cleanup) != 0, rc, cleanup);
187 
188  /* This should work because we passing in the specific object to be removed */
189  cleanup_count = 0;
190  ast_test_validate_cleanup(test, AST_VECTOR_REMOVE_ELEM_ORDERED(&sv1, ZZZ, cleanup) == 0, rc, cleanup);
191  ast_test_validate_cleanup(test, sv1.current == 99, rc, cleanup);
192  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
193  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == CCC, rc, cleanup);
194  ast_test_validate_cleanup(test, cleanup_count == 1, rc, cleanup);
195 
196  /* If we want a comparison by value, we need to pass in a comparison
197  * function.
198  */
199  cleanup_count = 0;
200  ast_test_validate_cleanup(test, AST_VECTOR_REMOVE_CMP_ORDERED(&sv1, "AAA", STRING_CMP, cleanup) == 0, rc, cleanup);
201  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 98, rc, cleanup);
202  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == CCC, rc, cleanup);
203  ast_test_validate_cleanup(test, cleanup_count == 1, rc, cleanup);
204 
205  /* Test INSERT_SORTED */
206  AST_VECTOR_FREE(&sv1);
207  ast_test_validate(test, AST_VECTOR_INIT(&sv1, 0) == 0);
208 
209  ast_test_validate_cleanup(test, AST_VECTOR_ADD_SORTED(&sv1, BBB, strcmp) == 0, rc, cleanup);
210  ast_test_validate_cleanup(test, AST_VECTOR_ADD_SORTED(&sv1, ZZZ, strcmp) == 0, rc, cleanup);
211  ast_test_validate_cleanup(test, AST_VECTOR_ADD_SORTED(&sv1, CCC, strcmp) == 0, rc, cleanup);
212  ast_test_validate_cleanup(test, AST_VECTOR_ADD_SORTED(&sv1, AAA, strcmp) == 0, rc, cleanup);
213  ast_test_validate_cleanup(test, AST_VECTOR_ADD_SORTED(&sv1, (char*)CCC2, strcmp) == 0, rc, cleanup);
214 
215  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
216  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == BBB, rc, cleanup);
217  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 2) == CCC, rc, cleanup);
218  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 3) == CCC2, rc, cleanup);
219  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 4) == ZZZ, rc, cleanup);
220 
221  cleanup_count = 0;
222  AST_VECTOR_RESET(&sv1, cleanup);
223  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 0, rc, cleanup);
224  ast_test_validate_cleanup(test, sv1.max >= 5, rc, cleanup);
225  ast_test_validate_cleanup(test, sv1.elems != NULL, rc, cleanup);
226  ast_test_validate_cleanup(test, cleanup_count == 5, rc, cleanup);
227 
228 cleanup:
229  AST_VECTOR_FREE(&sv1);
230  return rc;
231 }
232 
233 static void cleanup_int(int element)
234 {
235  cleanup_count++;
236 }
237 
238 AST_TEST_DEFINE(basic_ops_integer)
239 {
240  AST_VECTOR(test_struct, int) sv1;
241  int rc = AST_TEST_PASS;
242 
243  int AAA = 1;
244  int BBB = 3;
245  int CCC = 5;
246  int ZZZ = 26;
247 
248  switch (cmd) {
249  case TEST_INIT:
250  info->name = "basic_integer";
251  info->category = "/main/vector/";
252  info->summary = "Test integer vector basic ops";
253  info->description = "Test integer vector basic ops";
254  return AST_TEST_NOT_RUN;
255  case TEST_EXECUTE:
256  break;
257  }
258 
259  ast_test_validate(test, AST_VECTOR_INIT(&sv1, 3) == 0);
260  ast_test_validate_cleanup(test, sv1.max == 3, rc, cleanup);
261  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 0, rc, cleanup);
262 
263  ast_test_validate_cleanup(test, AST_VECTOR_APPEND(&sv1, AAA) == 0, rc, cleanup);
264  ast_test_validate_cleanup(test, sv1.max == 3, rc, cleanup);
265  ast_test_validate_cleanup(test, AST_VECTOR_APPEND(&sv1, BBB) == 0, rc, cleanup);
266  ast_test_validate_cleanup(test, sv1.max == 3, rc, cleanup);
267  ast_test_validate_cleanup(test, AST_VECTOR_APPEND(&sv1, CCC) == 0, rc, cleanup);
268  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 3, rc, cleanup);
269  ast_test_validate_cleanup(test, sv1.max == 3, rc, cleanup);
270  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
271  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == BBB, rc, cleanup);
272  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 2) == CCC, rc, cleanup);
273 
274  ast_test_validate_cleanup(test, AST_VECTOR_INSERT_AT(&sv1, 1, ZZZ) == 0, rc, cleanup);
275  ast_test_validate_cleanup(test, sv1.max >= 4, rc, cleanup);
276  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 4, rc, cleanup);
277  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
278  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == ZZZ, rc, cleanup);
279  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 2) == BBB, rc, cleanup);
280  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 3) == CCC, rc, cleanup);
281 
282  ast_test_validate_cleanup(test, *(int *)AST_VECTOR_GET_CMP(&sv1, AAA, AST_VECTOR_ELEM_DEFAULT_CMP) == AAA, rc, cleanup);
283  ast_test_validate_cleanup(test, *(int *)AST_VECTOR_GET_CMP(&sv1, ZZZ, AST_VECTOR_ELEM_DEFAULT_CMP) == ZZZ, rc, cleanup);
284 
285  /* Default first value */
286  ast_test_validate_cleanup(test, AST_VECTOR_DEFAULT(&sv1, 1, CCC) == 0, rc, cleanup);
287  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == CCC, rc, cleanup);
288  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == ZZZ, rc, cleanup);
289  /* Default all values */
290  ast_test_validate_cleanup(test, AST_VECTOR_DEFAULT(&sv1, 0, AAA) == 0, rc, cleanup);
291  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
292  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == AAA, rc, cleanup);
293  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 2) == AAA, rc, cleanup);
294  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 3) == AAA, rc, cleanup);
295  /* Default more values than are currently in the vector */
296  ast_test_validate_cleanup(test, AST_VECTOR_DEFAULT(&sv1, 5, BBB) == 0, rc, cleanup);
297  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 4) == BBB, rc, cleanup);
298 
299  /* Check getting index(es) */
300  ast_test_validate_cleanup(test, AST_VECTOR_GET_INDEX(&sv1, BBB, AST_VECTOR_ELEM_DEFAULT_CMP) == 0, rc, cleanup);
301  ast_test_validate_cleanup(test, AST_VECTOR_GET_INDEX_NTH(&sv1, 2, BBB, AST_VECTOR_ELEM_DEFAULT_CMP) == 1, rc, cleanup);
302  ast_test_validate_cleanup(test, AST_VECTOR_GET_INDEX_NTH(&sv1, 4, BBB, AST_VECTOR_ELEM_DEFAULT_CMP) == 3, rc, cleanup);
303 
304  AST_VECTOR_FREE(&sv1);
305  ast_test_validate(test, sv1.elems == NULL);
306  ast_test_validate(test, sv1.current == 0);
307  ast_test_validate(test, sv1.max == 0);
308 
309  ast_test_validate(test, AST_VECTOR_INIT(&sv1, 0) == 0);
310  ast_test_validate_cleanup(test, sv1.max == 0, rc, cleanup);
311  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 0, rc, cleanup);
312 
313  ast_test_validate_cleanup(test, AST_VECTOR_APPEND(&sv1, AAA) == 0, rc, cleanup);
314  ast_test_validate_cleanup(test, AST_VECTOR_APPEND(&sv1, BBB) == 0, rc, cleanup);
315  ast_test_validate_cleanup(test, AST_VECTOR_APPEND(&sv1, CCC) == 0, rc, cleanup);
316  ast_test_validate_cleanup(test, sv1.max >= 3, rc, cleanup);
317  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 3, rc, cleanup);
318 
319  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
320  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == BBB, rc, cleanup);
321  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 2) == CCC, rc, cleanup);
322 
323  /* Overwrite index 1 */
324  ast_test_validate_cleanup(test, AST_VECTOR_REPLACE(&sv1, 1, ZZZ) == 0, rc, cleanup);
325  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 3, rc, cleanup);
326  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
327  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == ZZZ, rc, cleanup);
328  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 2) == CCC, rc, cleanup);
329 
330  /* Remove index 0 and bring the last entry into it's empty slot */
331  ast_test_validate_cleanup(test, AST_VECTOR_REMOVE_UNORDERED(&sv1, 0) == 1, rc, cleanup);
332  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 2, rc, cleanup);
333  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == CCC, rc, cleanup);
334  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == ZZZ, rc, cleanup);
335 
336  /* Replace 0 and 2 leaving 1 alone */
337  ast_test_validate_cleanup(test, AST_VECTOR_REPLACE(&sv1, 0, AAA) == 0, rc, cleanup);
338  ast_test_validate_cleanup(test, AST_VECTOR_REPLACE(&sv1, 2, CCC) == 0, rc, cleanup);
339  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 3, rc, cleanup);
340  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
341  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == ZZZ, rc, cleanup);
342  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 2) == CCC, rc, cleanup);
343 
344  /* Remove 1 and compact preserving order */
345  ast_test_validate_cleanup(test, AST_VECTOR_REMOVE_ORDERED(&sv1, 1) == ZZZ, rc, cleanup);
346  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 2, rc, cleanup);
347  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
348  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == CCC, rc, cleanup);
349 
350  /* Equivalent of APPEND */
351  ast_test_validate_cleanup(test, AST_VECTOR_REPLACE(&sv1, 2, ZZZ) == 0, rc, cleanup);
352  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 3, rc, cleanup);
353 
354  /* This should work because we passing in the specific object to be removed */
355  cleanup_count = 0;
356  ast_test_validate_cleanup(test, AST_VECTOR_REMOVE_ELEM_ORDERED(&sv1, ZZZ, cleanup_int) == 0, rc, cleanup);
357  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 2, rc, cleanup);
358  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup);
359  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == CCC, rc, cleanup);
360  ast_test_validate_cleanup(test, cleanup_count == 1, rc, cleanup);
361 
362  /* If we want a comparison by value, we need to pass in a comparison
363  * function.
364  */
365  cleanup_count = 0;
366  ast_test_validate_cleanup(test, AST_VECTOR_REMOVE_CMP_ORDERED(&sv1, AAA, AST_VECTOR_ELEM_DEFAULT_CMP, cleanup_int) == 0, rc, cleanup);
367  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 1, rc, cleanup);
368  ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == CCC, rc, cleanup);
369  ast_test_validate_cleanup(test, cleanup_count == 1, rc, cleanup);
370 
371  /* This element is gone so we shouldn't be able to find it or delete it again. */
372  ast_test_validate_cleanup(test, AST_VECTOR_GET_CMP(&sv1, AAA, AST_VECTOR_ELEM_DEFAULT_CMP) == NULL, rc, cleanup);
373  ast_test_validate_cleanup(test, AST_VECTOR_REMOVE_CMP_ORDERED(&sv1, AAA, AST_VECTOR_ELEM_DEFAULT_CMP, cleanup_int) != 0, rc, cleanup);
374 
375  /* CCC should still be there though */
376  ast_test_validate_cleanup(test, *(int *)AST_VECTOR_GET_CMP(&sv1, CCC, AST_VECTOR_ELEM_DEFAULT_CMP) == CCC, rc, cleanup);
377 
378 cleanup:
379  AST_VECTOR_FREE(&sv1);
380  return rc;
381 }
382 
383 static int visits;
384 
385 static int cb_match(void *obj, void *arg)
386 {
387  visits++;
388  return strcmp(arg, obj) == 0 ? CMP_MATCH : 0;
389 }
390 
391 static int cb_visits(void *obj, int v)
392 {
393  visits++;
394  return visits == v ? CMP_STOP : 0;
395 }
396 
397 AST_TEST_DEFINE(callbacks)
398 {
399  AST_VECTOR(, char *) sv1;
400  typeof(sv1) *sv2 = NULL;
401 
402  int rc = AST_TEST_PASS;
403  char *AAA = "AAA";
404  char *AAA2 = "AAA";
405  char *BBB = "BBB";
406  char *CCC = "CCC";
407  char *DEF = "default_value";
408 
409  switch (cmd) {
410  case TEST_INIT:
411  info->name = "callbacks";
412  info->category = "/main/vector/";
413  info->summary = "Test vector callback ops";
414  info->description = "Test vector callback ops";
415  return AST_TEST_NOT_RUN;
416  case TEST_EXECUTE:
417  break;
418  }
419 
420  AST_VECTOR_INIT(&sv1, 32);
421 
422  AST_VECTOR_APPEND(&sv1, AAA);
423  AST_VECTOR_APPEND(&sv1, BBB);
424  AST_VECTOR_APPEND(&sv1, CCC);
425  AST_VECTOR_APPEND(&sv1, AAA2);
426 
427  visits = 0;
428  ast_test_validate_cleanup(test, AST_VECTOR_CALLBACK(&sv1, cb_match, DEF, "AAA") == AAA, rc, cleanup);
429  ast_test_validate_cleanup(test, visits == 1, rc, cleanup);
430 
431  visits = 0;
432  ast_test_validate_cleanup(test, AST_VECTOR_CALLBACK(&sv1, cb_match, DEF, "XYZ") == DEF, rc, cleanup);
433  ast_test_validate_cleanup(test, visits == 4, rc, cleanup);
434 
435  visits = 0;
436  ast_test_validate_cleanup(test, AST_VECTOR_CALLBACK(&sv1, cb_visits, DEF, 2) == DEF, rc, cleanup);
437  ast_test_validate_cleanup(test, visits == 2, rc, cleanup);
438 
439 
441  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(sv2) == 4, rc, cleanup);
442  ast_test_validate_cleanup(test, AST_VECTOR_GET(sv2, 0) == AAA, rc, cleanup);
443  ast_test_validate_cleanup(test, AST_VECTOR_GET(sv2, 1) == BBB, rc, cleanup);
444  ast_test_validate_cleanup(test, AST_VECTOR_GET(sv2, 2) == CCC, rc, cleanup);
445  ast_test_validate_cleanup(test, AST_VECTOR_GET(sv2, 3) == AAA2, rc, cleanup);
446 
447  AST_VECTOR_PTR_FREE(sv2);
448 
449  AST_VECTOR_APPEND(&sv1, AAA);
450  AST_VECTOR_APPEND(&sv1, BBB);
451  AST_VECTOR_APPEND(&sv1, CCC);
452  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&sv1) == 7, rc, cleanup);
453 
454  sv2 = AST_VECTOR_CALLBACK_MULTIPLE(&sv1, cb_match, "AAA");
455  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(sv2) == 3, rc, cleanup);
456  ast_test_validate_cleanup(test, AST_VECTOR_GET(sv2, 0) == AAA, rc, cleanup);
457  ast_test_validate_cleanup(test, AST_VECTOR_GET(sv2, 1) == AAA2, rc, cleanup);
458  ast_test_validate_cleanup(test, AST_VECTOR_GET(sv2, 2) == AAA, rc, cleanup);
459 
460 cleanup:
461  AST_VECTOR_FREE(&sv1);
462  AST_VECTOR_PTR_FREE(sv2);
463 
464  return rc;
465 }
466 
468 {
469  AST_VECTOR_RW(, char *) sv1;
470  int rc = AST_TEST_PASS;
471  struct timespec ts;
472 
473  switch (cmd) {
474  case TEST_INIT:
475  info->name = "locks";
476  info->category = "/main/vector/";
477  info->summary = "Test vector locking ops";
478  info->description = "Test vector locking ops";
479  return AST_TEST_NOT_RUN;
480  case TEST_EXECUTE:
481  break;
482  }
483 
484  /* We're not actually checking that locking works,
485  * just that the macro expansions work
486  */
487 
488  AST_VECTOR_RW_INIT(&sv1, 0);
489 
490  ast_test_validate_cleanup(test, AST_VECTOR_RW_RDLOCK(&sv1) == 0, rc, cleanup);
491  ast_test_validate_cleanup(test, AST_VECTOR_RW_UNLOCK(&sv1) == 0, rc, cleanup);
492  ast_test_validate_cleanup(test, AST_VECTOR_RW_WRLOCK(&sv1) == 0, rc, cleanup);
493  ast_test_validate_cleanup(test, AST_VECTOR_RW_UNLOCK(&sv1) == 0, rc, cleanup);
494 
495  ast_test_validate_cleanup(test, AST_VECTOR_RW_RDLOCK_TRY(&sv1) == 0, rc, cleanup);
496  ast_test_validate_cleanup(test, AST_VECTOR_RW_WRLOCK_TRY(&sv1) != 0, rc, cleanup);
497  ast_test_validate_cleanup(test, AST_VECTOR_RW_UNLOCK(&sv1) == 0, rc, cleanup);
498  ast_test_validate_cleanup(test, AST_VECTOR_RW_WRLOCK_TRY(&sv1) == 0, rc, cleanup);
499  ast_test_validate_cleanup(test, AST_VECTOR_RW_UNLOCK(&sv1) == 0, rc, cleanup);
500 
501  ts.tv_nsec = 0;
502  ts.tv_sec = 2;
503 
504  ast_test_validate_cleanup(test, AST_VECTOR_RW_RDLOCK_TIMED(&sv1, &ts) == 0, rc, cleanup);
505  ast_test_validate_cleanup(test, AST_VECTOR_RW_WRLOCK_TIMED(&sv1, &ts) != 0, rc, cleanup);
506  ast_test_validate_cleanup(test, AST_VECTOR_RW_UNLOCK(&sv1) == 0, rc, cleanup);
507  ast_test_validate_cleanup(test, AST_VECTOR_RW_WRLOCK_TIMED(&sv1, &ts) == 0, rc, cleanup);
508  ast_test_validate_cleanup(test, AST_VECTOR_RW_UNLOCK(&sv1) == 0, rc, cleanup);
509 
510 cleanup:
511  AST_VECTOR_RW_FREE(&sv1);
512 
513  return rc;
514 }
515 
516 static int unload_module(void)
517 {
518  AST_TEST_UNREGISTER(locks);
519  AST_TEST_UNREGISTER(callbacks);
520  AST_TEST_UNREGISTER(basic_ops_integer);
521  AST_TEST_UNREGISTER(basic_ops);
522 
523  return 0;
524 }
525 
526 static int load_module(void)
527 {
528  AST_TEST_REGISTER(locks);
529  AST_TEST_REGISTER(callbacks);
530  AST_TEST_REGISTER(basic_ops_integer);
531  AST_TEST_REGISTER(basic_ops);
532 
534 }
535 
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_VECTOR_RW_INIT(vec, size)
Initialize a vector with a read/write lock.
Definition: vector.h:158
#define AST_VECTOR_GET_INDEX(vec, value, cmp)
Get the 1st index from a vector that matches the given comparison.
Definition: vector.h:721
typedef typeof(dummy_tv_var_for_types.tv_sec) ast_time_t
static int visits
Definition: test_vector.c:383
#define AST_VECTOR_ADD_SORTED(vec, elem, cmp)
Add an element into a sorted vector.
Definition: vector.h:371
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
#define AST_VECTOR_GET_INDEX_NTH(vec, nth, value, cmp)
Get the nth index from a vector that matches the given comparison.
Definition: vector.h:698
Asterisk main include file. File version handling, generic pbx functions.
String manipulation functions.
#define AST_VECTOR_RW_WRLOCK_TIMED(vec, timespec)
Try to obtain write lock on vector failing after timeout if unable.
Definition: vector.h:940
#define AST_VECTOR_REMOVE_ELEM_ORDERED(vec, elem, cleanup)
Remove an element from a vector while maintaining order.
Definition: vector.h:600
#define AST_VECTOR_RW(name, type)
Define a vector structure with a read/write lock.
Definition: vector.h:93
#define AST_VECTOR_RW_UNLOCK(vec)
Unlock vector.
Definition: vector.h:900
#define AST_VECTOR_ELEM_DEFAULT_CMP(elem, value)
Default comparator for AST_VECTOR_REMOVE_ELEM_UNORDERED()
Definition: vector.h:564
static int cleanup_count
Definition: test_vector.c:43
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
Test Framework API.
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define AST_VECTOR_RW_RDLOCK_TRY(vec)
Try to obtain read lock on vector failing immediately if unable.
Definition: vector.h:910
#define AST_VECTOR_REMOVE_UNORDERED(vec, idx)
Remove an element from an unordered vector by index.
Definition: vector.h:438
#define AST_VECTOR_RW_RDLOCK(vec)
Obtain read lock on vector.
Definition: vector.h:880
#define NULL
Definition: resample.c:96
AST_TEST_DEFINE(basic_ops)
Definition: test_vector.c:54
#define AST_VECTOR_CALLBACK_MULTIPLE(vec, callback,...)
Execute a callback on every element in a vector returning the matching elements in a new vector...
Definition: vector.h:832
Utility functions.
#define AST_VECTOR_RW_RDLOCK_TIMED(vec, timespec)
Try to obtain read lock on vector failing after timeout if unable.
Definition: vector.h:930
static int load_module(void)
Definition: test_vector.c:526
#define AST_VECTOR_RW_WRLOCK_TRY(vec)
Try to obtain write lock on vector failing immediately if unable.
Definition: vector.h:920
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define AST_VECTOR_RW_FREE(vec)
Deallocates this locked vector.
Definition: vector.h:202
static int cb_visits(void *obj, int v)
Definition: test_vector.c:391
#define AST_VECTOR_REMOVE_ORDERED(vec, idx)
Remove an element from a vector by index while maintaining order.
Definition: vector.h:448
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44
#define STRING_CMP(a, b)
Definition: test_vector.c:50
#define AST_VECTOR_MATCH_ALL(element)
Default callback for AST_VECTOR_CALLBACK()
Definition: vector.h:754
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
static int cb_match(void *obj, void *arg)
Definition: test_vector.c:385
def info(msg)
static int unload_module(void)
Definition: test_vector.c:516
static void cleanup(char *element)
Definition: test_vector.c:45
#define AST_VECTOR_RW_WRLOCK(vec)
Obtain write lock on vector.
Definition: vector.h:890
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:627
Vector container support.
#define AST_VECTOR_GET_CMP(vec, value, cmp)
Get an element from a vector that matches the given comparison.
Definition: vector.h:733
#define AST_VECTOR_PTR_FREE(vec)
Deallocates this vector pointer.
Definition: vector.h:189
#define AST_VECTOR_REMOVE_CMP_ORDERED(vec, value, cmp, cleanup)
Remove an element from a vector that matches the given comparison while maintaining order...
Definition: vector.h:540
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
#define AST_VECTOR_REPLACE(vec, idx, elem)
Replace an element at a specific position in a vector, growing the vector if needed.
Definition: vector.h:284
#define AST_VECTOR_CALLBACK(vec, callback, default_value,...)
Execute a callback on every element in a vector returning the first matched.
Definition: vector.h:768
#define AST_VECTOR_INSERT_AT(vec, idx, elem)
Insert an element at a specific position in a vector, growing the vector if needed.
Definition: vector.h:338
#define AST_VECTOR_DEFAULT(vec, size, value)
Default a vector up to size with the given value.
Definition: vector.h:309
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
static void cleanup_int(int element)
Definition: test_vector.c:233