Asterisk - The Open Source Telephony Project GIT-master-a358458
test_dlinklists.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2008, Steve Murphy
5 *
6 * Steve Murphy <murf@digium.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/*! \file
20 *
21 * \brief Doubly-Linked List Tests
22 *
23 * \author\verbatim Steve Murphy <murf@digium.com> \endverbatim
24 *
25 * This module will run some DLL tests at load time
26 * \ingroup tests
27 */
28
29/*** MODULEINFO
30 <depend>TEST_FRAMEWORK</depend>
31 <support_level>core</support_level>
32 ***/
33
34#include "asterisk.h"
35
36#include "asterisk/file.h"
37#include "asterisk/channel.h"
38#include "asterisk/pbx.h"
39#include "asterisk/module.h"
40#include "asterisk/lock.h"
41#include "asterisk/app.h"
42
43
45
46/* Tests for DLLists! We really should, and here is a nice place to do it in asterisk */
47
48struct test1
49{
50 char name[10];
52};
53
55{
57 int count;
58};
59
60static void print_list(struct test_container *x, char *expect)
61{
62 struct test1 *t1;
63 char buff[1000];
64 buff[0] = 0;
66 strcat(buff,t1->name);
67 if (t1 != AST_DLLIST_LAST(&x->entries))
68 strcat(buff," <=> ");
69 }
70
71 ast_debug(1,"Got: %s [expect %s]\n", buff, expect);
72}
73
74static void print_list_backwards(struct test_container *x, char *expect)
75{
76 struct test1 *t1;
77 char buff[1000];
78 buff[0] = 0;
80 strcat(buff,t1->name);
81 if (t1 != AST_DLLIST_FIRST(&x->entries))
82 strcat(buff," <=> ");
83 }
84
85 ast_debug(1,"Got: %s [expect %s]\n", buff, expect);
86}
87
88static struct test_container *make_cont(void)
89{
90 struct test_container *t = ast_calloc(sizeof(struct test_container),1);
91 return t;
92}
93
94static struct test1 *make_test1(char *name)
95{
96 struct test1 *t1 = ast_calloc(sizeof(struct test1),1);
97 strcpy(t1->name, name);
98 return t1;
99}
100
102{
103 /* remove all the test1's */
104 struct test1 *t1;
107 ast_free(t1);
108 }
110 ast_free(x);
111}
112
113/* Macros to test:
114AST_DLLIST_LOCK(head)
115AST_RWDLLIST_WRLOCK(head)
116AST_RWDLLIST_WRLOCK(head)
117AST_RWDLLIST_RDLOCK(head)
118AST_DLLIST_TRYLOCK(head)
119AST_RWDLLIST_TRYWRLOCK(head)
120AST_RWDLLIST_TRYRDLOCK(head)
121AST_DLLIST_UNLOCK(head)
122AST_RWDLLIST_UNLOCK(head)
123
124AST_DLLIST_HEAD(name, type)
125AST_RWDLLIST_HEAD(name, type)
126AST_DLLIST_HEAD_NOLOCK(name, type)
127AST_DLLIST_HEAD_STATIC(name, type)
128AST_RWDLLIST_HEAD_STATIC(name, type)
129AST_DLLIST_HEAD_NOLOCK_STATIC(name, type)
130AST_DLLIST_HEAD_SET(head, entry)
131AST_RWDLLIST_HEAD_SET(head, entry)
132AST_DLLIST_HEAD_SET_NOLOCK(head, entry)
133AST_DLLIST_HEAD_INIT(head)
134AST_RWDLLIST_HEAD_INIT(head)
135AST_DLLIST_HEAD_INIT_NOLOCK(head)
136
137AST_RWDLLIST_HEAD_DESTROY(head)
138
139AST_DLLIST_ENTRY(type)
140
141--- the above not going to be dealt with here ---
142
143AST_DLLIST_INSERT_HEAD(head, elm, field)
144AST_DLLIST_TRAVERSE(head,var,field)
145AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_BEGIN(head, var, field)
146AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_END
147AST_DLLIST_FIRST(head)
148AST_DLLIST_LAST(head)
149AST_DLLIST_NEXT(elm, field)
150AST_DLLIST_PREV(elm, field)
151AST_DLLIST_EMPTY(head)
152AST_DLLIST_TRAVERSE_BACKWARDS(head,var,field)
153AST_DLLIST_INSERT_AFTER(head, listelm, elm, field)
154AST_DLLIST_INSERT_TAIL(head, elm, field)
155AST_DLLIST_REMOVE_HEAD(head, field)
156AST_DLLIST_REMOVE(head, elm, field)
157AST_DLLIST_TRAVERSE_SAFE_BEGIN(head, var, field)
158AST_DLLIST_TRAVERSE_SAFE_END
159AST_DLLIST_REMOVE_CURRENT(field)
160AST_DLLIST_MOVE_CURRENT(newhead, field)
161AST_DLLIST_INSERT_BEFORE_CURRENT(elm, field)
162
163
164AST_DLLIST_MOVE_CURRENT_BACKWARDS(newhead, field)
165AST_DLLIST_INSERT_BEFORE_CURRENT_BACKWARDS(elm, field)
166AST_DLLIST_HEAD_DESTROY(head)
167
168AST_DLLIST_APPEND_DLLIST(head, list, field)
169
170*/
171
172static void dll_tests(void)
173{
174 struct test_container *tc;
175 struct test1 *a;
176 struct test1 *b;
177 struct test1 *c;
178 struct test1 *d;
179 struct test1 *e;
180
181 ast_debug(1,"Test AST_DLLIST_INSERT_HEAD, AST_DLLIST_TRAVERSE, AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_BEGIN, AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_END\n");
182 tc = make_cont();
183 a = make_test1("A");
184 b = make_test1("B");
185 c = make_test1("C");
186 d = make_test1("D");
191 print_list(tc, "A <=> B <=> C <=> D");
192
194
195 tc = make_cont();
196
197 if (AST_DLLIST_EMPTY(&tc->entries))
198 ast_debug(1,"Test AST_DLLIST_EMPTY....OK\n");
199 else
200 ast_log(LOG_ERROR,"Test AST_DLLIST_EMPTY....PROBLEM!!\n");
201
202
203 a = make_test1("A");
204 b = make_test1("B");
205 c = make_test1("C");
206 d = make_test1("D");
207
208 ast_debug(1,"Test AST_DLLIST_INSERT_TAIL\n");
213 print_list(tc, "A <=> B <=> C <=> D");
214
215 if (AST_DLLIST_FIRST(&tc->entries) == a)
216 ast_debug(1,"Test AST_DLLIST_FIRST....OK\n");
217 else
218 ast_log(LOG_ERROR,"Test AST_DLLIST_FIRST....PROBLEM\n");
219
220 if (AST_DLLIST_LAST(&tc->entries) == d)
221 ast_debug(1,"Test AST_DLLIST_LAST....OK\n");
222 else
223 ast_log(LOG_ERROR,"Test AST_DLLIST_LAST....PROBLEM\n");
224
225 if (AST_DLLIST_NEXT(a,list) == b)
226 ast_debug(1,"Test AST_DLLIST_NEXT....OK\n");
227 else
228 ast_log(LOG_ERROR,"Test AST_DLLIST_NEXT....PROBLEM\n");
229
230 if (AST_DLLIST_PREV(d,list) == c)
231 ast_debug(1,"Test AST_DLLIST_PREV....OK\n");
232 else
233 ast_log(LOG_ERROR,"Test AST_DLLIST_PREV....PROBLEM\n");
234
236
237 tc = make_cont();
238
239 a = make_test1("A");
240 b = make_test1("B");
241 c = make_test1("C");
242 d = make_test1("D");
243
244 ast_debug(1,"Test AST_DLLIST_INSERT_AFTER, AST_DLLIST_TRAVERSE_BACKWARDS\n");
249 print_list_backwards(tc, "D <=> C <=> B <=> A");
250
251 ast_debug(1,"Test AST_DLLIST_REMOVE_HEAD\n");
253 print_list_backwards(tc, "D <=> C <=> B");
254 ast_debug(1,"Test AST_DLLIST_REMOVE_HEAD\n");
256 print_list_backwards(tc, "D <=> C");
257 ast_debug(1,"Test AST_DLLIST_REMOVE_HEAD\n");
259 print_list_backwards(tc, "D");
261
262 if (AST_DLLIST_EMPTY(&tc->entries))
263 ast_debug(1,"Test AST_DLLIST_REMOVE_HEAD....OK\n");
264 else
265 ast_log(LOG_ERROR,"Test AST_DLLIST_REMOVE_HEAD....PROBLEM!!\n");
266
271
272 ast_debug(1,"Test AST_DLLIST_REMOVE\n");
274 print_list(tc, "A <=> B <=> D");
276 print_list(tc, "B <=> D");
278 print_list(tc, "B");
280
281 if (AST_DLLIST_EMPTY(&tc->entries))
282 ast_debug(1,"Test AST_DLLIST_REMOVE....OK\n");
283 else
284 ast_log(LOG_ERROR,"Test AST_DLLIST_REMOVE....PROBLEM!!\n");
285
290
293 }
295 if (AST_DLLIST_EMPTY(&tc->entries))
296 ast_debug(1,"Test AST_DLLIST_REMOVE_CURRENT... OK\n");
297 else
298 ast_log(LOG_ERROR,"Test AST_DLLIST_REMOVE_CURRENT... PROBLEM\n");
299
300 ast_debug(1,"Test AST_DLLIST_MOVE_CURRENT, AST_DLLIST_INSERT_BEFORE_CURRENT\n");
305 if (e == a) {
307 }
308
309 if (e == b) {
310 AST_DLLIST_MOVE_CURRENT(&tc->entries, list); /* D A C B */
311 }
312
313 }
315 print_list(tc, "D <=> A <=> C <=> B");
316
318
319 tc = make_cont();
320
321 a = make_test1("A");
322 b = make_test1("B");
323 c = make_test1("C");
324 d = make_test1("D");
325
326 ast_debug(1,"Test: AST_DLLIST_MOVE_CURRENT_BACKWARDS and AST_DLLIST_INSERT_BEFORE_CURRENT_BACKWARDS\n");
331 if (e == c && AST_DLLIST_FIRST(&tc->entries) != c) {
333 print_list(tc, "C <=> A <=> B");
334 }
335
336 if (e == b) {
338 ast_free(b);
339 print_list(tc, "C <=> A");
340 }
341 if (e == a) {
343 print_list(tc, "C <=> A <=> D");
344 }
345
346 }
348 print_list(tc, "C <=> A <=> D");
349
351}
352
353static int unload_module(void)
354{
355 return 0;
356}
357
358static int load_module(void)
359{
360 dll_tests();
362}
363
364AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Test Doubly-Linked Lists");
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
static unsigned char * buff
Definition: chan_unistim.c:259
General Asterisk PBX channel definitions.
A set of macros to manage doubly-linked lists.
#define AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: dlinkedlists.h:888
#define AST_DLLIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: dlinkedlists.h:469
#define AST_DLLIST_ENTRY(type)
Declare previous/forward links inside a list entry.
Definition: dlinkedlists.h:413
#define AST_DLLIST_MOVE_CURRENT_BACKWARDS(newhead, field)
Move the current list entry to another list at the head.
Definition: dlinkedlists.h:801
#define AST_DLLIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: dlinkedlists.h:446
#define AST_DLLIST_TRAVERSE_BACKWARDS(head, var, field)
Loops over (traverses) the entries in a list in reverse order, starting at the end.
Definition: dlinkedlists.h:618
#define AST_DLLIST_INSERT_AFTER(head, listelm, elm, field)
Inserts a list entry after a given entry.
#define AST_DLLIST_MOVE_CURRENT(newhead, field)
Move the current list entry to another list at the tail.
Definition: dlinkedlists.h:782
#define AST_DLLIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
#define AST_DLLIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_DLLIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: dlinkedlists.h:849
#define AST_DLLIST_PREV(elm, field)
Returns the previous entry in the list before the given entry.
Definition: dlinkedlists.h:457
#define AST_DLLIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list node before the current node during a traversal.
Definition: dlinkedlists.h:696
#define AST_DLLIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define AST_DLLIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: dlinkedlists.h:576
#define AST_DLLIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: dlinkedlists.h:753
#define AST_DLLIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_DLLIST_FIRST(head)
Returns the first entry contained in a list.
Definition: dlinkedlists.h:422
#define AST_DLLIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: dlinkedlists.h:158
#define AST_DLLIST_LAST(head)
Returns the last entry contained in a list.
Definition: dlinkedlists.h:431
#define AST_DLLIST_INSERT_BEFORE_CURRENT_BACKWARDS(elm, field)
Inserts a list entry after the current entry during a backwards traversal. Since this is a backwards ...
Definition: dlinkedlists.h:904
#define AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_END
Closes a safe loop traversal block.
Definition: dlinkedlists.h:921
#define AST_DLLIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: dlinkedlists.h:913
Generic File Format Support. Should be included by clients of the file handling routines....
static const char name[]
Definition: format_mp3.c:68
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
Asterisk locking-related definitions:
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
Core PBX routines and definitions.
char name[10]
struct test1::@497 list
struct test_container::entries entries
static struct test1 * make_test1(char *name)
static void print_list(struct test_container *x, char *expect)
static void print_list_backwards(struct test_container *x, char *expect)
static struct test_container * make_cont(void)
static int load_module(void)
static void dll_tests(void)
static int unload_module(void)
static void destroy_test_container(struct test_container *x)
static struct test_val b
static struct test_val a
static struct test_val d
static struct test_val c