Merge "core: Tweak startup order."
[asterisk/asterisk.git] / tests / test_vector.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2015, Fairview 5 Engineering, LLC
5  *
6  * George Joseph <george.joseph@fairview5.com>
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 <george.joseph@fairview5.com>
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
440         sv2 = AST_VECTOR_CALLBACK_MULTIPLE(&sv1, AST_VECTOR_MATCH_ALL);
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
467 AST_TEST_DEFINE(locks)
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
533         return AST_MODULE_LOAD_SUCCESS;
534 }
535
536 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Vector test module");