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