Merged revisions 332177 via svnmerge from
[asterisk/asterisk.git] / tests / test_format_api.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2010, Digium, Inc.
5  *
6  * David Vossel <dvossel@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 /*!
20  * \file
21  * \brief Tests for the ast_event API
22  *
23  * \author David Vossel <dvossel@digium.com>
24  *
25  * \ingroup tests
26  *
27  */
28
29 /*** MODULEINFO
30         <depend>TEST_FRAMEWORK</depend>
31  ***/
32
33 #include "asterisk.h"
34
35 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
36
37 #include "asterisk/module.h"
38 #include "asterisk/test.h"
39 #include "asterisk/format.h"
40 #include "asterisk/format_cap.h"
41 #include "asterisk/strings.h"
42
43 /*! These are the keys for accessing attributes */
44 enum test_attr_keys {
45         TEST_ATTR_KEY_SAMP_RATE,
46         TEST_ATTR_KEY_STRING,
47 };
48
49 /*! These are the values for the TEST_ATTR_KEY_SAMP_RATE key */
50 enum test_attr_vals_samp {
51         TEST_ATTR_VAL_SAMP_8KHZ  = (1 << 0),
52         TEST_ATTR_VAL_SAMP_12KHZ = (1 << 1),
53         TEST_ATTR_VAL_SAMP_16KHZ = (1 << 2),
54         TEST_ATTR_VAL_SAMP_32KHZ = (1 << 3),
55         TEST_ATTR_VAL_SAMP_48KHZ = (1 << 4),
56 };
57
58 /*! This is the attribute structure used for our test interface. */
59 struct test_attr {
60         enum test_attr_vals_samp samp_flags;
61         char string[32];
62 };
63
64 static enum ast_format_cmp_res test_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2)
65 {
66         struct test_attr *attr1 = (struct test_attr *) fattr1;
67         struct test_attr *attr2 = (struct test_attr *) fattr2;
68
69         if ((attr1->samp_flags == attr2->samp_flags) &&
70                 !(strcmp(attr1->string, attr2->string))) {
71                 return AST_FORMAT_CMP_EQUAL;
72         }
73         if ((attr1->samp_flags != (attr1->samp_flags & attr2->samp_flags)) ||
74                 (!ast_strlen_zero(attr1->string) && strcmp(attr1->string, attr2->string))) {
75                 return AST_FORMAT_CMP_NOT_EQUAL;
76         }
77         return AST_FORMAT_CMP_SUBSET;
78 }
79
80 static int test_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result)
81 {
82         struct test_attr *attr1 = (struct test_attr *) fattr1;
83         struct test_attr *attr2 = (struct test_attr *) fattr2;
84         struct test_attr *attr_res = (struct test_attr *) result;
85         int joint = -1;
86
87         attr_res->samp_flags = (attr1->samp_flags & attr2->samp_flags);
88
89         if (attr_res->samp_flags) {
90                 joint = 0;
91         }
92
93         if (!strcmp(attr1->string, attr2->string)) {
94                 ast_copy_string(attr_res->string, attr1->string, sizeof(attr_res->string));
95                 joint = 0;
96         }
97
98         return joint;
99 }
100
101 static void test_set(struct ast_format_attr *fattr, va_list ap)
102 {
103         enum test_attr_keys key;
104         struct test_attr *attr = (struct test_attr *) fattr;
105         char *string;
106
107         for (key = va_arg(ap, int);
108                 key != AST_FORMAT_ATTR_END;
109                 key = va_arg(ap, int))
110         {
111                 switch (key) {
112                 case TEST_ATTR_KEY_SAMP_RATE:
113                         attr->samp_flags = (va_arg(ap, int) | attr->samp_flags);
114                         break;
115                 case TEST_ATTR_KEY_STRING:
116                         string = va_arg(ap, char *);
117                         if (!ast_strlen_zero(string)) {
118                                 ast_copy_string(attr->string, string, sizeof(attr->string));
119                         }
120                         break;
121                 default:
122                         ast_log(LOG_WARNING, "unknown attribute type %d\n", key);
123                 }
124         }
125 }
126
127 /*! uLaw does not actually have any attributes associated with it.
128  * This is just for the purpose of testing. We are guaranteed there
129  * will never exist a interface for uLaw already. */
130 static struct ast_format_attr_interface test_interface = {
131         .id = AST_FORMAT_TESTLAW,
132         .format_attr_cmp = test_cmp,
133         .format_attr_get_joint = test_getjoint,
134         .format_attr_set = test_set
135 };
136
137 /*!
138  * \internal
139  */
140 AST_TEST_DEFINE(format_test1)
141 {
142         struct ast_format format1 = { 0, };
143         struct ast_format format2 = { 0, };
144         struct ast_format joint = { 0, };
145
146         switch (cmd) {
147         case TEST_INIT:
148                 info->name = "ast_format_test1";
149                 info->category = "/main/format/";
150                 info->summary = "Test ast_format with attributes.";
151                 info->description =
152                         "This test exercises the Ast Format API by creating and registering "
153                         "a custom ast_format_attr_interface and performing various function "
154                         "calls on ast_formats using the interface. ";
155                 return AST_TEST_NOT_RUN;
156         case TEST_EXECUTE:
157                 break;
158         }
159
160         if (ast_format_attr_reg_interface(&test_interface)) {
161                 ast_test_status_update(test, "test_interface failed to register.\n");
162                 return AST_TEST_FAIL;
163         }
164
165         /* set a format with a single attribute. */
166         ast_format_set(&format1, AST_FORMAT_TESTLAW, 1,
167                 TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
168                 AST_FORMAT_ATTR_END);
169         if (ast_format_isset(&format1, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, AST_FORMAT_ATTR_END)) {
170                 ast_test_status_update(test, "format1 did not set number attribute correctly.\n");
171                 return AST_TEST_FAIL;
172         }
173         if (!ast_format_isset(&format1, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_12KHZ, AST_FORMAT_ATTR_END)) {
174                 ast_test_status_update(test, "format1 did not determine isset on number correctly. \n");
175                 return AST_TEST_FAIL;
176         }
177
178         /* append the string attribute to a format with previous attributes already set */
179         ast_format_append(&format1,
180                 TEST_ATTR_KEY_STRING,"String",
181                 AST_FORMAT_ATTR_END);
182         if (ast_format_isset(&format1, TEST_ATTR_KEY_STRING, "String", AST_FORMAT_ATTR_END)) {
183                 ast_test_status_update(test, "format1 did not set string attribute correctly.\n");
184                 return AST_TEST_FAIL;
185         }
186         if (!ast_format_isset(&format1, TEST_ATTR_KEY_STRING, "Not a string", AST_FORMAT_ATTR_END)) {
187                 ast_test_status_update(test, "format1 did not determine isset on string correctly. \n");
188                 return AST_TEST_FAIL;
189         }
190
191         /* set format2 with both STRING and NUMBER at the same time */
192         ast_format_set(&format2, AST_FORMAT_TESTLAW, 1,
193                 TEST_ATTR_KEY_STRING, "MOOOoo",
194                 TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
195                 TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ,
196                 AST_FORMAT_ATTR_END);
197         /* perform isset with multiple key value pairs. */
198
199         if (ast_format_isset(&format2,
200                         TEST_ATTR_KEY_STRING, "MOOOoo",
201                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ,
202                         AST_FORMAT_ATTR_END)) {
203
204                 ast_test_status_update(test, "format2 did not set attributes correctly.\n");
205                 return AST_TEST_FAIL;
206         }
207         if (!ast_format_isset(&format2,
208                         TEST_ATTR_KEY_STRING, "WRONG",
209                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
210                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ,
211                         AST_FORMAT_ATTR_END)) {
212
213                 ast_test_status_update(test, "format2 did not deterine isset correctly.\n");
214                 return AST_TEST_FAIL;
215         }
216
217         /* get joint attributes between format1 and format2. */
218         if (ast_format_joint(&format1, &format2, &joint)) {
219                 ast_test_status_update(test, "failed to get joint attributes.\n");
220                 return AST_TEST_FAIL;
221         }
222         if (ast_format_isset(&joint, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, AST_FORMAT_ATTR_END)) {
223                 ast_test_status_update(test, "joint attribute was not what we expected.\n");
224                 return AST_TEST_FAIL;
225         }
226
227         /* exercise compare functions */
228         if (ast_format_cmp(&format1, &format2) != AST_FORMAT_CMP_NOT_EQUAL) {
229                 ast_test_status_update(test, "cmp 1 failed.\n");
230                 return AST_TEST_FAIL;
231         }
232         if (ast_format_cmp(&format1, &format1) != AST_FORMAT_CMP_EQUAL) {
233                 ast_test_status_update(test, "cmp 2 failed.\n");
234                 return AST_TEST_FAIL;
235         }
236         if (ast_format_cmp(&joint, &format1) != AST_FORMAT_CMP_SUBSET) {
237                 ast_test_status_update(test, "cmp 3 failed.\n");
238                 return AST_TEST_FAIL;
239         }
240
241         /* unregister interface */
242         if (ast_format_attr_unreg_interface(&test_interface)) {
243                 ast_test_status_update(test, "test_interface failed to unregister.\n");
244                 return AST_TEST_FAIL;
245         }
246
247         return AST_TEST_PASS;
248 }
249
250 /*!
251  * \internal
252  */
253 AST_TEST_DEFINE(format_test2)
254 {
255         struct ast_format format = { 0, };
256
257         switch (cmd) {
258         case TEST_INIT:
259                 info->name = "ast_format_test2";
260                 info->category = "/main/format/";
261                 info->summary = "Test ast_format unique id and category system";
262                 info->description =
263                         "This test exercises the Ast Format unique id and category "
264                         "system by creating formats of various types and verifying "
265                         "their category matches what we expect.";
266                 return AST_TEST_NOT_RUN;
267         case TEST_EXECUTE:
268                 break;
269         }
270
271         ast_format_set(&format, AST_FORMAT_ULAW, 0);
272         if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_AUDIO) {
273                 ast_test_status_update(test, "audio type failed\n");
274                 return AST_TEST_FAIL;
275         }
276
277         ast_format_set(&format, AST_FORMAT_H264, 0);
278         if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_VIDEO) {
279                 ast_test_status_update(test, "video type failed\n");
280                 return AST_TEST_FAIL;
281         }
282
283         ast_format_set(&format, AST_FORMAT_JPEG, 0);
284         if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_IMAGE) {
285                 ast_test_status_update(test, "image type failed\n");
286                 return AST_TEST_FAIL;
287         }
288
289         ast_format_set(&format, AST_FORMAT_T140, 0);
290         if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_TEXT) {
291                 ast_test_status_update(test, "text type failed\n");
292                 return AST_TEST_FAIL;
293         }
294
295         return AST_TEST_PASS;
296 }
297
298 static int container_test1_helper(struct ast_format_cap *cap1, struct ast_format_cap *cap2, struct ast_test *test)
299 {
300
301         int res = AST_TEST_PASS;
302         struct ast_format_cap *cap_joint = NULL;
303         struct ast_format tmpformat;
304
305         if (ast_format_attr_reg_interface(&test_interface)) {
306                 ast_test_status_update(test, "test_interface failed to register.\n");
307                 ast_format_cap_destroy(cap1);
308                 ast_format_cap_destroy(cap2);
309                 return AST_TEST_FAIL;
310         }
311
312         ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0));
313         ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0));
314         ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_G722, 0));
315         ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0));
316         ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_H264, 0));
317         ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_H263, 0));
318         ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_T140, 0));
319         ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0));
320         ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1,
321                         TEST_ATTR_KEY_STRING, "testing caps hooray",
322                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
323                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ,
324                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_32KHZ,
325                         AST_FORMAT_ATTR_END));
326
327         /* Test is compatible */
328         if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0)) ||
329                 !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) ||
330                 !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) ||
331                 !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_H264, 0)) ||
332                 !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0)) ||
333                 !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) {
334                 ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 1.\n");
335                 res = AST_TEST_FAIL;
336                 goto test3_cleanup;
337         }
338
339         /* Test things that are not compatible */
340         if (ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_SPEEX, 0)) ||
341                 ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_SPEEX16, 0)) ||
342                 ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_H261, 0))) {
343                 ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 2.\n");
344                 res = AST_TEST_FAIL;
345                 goto test3_cleanup;
346         }
347
348         /* Test compatiblity with format with attributes. */
349         if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1,
350                         TEST_ATTR_KEY_STRING, "testing caps hooray",
351                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
352                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ,
353                         AST_FORMAT_ATTR_END))) {
354
355                 ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 3.\n");
356                 res = AST_TEST_FAIL;
357                 goto test3_cleanup;
358         }
359         if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1,
360                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
361                         AST_FORMAT_ATTR_END))) {
362
363                 ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 4.\n");
364                 res = AST_TEST_FAIL;
365                 goto test3_cleanup;
366         }
367         if (ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1,
368                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
369                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ, /* 48khz was not compatible, so this should fail iscompatible check */
370                         AST_FORMAT_ATTR_END))) {
371
372                 ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 5.\n");
373                 res = AST_TEST_FAIL;
374                 goto test3_cleanup;
375         }
376
377         /* Lets start testing the functions that compare ast_format_cap objects.
378          * Genreate the cap2 object to contain some similar formats as cap1
379          * and some different formats as well. */
380         ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0));
381         ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0));
382         ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_SIREN7, 0));
383         ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_H261, 0));
384         ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_T140, 0));
385         ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1,
386                         TEST_ATTR_KEY_STRING, "testing caps hooray",
387                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
388                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_12KHZ,
389                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ,
390                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_32KHZ,
391                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ,
392                         AST_FORMAT_ATTR_END));
393
394
395         /* find joint formats between cap1 and cap2 */
396         cap_joint = ast_format_cap_joint(cap1, cap2);
397
398         if (!cap_joint) {
399                 ast_test_status_update(test, "failed to create joint capabilities correctly.\n");
400                 res = AST_TEST_FAIL;
401                 goto test3_cleanup;
402         }
403         /* determine if cap_joint is what we think it should be */
404         if (!ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) ||
405                 !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) ||
406                 !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0)) ||
407                 !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1,
408                         TEST_ATTR_KEY_STRING, "testing caps hooray",
409                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
410                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ,
411                         AST_FORMAT_ATTR_END))) {
412
413                 ast_test_status_update(test, "ast cap_joint failed to properly detect compatibility test 1.\n");
414                 res = AST_TEST_FAIL;
415                 goto test3_cleanup;
416         }
417         /* make sure joint cap does not have formats that should not be there */
418         if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_SIREN7, 0)) ||
419                 ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1,
420                         TEST_ATTR_KEY_STRING, "testing caps hooray",
421                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ,
422                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ,
423                         TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ,
424                         AST_FORMAT_ATTR_END))) {
425
426                 ast_test_status_update(test, "ast cap_joint failed to properly detect compatibility test 1.\n");
427                 res = AST_TEST_FAIL;
428                 goto test3_cleanup;
429         }
430
431         /* Lets test removing a capability */
432         if (ast_format_cap_remove(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) {
433                 ast_test_status_update(test, "ast_format_cap_remove failed. \n");
434                 res = AST_TEST_FAIL;
435                 goto test3_cleanup;
436         }
437         /* Lets make sure what we just removed does not still exist */
438         if (ast_format_cap_iscompatible(cap_joint, &tmpformat)) {
439                 ast_test_status_update(test, "ast_format_cap_remove failed 2. \n");
440                 res = AST_TEST_FAIL;
441                 goto test3_cleanup;
442         }
443         /* Lets test removing a capability by id.*/
444         if (ast_format_cap_remove_byid(cap_joint, AST_FORMAT_GSM)) {
445                 ast_test_status_update(test, "ast_format_cap_remove failed 3. \n");
446                 res = AST_TEST_FAIL;
447                 goto test3_cleanup;
448         }
449         /* Lets make sure what we just removed does not still exist */
450         if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0))) {
451                 ast_test_status_update(test, "ast_format_cap_remove failed 4. \n");
452                 res = AST_TEST_FAIL;
453                 goto test3_cleanup;
454         }
455
456         /* lets test getting joint formats by type */
457         ast_format_cap_destroy(cap_joint);
458         if (!(cap_joint = ast_format_cap_get_type(cap1, AST_FORMAT_TYPE_VIDEO))) {
459                 ast_test_status_update(test, "ast_format_cap_get_type failed.\n");
460                 res = AST_TEST_FAIL;
461                 goto test3_cleanup;
462         }
463         /* lets make sure our joint capability structure has what we expect */
464         if (!ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_H264, 0)) ||
465                 !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_H263, 0))) {
466                 ast_test_status_update(test, "get_type failed 2.\n");
467                 res = AST_TEST_FAIL;
468                 goto test3_cleanup;
469         }
470         /* now make sure joint does not have anything but video */
471         if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0)) ||
472                 ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) ||
473                 ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) ||
474                 ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0)) ||
475                 ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) {
476                 ast_test_status_update(test, "get_type failed 3.\n");
477                 res = AST_TEST_FAIL;
478                 goto test3_cleanup;
479         }
480
481         /* now lets remove everythign from cap_joint */
482         ast_format_cap_remove_all(cap_joint);
483         if (!ast_format_cap_is_empty(cap_joint)) {
484                 ast_test_status_update(test, "failed to remove all\n");
485                 res = AST_TEST_FAIL;
486                 goto test3_cleanup;
487         }
488
489         /* now lets add all by type */
490         ast_format_cap_add_all_by_type(cap_joint, AST_FORMAT_TYPE_AUDIO);
491         if (ast_format_cap_is_empty(cap_joint)) {
492                         ast_test_status_update(test, "failed to add all by type AUDIO\n");
493                         res = AST_TEST_FAIL;
494         }
495         ast_format_cap_iter_start(cap_joint);
496         while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) {
497                 if (AST_FORMAT_GET_TYPE(tmpformat.id) != AST_FORMAT_TYPE_AUDIO) {
498                         ast_test_status_update(test, "failed to add all by type AUDIO\n");
499                         res = AST_TEST_FAIL;
500                         ast_format_cap_iter_end(cap_joint);
501                         goto test3_cleanup;
502                 }
503         }
504         ast_format_cap_iter_end(cap_joint);
505
506         /* test append */
507         ast_format_cap_append(cap_joint, cap1);
508         ast_format_cap_iter_start(cap1);
509         while (!(ast_format_cap_iter_next(cap1, &tmpformat))) {
510                 if (!ast_format_cap_iscompatible(cap_joint, &tmpformat)) {
511                         ast_test_status_update(test, "failed to append format capabilities.\n");
512                         res = AST_TEST_FAIL;
513                         ast_format_cap_iter_end(cap1);
514                         goto test3_cleanup;
515                 }
516         }
517         ast_format_cap_iter_end(cap1);
518
519         /* test copy */
520         cap1 = ast_format_cap_destroy(cap1);
521         cap1 = ast_format_cap_dup(cap_joint);
522         if (!ast_format_cap_identical(cap_joint, cap1)) {
523                         ast_test_status_update(test, "failed to copy capabilities\n");
524                         res = AST_TEST_FAIL;
525                         goto test3_cleanup;
526         }
527
528         /* test remove by type */
529         ast_format_cap_remove_bytype(cap_joint, AST_FORMAT_TYPE_AUDIO);
530         if (ast_format_cap_has_type(cap_joint, AST_FORMAT_TYPE_AUDIO)) {
531                 ast_test_status_update(test, "failed to remove all by type audio\n");
532                 res = AST_TEST_FAIL;
533                 goto test3_cleanup;
534         }
535         if (!ast_format_cap_has_type(cap_joint, AST_FORMAT_TYPE_TEXT)) { /* it should still have text */
536                 ast_test_status_update(test, "failed to remove all by type audio\n");
537                 res = AST_TEST_FAIL;
538                 goto test3_cleanup;
539         }
540         ast_format_cap_iter_start(cap_joint);
541         while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) {
542                 if (AST_FORMAT_GET_TYPE(tmpformat.id) == AST_FORMAT_TYPE_AUDIO) {
543                         ast_test_status_update(test, "failed to remove all by type audio\n");
544                         res = AST_TEST_FAIL;
545                         ast_format_cap_iter_end(cap_joint);
546                         goto test3_cleanup;
547                 }
548         }
549         ast_format_cap_iter_end(cap_joint);
550
551         /* test add all */
552         ast_format_cap_remove_all(cap_joint);
553         ast_format_cap_add_all(cap_joint);
554         {
555                 int video = 0, audio = 0, text = 0, image = 0;
556                 ast_format_cap_iter_start(cap_joint);
557                 while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) {
558                         switch (AST_FORMAT_GET_TYPE(tmpformat.id)) {
559                         case AST_FORMAT_TYPE_AUDIO:
560                                 audio++;
561                                 break;
562                         case AST_FORMAT_TYPE_VIDEO:
563                                 video++;
564                                 break;
565                         case AST_FORMAT_TYPE_TEXT:
566                                 text++;
567                                 break;
568                         case AST_FORMAT_TYPE_IMAGE:
569                                 image++;
570                                 break;
571                         }
572                 }
573                 ast_format_cap_iter_end(cap_joint);
574                 if (!video || !audio || !text || !image) {
575                         ast_test_status_update(test, "failed to add all\n");
576                         res = AST_TEST_FAIL;
577                         ast_format_cap_iter_end(cap_joint);
578                         goto test3_cleanup;
579                 }
580         }
581
582         /* test copy2 */
583         ast_format_cap_copy(cap2, cap_joint);
584         if (!ast_format_cap_identical(cap2, cap_joint)) {
585                 ast_test_status_update(test, "ast_format_cap_copy failed\n");
586                 res = AST_TEST_FAIL;
587                 goto test3_cleanup;
588         }
589
590 test3_cleanup:
591         ast_format_cap_destroy(cap1);
592         ast_format_cap_destroy(cap2);
593         ast_format_cap_destroy(cap_joint);
594
595         /* unregister interface */
596         if (ast_format_attr_unreg_interface(&test_interface)) {
597                 ast_test_status_update(test, "test_interface failed to unregister.\n");
598                 res = AST_TEST_FAIL;
599         }
600
601         return res;
602 }
603
604 /*!
605  * \internal
606  */
607 AST_TEST_DEFINE(container_test1_nolock)
608 {
609         struct ast_format_cap *cap1;
610         struct ast_format_cap *cap2;
611
612         switch (cmd) {
613         case TEST_INIT:
614                 info->name = "container_test_1_no_locking";
615                 info->category = "/main/format/";
616                 info->summary = "Test ast_format and ast_format_cap structures, no locking";
617                 info->description =
618                         "This test exercises the Ast Format Capability API by creating "
619                         "capability structures and performing various API calls on them.";
620                 return AST_TEST_NOT_RUN;
621         case TEST_EXECUTE:
622                 break;
623         }
624
625         cap1 = ast_format_cap_alloc_nolock();
626         cap2 = ast_format_cap_alloc_nolock();
627
628         if (!cap1 || !cap2) {
629                 ast_test_status_update(test, "cap alloc failed.\n");
630                 return AST_TEST_FAIL;
631         }
632         return container_test1_helper(cap1, cap2, test);
633 }
634
635
636 /*!
637  * \internal
638  */
639 AST_TEST_DEFINE(container_test1_withlock)
640 {
641         struct ast_format_cap *cap1;
642         struct ast_format_cap *cap2;
643
644         switch (cmd) {
645         case TEST_INIT:
646                 info->name = "container_test1_with_locking";
647                 info->category = "/main/format/";
648                 info->summary = "Test ast_format and ast_format_cap structures, with locking";
649                 info->description =
650                         "This test exercises the Ast Format Capability API by creating "
651                         "capability structures and performing various API calls on them.";
652                 return AST_TEST_NOT_RUN;
653         case TEST_EXECUTE:
654                 break;
655         }
656
657         cap1 = ast_format_cap_alloc();
658         cap2 = ast_format_cap_alloc();
659
660         if (!cap1 || !cap2) {
661                 ast_test_status_update(test, "cap alloc failed.\n");
662                 return AST_TEST_FAIL;
663         }
664         return container_test1_helper(cap1, cap2, test);
665 }
666
667 static int container_test2_no_locking_helper(struct ast_format_cap *cap, struct ast_test *test)
668 {
669         int num = 0;
670         struct ast_format tmpformat = { 0, };
671
672         ast_format_cap_add(cap, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0));
673         ast_format_cap_add(cap, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0));
674         ast_format_cap_add(cap, ast_format_set(&tmpformat, AST_FORMAT_G722, 0));
675
676         ast_format_cap_iter_start(cap);
677         while (!ast_format_cap_iter_next(cap, &tmpformat)) {
678                 num++;
679         }
680         ast_format_cap_iter_end(cap);
681
682         ast_format_cap_iter_start(cap);
683         while (!ast_format_cap_iter_next(cap, &tmpformat)) {
684                 num++;
685         }
686         ast_format_cap_iter_end(cap);
687
688         ast_format_cap_destroy(cap);
689         ast_test_status_update(test, "%d items iterated over\n", num);
690         return (num == 6) ? AST_TEST_PASS : AST_TEST_FAIL;
691
692 }
693
694 /*!
695  * \internal
696  */
697 AST_TEST_DEFINE(container_test2_no_locking)
698 {
699         struct ast_format_cap *cap;
700
701         switch (cmd) {
702         case TEST_INIT:
703                 info->name = "container_test2_no_locking";
704                 info->category = "/main/format/";
705                 info->summary = "Test ast_format_cap iterator, no locking";
706                 info->description =
707                         "This test exercises the Ast Capability API iterators.";
708                 return AST_TEST_NOT_RUN;
709         case TEST_EXECUTE:
710                 break;
711         }
712
713         cap = ast_format_cap_alloc_nolock();
714         if (!cap) {
715                 ast_test_status_update(test, "alloc failed\n");
716                 return AST_TEST_FAIL;
717         }
718         return container_test2_no_locking_helper(cap, test);
719 }
720
721 /*!
722  * \internal
723  */
724 AST_TEST_DEFINE(container_test2_with_locking)
725 {
726         struct ast_format_cap *cap;
727
728         switch (cmd) {
729         case TEST_INIT:
730                 info->name = "container_test2_with_locking";
731                 info->category = "/main/format/";
732                 info->summary = "Test ast_format_cap iterator, with locking";
733                 info->description =
734                         "This test exercises the Ast Capability API iterators.";
735                 return AST_TEST_NOT_RUN;
736         case TEST_EXECUTE:
737                 break;
738         }
739
740         cap = ast_format_cap_alloc();
741         if (!cap) {
742                 ast_test_status_update(test, "alloc failed\n");
743                 return AST_TEST_FAIL;
744         }
745         return container_test2_no_locking_helper(cap, test);
746 }
747
748
749 static int container_test3_helper(int nolocking, struct ast_test *test)
750 {
751         int x;
752         int res = AST_TEST_PASS;
753         struct ast_format_cap *cap1;
754         struct ast_format_cap *cap2;
755         struct ast_format_cap *joint;
756
757         for (x = 0; x < 2000; x++) {
758                 if (nolocking) {
759                         cap1 = ast_format_cap_alloc_nolock();
760                         cap2 = ast_format_cap_alloc_nolock();
761                         joint = ast_format_cap_alloc_nolock();
762                 } else {
763                         cap1 = ast_format_cap_alloc();
764                         cap2 = ast_format_cap_alloc();
765                         joint = ast_format_cap_alloc();
766                 }
767                 if (!cap1 || !cap2 || !joint) {
768                         ast_test_status_update(test, "cap alloc fail\n");
769                         return AST_TEST_FAIL;
770                 }
771                 ast_format_cap_add_all(cap1);
772                 ast_format_cap_add_all_by_type(cap2, AST_FORMAT_TYPE_AUDIO);
773                 ast_format_cap_joint_copy(cap1, cap2, joint);
774                 if (!(ast_format_cap_identical(cap2, joint))) {
775                         ast_test_status_update(test, "failed identical test\n");
776                         res = AST_TEST_FAIL;
777                         cap1 = ast_format_cap_destroy(cap1);
778                         cap2 = ast_format_cap_destroy(cap2);
779                         joint = ast_format_cap_destroy(joint);
780                         break;
781                 }
782                 cap1 = ast_format_cap_destroy(cap1);
783                 cap2 = ast_format_cap_destroy(cap2);
784                 joint = ast_format_cap_destroy(joint);
785         }
786         return res;
787 }
788
789 /*!
790  * \internal
791  */
792 AST_TEST_DEFINE(container_test3_nolock)
793 {
794         switch (cmd) {
795         case TEST_INIT:
796                 info->name = "container_test3_no_locking";
797                 info->category = "/main/format/";
798                 info->summary = "Load Test ast_format_cap no locking.";
799                 info->description =
800                         "This test exercises the Ast Capability API and its iterators for the purpose "
801                         "of measuring performance.";
802                 return AST_TEST_NOT_RUN;
803         case TEST_EXECUTE:
804                 break;
805         }
806
807         return container_test3_helper(1, test);
808 }
809
810 /*!
811  * \internal
812  */
813 AST_TEST_DEFINE(container_test3_withlock)
814 {
815         switch (cmd) {
816         case TEST_INIT:
817                 info->name = "container_test3_with_locking";
818                 info->category = "/main/format/";
819                 info->summary = "Load Test ast_format_cap with locking.";
820                 info->description =
821                         "This test exercises the Ast Capability API and its iterators for the purpose "
822                         "of measuring performance.";
823                 return AST_TEST_NOT_RUN;
824         case TEST_EXECUTE:
825                 break;
826         }
827
828         return container_test3_helper(0, test);
829 }
830
831 static int unload_module(void)
832 {
833         AST_TEST_UNREGISTER(format_test1);
834         AST_TEST_UNREGISTER(format_test2);
835         AST_TEST_UNREGISTER(container_test1_nolock);
836         AST_TEST_UNREGISTER(container_test1_withlock);
837         AST_TEST_UNREGISTER(container_test2_no_locking);
838         AST_TEST_UNREGISTER(container_test2_with_locking);
839         AST_TEST_UNREGISTER(container_test3_nolock);
840         AST_TEST_UNREGISTER(container_test3_withlock);
841
842         return 0;
843 }
844
845 static int load_module(void)
846 {
847         AST_TEST_REGISTER(format_test1);
848         AST_TEST_REGISTER(format_test2);
849         AST_TEST_REGISTER(container_test1_nolock);
850         AST_TEST_REGISTER(container_test1_withlock);
851         AST_TEST_REGISTER(container_test2_no_locking);
852         AST_TEST_REGISTER(container_test2_with_locking);
853         AST_TEST_REGISTER(container_test3_nolock);
854         AST_TEST_REGISTER(container_test3_withlock);
855
856         return AST_MODULE_LOAD_SUCCESS;
857 }
858
859 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "ast_format API Tests");