bridges/bridge_t38: Add a bridging module for managing T.38 state
[asterisk/asterisk.git] / tests / test_core_format.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2014, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@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 Core Format API Unit Tests
22  *
23  * \author Joshua Colp <jcolp@digium.com>
24  *
25  */
26
27 /*** MODULEINFO
28         <depend>TEST_FRAMEWORK</depend>
29         <support_level>core</support_level>
30  ***/
31
32 #include "asterisk.h"
33
34 ASTERISK_REGISTER_FILE()
35
36 #include "asterisk/test.h"
37 #include "asterisk/module.h"
38 #include "asterisk/codec.h"
39 #include "asterisk/format.h"
40
41 #define TEST_CATEGORY "/main/core_format/"
42
43 static void test_core_format_destroy(struct ast_format *format);
44 static int test_core_format_clone(const struct ast_format *src, struct ast_format *dst);
45 static enum ast_format_cmp_res test_core_format_cmp(const struct ast_format *format1, const struct ast_format *format2);
46 static struct ast_format *test_core_format_get_joint(const struct ast_format *format1, const struct ast_format *format2);
47 static struct ast_format *test_core_format_attribute_set(const struct ast_format *format, const char *name, const char *value);
48 static const void *test_core_format_attribute_get(const struct ast_format *format, const char *name);
49 static struct ast_format *test_core_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes);
50 static void test_core_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str);
51
52 /*! \brief A format attribute 'module' used by the unit tests */
53 static struct ast_format_interface test_core_format_attr = {
54         .format_destroy = &test_core_format_destroy,
55         .format_clone = &test_core_format_clone,
56         .format_cmp = &test_core_format_cmp,
57         .format_get_joint = &test_core_format_get_joint,
58         .format_attribute_set = &test_core_format_attribute_set,
59         .format_attribute_get = &test_core_format_attribute_get,
60         .format_parse_sdp_fmtp = &test_core_format_parse_sdp_fmtp,
61         .format_generate_sdp_fmtp = &test_core_format_generate_sdp_fmtp,
62 };
63
64 /*! \brief A test piece of data to associate with \ref test_core_format_attr */
65 struct test_core_format_pvt {
66         /*! Some data field */
67         int field_one;
68         /*! Another arbitrary data field */
69         int field_two;
70 };
71
72 /*! \brief A test codec for these unit tests. Should be used with \c test_core_format */
73 static struct ast_codec test_core_format_codec = {
74         .name = "test_core_format_codec",
75         .description = "Unit test codec used by test_core_format",
76         .type = AST_MEDIA_TYPE_AUDIO,
77         .sample_rate = 8000,
78         .minimum_ms = 10,
79         .maximum_ms = 150,
80         .default_ms = 20,
81 };
82
83 /*! \brief Tracking object used to verify format attribute callbacks */
84 struct callbacks_called {
85         /*! Number of times \ref test_core_format_destroy was called */
86         int format_destroy;
87         /*! Number of times \ref test_core_format_clone was called */
88         int format_clone;
89         /*! Number of times \ref test_core_format_cmp was called */
90         int format_cmp;
91         /*! Number of times \ref test_core_format_get_joint was called */
92         int format_get_joint;
93         /*! Number of times \ref test_core_format_attribute_set was called */
94         int format_attribute_set;
95         /*! Number of times \ref test_core_format_parse_sdp_fmtp was called */
96         int format_parse_sdp_fmtp;
97         /*! Number of times \ref test_core_format_generate_sdp_fmtp was called */
98         int format_generate_sdp_fmtp;
99 };
100
101 /*! \brief A global tracking object. Cleared out by the test init cb */
102 static struct callbacks_called test_callbacks_called;
103
104 /*! \brief Format attribute callback for when format attributes are to be destroyed */
105 static void test_core_format_destroy(struct ast_format *format)
106 {
107         struct test_core_format_pvt *pvt = ast_format_get_attribute_data(format);
108
109         ast_free(pvt);
110         ++test_callbacks_called.format_destroy;
111 }
112
113 /*! \brief Format attribute callback called during format cloning */
114 static int test_core_format_clone(const struct ast_format *src, struct ast_format *dst)
115 {
116         struct test_core_format_pvt *pvt = ast_format_get_attribute_data(src);
117         struct test_core_format_pvt *new_pvt;
118
119         new_pvt = ast_calloc(1, sizeof(*new_pvt));
120         if (!new_pvt) {
121                 return -1;
122         }
123
124         if (pvt) {
125                 *new_pvt = *pvt;
126         }
127         ast_format_set_attribute_data(dst, new_pvt);
128
129         ++test_callbacks_called.format_clone;
130
131         return 0;
132 }
133
134 /*! \brief Format attribute callback called during format comparison */
135 static enum ast_format_cmp_res test_core_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
136 {
137         struct test_core_format_pvt *pvt1 = ast_format_get_attribute_data(format1);
138         struct test_core_format_pvt *pvt2 = ast_format_get_attribute_data(format2);
139
140         ++test_callbacks_called.format_cmp;
141         if (pvt1 == pvt2) {
142                 return AST_FORMAT_CMP_EQUAL;
143         }
144
145         if ((!pvt1 && pvt2 && (pvt2->field_one != 0 || pvt2->field_two != 0))
146                 || (pvt1 && !pvt2 && (pvt1->field_one != 0 || pvt1->field_two != 0))) {
147                 return AST_FORMAT_CMP_NOT_EQUAL;
148         }
149
150         if (pvt1 && pvt2) {
151                 if (!memcmp(pvt1, pvt2, sizeof(*pvt1))) {
152                         return AST_FORMAT_CMP_EQUAL;
153                 } else {
154                         return AST_FORMAT_CMP_NOT_EQUAL;
155                 }
156         }
157
158         return AST_FORMAT_CMP_EQUAL;
159 }
160
161 /*!
162  * \brief Format attribute callback called during joint format capability
163  * \note Our test will assume the max of attributes \c field_one and \c field_two
164  */
165 static struct ast_format *test_core_format_get_joint(const struct ast_format *format1, const struct ast_format *format2)
166 {
167         struct test_core_format_pvt *pvt1 = ast_format_get_attribute_data(format1);
168         struct test_core_format_pvt *pvt2 = ast_format_get_attribute_data(format2);
169         struct ast_format *joint;
170         struct test_core_format_pvt *joint_pvt;
171
172         joint = ast_format_clone(format1);
173         if (!joint) {
174                 return NULL;
175         }
176         joint_pvt = ast_format_get_attribute_data(joint);
177
178         joint_pvt->field_one = MAX(pvt1 ? pvt1->field_one : 0, pvt2 ? pvt2->field_one : 0);
179         joint_pvt->field_two = MAX(pvt2 ? pvt2->field_two : 0, pvt2 ? pvt2->field_two : 0);
180
181         ++test_callbacks_called.format_get_joint;
182
183         return joint;
184 }
185
186 /*! \brief Format attribute callback for setting an attribute on a format */
187 static struct ast_format *test_core_format_attribute_set(const struct ast_format *format, const char *name, const char *value)
188 {
189         struct ast_format *clone = ast_format_clone(format);
190         struct test_core_format_pvt *clone_pvt;
191
192         if (!clone) {
193                 return NULL;
194         }
195         clone_pvt = ast_format_get_attribute_data(clone);
196
197         if (!strcmp(name, "one")) {
198                 clone_pvt->field_one = atoi(value);
199         } else if (!strcmp(name, "two")) {
200                 clone_pvt->field_two = atoi(value);
201         }
202         ++test_callbacks_called.format_attribute_set;
203
204         return clone;
205 }
206
207 /*! \brief Format attribute callback for retrieving an attribute */
208 static const void *test_core_format_attribute_get(const struct ast_format *format, const char *name)
209 {
210         struct test_core_format_pvt *pvt = ast_format_get_attribute_data(format);
211
212         if (!strcmp(name, "one")) {
213                 return &pvt->field_one;
214         } else if (!strcmp(name, "two")) {
215                 return &pvt->field_two;
216         }
217         return NULL;
218 }
219
220 /*! \brief Format attribute callback to construct a format from an SDP fmtp line */
221 static struct ast_format *test_core_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
222 {
223         struct ast_format *clone = ast_format_clone(format);
224         struct test_core_format_pvt *pvt;
225
226         if (!clone) {
227                 return NULL;
228         }
229
230         pvt = ast_format_get_attribute_data(clone);
231
232         if (sscanf(attributes, "one=%d;two=%d", &pvt->field_one, &pvt->field_two) != 2) {
233                 ao2_ref(clone, -1);
234                 return NULL;
235         }
236
237         ++test_callbacks_called.format_parse_sdp_fmtp;
238         return clone;
239 }
240
241 /*! \brief Format attribute callback to generate an SDP fmtp line from a format */
242 static void test_core_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
243 {
244         struct test_core_format_pvt *pvt = ast_format_get_attribute_data(format);
245
246         if (!pvt) {
247                 return;
248         }
249
250         ast_str_append(str, 0, "a=fmtp:%u one=%d;two=%d\r\n", payload, pvt->field_one, pvt->field_two);
251
252         ++test_callbacks_called.format_generate_sdp_fmtp;
253 }
254
255 AST_TEST_DEFINE(format_create)
256 {
257         RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
258         RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
259
260         switch (cmd) {
261         case TEST_INIT:
262                 info->name = __PRETTY_FUNCTION__;
263                 info->category = TEST_CATEGORY;
264                 info->summary = "Format creation unit test";
265                 info->description =
266                         "Test creation of a format";
267                 return AST_TEST_NOT_RUN;
268         case TEST_EXECUTE:
269                 break;
270         }
271
272         codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
273         if (!codec) {
274                 ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
275                 return AST_TEST_FAIL;
276         }
277
278         format = ast_format_create(codec);
279         if (!format) {
280                 ast_test_status_update(test, "Could not create format using built-in codec\n");
281                 return AST_TEST_FAIL;
282         } else if (ast_format_get_codec_id(format) != codec->id) {
283                 ast_test_status_update(test, "Created format does not contain provided codec\n");
284                 return AST_TEST_FAIL;
285         }
286
287         ao2_ref(format, -1);
288         format = ast_format_create_named("super_ulaw", codec);
289         if (!format) {
290                 ast_test_status_update(test, "Could not create format using built-in codec\n");
291                 return AST_TEST_FAIL;
292         } else if (ast_format_get_codec_id(format) != codec->id) {
293                 ast_test_status_update(test, "Created format does not contain provided codec\n");
294                 return AST_TEST_FAIL;
295         }
296
297         return AST_TEST_PASS;
298 }
299
300 AST_TEST_DEFINE(format_create_attr)
301 {
302         RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
303         RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
304         RAII_VAR(struct ast_format *, format_w_attr, NULL, ao2_cleanup);
305
306         switch (cmd) {
307         case TEST_INIT:
308                 info->name = __PRETTY_FUNCTION__;
309                 info->category = TEST_CATEGORY;
310                 info->summary = "Format creation w/ attributes unit test";
311                 info->description =
312                         "Test creation of a format with attributes";
313                 return AST_TEST_NOT_RUN;
314         case TEST_EXECUTE:
315                 break;
316         }
317
318         codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000);
319         if (!codec) {
320                 ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n");
321                 return AST_TEST_FAIL;
322         }
323
324         format = ast_format_create(codec);
325         if (!format) {
326                 ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n");
327                 return AST_TEST_FAIL;
328         } else if (ast_format_get_codec_id(format) != codec->id) {
329                 ast_test_status_update(test, "Created format does not contain provided codec\n");
330                 return AST_TEST_FAIL;
331         }
332
333         format_w_attr = ast_format_attribute_set(format, "one", "1");
334         if (!format_w_attr) {
335                 ast_test_status_update(test, "Could not create format with attributes using test_core_format_codec codec\n");
336                 return AST_TEST_FAIL;
337         } else if (ast_format_get_codec_id(format_w_attr) != codec->id) {
338                 ast_test_status_update(test, "Created format does not contain provided codec\n");
339                 return AST_TEST_FAIL;
340         } else if (ast_format_cmp(format, format_w_attr) == AST_FORMAT_CMP_EQUAL) {
341                 ast_test_status_update(test, "Format with attributes should not be equal to format without attributes\n");
342                 return AST_TEST_FAIL;
343         }
344
345         ast_test_validate(test, test_callbacks_called.format_attribute_set == 1);
346         ast_test_validate(test, test_callbacks_called.format_cmp == 1);
347
348         return AST_TEST_PASS;
349 }
350
351 AST_TEST_DEFINE(format_retrieve_attr)
352 {
353         RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
354         RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
355         RAII_VAR(struct ast_format *, format_w_attr, NULL, ao2_cleanup);
356
357         switch (cmd) {
358         case TEST_INIT:
359                 info->name = __PRETTY_FUNCTION__;
360                 info->category = TEST_CATEGORY;
361                 info->summary = "Format attribute retrieval unit test";
362                 info->description =
363                         "Test retrieval of format attributes";
364                 return AST_TEST_NOT_RUN;
365         case TEST_EXECUTE:
366                 break;
367         }
368
369         codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000);
370         if (!codec) {
371                 ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n");
372                 return AST_TEST_FAIL;
373         }
374
375         format = ast_format_create(codec);
376         if (!format) {
377                 ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n");
378                 return AST_TEST_FAIL;
379         }
380
381         format_w_attr = ast_format_attribute_set(format, "one", "1");
382         if (!format_w_attr) {
383                 ast_test_status_update(test, "Could not create format with attributes using test_core_format_codec codec\n");
384                 return AST_TEST_FAIL;
385         }
386
387         if (*((int *)ast_format_attribute_get(format_w_attr, "one")) != 1) {
388                 ast_test_status_update(test, "Could not retrieve valid format attribute\n");
389                 return AST_TEST_FAIL;
390         }
391
392         if (ast_format_attribute_get(format_w_attr, "foo") != NULL) {
393                 ast_test_status_update(test, "Retrieved invalid format attribute\n");
394                 return AST_TEST_FAIL;
395         }
396
397         return AST_TEST_PASS;
398 }
399
400 AST_TEST_DEFINE(format_clone)
401 {
402         RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
403         RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
404         RAII_VAR(struct ast_format *, format_w_attr, NULL, ao2_cleanup);
405         RAII_VAR(struct ast_format *, clone, NULL, ao2_cleanup);
406
407         switch (cmd) {
408         case TEST_INIT:
409                 info->name = __PRETTY_FUNCTION__;
410                 info->category = TEST_CATEGORY;
411                 info->summary = "Format cloning unit test";
412                 info->description =
413                         "Test cloning of a format";
414                 return AST_TEST_NOT_RUN;
415         case TEST_EXECUTE:
416                 break;
417         }
418
419         codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000);
420         if (!codec) {
421                 ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n");
422                 return AST_TEST_FAIL;
423         }
424
425         format = ast_format_create(codec);
426         if (!format) {
427                 ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n");
428                 return AST_TEST_FAIL;
429         } else if (ast_format_get_codec_id(format) != codec->id) {
430                 ast_test_status_update(test, "Created format does not contain provided codec\n");
431                 return AST_TEST_FAIL;
432         }
433
434         format_w_attr = ast_format_attribute_set(format, "one", "1");
435         if (!format_w_attr) {
436                 ast_test_status_update(test, "Could not create format with attributes using test_core_format_codec codec\n");
437                 return AST_TEST_FAIL;
438         } else if (ast_format_get_codec_id(format_w_attr) != codec->id) {
439                 ast_test_status_update(test, "Created format does not contain provided codec\n");
440                 return AST_TEST_FAIL;
441         }
442
443         /* Test cloning a format without attributes */
444         clone = ast_format_clone(format);
445         if (!clone) {
446                 ast_test_status_update(test, "Could not create cloned format\n");
447                 return AST_TEST_FAIL;
448         } else if (ast_format_get_codec_id(clone) != codec->id) {
449                 ast_test_status_update(test, "Cloned format does not contain provided codec\n");
450                 return AST_TEST_FAIL;
451         } else if (clone == format) {
452                 ast_test_status_update(test, "Cloned format pointer is the same as original format pointer\n");
453                 return AST_TEST_FAIL;
454         } else if (ast_format_cmp(clone, format) != AST_FORMAT_CMP_EQUAL) {
455                 ast_test_status_update(test, "Cloned format is not the same as its original format\n");
456                 return AST_TEST_FAIL;
457         }
458         ao2_ref(clone, -1);
459
460         /* Test cloning a format with attributes */
461         clone = ast_format_clone(format_w_attr);
462         if (!clone) {
463                 ast_test_status_update(test, "Could not create cloned format\n");
464                 return AST_TEST_FAIL;
465         } else if (ast_format_get_codec_id(clone) != codec->id) {
466                 ast_test_status_update(test, "Cloned format does not contain provided codec\n");
467                 return AST_TEST_FAIL;
468         } else if (clone == format_w_attr) {
469                 ast_test_status_update(test, "Cloned format pointer is the same as original format pointer\n");
470                 return AST_TEST_FAIL;
471         } else if (ast_format_cmp(clone, format_w_attr) != AST_FORMAT_CMP_EQUAL) {
472                 ast_test_status_update(test, "Cloned format is not the same as its original format\n");
473                 return AST_TEST_FAIL;
474         }
475         ast_test_validate(test, test_callbacks_called.format_attribute_set == 1);
476         ast_test_validate(test, test_callbacks_called.format_clone == 3);
477         ast_test_validate(test, test_callbacks_called.format_cmp == 2);
478
479         return AST_TEST_PASS;
480 }
481
482 AST_TEST_DEFINE(format_cmp_same_codec)
483 {
484         RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
485         RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
486         RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
487         RAII_VAR(struct ast_format *, named, NULL, ao2_cleanup);
488
489         switch (cmd) {
490         case TEST_INIT:
491                 info->name = __PRETTY_FUNCTION__;
492                 info->category = TEST_CATEGORY;
493                 info->summary = "Format comparison unit test";
494                 info->description =
495                         "Test comparison of two different formats with same codec";
496                 return AST_TEST_NOT_RUN;
497         case TEST_EXECUTE:
498                 break;
499         }
500
501         codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
502         if (!codec) {
503                 ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
504                 return AST_TEST_FAIL;
505         }
506
507         first = ast_format_create(codec);
508         if (!first) {
509                 ast_test_status_update(test, "Could not create first format using built-in codec\n");
510                 return AST_TEST_FAIL;
511         }
512
513         second = ast_format_create(codec);
514         if (!second) {
515                 ast_test_status_update(test, "Could not create second format using built-in codec\n");
516                 return AST_TEST_FAIL;
517         }
518
519         named = ast_format_create_named("super_ulaw", codec);
520         if (!named) {
521                 ast_test_status_update(test, "Could not create named format using built-in codec\n");
522                 return AST_TEST_FAIL;
523         }
524
525         if (ast_format_cmp(first, second) != AST_FORMAT_CMP_EQUAL) {
526                 ast_test_status_update(test, "Two formats that are the same compared as not being equal\n");
527                 return AST_TEST_FAIL;
528         }
529
530         if (ast_format_cmp(first, named) != AST_FORMAT_CMP_EQUAL) {
531                 ast_test_status_update(test, "Two formats that are the same compared as not being equal\n");
532                 return AST_TEST_FAIL;
533         }
534
535         return AST_TEST_PASS;
536 }
537
538 AST_TEST_DEFINE(format_cmp_different_codec)
539 {
540         RAII_VAR(struct ast_codec *, first_codec, NULL, ao2_cleanup);
541         RAII_VAR(struct ast_codec *, second_codec, NULL, ao2_cleanup);
542         RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
543         RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
544
545         switch (cmd) {
546         case TEST_INIT:
547                 info->name = __PRETTY_FUNCTION__;
548                 info->category = TEST_CATEGORY;
549                 info->summary = "Format comparison unit test";
550                 info->description =
551                         "Test comparison of two different formats with different codec";
552                 return AST_TEST_NOT_RUN;
553         case TEST_EXECUTE:
554                 break;
555         }
556
557         first_codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
558         if (!first_codec) {
559                 ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
560                 return AST_TEST_FAIL;
561         }
562
563         first = ast_format_create(first_codec);
564         if (!first) {
565                 ast_test_status_update(test, "Could not create first format using built-in codec\n");
566                 return AST_TEST_FAIL;
567         }
568
569         second_codec = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
570         if (!second_codec) {
571                 ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
572                 return AST_TEST_FAIL;
573         }
574
575         second = ast_format_create(second_codec);
576         if (!second) {
577                 ast_test_status_update(test, "Could not create second format using built-in codec\n");
578                 return AST_TEST_FAIL;
579         }
580
581         if (ast_format_cmp(first, second) != AST_FORMAT_CMP_NOT_EQUAL) {
582                 ast_test_status_update(test, "Two formats that have different codecs did not compare as being not equal\n");
583                 return AST_TEST_FAIL;
584         }
585
586         return AST_TEST_PASS;
587 }
588
589 AST_TEST_DEFINE(format_attr_cmp_same_codec)
590 {
591         RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
592         RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
593         RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
594         RAII_VAR(struct ast_format *, original, NULL, ao2_cleanup);
595
596         switch (cmd) {
597         case TEST_INIT:
598                 info->name = __PRETTY_FUNCTION__;
599                 info->category = TEST_CATEGORY;
600                 info->summary = "Format with attributes comparison unit test";
601                 info->description =
602                         "Test comparison of two different formats with attributes with same codec";
603                 return AST_TEST_NOT_RUN;
604         case TEST_EXECUTE:
605                 break;
606         }
607
608         codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000);
609         if (!codec) {
610                 ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n");
611                 return AST_TEST_FAIL;
612         }
613
614         original = ast_format_create(codec);
615         if (!original) {
616                 ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n");
617                 return AST_TEST_FAIL;
618         }
619
620         first = ast_format_attribute_set(original, "one", "1");
621         if (!first) {
622                 ast_test_status_update(test, "Could not create first format with attributes\n");
623                 return AST_TEST_FAIL;
624         }
625
626         second = ast_format_attribute_set(original, "two", "1");
627         if (!second) {
628                 ast_test_status_update(test, "Could not create second format with attributes\n");
629                 return AST_TEST_FAIL;
630         }
631
632         if (ast_format_cmp(first, second) == AST_FORMAT_CMP_EQUAL) {
633                 ast_test_status_update(test, "Formats with different attributes were compared to be equal when they should not\n");
634                 return AST_TEST_FAIL;
635         }
636
637         ao2_ref(second, -1);
638         second = ast_format_attribute_set(original, "one", "1");
639
640         if (ast_format_cmp(first, second) != AST_FORMAT_CMP_EQUAL) {
641                 ast_test_status_update(test, "Formats with the same attributes should be equal\n");
642                 return AST_TEST_FAIL;
643         }
644
645         ast_test_validate(test, test_callbacks_called.format_attribute_set == 3);
646         ast_test_validate(test, test_callbacks_called.format_cmp == 2);
647
648         return AST_TEST_PASS;
649 }
650
651 AST_TEST_DEFINE(format_joint_same_codec)
652 {
653         RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
654         RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
655         RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
656         RAII_VAR(struct ast_format *, joint, NULL, ao2_cleanup);
657
658         switch (cmd) {
659         case TEST_INIT:
660                 info->name = __PRETTY_FUNCTION__;
661                 info->category = TEST_CATEGORY;
662                 info->summary = "Joint format unit test";
663                 info->description =
664                         "Test joint format creation using two different formats with same codec";
665                 return AST_TEST_NOT_RUN;
666         case TEST_EXECUTE:
667                 break;
668         }
669
670         codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
671         if (!codec) {
672                 ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
673                 return AST_TEST_FAIL;
674         }
675
676         first = ast_format_create(codec);
677         if (!first) {
678                 ast_test_status_update(test, "Could not create first format using built-in codec\n");
679                 return AST_TEST_FAIL;
680         }
681
682         second = ast_format_create(codec);
683         if (!second) {
684                 ast_test_status_update(test, "Could not create second format using built-in codec\n");
685                 return AST_TEST_FAIL;
686         }
687
688         joint = ast_format_joint(first, second);
689         if (!joint) {
690                 ast_test_status_update(test, "Failed to create a joint format using two formats of same codec\n");
691                 return AST_TEST_FAIL;
692         } else if (ast_format_get_codec_id(joint) != codec->id) {
693                 ast_test_status_update(test, "Returned joint format does not contain expected codec\n");
694                 return AST_TEST_FAIL;
695         }
696
697         return AST_TEST_PASS;
698 }
699
700 AST_TEST_DEFINE(format_attr_joint_same_codec)
701 {
702         RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
703         RAII_VAR(struct ast_format *, original, NULL, ao2_cleanup);
704         RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
705         RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
706         RAII_VAR(struct ast_format *, joint, NULL, ao2_cleanup);
707         struct ast_str *fmtp = ast_str_alloca(64);
708
709         switch (cmd) {
710         case TEST_INIT:
711                 info->name = __PRETTY_FUNCTION__;
712                 info->category = TEST_CATEGORY;
713                 info->summary = "Joint format attribute unit test";
714                 info->description =
715                         "Test joint format creation using two different formats with attributes and with same codec";
716                 return AST_TEST_NOT_RUN;
717         case TEST_EXECUTE:
718                 break;
719         }
720
721         codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000);
722         if (!codec) {
723                 ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n");
724                 return AST_TEST_FAIL;
725         }
726
727         original = ast_format_create(codec);
728         if (!original) {
729                 ast_test_status_update(test, "Could not create format from test_core_format_codec codec\n");
730                 return AST_TEST_FAIL;
731         }
732
733         first = ast_format_attribute_set(original, "one", "2");
734         if (!first) {
735                 ast_test_status_update(test, "Could not create first format using test_core_format_codec codec\n");
736                 return AST_TEST_FAIL;
737         }
738
739         second = ast_format_attribute_set(original, "one", "5");
740         if (!second) {
741                 ast_test_status_update(test, "Could not create second format using test_core_format_codec codec\n");
742                 return AST_TEST_FAIL;
743         }
744
745         joint = ast_format_joint(first, second);
746         if (!joint) {
747                 ast_test_status_update(test, "Failed to create a joint format using two formats of same codec\n");
748                 return AST_TEST_FAIL;
749         } else if (ast_format_get_codec_id(joint) != codec->id) {
750                 ast_test_status_update(test, "Returned joint format does not contain expected codec\n");
751                 return AST_TEST_FAIL;
752         }
753
754         ast_format_generate_sdp_fmtp(joint, 100, &fmtp);
755         ast_test_validate(test, strcmp("a=fmtp:100 one=5;two=0\r\n", ast_str_buffer(fmtp)) == 0);
756
757         ast_test_validate(test, test_callbacks_called.format_attribute_set == 2);
758         ast_test_validate(test, test_callbacks_called.format_get_joint == 1);
759         ast_test_validate(test, test_callbacks_called.format_generate_sdp_fmtp == 1);
760
761         return AST_TEST_PASS;
762 }
763
764 AST_TEST_DEFINE(format_joint_different_codec)
765 {
766         RAII_VAR(struct ast_codec *, first_codec, NULL, ao2_cleanup);
767         RAII_VAR(struct ast_codec *, second_codec, NULL, ao2_cleanup);
768         RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup);
769         RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup);
770         RAII_VAR(struct ast_format *, joint, NULL, ao2_cleanup);
771
772         switch (cmd) {
773         case TEST_INIT:
774                 info->name = __PRETTY_FUNCTION__;
775                 info->category = TEST_CATEGORY;
776                 info->summary = "Joint format unit test";
777                 info->description =
778                         "Test that there is no joint format between two different formats with different codec";
779                 return AST_TEST_NOT_RUN;
780         case TEST_EXECUTE:
781                 break;
782         }
783
784         first_codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
785         if (!first_codec) {
786                 ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
787                 return AST_TEST_FAIL;
788         }
789
790         first = ast_format_create(first_codec);
791         if (!first) {
792                 ast_test_status_update(test, "Could not create first format using built-in codec\n");
793                 return AST_TEST_FAIL;
794         }
795
796         second_codec = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000);
797         if (!second_codec) {
798                 ast_test_status_update(test, "Could not retrieve built-in alaw codec\n");
799                 return AST_TEST_FAIL;
800         }
801
802         second = ast_format_create(second_codec);
803         if (!second) {
804                 ast_test_status_update(test, "Could not create second format using built-in codec\n");
805                 return AST_TEST_FAIL;
806         }
807
808         joint = ast_format_joint(first, second);
809         if (joint) {
810                 ast_test_status_update(test, "Got a joint format between two formats with different codecs\n");
811                 return AST_TEST_FAIL;
812         }
813
814         return AST_TEST_PASS;
815 }
816
817 AST_TEST_DEFINE(format_copy)
818 {
819         RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
820         RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
821         RAII_VAR(struct ast_format *, copy, NULL, ao2_cleanup);
822
823         switch (cmd) {
824         case TEST_INIT:
825                 info->name = __PRETTY_FUNCTION__;
826                 info->category = TEST_CATEGORY;
827                 info->summary = "Format copying unit test";
828                 info->description =
829                         "Test copying of a format";
830                 return AST_TEST_NOT_RUN;
831         case TEST_EXECUTE:
832                 break;
833         }
834
835         codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
836         if (!codec) {
837                 ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
838                 return AST_TEST_FAIL;
839         }
840
841         format = ast_format_create(codec);
842         if (!format) {
843                 ast_test_status_update(test, "Could not create format using built-in codec\n");
844                 return AST_TEST_FAIL;
845         }
846
847         copy = ao2_bump(format);
848         if (!copy) {
849                 ast_test_status_update(test, "Copying of a just created format failed\n");
850                 return AST_TEST_FAIL;
851         } else if (copy != format) {
852                 ast_test_status_update(test, "Copying of a format returned a new format instead of the same one\n");
853                 return AST_TEST_FAIL;
854         }
855
856         return AST_TEST_PASS;
857 }
858
859 AST_TEST_DEFINE(format_attribute_set_without_interface)
860 {
861         RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
862         RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
863
864         switch (cmd) {
865         case TEST_INIT:
866                 info->name = __PRETTY_FUNCTION__;
867                 info->category = TEST_CATEGORY;
868                 info->summary = "Format attribute setting unit test";
869                 info->description =
870                         "Test that attribute setting on a format without an interface fails";
871                 return AST_TEST_NOT_RUN;
872         case TEST_EXECUTE:
873                 break;
874         }
875
876         codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
877         if (!codec) {
878                 ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
879                 return AST_TEST_FAIL;
880         }
881
882         format = ast_format_create(codec);
883         if (!format) {
884                 ast_test_status_update(test, "Could not create format using built-in codec\n");
885                 return AST_TEST_FAIL;
886         }
887
888         if (!ast_format_attribute_set(format, "bees", "cool")) {
889                 ast_test_status_update(test, "Successfully set an attribute on a format without an interface\n");
890                 return AST_TEST_FAIL;
891         }
892
893         return AST_TEST_PASS;
894 }
895
896 AST_TEST_DEFINE(format_attribute_get_without_interface)
897 {
898         RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
899         RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
900
901         switch (cmd) {
902         case TEST_INIT:
903                 info->name = __PRETTY_FUNCTION__;
904                 info->category = TEST_CATEGORY;
905                 info->summary = "Format attribute retrieval unit test";
906                 info->description =
907                         "Test that attribute retrieval on a format without an interface fails";
908                 return AST_TEST_NOT_RUN;
909         case TEST_EXECUTE:
910                 break;
911         }
912
913         codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
914         if (!codec) {
915                 ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
916                 return AST_TEST_FAIL;
917         }
918
919         format = ast_format_create(codec);
920         if (!format) {
921                 ast_test_status_update(test, "Could not create format using built-in codec\n");
922                 return AST_TEST_FAIL;
923         }
924
925         if (ast_format_attribute_get(format, "bees") != NULL) {
926                 ast_test_status_update(test, "Successfully retrieved an attribute on a format without an interface\n");
927                 return AST_TEST_FAIL;
928         }
929
930         return AST_TEST_PASS;
931 }
932
933 AST_TEST_DEFINE(format_parse_sdp_fmtp_without_interface)
934 {
935         RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
936         RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
937         RAII_VAR(struct ast_format *, generated, NULL, ao2_cleanup);
938
939         switch (cmd) {
940         case TEST_INIT:
941                 info->name = __PRETTY_FUNCTION__;
942                 info->category = TEST_CATEGORY;
943                 info->summary = "Format sdp parse unit test";
944                 info->description =
945                         "Test that sdp parsing on a format without an interface fails";
946                 return AST_TEST_NOT_RUN;
947         case TEST_EXECUTE:
948                 break;
949         }
950
951         codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000);
952         if (!codec) {
953                 ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n");
954                 return AST_TEST_FAIL;
955         }
956
957         format = ast_format_create(codec);
958         if (!format) {
959                 ast_test_status_update(test, "Could not create format using built-in codec\n");
960                 return AST_TEST_FAIL;
961         }
962
963         generated = ast_format_parse_sdp_fmtp(format, "tacos");
964         if (generated != format) {
965                 ast_test_status_update(test, "Successfully parsed SDP on a format without an interface\n");
966                 return AST_TEST_FAIL;
967         }
968
969         return AST_TEST_PASS;
970 }
971
972 AST_TEST_DEFINE(format_parse_and_generate_sdp_fmtp)
973 {
974         RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup);
975         RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup);
976         RAII_VAR(struct ast_format *, generated, NULL, ao2_cleanup);
977         struct ast_str *fmtp = ast_str_alloca(64);
978
979         switch (cmd) {
980         case TEST_INIT:
981                 info->name = __PRETTY_FUNCTION__;
982                 info->category = TEST_CATEGORY;
983                 info->summary = "Format sdp parse/generate unit test";
984                 info->description =
985                         "Test that sdp parsing and generation on a format with an interface succeeds";
986                 return AST_TEST_NOT_RUN;
987         case TEST_EXECUTE:
988                 break;
989         }
990
991         codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000);
992         if (!codec) {
993                 ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n");
994                 return AST_TEST_FAIL;
995         }
996
997         format = ast_format_create(codec);
998         if (!format) {
999                 ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n");
1000                 return AST_TEST_FAIL;
1001         }
1002
1003         generated = ast_format_parse_sdp_fmtp(format, "one=1000;two=256");
1004         if (format == generated) {
1005                 ast_test_status_update(test, "Failed to parse SDP on a format without an interface\n");
1006                 return AST_TEST_FAIL;
1007         }
1008
1009         ast_format_generate_sdp_fmtp(generated, 8, &fmtp);
1010
1011         ast_test_validate(test, strcmp("a=fmtp:8 one=1000;two=256\r\n", ast_str_buffer(fmtp)) == 0);
1012         ast_test_validate(test, test_callbacks_called.format_parse_sdp_fmtp == 1);
1013         ast_test_validate(test, test_callbacks_called.format_generate_sdp_fmtp == 1);
1014
1015         return AST_TEST_PASS;
1016 }
1017
1018 static int test_core_format_init(struct ast_test_info *info, struct ast_test *test)
1019 {
1020         memset(&test_callbacks_called, 0, sizeof(test_callbacks_called));
1021
1022         return 0;
1023 }
1024
1025 static int unload_module(void)
1026 {
1027         AST_TEST_UNREGISTER(format_create);
1028         AST_TEST_UNREGISTER(format_create_attr);
1029         AST_TEST_UNREGISTER(format_retrieve_attr);
1030         AST_TEST_UNREGISTER(format_clone);
1031         AST_TEST_UNREGISTER(format_cmp_same_codec);
1032         AST_TEST_UNREGISTER(format_attr_cmp_same_codec);
1033         AST_TEST_UNREGISTER(format_cmp_different_codec);
1034         AST_TEST_UNREGISTER(format_joint_same_codec);
1035         AST_TEST_UNREGISTER(format_attr_joint_same_codec);
1036         AST_TEST_UNREGISTER(format_joint_different_codec);
1037         AST_TEST_UNREGISTER(format_copy);
1038         AST_TEST_UNREGISTER(format_attribute_set_without_interface);
1039         AST_TEST_UNREGISTER(format_attribute_get_without_interface);
1040         AST_TEST_UNREGISTER(format_parse_sdp_fmtp_without_interface);
1041         AST_TEST_UNREGISTER(format_parse_and_generate_sdp_fmtp);
1042
1043         return 0;
1044 }
1045
1046 static int load_module(void)
1047 {
1048         /* Test codec/format interface used by this module */
1049         if (ast_codec_register(&test_core_format_codec)) {
1050                 ast_log(AST_LOG_ERROR, "Failed to register test_core_format_codec\n");
1051                 return AST_MODULE_LOAD_DECLINE;
1052         }
1053
1054         if (ast_format_interface_register("test_core_format_codec", &test_core_format_attr)) {
1055                 ast_log(AST_LOG_ERROR, "Failed to register format interface for test_core_format_codec\n");
1056                 return AST_MODULE_LOAD_DECLINE;
1057         }
1058
1059         AST_TEST_REGISTER(format_create);
1060         AST_TEST_REGISTER(format_create_attr);
1061         AST_TEST_REGISTER(format_retrieve_attr);
1062         AST_TEST_REGISTER(format_clone);
1063         AST_TEST_REGISTER(format_cmp_same_codec);
1064         AST_TEST_REGISTER(format_attr_cmp_same_codec);
1065         AST_TEST_REGISTER(format_cmp_different_codec);
1066         AST_TEST_REGISTER(format_joint_same_codec);
1067         AST_TEST_REGISTER(format_attr_joint_same_codec);
1068         AST_TEST_REGISTER(format_joint_different_codec);
1069         AST_TEST_REGISTER(format_copy);
1070         AST_TEST_REGISTER(format_attribute_set_without_interface);
1071         AST_TEST_REGISTER(format_attribute_get_without_interface);
1072         AST_TEST_REGISTER(format_parse_sdp_fmtp_without_interface);
1073         AST_TEST_REGISTER(format_parse_and_generate_sdp_fmtp);
1074
1075         ast_test_register_init(TEST_CATEGORY, &test_core_format_init);
1076
1077         return AST_MODULE_LOAD_SUCCESS;
1078 }
1079
1080 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Core format API test module");