Asterisk - The Open Source Telephony Project GIT-master-7e7a603
test_stream.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2017, 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 Media Stream 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/stream.h"
37#include "asterisk/format.h"
38#include "asterisk/format_cap.h"
40#include "asterisk/channel.h"
41#include "asterisk/uuid.h"
42
43AST_TEST_DEFINE(stream_create)
44{
45 RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
46
47 switch (cmd) {
48 case TEST_INIT:
49 info->name = "stream_create";
50 info->category = "/main/stream/";
51 info->summary = "stream create unit test";
52 info->description =
53 "Test that creating a stream results in a stream with the expected values";
54 return AST_TEST_NOT_RUN;
55 case TEST_EXECUTE:
56 break;
57 }
58
59 stream = ast_stream_alloc("test", AST_MEDIA_TYPE_AUDIO);
60 if (!stream) {
61 ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
62 return AST_TEST_FAIL;
63 }
64
66 ast_test_status_update(test, "Newly created stream does not have expected inactive stream state\n");
67 return AST_TEST_FAIL;
68 }
69
71 ast_test_status_update(test, "Newly created stream does not have expected audio media type\n");
72 return AST_TEST_FAIL;
73 }
74
75 if (strcmp(ast_stream_get_name(stream), "test")) {
76 ast_test_status_update(test, "Newly created stream does not have expected name of test\n");
77 return AST_TEST_FAIL;
78 }
79
80 return AST_TEST_PASS;
81}
82
83AST_TEST_DEFINE(stream_create_no_name)
84{
85 RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
86
87 switch (cmd) {
88 case TEST_INIT:
89 info->name = "stream_create_no_name";
90 info->category = "/main/stream/";
91 info->summary = "stream create (without a name) unit test";
92 info->description =
93 "Test that creating a stream with no name works";
94 return AST_TEST_NOT_RUN;
95 case TEST_EXECUTE:
96 break;
97 }
98
100 if (!stream) {
101 ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
102 return AST_TEST_FAIL;
103 }
104
105 return AST_TEST_PASS;
106}
107
108AST_TEST_DEFINE(stream_set_type)
109{
110 RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
111
112 switch (cmd) {
113 case TEST_INIT:
114 info->name = "stream_set_type";
115 info->category = "/main/stream/";
116 info->summary = "stream type setting unit test";
117 info->description =
118 "Test that changing the type of a stream works";
119 return AST_TEST_NOT_RUN;
120 case TEST_EXECUTE:
121 break;
122 }
123
124 stream = ast_stream_alloc("test", AST_MEDIA_TYPE_AUDIO);
125 if (!stream) {
126 ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
127 return AST_TEST_FAIL;
128 }
129
131 ast_test_status_update(test, "Newly created stream does not have expected audio media type\n");
132 return AST_TEST_FAIL;
133 }
134
136
138 ast_test_status_update(test, "Changed stream does not have expected video media type\n");
139 return AST_TEST_FAIL;
140 }
141
142 return AST_TEST_PASS;
143}
144
145AST_TEST_DEFINE(stream_set_formats)
146{
147 RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
148 RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
149
150 switch (cmd) {
151 case TEST_INIT:
152 info->name = "stream_set_formats";
153 info->category = "/main/stream/";
154 info->summary = "stream formats setting unit test";
155 info->description =
156 "Test that changing the formats of a stream works";
157 return AST_TEST_NOT_RUN;
158 case TEST_EXECUTE:
159 break;
160 }
161
163 if (!caps) {
164 ast_test_status_update(test, "Failed to create a format capabilities structure for testing\n");
165 return AST_TEST_FAIL;
166 }
167
168 stream = ast_stream_alloc("test", AST_MEDIA_TYPE_AUDIO);
169 if (!stream) {
170 ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
171 return AST_TEST_FAIL;
172 }
173
174 ast_stream_set_formats(stream, caps);
175
176 if (ast_stream_get_formats(stream) != caps) {
177 ast_test_status_update(test, "Changed stream does not have expected formats\n");
178 return AST_TEST_FAIL;
179 }
180
182
183 if (ast_stream_get_formats(stream)) {
184 ast_test_status_update(test, "Retrieved formats from stream despite removing them\n");
185 return AST_TEST_FAIL;
186 }
187
188 return AST_TEST_PASS;
189}
190
191AST_TEST_DEFINE(stream_set_state)
192{
193 RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
194
195 switch (cmd) {
196 case TEST_INIT:
197 info->name = "stream_set_state";
198 info->category = "/main/stream/";
199 info->summary = "stream state setting unit test";
200 info->description =
201 "Test that changing the state of a stream works";
202 return AST_TEST_NOT_RUN;
203 case TEST_EXECUTE:
204 break;
205 }
206
207 stream = ast_stream_alloc("test", AST_MEDIA_TYPE_AUDIO);
208 if (!stream) {
209 ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
210 return AST_TEST_FAIL;
211 }
212
214 ast_test_status_update(test, "Newly created stream does not have expected inactive stream state\n");
215 return AST_TEST_FAIL;
216 }
217
219
221 ast_test_status_update(test, "Changed stream does not have expected sendrecv state\n");
222 return AST_TEST_FAIL;
223 }
224
225 return AST_TEST_PASS;
226}
227
228AST_TEST_DEFINE(stream_metadata)
229{
230 RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
231 char track_label[AST_UUID_STR_LEN + 1];
232 const char *stream_track_label;
233 int rc;
234
235 switch (cmd) {
236 case TEST_INIT:
237 info->name = "stream_metadata";
238 info->category = "/main/stream/";
239 info->summary = "stream metadata unit test";
240 info->description =
241 "Test that metadata operations on a stream works";
242 return AST_TEST_NOT_RUN;
243 case TEST_EXECUTE:
244 break;
245 }
246
247 stream = ast_stream_alloc("test", AST_MEDIA_TYPE_AUDIO);
248 if (!stream) {
249 ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
250 return AST_TEST_FAIL;
251 }
252
253 stream_track_label = ast_stream_get_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL");
254 if (stream_track_label) {
255 ast_test_status_update(test, "New stream HAD a track label\n");
256 return AST_TEST_FAIL;
257 }
258
259 ast_uuid_generate_str(track_label, sizeof(track_label));
260 rc = ast_stream_set_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL", track_label);
261 if (rc != 0) {
262 ast_test_status_update(test, "Failed to add track label\n");
263 return AST_TEST_FAIL;
264 }
265
266 stream_track_label = ast_stream_get_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL");
267 if (!stream_track_label) {
268 ast_test_status_update(test, "Changed stream does not have a track label\n");
269 return AST_TEST_FAIL;
270 }
271
272 if (strcmp(stream_track_label, track_label) != 0) {
273 ast_test_status_update(test, "Changed stream did not return same track label\n");
274 return AST_TEST_FAIL;
275 }
276
277 rc = ast_stream_set_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL", NULL);
278 if (rc != 0) {
279 ast_test_status_update(test, "Failed to remove track label\n");
280 return AST_TEST_FAIL;
281 }
282
283 stream_track_label = ast_stream_get_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL");
284 if (stream_track_label) {
285 ast_test_status_update(test, "Changed stream still had a track label after we removed it\n");
286 return AST_TEST_FAIL;
287 }
288
289 return AST_TEST_PASS;
290}
291
292AST_TEST_DEFINE(stream_topology_create)
293{
295
296 switch (cmd) {
297 case TEST_INIT:
298 info->name = "stream_topology_create";
299 info->category = "/main/stream/";
300 info->summary = "stream topology creation unit test";
301 info->description =
302 "Test that creating a stream topology works";
303 return AST_TEST_NOT_RUN;
304 case TEST_EXECUTE:
305 break;
306 }
307
308 topology = ast_stream_topology_alloc();
309 if (!topology) {
310 ast_test_status_update(test, "Failed to create media stream topology\n");
311 return AST_TEST_FAIL;
312 }
313
314 return AST_TEST_PASS;
315}
316
317AST_TEST_DEFINE(stream_topology_clone)
318{
321 struct ast_stream *audio_stream, *video_stream;
322 char audio_track_label[AST_UUID_STR_LEN + 1];
323 char video_track_label[AST_UUID_STR_LEN + 1];
324 const char *original_track_label;
325 const char *cloned_track_label;
326 int rc;
327
328 switch (cmd) {
329 case TEST_INIT:
330 info->name = "stream_topology_clone";
331 info->category = "/main/stream/";
332 info->summary = "stream topology cloning unit test";
333 info->description =
334 "Test that cloning a stream topology results in a clone with the same contents";
335 return AST_TEST_NOT_RUN;
336 case TEST_EXECUTE:
337 break;
338 }
339
340 topology = ast_stream_topology_alloc();
341 if (!topology) {
342 ast_test_status_update(test, "Failed to create media stream topology\n");
343 return AST_TEST_FAIL;
344 }
345
346 audio_stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
347 if (!audio_stream) {
348 ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
349 return AST_TEST_FAIL;
350 }
351
352 ast_uuid_generate_str(audio_track_label, sizeof(audio_track_label));
353 rc = ast_stream_set_metadata(audio_stream, "AST_STREAM_METADATA_TRACK_LABEL", audio_track_label);
354 if (rc != 0) {
355 ast_test_status_update(test, "Failed to add track label\n");
356 return AST_TEST_FAIL;
357 }
358
359 if (ast_stream_topology_append_stream(topology, audio_stream) == -1) {
360 ast_test_status_update(test, "Failed to append valid audio stream to stream topology\n");
361 ast_stream_free(audio_stream);
362 return AST_TEST_FAIL;
363 }
364
365 video_stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
366 if (!video_stream) {
367 ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
368 return AST_TEST_FAIL;
369 }
370
371 ast_uuid_generate_str(video_track_label, sizeof(video_track_label));
372 rc = ast_stream_set_metadata(video_stream, "AST_STREAM_METADATA_TRACK_LABEL", video_track_label);
373 if (rc != 0) {
374 ast_test_status_update(test, "Failed to add track label\n");
375 return AST_TEST_FAIL;
376 }
377
378 if (ast_stream_topology_append_stream(topology, video_stream) == -1) {
379 ast_test_status_update(test, "Failed to append valid video stream to stream topology\n");
380 ast_stream_free(video_stream);
381 return AST_TEST_FAIL;
382 }
383
384 cloned = ast_stream_topology_clone(topology);
385 if (!cloned) {
386 ast_test_status_update(test, "Failed to clone a perfectly good stream topology\n");
387 return AST_TEST_FAIL;
388 }
389
391 ast_test_status_update(test, "Cloned stream topology does not contain same number of streams as original\n");
392 return AST_TEST_FAIL;
393 }
394
396 ast_test_status_update(test, "Cloned audio stream does not contain same type as original\n");
397 return AST_TEST_FAIL;
398 }
399
400 original_track_label = ast_stream_get_metadata(ast_stream_topology_get_stream(topology, 0),
401 "AST_STREAM_METADATA_TRACK_LABEL");
402 if (!original_track_label) {
403 ast_test_status_update(test, "Original topology stream 0 does not contain metadata\n");
404 return AST_TEST_FAIL;
405 }
406 cloned_track_label = ast_stream_get_metadata(ast_stream_topology_get_stream(cloned, 0),
407 "AST_STREAM_METADATA_TRACK_LABEL");
408 if (!cloned_track_label) {
409 ast_test_status_update(test, "Cloned topology stream 0 does not contain metadata\n");
410 return AST_TEST_FAIL;
411 }
412 if (strcmp(original_track_label, cloned_track_label) != 0) {
413 ast_test_status_update(test, "Cloned topology stream 0 track label was not the same as the original\n");
414 return AST_TEST_FAIL;
415 }
416
418 ast_test_status_update(test, "Cloned video stream does not contain same type as original\n");
419 return AST_TEST_FAIL;
420 }
421
422 original_track_label = ast_stream_get_metadata(ast_stream_topology_get_stream(topology, 1),
423 "AST_STREAM_METADATA_TRACK_LABEL");
424 if (!original_track_label) {
425 ast_test_status_update(test, "Original topology stream 1 does not contain metadata\n");
426 return AST_TEST_FAIL;
427 }
428 cloned_track_label = ast_stream_get_metadata(ast_stream_topology_get_stream(cloned, 1),
429 "AST_STREAM_METADATA_TRACK_LABEL");
430 if (!cloned_track_label) {
431 ast_test_status_update(test, "Cloned topology stream 1 does not contain metadata\n");
432 return AST_TEST_FAIL;
433 }
434 if (strcmp(original_track_label, cloned_track_label) != 0) {
435 ast_test_status_update(test, "Cloned topology stream 1 track label was not the same as the original\n");
436 return AST_TEST_FAIL;
437 }
438
439 return AST_TEST_PASS;
440}
441
442AST_TEST_DEFINE(stream_topology_append_stream)
443{
445 struct ast_stream *audio_stream, *video_stream;
446 int position;
447
448 switch (cmd) {
449 case TEST_INIT:
450 info->name = "stream_topology_append_stream";
451 info->category = "/main/stream/";
452 info->summary = "stream topology stream appending unit test";
453 info->description =
454 "Test that appending streams to a stream topology works";
455 return AST_TEST_NOT_RUN;
456 case TEST_EXECUTE:
457 break;
458 }
459
460 topology = ast_stream_topology_alloc();
461 if (!topology) {
462 ast_test_status_update(test, "Failed to create media stream topology\n");
463 return AST_TEST_FAIL;
464 }
465
466 audio_stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
467 if (!audio_stream) {
468 ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
469 return AST_TEST_FAIL;
470 }
471
472 position = ast_stream_topology_append_stream(topology, audio_stream);
473 if (position == -1) {
474 ast_test_status_update(test, "Failed to append valid audio stream to stream topology\n");
475 ast_stream_free(audio_stream);
476 return AST_TEST_FAIL;
477 } else if (position != 0) {
478 ast_test_status_update(test, "Appended audio stream to stream topology but position is '%d' instead of 0\n",
479 position);
480 return AST_TEST_FAIL;
481 }
482
483 if (ast_stream_topology_get_count(topology) != 1) {
484 ast_test_status_update(test, "Appended an audio stream to the stream topology but stream count is '%d' on it, not 1\n",
486 return AST_TEST_FAIL;
487 }
488
489 if (ast_stream_topology_get_stream(topology, 0) != audio_stream) {
490 ast_test_status_update(test, "Appended an audio stream to the stream topology but returned stream doesn't match\n");
491 return AST_TEST_FAIL;
492 }
493
494 if (ast_stream_get_position(audio_stream) != 0) {
495 ast_test_status_update(test, "Appended audio stream says it is at position '%d' instead of 0\n",
496 ast_stream_get_position(audio_stream));
497 return AST_TEST_FAIL;
498 }
499
500 video_stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
501 if (!video_stream) {
502 ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
503 return AST_TEST_FAIL;
504 }
505
506 position = ast_stream_topology_append_stream(topology, video_stream);
507 if (position == -1) {
508 ast_test_status_update(test, "Failed to append valid video stream to stream topology\n");
509 ast_stream_free(video_stream);
510 return AST_TEST_FAIL;
511 } else if (position != 1) {
512 ast_test_status_update(test, "Appended video stream to stream topology but position is '%d' instead of 1\n",
513 position);
514 return AST_TEST_FAIL;
515 }
516
517 if (ast_stream_topology_get_count(topology) != 2) {
518 ast_test_status_update(test, "Appended a video stream to the stream topology but stream count is '%d' on it, not 2\n",
520 return AST_TEST_FAIL;
521 }
522
523 if (ast_stream_topology_get_stream(topology, 1) != video_stream) {
524 ast_test_status_update(test, "Appended a video stream to the stream topology but returned stream doesn't match\n");
525 return AST_TEST_FAIL;
526 }
527
528 if (ast_stream_get_position(video_stream) != 1) {
529 ast_test_status_update(test, "Appended video stream says it is at position '%d' instead of 1\n",
530 ast_stream_get_position(video_stream));
531 return AST_TEST_FAIL;
532 }
533
534 return AST_TEST_PASS;
535}
536
537AST_TEST_DEFINE(stream_topology_set_stream)
538{
540 struct ast_stream *audio_stream, *video_stream;
541
542 switch (cmd) {
543 case TEST_INIT:
544 info->name = "stream_topology_set_stream";
545 info->category = "/main/stream/";
546 info->summary = "stream topology stream setting unit test";
547 info->description =
548 "Test that setting streams at a specific position in a topology works";
549 return AST_TEST_NOT_RUN;
550 case TEST_EXECUTE:
551 break;
552 }
553
554 topology = ast_stream_topology_alloc();
555 if (!topology) {
556 ast_test_status_update(test, "Failed to create media stream topology\n");
557 return AST_TEST_FAIL;
558 }
559
560 audio_stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
561 if (!audio_stream) {
562 ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
563 return AST_TEST_FAIL;
564 }
565
566 if (ast_stream_topology_set_stream(topology, 0, audio_stream)) {
567 ast_test_status_update(test, "Failed to set an audio stream to a position where it is permitted\n");
568 ast_stream_free(audio_stream);
569 return AST_TEST_FAIL;
570 }
571
572 if (ast_stream_topology_get_count(topology) != 1) {
573 ast_test_status_update(test, "Set an audio stream on the stream topology but stream count is '%d' on it, not 1\n",
575 return AST_TEST_FAIL;
576 }
577
578 if (ast_stream_topology_get_stream(topology, 0) != audio_stream) {
579 ast_test_status_update(test, "Set an audio stream on the stream topology but returned stream doesn't match\n");
580 return AST_TEST_FAIL;
581 }
582
583 if (ast_stream_get_position(audio_stream) != 0) {
584 ast_test_status_update(test, "Set audio stream says it is at position '%d' instead of 0\n",
585 ast_stream_get_position(audio_stream));
586 return AST_TEST_FAIL;
587 }
588
589 video_stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
590 if (!video_stream) {
591 ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
592 return AST_TEST_FAIL;
593 }
594
595 if (ast_stream_topology_set_stream(topology, 0, video_stream)) {
596 ast_test_status_update(test, "Failed to set a video stream to a position where it is permitted\n");
597 ast_stream_free(video_stream);
598 return AST_TEST_FAIL;
599 }
600
601 if (ast_stream_topology_get_count(topology) != 1) {
602 ast_test_status_update(test, "Set a video stream on the stream topology but stream count is '%d' on it, not 1\n",
604 return AST_TEST_FAIL;
605 }
606
607 if (ast_stream_topology_get_stream(topology, 0) != video_stream) {
608 ast_test_status_update(test, "Set a video stream on the stream topology but returned stream doesn't match\n");
609 return AST_TEST_FAIL;
610 }
611
612 if (ast_stream_get_position(video_stream) != 0) {
613 ast_test_status_update(test, "Set video stream says it is at position '%d' instead of 0\n",
614 ast_stream_get_position(video_stream));
615 return AST_TEST_FAIL;
616 }
617
618 audio_stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
619 if (!audio_stream) {
620 ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
621 return AST_TEST_FAIL;
622 }
623
624 if (ast_stream_topology_set_stream(topology, 1, audio_stream)) {
625 ast_test_status_update(test, "Failed to set an audio stream to a position where it is permitted\n");
626 ast_stream_free(audio_stream);
627 return AST_TEST_FAIL;
628 }
629
630 if (ast_stream_topology_get_count(topology) != 2) {
631 ast_test_status_update(test, "Set an audio stream on the stream topology but stream count is '%d' on it, not 2\n",
633 return AST_TEST_FAIL;
634 }
635
636 if (ast_stream_topology_get_stream(topology, 1) != audio_stream) {
637 ast_test_status_update(test, "Set an audio stream on the stream topology but returned stream doesn't match\n");
638 return AST_TEST_FAIL;
639 }
640
641 if (ast_stream_get_position(audio_stream) != 1) {
642 ast_test_status_update(test, "Set audio stream says it is at position '%d' instead of 1\n",
643 ast_stream_get_position(audio_stream));
644 return AST_TEST_FAIL;
645 }
646
647 return AST_TEST_PASS;
648}
649
650static int check_stream_positions(struct ast_test *test, const struct ast_stream_topology *topology)
651{
652 const struct ast_stream *stream;
653 int idx;
654 int pos;
655 enum ast_media_type type;
656
657 for (idx = 0; idx < ast_stream_topology_get_count(topology); ++idx) {
658 stream = ast_stream_topology_get_stream(topology, idx);
659 pos = ast_stream_get_position(stream);
660 if (idx != pos) {
661 type = ast_stream_get_type(stream);
662 ast_test_status_update(test, "Failed: '%s' stream says it is at position %d instead of %d\n",
663 ast_codec_media_type2str(type), pos, idx);
664 return -1;
665 }
666 }
667 return 0;
668}
669
670AST_TEST_DEFINE(stream_topology_del_stream)
671{
673 struct ast_stream *stream;
674 enum ast_media_type type;
675 int idx;
676
677 switch (cmd) {
678 case TEST_INIT:
679 info->name = "stream_topology_del_stream";
680 info->category = "/main/stream/";
681 info->summary = "stream topology stream delete unit test";
682 info->description =
683 "Test that deleting streams at a specific position in a topology works";
684 return AST_TEST_NOT_RUN;
685 case TEST_EXECUTE:
686 break;
687 }
688
689 topology = ast_stream_topology_alloc();
690 if (!topology) {
691 ast_test_status_update(test, "Failed to create media stream topology\n");
692 return AST_TEST_FAIL;
693 }
694
695 /* Create streams */
698 if (!stream) {
699 ast_test_status_update(test, "Failed to create '%s' stream for testing stream topology\n",
701 return AST_TEST_FAIL;
702 }
703 if (ast_stream_topology_append_stream(topology, stream) == -1) {
704 ast_test_status_update(test, "Failed to append '%s' stream to topology\n",
706 ast_stream_free(stream);
707 return AST_TEST_FAIL;
708 }
709 }
710
711 /* Check initial stream positions and types for sanity. */
713 for (idx = 0; idx < ast_stream_topology_get_count(topology); ++idx, ++type) {
714 stream = ast_stream_topology_get_stream(topology, idx);
715 if (type != ast_stream_get_type(stream)) {
716 ast_test_status_update(test, "Initial topology types failed: Expected:%s Got:%s\n",
719 return AST_TEST_FAIL;
720 }
721 }
722 if (check_stream_positions(test, topology)) {
723 ast_test_status_update(test, "Initial topology positions failed.\n");
724 return AST_TEST_FAIL;
725 }
726
727 /* Try to delete outside of topology size */
729 ast_test_status_update(test, "Deleting stream outside of topology succeeded!\n");
730 return AST_TEST_FAIL;
731 }
732
733 /* Try to delete the last topology stream */
735 ast_test_status_update(test, "Failed deleting last stream of topology.\n");
736 return AST_TEST_FAIL;
737 }
738 if (check_stream_positions(test, topology)) {
739 ast_test_status_update(test, "Last stream delete topology positions failed.\n");
740 return AST_TEST_FAIL;
741 }
742 stream = ast_stream_topology_get_stream(topology, ast_stream_topology_get_count(topology) - 1);
743 type = ast_stream_get_type(stream);
744 if (type != AST_MEDIA_TYPE_END - 2) {
745 ast_test_status_update(test, "Last stream delete types failed: Expected:%s Got:%s\n",
748 return AST_TEST_FAIL;
749 }
750
751 /* Try to delete the second stream in the topology */
752 if (ast_stream_topology_del_stream(topology, 1)) {
753 ast_test_status_update(test, "Failed deleting second stream in topology.\n");
754 return AST_TEST_FAIL;
755 }
756 if (check_stream_positions(test, topology)) {
757 ast_test_status_update(test, "Second stream delete topology positions failed.\n");
758 return AST_TEST_FAIL;
759 }
760 stream = ast_stream_topology_get_stream(topology, 1);
761 type = ast_stream_get_type(stream);
762 if (type != AST_MEDIA_TYPE_UNKNOWN + 2) {
763 ast_test_status_update(test, "Second stream delete types failed: Expected:%s Got:%s\n",
766 return AST_TEST_FAIL;
767 }
768
769 /* Try to delete the first stream in the topology */
770 if (ast_stream_topology_del_stream(topology, 0)) {
771 ast_test_status_update(test, "Failed deleting first stream in topology.\n");
772 return AST_TEST_FAIL;
773 }
774 if (check_stream_positions(test, topology)) {
775 ast_test_status_update(test, "First stream delete topology positions failed.\n");
776 return AST_TEST_FAIL;
777 }
778 stream = ast_stream_topology_get_stream(topology, 0);
779 type = ast_stream_get_type(stream);
780 if (type != AST_MEDIA_TYPE_UNKNOWN + 2) {
781 ast_test_status_update(test, "First stream delete types failed: Expected:%s Got:%s\n",
784 return AST_TEST_FAIL;
785 }
786
787 return AST_TEST_PASS;
788}
789
790AST_TEST_DEFINE(stream_topology_create_from_format_cap)
791{
793 RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
794
795 switch (cmd) {
796 case TEST_INIT:
797 info->name = "stream_topology_create_from_format_cap";
798 info->category = "/main/stream/";
799 info->summary = "stream topology creation from format capabilities unit test";
800 info->description =
801 "Test that creating a stream topology from format capabilities results in the expected streams";
802 return AST_TEST_NOT_RUN;
803 case TEST_EXECUTE:
804 break;
805 }
806
808 if (!caps) {
809 ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
810 return AST_TEST_FAIL;
811 }
812
814 ast_test_status_update(test, "Failed to append a ulaw format to capabilities for stream topology creation\n");
815 return AST_TEST_FAIL;
816 }
817
819 ast_test_status_update(test, "Failed to append an alaw format to capabilities for stream topology creation\n");
820 return AST_TEST_FAIL;
821 }
822
824 if (!topology) {
825 ast_test_status_update(test, "Failed to create a stream topology using a perfectly good format capabilities\n");
826 return AST_TEST_FAIL;
827 }
828
829 if (ast_stream_topology_get_count(topology) != 1) {
830 ast_test_status_update(test, "Expected a stream topology with 1 stream but it has %d streams\n",
832 return AST_TEST_FAIL;
833 }
834
836 ast_test_status_update(test, "Produced stream topology has a single stream of type %s instead of audio\n",
838 return AST_TEST_FAIL;
839 }
840
841 ast_stream_topology_free(topology);
842 topology = NULL;
843
845
847 if (!topology) {
848 ast_test_status_update(test, "Failed to create a stream topology using a perfectly good format capabilities\n");
849 return AST_TEST_FAIL;
850 }
851
852 if (ast_stream_topology_get_count(topology) != 2) {
853 ast_test_status_update(test, "Expected a stream topology with 2 streams but it has %d streams\n",
855 return AST_TEST_FAIL;
856 }
857
859 ast_test_status_update(test, "Produced stream topology has a first stream of type %s instead of audio\n",
861 return AST_TEST_FAIL;
862 }
863
865 ast_test_status_update(test, "Produced stream topology has a second stream of type %s instead of video\n",
867 return AST_TEST_FAIL;
868 }
869
870 return AST_TEST_PASS;
871}
872
873AST_TEST_DEFINE(stream_topology_get_first_stream_by_type)
874{
876 struct ast_stream *first_stream;
877 struct ast_stream *second_stream;
878 struct ast_stream *third_stream;
879 struct ast_stream *fourth_stream;
880 struct ast_stream *fifth_stream;
881 struct ast_stream *sixth_stream;
882
883 switch (cmd) {
884 case TEST_INIT:
885 info->name = "stream_topology_get_first_stream_by_type";
886 info->category = "/main/stream/";
887 info->summary = "stream topology getting first stream by type unit test";
888 info->description =
889 "Test that getting the first stream by type from a topology actually returns the first stream";
890 return AST_TEST_NOT_RUN;
891 case TEST_EXECUTE:
892 break;
893 }
894
895 topology = ast_stream_topology_alloc();
896 if (!topology) {
897 ast_test_status_update(test, "Failed to create media stream topology\n");
898 return AST_TEST_FAIL;
899 }
900
901 first_stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
902 if (!first_stream) {
903 ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
904 return AST_TEST_FAIL;
905 }
907
908 if (ast_stream_topology_append_stream(topology, first_stream) == -1) {
909 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
910 ast_stream_free(first_stream);
911 return AST_TEST_FAIL;
912 }
913
914 second_stream = ast_stream_alloc("audio2", AST_MEDIA_TYPE_AUDIO);
915 if (!second_stream) {
916 ast_test_status_update(test, "Failed to create a second audio stream for testing stream topology\n");
917 return AST_TEST_FAIL;
918 }
919
920 if (ast_stream_topology_append_stream(topology, second_stream) == -1) {
921 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
922 ast_stream_free(second_stream);
923 return AST_TEST_FAIL;
924 }
925
926 third_stream = ast_stream_alloc("audio3", AST_MEDIA_TYPE_AUDIO);
927 if (!third_stream) {
928 ast_test_status_update(test, "Failed to create a third audio stream for testing stream topology\n");
929 return AST_TEST_FAIL;
930 }
931
932 if (ast_stream_topology_append_stream(topology, third_stream) == -1) {
933 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
934 ast_stream_free(third_stream);
935 return AST_TEST_FAIL;
936 }
937
938 fourth_stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
939 if (!fourth_stream) {
940 ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
941 return AST_TEST_FAIL;
942 }
944
945 if (ast_stream_topology_append_stream(topology, fourth_stream) == -1) {
946 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
947 ast_stream_free(fourth_stream);
948 return AST_TEST_FAIL;
949 }
950
951 fifth_stream = ast_stream_alloc("video2", AST_MEDIA_TYPE_VIDEO);
952 if (!fifth_stream) {
953 ast_test_status_update(test, "Failed to create a second video stream for testing stream topology\n");
954 return AST_TEST_FAIL;
955 }
956
957 if (ast_stream_topology_append_stream(topology, fifth_stream) == -1) {
958 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
959 ast_stream_free(fifth_stream);
960 return AST_TEST_FAIL;
961 }
962
963 sixth_stream = ast_stream_alloc("video3", AST_MEDIA_TYPE_VIDEO);
964 if (!sixth_stream) {
965 ast_test_status_update(test, "Failed to create a third video stream for testing stream topology\n");
966 return AST_TEST_FAIL;
967 }
968
969 if (ast_stream_topology_append_stream(topology, sixth_stream) == -1) {
970 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
971 ast_stream_free(sixth_stream);
972 return AST_TEST_FAIL;
973 }
974
976 ast_test_status_update(test, "Retrieved first audio stream from topology but it is not the correct one\n");
977 return AST_TEST_FAIL;
978 }
979
981 ast_test_status_update(test, "Retrieved first video stream from topology but it is not the correct one\n");
982 return AST_TEST_FAIL;
983 }
984
985 return AST_TEST_PASS;
986}
987
988static const struct ast_channel_tech mock_channel_tech = {
989};
990
991AST_TEST_DEFINE(stream_topology_create_from_channel_nativeformats)
992{
994 RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
995 struct ast_channel *mock_channel;
997 struct ast_str *codec_have_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
998 struct ast_str *codec_wanted_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
999
1000 switch (cmd) {
1001 case TEST_INIT:
1002 info->name = "stream_topology_create_from_channel_nativeformats";
1003 info->category = "/main/stream/";
1004 info->summary = "stream topology creation from channel native formats unit test";
1005 info->description =
1006 "Test that creating a stream topology from the setting of channel nativeformats results in the expected streams";
1007 return AST_TEST_NOT_RUN;
1008 case TEST_EXECUTE:
1009 break;
1010 }
1011
1013 if (!caps) {
1014 ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
1015 return AST_TEST_FAIL;
1016 }
1017
1018 if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
1019 ast_test_status_update(test, "Failed to append a ulaw format to capabilities for channel nativeformats\n");
1020 return AST_TEST_FAIL;
1021 }
1022
1023 if (ast_format_cap_append(caps, ast_format_alaw, 0)) {
1024 ast_test_status_update(test, "Failed to append an alaw format to capabilities for channel nativeformats\n");
1025 return AST_TEST_FAIL;
1026 }
1027
1028 if (ast_format_cap_append(caps, ast_format_h264, 0)) {
1029 ast_test_status_update(test, "Failed to append an h264 format to capabilities for channel nativeformats\n");
1030 return AST_TEST_FAIL;
1031 }
1032
1033 mock_channel = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "TestChannel");
1034 if (!mock_channel) {
1035 ast_test_status_update(test, "Failed to create a mock channel for testing\n");
1036 return AST_TEST_FAIL;
1037 }
1038
1040 ast_channel_nativeformats_set(mock_channel, caps);
1041
1042 if (!ast_channel_get_stream_topology(mock_channel)) {
1043 ast_test_status_update(test, "Set nativeformats with ulaw, alaw, and h264 on channel but it did not create a topology\n");
1044 goto end;
1045 }
1046
1048 ast_test_status_update(test, "Set nativeformats on a channel to ulaw, alaw, and h264 and received '%d' streams instead of expected 2\n",
1050 goto end;
1051 }
1052
1054 ast_test_status_update(test, "First stream on channel is of %s when it should be audio\n",
1056 goto end;
1057 }
1058
1061 ast_test_status_update(test, "Formats on audio stream of channel are '%s' when they should be '%s'\n",
1063 ast_format_cap_get_names(caps, &codec_wanted_buf));
1064 goto end;
1065 }
1066
1068 ast_test_status_update(test, "Second stream on channel is of type %s when it should be video\n",
1070 goto end;
1071 }
1072
1074
1075 if (ast_format_cap_append(caps, ast_format_h264, 0)) {
1076 ast_test_status_update(test, "Failed to append h264 video codec to capabilities for capabilities comparison\n");
1077 goto end;
1078 }
1079
1081 ast_test_status_update(test, "Formats on video stream of channel are '%s' when they should be '%s'\n",
1083 ast_format_cap_get_names(caps, &codec_wanted_buf));
1084 goto end;
1085 }
1086
1087 res = AST_TEST_PASS;
1088
1089end:
1090 ast_channel_unlock(mock_channel);
1091 ast_hangup(mock_channel);
1092
1093 return res;
1094}
1095
1098 unsigned int wrote;
1099 unsigned int wrote_stream;
1106 unsigned int indicated_changed;
1107};
1108
1109static struct ast_frame *mock_channel_read(struct ast_channel *chan)
1110{
1111 struct mock_channel_pvt *pvt = ast_channel_tech_pvt(chan);
1112 struct ast_frame f = { 0, };
1113 struct ast_frame *head_frame = NULL;
1114 struct ast_frame *tail_frame = NULL;
1115 int i;
1116
1117 if (pvt->frames_per_read == 0) {
1118 pvt->frames_per_read = 1;
1119 }
1120 for (i = 0; i < pvt->frames_per_read && pvt->frame_count < pvt->frame_limit; i++) {
1121 struct ast_frame *fr;
1122
1123 if (pvt->frame_count % 2 == 0) {
1126 } else {
1129 }
1130 f.seqno = pvt->frame_count;
1131 f.stream_num = pvt->frame_count % pvt->streams;
1132 pvt->frame_count++;
1133 fr = ast_frdup(&f);
1134 if (!head_frame) {
1135 head_frame = fr;
1136 } else {
1137 tail_frame->frame_list.next = fr;
1138 }
1139 tail_frame = fr;
1140 }
1141
1142 return(head_frame);
1143}
1144
1145static int mock_channel_write(struct ast_channel *chan, struct ast_frame *fr)
1146{
1147 struct mock_channel_pvt *pvt = ast_channel_tech_pvt(chan);
1148
1149 pvt->wrote = 1;
1150
1151 return 0;
1152}
1153
1154static int mock_channel_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
1155{
1156 struct mock_channel_pvt *pvt = ast_channel_tech_pvt(chan);
1157
1159 pvt->indicated_change_request = 1;
1160 } else if (condition == AST_CONTROL_STREAM_TOPOLOGY_CHANGED) {
1161 pvt->indicated_changed = 1;
1162 }
1163
1164 return 0;
1165}
1166
1167static int mock_channel_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame *fr)
1168{
1169 struct mock_channel_pvt *pvt = ast_channel_tech_pvt(chan);
1170
1171 pvt->wrote_stream = 1;
1172 pvt->stream_num = stream_num;
1173
1174 return 0;
1175}
1176
1179 .write_stream = mock_channel_write_stream,
1180};
1181
1182AST_TEST_DEFINE(stream_topology_channel_set)
1183{
1185 struct ast_channel *mock_channel;
1187
1188 switch (cmd) {
1189 case TEST_INIT:
1190 info->name = "stream_topology_channel_set";
1191 info->category = "/main/stream/";
1192 info->summary = "stream topology setting on a channel unit test";
1193 info->description =
1194 "Test that setting a stream topology on a channel works";
1195 return AST_TEST_NOT_RUN;
1196 case TEST_EXECUTE:
1197 break;
1198 }
1199
1200 topology = ast_stream_topology_alloc();
1201 if (!topology) {
1202 ast_test_status_update(test, "Failed to create media stream topology\n");
1203 return AST_TEST_FAIL;
1204 }
1205
1206 mock_channel = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "TestChannel");
1207 if (!mock_channel) {
1208 ast_test_status_update(test, "Failed to create a mock channel for testing\n");
1209 return AST_TEST_FAIL;
1210 }
1211
1213 ast_channel_set_stream_topology(mock_channel, topology);
1214
1215 if (ast_channel_get_stream_topology(mock_channel) != topology) {
1216 ast_test_status_update(test, "Set an explicit stream topology on a channel but the returned one did not match it\n");
1217 res = AST_TEST_FAIL;
1218 }
1219
1220 topology = NULL;
1221 ast_channel_unlock(mock_channel);
1222 ast_hangup(mock_channel);
1223
1224 return res;
1225}
1226
1227static int mock_channel_hangup(struct ast_channel *chan)
1228{
1229 struct mock_channel_pvt *pvt = ast_channel_tech_pvt(chan);
1230
1231 if (pvt->mallocd) {
1232 ast_free(pvt);
1233 }
1234
1236 return 0;
1237}
1238
1241 .write_video = mock_channel_write,
1242 .hangup = mock_channel_hangup,
1243};
1244
1245AST_TEST_DEFINE(stream_write_non_multistream)
1246{
1247 RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
1248 struct ast_channel *mock_channel;
1249 struct mock_channel_pvt pvt = { 0, };
1251 struct ast_frame frame = { 0, };
1252
1253 switch (cmd) {
1254 case TEST_INIT:
1255 info->name = "stream_write_non_multistream";
1256 info->category = "/main/stream/";
1257 info->summary = "stream writing to non-multistream capable channel test";
1258 info->description =
1259 "Test that writing frames to a non-multistream channel works as expected";
1260 return AST_TEST_NOT_RUN;
1261 case TEST_EXECUTE:
1262 break;
1263 }
1264
1266 if (!caps) {
1267 ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
1268 return AST_TEST_FAIL;
1269 }
1270
1271 if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
1272 ast_test_status_update(test, "Failed to append a ulaw format to capabilities for channel nativeformats\n");
1273 return AST_TEST_FAIL;
1274 }
1275
1276 if (ast_format_cap_append(caps, ast_format_h264, 0)) {
1277 ast_test_status_update(test, "Failed to append an h264 format to capabilities for channel nativeformats\n");
1278 return AST_TEST_FAIL;
1279 }
1280
1281 mock_channel = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "TestChannel");
1282 if (!mock_channel) {
1283 ast_test_status_update(test, "Failed to create a mock channel for testing\n");
1284 return AST_TEST_FAIL;
1285 }
1286
1288 ast_channel_nativeformats_set(mock_channel, caps);
1289
1290 pvt.wrote = 0;
1291 ast_channel_tech_pvt_set(mock_channel, &pvt);
1292 ast_channel_unlock(mock_channel);
1293
1294 frame.frametype = AST_FRAME_VOICE;
1296
1297 if (ast_write(mock_channel, &frame)) {
1298 ast_test_status_update(test, "Failed to write a ulaw frame to the mock channel when it should be fine\n");
1299 goto end;
1300 }
1301
1302 if (!pvt.wrote) {
1303 ast_test_status_update(test, "Successfully wrote a frame of ulaw but it never reached the channel driver\n");
1304 goto end;
1305 }
1306
1307 pvt.wrote = 0;
1308
1309 if (!ast_write_stream(mock_channel, 2, &frame) || pvt.wrote) {
1310 ast_test_status_update(test, "Successfully wrote a frame of ulaw to a non-existent stream\n");
1311 goto end;
1312 }
1313
1314 frame.frametype = AST_FRAME_VIDEO;
1316
1317 if (ast_write(mock_channel, &frame)) {
1318 ast_test_status_update(test, "Failed to write an h264 frame to the mock channel when it should be fine\n");
1319 goto end;
1320 }
1321
1322 if (!pvt.wrote) {
1323 ast_test_status_update(test, "Successfully wrote a frame of h264 but it never reached the channel driver\n");
1324 goto end;
1325 }
1326
1327 res = AST_TEST_PASS;
1328
1329end:
1330 ast_hangup(mock_channel);
1331
1332 return res;
1333}
1334
1337 .write_video = mock_channel_write,
1338 .write_stream = mock_channel_write_stream,
1339 .read_stream = mock_channel_read,
1340 .hangup = mock_channel_hangup,
1341};
1342
1343AST_TEST_DEFINE(stream_write_multistream)
1344{
1345 RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
1347 struct ast_stream *stream;
1348 struct ast_channel *mock_channel;
1349 struct mock_channel_pvt pvt = { 0, };
1351 struct ast_frame frame = { 0, };
1352
1353 switch (cmd) {
1354 case TEST_INIT:
1355 info->name = "stream_write_multistream";
1356 info->category = "/main/stream/";
1357 info->summary = "stream writing to multistream capable channel test";
1358 info->description =
1359 "Test that writing frames to a multistream channel works as expected";
1360 return AST_TEST_NOT_RUN;
1361 case TEST_EXECUTE:
1362 break;
1363 }
1364
1365 topology = ast_stream_topology_alloc();
1366 if (!topology) {
1367 ast_test_status_update(test, "Failed to create media stream topology\n");
1368 return AST_TEST_FAIL;
1369 }
1370
1371 stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
1372 if (!stream) {
1373 ast_test_status_update(test, "Failed to create an audio stream for testing multistream writing\n");
1374 return AST_TEST_FAIL;
1375 }
1376
1377 if (ast_stream_topology_append_stream(topology, stream) == -1) {
1378 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
1379 ast_stream_free(stream);
1380 return AST_TEST_FAIL;
1381 }
1382
1383 stream = ast_stream_alloc("audio2", AST_MEDIA_TYPE_AUDIO);
1384 if (!stream) {
1385 ast_test_status_update(test, "Failed to create an audio stream for testing multistream writing\n");
1386 return AST_TEST_FAIL;
1387 }
1388
1389 if (ast_stream_topology_append_stream(topology, stream) == -1) {
1390 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
1391 ast_stream_free(stream);
1392 return AST_TEST_FAIL;
1393 }
1394
1395 stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
1396 if (!stream) {
1397 ast_test_status_update(test, "Failed to create a video stream for testing multistream writing\n");
1398 return AST_TEST_FAIL;
1399 }
1400
1401 if (ast_stream_topology_append_stream(topology, stream) == -1) {
1402 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
1403 ast_stream_free(stream);
1404 return AST_TEST_FAIL;
1405 }
1406
1407 stream = ast_stream_alloc("video2", AST_MEDIA_TYPE_VIDEO);
1408 if (!stream) {
1409 ast_test_status_update(test, "Failed to create a video stream for testing multistream writing\n");
1410 return AST_TEST_FAIL;
1411 }
1412
1413 if (ast_stream_topology_append_stream(topology, stream) == -1) {
1414 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
1415 ast_stream_free(stream);
1416 return AST_TEST_FAIL;
1417 }
1418
1420 if (!caps) {
1421 ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
1422 return AST_TEST_FAIL;
1423 }
1424
1425 if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
1426 ast_test_status_update(test, "Failed to append a ulaw format to capabilities for channel nativeformats\n");
1427 return AST_TEST_FAIL;
1428 }
1429
1430 if (ast_format_cap_append(caps, ast_format_h264, 0)) {
1431 ast_test_status_update(test, "Failed to append an h264 format to capabilities for channel nativeformats\n");
1432 return AST_TEST_FAIL;
1433 }
1434
1435 mock_channel = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "TestChannel");
1436 if (!mock_channel) {
1437 ast_test_status_update(test, "Failed to create a mock channel for testing\n");
1438 return AST_TEST_FAIL;
1439 }
1440
1442 ast_channel_set_stream_topology(mock_channel, topology);
1443 ast_channel_nativeformats_set(mock_channel, caps);
1444 topology = NULL;
1445
1446 ast_channel_tech_pvt_set(mock_channel, &pvt);
1447 ast_channel_unlock(mock_channel);
1448
1449 frame.frametype = AST_FRAME_VOICE;
1451 pvt.stream_num = -1;
1452
1453 if (ast_write(mock_channel, &frame)) {
1454 ast_test_status_update(test, "Failed to write a ulaw frame to the mock channel when it should be fine\n");
1455 goto end;
1456 }
1457
1458 if (pvt.wrote) {
1459 ast_test_status_update(test, "Successfully wrote a frame of ulaw but it ended up on the old write callback instead of write_stream\n");
1460 goto end;
1461 }
1462
1463 if (!pvt.wrote_stream) {
1464 ast_test_status_update(test, "Successfully wrote a frame of ulaw but it never reached the channel driver\n");
1465 goto end;
1466 }
1467
1468 if (pvt.stream_num != 0) {
1469 ast_test_status_update(test, "Successfully wrote a frame of ulaw to the default stream but it ended up on stream %d and not 0\n",
1470 pvt.stream_num);
1471 goto end;
1472 }
1473
1474 pvt.wrote_stream = 0;
1475 pvt.stream_num = -1;
1476
1477 if (ast_write_stream(mock_channel, 0, &frame)) {
1478 ast_test_status_update(test, "Failed to write a ulaw frame to the first audio stream\n");
1479 goto end;
1480 }
1481
1482 if (pvt.wrote) {
1483 ast_test_status_update(test, "Successfully wrote a frame of ulaw to the first audio stream but it ended up on the old write callback instead of write_stream\n");
1484 goto end;
1485 }
1486
1487 if (!pvt.wrote_stream) {
1488 ast_test_status_update(test, "Successfully wrote a frame of ulaw to the first audio stream but it never reached the channel driver\n");
1489 goto end;
1490 }
1491
1492 if (pvt.stream_num != 0) {
1493 ast_test_status_update(test, "Successfully wrote a frame of ulaw to the first audio stream but it ended up on stream %d and not 0\n",
1494 pvt.stream_num);
1495 goto end;
1496 }
1497
1498 pvt.wrote_stream = 0;
1499 pvt.stream_num = -1;
1500
1501 if (ast_write_stream(mock_channel, 1, &frame)) {
1502 ast_test_status_update(test, "Failed to write a ulaw frame to the second audio stream\n");
1503 goto end;
1504 }
1505
1506 if (pvt.wrote) {
1507 ast_test_status_update(test, "Successfully wrote a frame of ulaw to the second audio stream but it ended up on the old write callback instead of write_stream\n");
1508 goto end;
1509 }
1510
1511 if (!pvt.wrote_stream) {
1512 ast_test_status_update(test, "Successfully wrote a frame of ulaw to the second audio stream but it never reached the channel driver\n");
1513 goto end;
1514 }
1515
1516 if (pvt.stream_num != 1) {
1517 ast_test_status_update(test, "Successfully wrote a frame of ulaw to the second audio stream but it ended up on stream %d and not 1\n",
1518 pvt.stream_num);
1519 goto end;
1520 }
1521
1522 pvt.wrote_stream = 0;
1523 pvt.stream_num = -1;
1524
1525 frame.frametype = AST_FRAME_VIDEO;
1527
1528 if (ast_write(mock_channel, &frame)) {
1529 ast_test_status_update(test, "Failed to write an h264 frame to the mock channel when it should be fine\n");
1530 goto end;
1531 }
1532
1533 if (pvt.wrote) {
1534 ast_test_status_update(test, "Successfully wrote a frame of h264 but it ended up on the old write callback instead of write_stream\n");
1535 goto end;
1536 }
1537
1538 if (!pvt.wrote_stream) {
1539 ast_test_status_update(test, "Successfully wrote a frame of h264 but it never reached the channel driver\n");
1540 goto end;
1541 }
1542
1543 if (pvt.stream_num != 2) {
1544 ast_test_status_update(test, "Successfully wrote a frame of h264 to the default stream but it ended up on stream %d and not 2\n",
1545 pvt.stream_num);
1546 goto end;
1547 }
1548
1549 pvt.wrote_stream = 0;
1550 pvt.stream_num = -1;
1551
1552 if (ast_write_stream(mock_channel, 2, &frame)) {
1553 ast_test_status_update(test, "Failed to write an h264 frame to the first video stream\n");
1554 goto end;
1555 }
1556
1557 if (pvt.wrote) {
1558 ast_test_status_update(test, "Successfully wrote a frame of h264 to the first video stream but it ended up on the old write callback instead of write_stream\n");
1559 goto end;
1560 }
1561
1562 if (!pvt.wrote_stream) {
1563 ast_test_status_update(test, "Successfully wrote a frame of h264 to the first video stream but it never reached the channel driver\n");
1564 goto end;
1565 }
1566
1567 if (pvt.stream_num != 2) {
1568 ast_test_status_update(test, "Successfully wrote a frame of h264 to the first video stream but it ended up on stream %d and not 2\n",
1569 pvt.stream_num);
1570 goto end;
1571 }
1572
1573 pvt.wrote_stream = 0;
1574 pvt.stream_num = -1;
1575
1576 if (ast_write_stream(mock_channel, 3, &frame)) {
1577 ast_test_status_update(test, "Failed to write an h264 frame to the second video stream\n");
1578 goto end;
1579 }
1580
1581 if (pvt.wrote) {
1582 ast_test_status_update(test, "Successfully wrote a frame of h264 to the second video stream but it ended up on the old write callback instead of write_stream\n");
1583 goto end;
1584 }
1585
1586 if (!pvt.wrote_stream) {
1587 ast_test_status_update(test, "Successfully wrote a frame of h264 to the second video stream but it never reached the channel driver\n");
1588 goto end;
1589 }
1590
1591 if (pvt.stream_num != 3) {
1592 ast_test_status_update(test, "Successfully wrote a frame of h264 to the second video stream but it ended up on stream %d and not 3\n",
1593 pvt.stream_num);
1594 goto end;
1595 }
1596
1597 pvt.wrote_stream = 0;
1598 pvt.stream_num = -1;
1599
1600 if (!ast_write_stream(mock_channel, 9, &frame)) {
1601 ast_test_status_update(test, "Successfully wrote a frame of h264 to a non-existent stream\n");
1602 goto end;
1603 }
1604
1605 if (pvt.wrote) {
1606 ast_test_status_update(test, "Successfully wrote a frame of h264 to a non-existent stream and it ended up on the old write callback\n");
1607 goto end;
1608 }
1609
1610 if (pvt.wrote_stream) {
1611 ast_test_status_update(test, "Successfully wrote a frame of h264 to a non-existent stream and it ended up on the write_stream callback\n");
1612 goto end;
1613 }
1614
1615 res = AST_TEST_PASS;
1616
1617end:
1618 ast_hangup(mock_channel);
1619
1620 return res;
1621}
1622
1623static int load_stream_readqueue(struct ast_channel *chan, int frames)
1624{
1625 struct mock_channel_pvt *pvt = ast_channel_tech_pvt(chan);
1626 struct ast_frame f = { 0, };
1627 struct ast_frame *frame = NULL;
1628 int i;
1629
1630 while ((frame = AST_LIST_REMOVE_HEAD(ast_channel_readq(chan), frame_list)))
1631 ast_frfree(frame);
1632
1633 for (i = 0; i < frames; i++) {
1634 if (pvt->frame_count % 2 == 0) {
1637 } else {
1640 }
1641 f.stream_num = pvt->frame_count % pvt->streams;
1642 f.seqno = pvt->frame_count;
1643 ast_queue_frame(chan, &f);
1644 pvt->frame_count++;
1645 }
1646
1647 return 0;
1648}
1649
1650static struct ast_channel *make_channel(struct ast_test *test, int streams,
1651 struct ast_channel_tech *tech)
1652{
1653 RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
1654 struct ast_channel *mock_channel = NULL;
1655 struct mock_channel_pvt *pvt = NULL;
1656 struct ast_stream_topology *topology = NULL;
1657 struct ast_stream *stream;
1659 int i;
1660
1661 mock_channel = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "TestChannel");
1662 ast_test_validate_cleanup(test, mock_channel, res, done);
1663 ast_channel_tech_set(mock_channel, tech);
1664
1665 if (tech->read_stream) {
1666 topology = ast_stream_topology_alloc();
1667 ast_test_validate_cleanup(test, topology, res, done);
1668
1669 for (i = 0; i < streams; i++) {
1670 stream = ast_stream_alloc((i % 2 ? "video": "audio"), (i % 2 ? AST_MEDIA_TYPE_VIDEO : AST_MEDIA_TYPE_AUDIO));
1671 ast_test_validate_cleanup(test, stream, res, done);
1672 ast_test_validate_cleanup(test, ast_stream_topology_append_stream(topology, stream) == i, res, done);
1673 }
1674 ast_test_validate_cleanup(test, ast_stream_topology_get_count(topology) == streams, res, done);
1675 ast_channel_set_stream_topology(mock_channel, topology);
1676 topology = NULL;
1677 } else {
1679 ast_test_validate_cleanup(test, caps, res, done);
1680
1681 ast_test_validate_cleanup(test, ast_format_cap_append(caps, ast_format_ulaw, 0) == 0, res, done);
1682 ast_test_validate_cleanup(test, ast_format_cap_append(caps, ast_format_h264, 0) == 0, res, done);
1683 ast_channel_nativeformats_set(mock_channel, caps);
1684 }
1685
1686 pvt = ast_calloc(1, sizeof(*pvt));
1687 ast_test_validate_cleanup(test, pvt, res, done);
1688 pvt->mallocd = 1;
1689 ast_channel_tech_pvt_set(mock_channel, pvt);
1690
1691 ast_channel_unlock(mock_channel);
1692
1693done:
1694 ast_stream_topology_free(topology);
1695 if (res == AST_TEST_FAIL && mock_channel) {
1696 ast_hangup(mock_channel);
1697 }
1698
1699 return mock_channel;
1700}
1701
1706
1707static struct ast_frame *read_from_chan(enum CHANNEL_READ_TYPE rt, struct ast_channel *chan)
1708{
1709 if (rt == CHANNEL_READ_STREAM) {
1710 return ast_read_stream(chan);
1711 } else {
1712 return ast_read(chan);
1713 }
1714}
1715
1716static enum ast_test_result_state read_test(struct ast_test *test, struct ast_channel_tech *tech,
1717 enum CHANNEL_READ_TYPE rt, int streams, int frames, int frames_per_read, int expected_nulls)
1718{
1719 struct ast_channel *mock_channel;
1720 struct mock_channel_pvt *pvt;
1721 struct ast_frame *fr = NULL;
1723 int i = 0;
1724 int null_frames = 0;
1725
1726 ast_test_status_update(test, "ChanType: %s ReadType: %s Streams: %d Frames: %d Frames per read: %d Expected Nulls: %d\n",
1727 tech->read_stream ? "MULTI" : "NON-MULTI",
1728 rt == CHANNEL_READ_STREAM ? "STREAM" : "NON-STREAM",
1729 streams, frames, frames_per_read, expected_nulls);
1730 mock_channel = make_channel(test, 4, tech);
1731 ast_test_validate_cleanup(test, mock_channel, res, done);
1732
1733 pvt = ast_channel_tech_pvt(mock_channel);
1734 pvt->frame_count = 0;
1735 pvt->frame_limit = frames;
1736 pvt->streams = streams;
1737 pvt->frames_per_read = frames_per_read;
1738
1739 load_stream_readqueue(mock_channel, frames / 2);
1740 ast_channel_fdno_set(mock_channel, 0);
1741
1742 while ((fr = read_from_chan(rt, mock_channel))) {
1743 ast_channel_fdno_set(mock_channel, 0);
1744 if (fr->frametype != AST_FRAME_NULL) {
1745 ast_test_validate_cleanup(test, i == fr->seqno, res, done);
1746 ast_test_validate_cleanup(test, fr->frametype == ( i % 2 ? AST_FRAME_VIDEO : AST_FRAME_VOICE), res, done);
1747 ast_test_validate_cleanup(test, fr->stream_num == ( i % streams ), res, done);
1748 ast_frfree(fr);
1749 } else {
1750 null_frames++;
1751 }
1752 fr = NULL;
1753 i++;
1754 }
1755 ast_test_validate_cleanup(test, i == frames, res, done);
1756 ast_test_validate_cleanup(test, null_frames == expected_nulls, res, done);
1757
1758done:
1759 ast_test_status_update(test, " Frames read: %d NULL frames: %d\n", i, null_frames);
1760 ast_hangup(mock_channel);
1761
1762 return res;
1763}
1764
1765AST_TEST_DEFINE(stream_read_non_multistream)
1766{
1767 struct ast_channel_tech tech = {
1769 .hangup = mock_channel_hangup,
1770 };
1771
1773
1774 switch (cmd) {
1775 case TEST_INIT:
1776 info->name = "stream_read_non_multistream";
1777 info->category = "/main/stream/";
1778 info->summary = "stream reading from non-multistream capable channel test";
1779 info->description =
1780 "Test that reading frames from a non-multistream channel works as expected";
1781 return AST_TEST_NOT_RUN;
1782 case TEST_EXECUTE:
1783 break;
1784 }
1785
1786 res = read_test(test, &tech, CHANNEL_READ, 2, 16, 1, 0);
1787 ast_test_validate(test, res == AST_TEST_PASS, "non multi, non read stream, 2 stream");
1788
1789 res = read_test(test, &tech, CHANNEL_READ_STREAM, 2, 16, 1, 0);
1790 ast_test_validate(test, res == AST_TEST_PASS, "non multi, read stream, 2 stream");
1791
1792 res = read_test(test, &tech, CHANNEL_READ, 2, 16, 3, 0);
1793 ast_test_validate(test, res == AST_TEST_PASS, "non multi, non read stream, 2 stream, 3 frames per read");
1794
1795 res = read_test(test, &tech, CHANNEL_READ_STREAM, 2, 16, 3, 0);
1796 ast_test_validate(test, res == AST_TEST_PASS, "non multi, read stream, 2 stream, 3 frames per read");
1797
1798 return res;
1799}
1800
1801AST_TEST_DEFINE(stream_read_multistream)
1802{
1803 struct ast_channel_tech tech = {
1805 .write_stream = mock_channel_write_stream,
1806 .hangup = mock_channel_hangup,
1807 };
1809
1810 switch (cmd) {
1811 case TEST_INIT:
1812 info->name = "stream_read_multistream";
1813 info->category = "/main/stream/";
1814 info->summary = "stream reading from multistream capable channel test";
1815 info->description =
1816 "Test that reading frames from a multistream channel works as expected";
1817 return AST_TEST_NOT_RUN;
1818 case TEST_EXECUTE:
1819 break;
1820 }
1821
1822 res = read_test(test, &tech, CHANNEL_READ, 2, 16, 1, 0);
1823 ast_test_validate(test, res == AST_TEST_PASS, "multi, non read stream, 2 stream");
1824
1825 res = read_test(test, &tech, CHANNEL_READ_STREAM, 2, 16, 1, 0);
1826 ast_test_validate(test, res == AST_TEST_PASS, "multi, read stream, 2 stream");
1827
1828 res = read_test(test, &tech, CHANNEL_READ, 4, 16, 1, 8);
1829 ast_test_validate(test, res == AST_TEST_PASS, "multi, non read stream, 4 stream");
1830
1831 res = read_test(test, &tech, CHANNEL_READ_STREAM, 4, 16, 1, 0);
1832 ast_test_validate(test, res == AST_TEST_PASS, "multi, read stream, 4 stream");
1833
1834 res = read_test(test, &tech, CHANNEL_READ, 2, 16, 3, 0);
1835 ast_test_validate(test, res == AST_TEST_PASS, "multi, non read stream, 2 stream, 3 frames per read");
1836
1837 res = read_test(test, &tech, CHANNEL_READ_STREAM, 2, 16, 3, 0);
1838 ast_test_validate(test, res == AST_TEST_PASS, "multi, read stream, 2 stream, 3 frames per read");
1839
1840 res = read_test(test, &tech, CHANNEL_READ, 4, 16, 3, 8);
1841 ast_test_validate(test, res == AST_TEST_PASS, "multi, non read stream, 4 stream, 3 frames per read");
1842
1843 res = read_test(test, &tech, CHANNEL_READ_STREAM, 4, 16, 3, 0);
1844 ast_test_validate(test, res == AST_TEST_PASS, "multi, read stream, 4 stream, 3 frames per read");
1845
1846 return res;
1847}
1848
1849AST_TEST_DEFINE(stream_topology_change_request_from_application_non_multistream)
1850{
1851 struct ast_channel_tech tech = {
1853 .indicate = mock_channel_indicate,
1854 .hangup = mock_channel_hangup,
1855 };
1856 struct ast_channel *mock_channel;
1857 struct mock_channel_pvt *pvt;
1859 int change_res;
1861
1862 switch (cmd) {
1863 case TEST_INIT:
1864 info->name = "stream_topology_change_request_from_application_non_multistream";
1865 info->category = "/main/stream/";
1866 info->summary = "stream topology changing on non-multistream channel test";
1867 info->description =
1868 "Test that an application trying to change the stream topology of a non-multistream channel gets a failure";
1869 return AST_TEST_NOT_RUN;
1870 case TEST_EXECUTE:
1871 break;
1872 }
1873
1874 mock_channel = make_channel(test, 1, &tech);
1875 ast_test_validate_cleanup(test, mock_channel, res, done);
1876
1877 pvt = ast_channel_tech_pvt(mock_channel);
1878 pvt->indicated_change_request = 0;
1879 pvt->indicated_changed = 0;
1880
1881 topology = ast_stream_topology_alloc();
1882 ast_test_validate_cleanup(test, topology, res, done);
1883
1884 change_res = ast_channel_request_stream_topology_change(mock_channel, topology, NULL);
1885
1886 ast_test_validate_cleanup(test, change_res == -1, res, done);
1887 ast_test_validate_cleanup(test, !pvt->indicated_change_request, res, done);
1888
1889 ast_channel_lock(mock_channel);
1890 change_res = ast_channel_stream_topology_changed(mock_channel, topology);
1891 ast_channel_unlock(mock_channel);
1892
1893 ast_test_validate_cleanup(test, change_res == -1, res, done);
1894 ast_test_validate_cleanup(test, !pvt->indicated_changed, res, done);
1895
1896done:
1897 ast_hangup(mock_channel);
1898
1899 return res;
1900}
1901
1902AST_TEST_DEFINE(stream_topology_change_request_from_channel_non_multistream)
1903{
1904 struct ast_channel_tech tech = {
1906 .write_stream = mock_channel_write_stream,
1907 .indicate = mock_channel_indicate,
1908 .hangup = mock_channel_hangup,
1909 };
1910 struct ast_channel *mock_channel;
1911 struct mock_channel_pvt *pvt;
1914 struct ast_frame request_change = {
1917 };
1918 struct ast_frame *fr = NULL;
1919
1920 switch (cmd) {
1921 case TEST_INIT:
1922 info->name = "stream_topology_change_request_from_channel_non_multistream";
1923 info->category = "/main/stream/";
1924 info->summary = "channel requesting stream topology change to non-multistream application test";
1925 info->description =
1926 "Test that a channel requesting a stream topology change from a non-multistream application does not work";
1927 return AST_TEST_NOT_RUN;
1928 case TEST_EXECUTE:
1929 break;
1930 }
1931
1932 mock_channel = make_channel(test, 1, &tech);
1933 ast_test_validate_cleanup(test, mock_channel, res, done);
1934
1935 pvt = ast_channel_tech_pvt(mock_channel);
1936 pvt->indicated_changed = 0;
1937
1938 topology = ast_stream_topology_alloc();
1939 ast_test_validate_cleanup(test, topology, res, done);
1940
1941 request_change.data.ptr = topology;
1942 ast_queue_frame(mock_channel, &request_change);
1943
1944 fr = ast_read(mock_channel);
1945 ast_test_validate_cleanup(test, fr, res, done);
1946 ast_test_validate_cleanup(test, fr == &ast_null_frame, res, done);
1947 ast_test_validate_cleanup(test, pvt->indicated_changed, res, done);
1948
1949done:
1950 if (fr) {
1951 ast_frfree(fr);
1952 }
1953 ast_hangup(mock_channel);
1954
1955 return res;
1956}
1957
1958AST_TEST_DEFINE(stream_topology_change_request_from_application)
1959{
1960 struct ast_channel_tech tech = {
1962 .write_stream = mock_channel_write_stream,
1963 .indicate = mock_channel_indicate,
1964 .hangup = mock_channel_hangup,
1965 };
1966 struct ast_channel *mock_channel;
1967 struct mock_channel_pvt *pvt;
1969 int change_res;
1971
1972 switch (cmd) {
1973 case TEST_INIT:
1974 info->name = "stream_topology_change_request_from_application";
1975 info->category = "/main/stream/";
1976 info->summary = "stream topology change request from application test";
1977 info->description =
1978 "Test that an application changing the stream topology of a multistream capable channel receives success";
1979 return AST_TEST_NOT_RUN;
1980 case TEST_EXECUTE:
1981 break;
1982 }
1983
1984 mock_channel = make_channel(test, 1, &tech);
1985 ast_test_validate_cleanup(test, mock_channel, res, done);
1986
1987 pvt = ast_channel_tech_pvt(mock_channel);
1988 pvt->indicated_change_request = 0;
1989 pvt->indicated_changed = 0;
1990
1991 topology = ast_stream_topology_alloc();
1992 ast_test_validate_cleanup(test, topology, res, done);
1993
1994 change_res = ast_channel_request_stream_topology_change(mock_channel, topology, NULL);
1995
1996 ast_test_validate_cleanup(test, !change_res, res, done);
1997 ast_test_validate_cleanup(test, pvt->indicated_change_request, res, done);
1998
1999 ast_channel_lock(mock_channel);
2000 change_res = ast_channel_stream_topology_changed(mock_channel, topology);
2001 ast_channel_unlock(mock_channel);
2002
2003 ast_test_validate_cleanup(test, !change_res, res, done);
2004 ast_test_validate_cleanup(test, pvt->indicated_changed, res, done);
2005
2006done:
2007 ast_hangup(mock_channel);
2008
2009 return res;
2010}
2011
2012AST_TEST_DEFINE(stream_topology_change_request_from_channel)
2013{
2014 struct ast_channel_tech tech = {
2016 .write_stream = mock_channel_write_stream,
2017 .indicate = mock_channel_indicate,
2018 .hangup = mock_channel_hangup,
2019 };
2020 struct ast_channel *mock_channel;
2021 struct mock_channel_pvt *pvt;
2024 struct ast_frame request_change = {
2027 };
2028 struct ast_frame *fr = NULL;
2029
2030 switch (cmd) {
2031 case TEST_INIT:
2032 info->name = "stream_topology_change_request_from_channel";
2033 info->category = "/main/stream/";
2034 info->summary = "channel requesting stream topology change to multistream application test";
2035 info->description =
2036 "Test that a channel requesting a stream topology change from a multistream application works";
2037 return AST_TEST_NOT_RUN;
2038 case TEST_EXECUTE:
2039 break;
2040 }
2041
2042 mock_channel = make_channel(test, 1, &tech);
2043 ast_test_validate_cleanup(test, mock_channel, res, done);
2044
2045 pvt = ast_channel_tech_pvt(mock_channel);
2046 pvt->indicated_changed = 0;
2047
2048 topology = ast_stream_topology_alloc();
2049 ast_test_validate_cleanup(test, topology, res, done);
2050
2051 request_change.data.ptr = topology;
2052 ast_queue_frame(mock_channel, &request_change);
2053
2054 fr = ast_read_stream(mock_channel);
2055 ast_test_validate_cleanup(test, fr, res, done);
2056 ast_test_validate_cleanup(test, fr->frametype == AST_FRAME_CONTROL, res, done);
2057 ast_test_validate_cleanup(test, fr->subclass.integer == AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE, res, done);
2058 ast_test_validate_cleanup(test, !pvt->indicated_changed, res, done);
2059
2060done:
2061 if (fr) {
2062 ast_frfree(fr);
2063 }
2064 ast_hangup(mock_channel);
2065
2066 return res;
2067}
2068
2069AST_TEST_DEFINE(format_cap_from_stream_topology)
2070{
2071 RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
2072 RAII_VAR(struct ast_format_cap *, stream_caps, NULL, ao2_cleanup);
2073 struct ast_stream_topology *topology;
2074 struct ast_stream *stream;
2075 struct ast_format_cap *new_cap;
2076
2077 switch (cmd) {
2078 case TEST_INIT:
2079 info->name = "format_cap_from_stream_topology";
2080 info->category = "/main/stream/";
2081 info->summary = "stream topology to format capabilities conversion test";
2082 info->description =
2083 "Test that converting a stream topology to format capabilities results in expected formats";
2084 return AST_TEST_NOT_RUN;
2085 case TEST_EXECUTE:
2086 break;
2087 }
2088
2090 if (!caps) {
2091 ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
2092 return AST_TEST_FAIL;
2093 }
2094
2095 if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
2096 ast_test_status_update(test, "Failed to append ulaw format to capabilities\n");
2097 return AST_TEST_FAIL;
2098 }
2099
2100 if (ast_format_cap_append(caps, ast_format_h264, 0)) {
2101 ast_test_status_update(test, "Failed to append h264 format to capabilities\n");
2102 return AST_TEST_FAIL;
2103 }
2104
2106 if (!topology) {
2107 ast_test_status_update(test, "Failed to create a stream topology from format capabilities of ulaw and h264\n");
2108 return AST_TEST_FAIL;
2109 }
2110
2111 /*
2112 * Append declined stream with formats that should not be included
2113 * in combined topology caps.
2114 */
2115 stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
2116 if (!stream) {
2117 ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
2118 ast_stream_topology_free(topology);
2119 return AST_TEST_FAIL;
2120 }
2123 if (!new_cap) {
2124 ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
2125 ast_stream_free(stream);
2126 ast_stream_topology_free(topology);
2127 return AST_TEST_FAIL;
2128 }
2129 if (ast_format_cap_append(new_cap, ast_format_alaw, 0)) {
2130 ast_test_status_update(test, "Failed to append alaw format to capabilities\n");
2131 ao2_cleanup(new_cap);
2132 ast_stream_free(stream);
2133 ast_stream_topology_free(topology);
2134 return AST_TEST_FAIL;
2135 }
2136 ast_stream_set_formats(stream, new_cap);
2137 ao2_cleanup(new_cap);
2138 if (ast_stream_topology_append_stream(topology, stream) == -1) {
2139 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
2140 ast_stream_free(stream);
2141 ast_stream_topology_free(topology);
2142 return AST_TEST_FAIL;
2143 }
2144
2145 stream_caps = ast_stream_topology_get_formats(topology);
2146 if (!stream_caps) {
2147 ast_test_status_update(test, "Failed to create a format capabilities from a stream topology\n");
2148 ast_stream_topology_free(topology);
2149 return AST_TEST_FAIL;
2150 }
2151
2152 ast_stream_topology_free(topology);
2153
2154 if (!ast_format_cap_identical(caps, stream_caps)) {
2155 ast_test_status_update(test, "Converting format capabilities into topology and back resulted in different formats\n");
2156 return AST_TEST_FAIL;
2157 }
2158
2159 return AST_TEST_PASS;
2160}
2161
2162#define topology_append_stream(topology, name, type, res, label) \
2163 do { \
2164 struct ast_stream *__stream = ast_stream_alloc((name), (type)); \
2165 ast_test_validate_cleanup(test, __stream, res, label); \
2166 if (ast_stream_topology_append_stream((topology), __stream) < 0) { \
2167 ast_stream_free(__stream); \
2168 res = AST_TEST_FAIL; \
2169 goto label; \
2170 } \
2171 } while(0)
2172
2173AST_TEST_DEFINE(stream_topology_map_create)
2174{
2176
2177 struct ast_vector_int types = { NULL };
2178 struct ast_vector_int v0 = { NULL };
2179 struct ast_vector_int v1 = { NULL };
2180
2182
2183 switch (cmd) {
2184 case TEST_INIT:
2185 info->name = "stream_topology_map_create";
2186 info->category = "/main/stream/";
2187 info->summary = "stream topology map creation unit test";
2188 info->description =
2189 "Test that creating a stream topology map works";
2190 return AST_TEST_NOT_RUN;
2191 case TEST_EXECUTE:
2192 break;
2193 }
2194
2195 ast_test_validate(test, AST_VECTOR_INIT(&types, 5) == 0);
2196
2197 /* Map a first topology and check that it mapped one to one */
2198 ast_test_validate_cleanup(test, (t0 = ast_stream_topology_alloc()), res, done);
2201
2202 ast_stream_topology_map(t0, &types, &v0, &v1);
2203 ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&types) == 2, res, done);
2204 ast_test_validate_cleanup(test, AST_VECTOR_GET(&types, 0) == AST_MEDIA_TYPE_AUDIO, res, done);
2205 ast_test_validate_cleanup(test, AST_VECTOR_GET(&types, 1) == AST_MEDIA_TYPE_VIDEO, res, done);
2206 ast_test_validate_cleanup(test, AST_VECTOR_GET(&v0, 0) == 0, res, done);
2207 ast_test_validate_cleanup(test, AST_VECTOR_GET(&v0, 1) == 1, res, done);
2208 ast_test_validate_cleanup(test, AST_VECTOR_GET(&v1, 0) == 0, res, done);
2209 ast_test_validate_cleanup(test, AST_VECTOR_GET(&v1, 1) == 1, res, done);
2210
2211 /* Map a second topology and check that it merged */
2213 ast_test_validate_cleanup(test, (t0 = ast_stream_topology_alloc()), res, done);
2216
2217 ast_stream_topology_map(t0, &types, &v0, &v1);
2218 ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&types) == 2, res, done);
2219 ast_test_validate_cleanup(test, AST_VECTOR_GET(&types, 0) == AST_MEDIA_TYPE_AUDIO, res, done);
2220 ast_test_validate_cleanup(test, AST_VECTOR_GET(&types, 1) == AST_MEDIA_TYPE_VIDEO, res, done);
2221 ast_test_validate_cleanup(test, AST_VECTOR_GET(&v0, 0) == 1, res, done);
2222 ast_test_validate_cleanup(test, AST_VECTOR_GET(&v0, 1) == 0, res, done);
2223 ast_test_validate_cleanup(test, AST_VECTOR_GET(&v1, 0) == 1, res, done);
2224 ast_test_validate_cleanup(test, AST_VECTOR_GET(&v1, 1) == 0, res, done);
2225
2226 /* Map a third topology with more streams and check that it merged */
2228 ast_test_validate_cleanup(test, (t0 = ast_stream_topology_alloc()), res, done);
2232
2233 ast_stream_topology_map(t0, &types, &v0, &v1);
2234 ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&types) == 3, res, done);
2235 ast_test_validate_cleanup(test, AST_VECTOR_GET(&types, 0) == AST_MEDIA_TYPE_AUDIO, res, done);
2236 ast_test_validate_cleanup(test, AST_VECTOR_GET(&types, 1) == AST_MEDIA_TYPE_VIDEO, res, done);
2237 ast_test_validate_cleanup(test, AST_VECTOR_GET(&types, 2) == AST_MEDIA_TYPE_AUDIO, res, done);
2238 ast_test_validate_cleanup(test, AST_VECTOR_GET(&v0, 0) == 1, res, done);
2239 ast_test_validate_cleanup(test, AST_VECTOR_GET(&v0, 1) == 0, res, done);
2240 ast_test_validate_cleanup(test, AST_VECTOR_GET(&v0, 2) == 2, res, done);
2241 ast_test_validate_cleanup(test, AST_VECTOR_GET(&v1, 0) == 1, res, done);
2242 ast_test_validate_cleanup(test, AST_VECTOR_GET(&v1, 1) == 0, res, done);
2243 ast_test_validate_cleanup(test, AST_VECTOR_GET(&v1, 2) == 2, res, done);
2244
2245done:
2246 AST_VECTOR_FREE(&v1);
2247 AST_VECTOR_FREE(&v0);
2248 AST_VECTOR_FREE(&types);
2249
2250 return res;
2251}
2252
2253static int unload_module(void)
2254{
2255 AST_TEST_UNREGISTER(stream_create);
2256 AST_TEST_UNREGISTER(stream_create_no_name);
2257 AST_TEST_UNREGISTER(stream_set_type);
2258 AST_TEST_UNREGISTER(stream_set_formats);
2259 AST_TEST_UNREGISTER(stream_set_state);
2260 AST_TEST_UNREGISTER(stream_metadata);
2261 AST_TEST_UNREGISTER(stream_topology_create);
2262 AST_TEST_UNREGISTER(stream_topology_clone);
2263 AST_TEST_UNREGISTER(stream_topology_clone);
2264 AST_TEST_UNREGISTER(stream_topology_append_stream);
2265 AST_TEST_UNREGISTER(stream_topology_set_stream);
2266 AST_TEST_UNREGISTER(stream_topology_del_stream);
2267 AST_TEST_UNREGISTER(stream_topology_create_from_format_cap);
2268 AST_TEST_UNREGISTER(stream_topology_get_first_stream_by_type);
2269 AST_TEST_UNREGISTER(stream_topology_create_from_channel_nativeformats);
2270 AST_TEST_UNREGISTER(stream_topology_channel_set);
2271 AST_TEST_UNREGISTER(stream_write_non_multistream);
2272 AST_TEST_UNREGISTER(stream_write_multistream);
2273 AST_TEST_UNREGISTER(stream_read_non_multistream);
2274 AST_TEST_UNREGISTER(stream_read_multistream);
2275 AST_TEST_UNREGISTER(stream_topology_change_request_from_application_non_multistream);
2276 AST_TEST_UNREGISTER(stream_topology_change_request_from_channel_non_multistream);
2277 AST_TEST_UNREGISTER(stream_topology_change_request_from_application);
2278 AST_TEST_UNREGISTER(stream_topology_change_request_from_channel);
2279 AST_TEST_UNREGISTER(format_cap_from_stream_topology);
2280 AST_TEST_UNREGISTER(stream_topology_map_create);
2281 return 0;
2282}
2283
2284static int load_module(void)
2285{
2286 AST_TEST_REGISTER(stream_create);
2287 AST_TEST_REGISTER(stream_create_no_name);
2288 AST_TEST_REGISTER(stream_set_type);
2289 AST_TEST_REGISTER(stream_set_formats);
2290 AST_TEST_REGISTER(stream_set_state);
2291 AST_TEST_REGISTER(stream_metadata);
2292 AST_TEST_REGISTER(stream_topology_create);
2293 AST_TEST_REGISTER(stream_topology_clone);
2294 AST_TEST_REGISTER(stream_topology_append_stream);
2295 AST_TEST_REGISTER(stream_topology_set_stream);
2296 AST_TEST_REGISTER(stream_topology_del_stream);
2297 AST_TEST_REGISTER(stream_topology_create_from_format_cap);
2298 AST_TEST_REGISTER(stream_topology_get_first_stream_by_type);
2299 AST_TEST_REGISTER(stream_topology_create_from_channel_nativeformats);
2300 AST_TEST_REGISTER(stream_topology_channel_set);
2301 AST_TEST_REGISTER(stream_write_non_multistream);
2302 AST_TEST_REGISTER(stream_write_multistream);
2303 AST_TEST_REGISTER(stream_read_non_multistream);
2304 AST_TEST_REGISTER(stream_read_multistream);
2305 AST_TEST_REGISTER(stream_topology_change_request_from_application_non_multistream);
2306 AST_TEST_REGISTER(stream_topology_change_request_from_channel_non_multistream);
2307 AST_TEST_REGISTER(stream_topology_change_request_from_application);
2308 AST_TEST_REGISTER(stream_topology_change_request_from_channel);
2309 AST_TEST_REGISTER(format_cap_from_stream_topology);
2310 AST_TEST_REGISTER(stream_topology_map_create);
2312}
2313
2314AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Media Stream API test module");
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
static const char type[]
Definition: chan_ooh323.c:109
General Asterisk PBX channel definitions.
int ast_channel_request_stream_topology_change(struct ast_channel *chan, struct ast_stream_topology *topology, void *change_source)
Request that the stream topology of a channel change.
Definition: channel.c:10966
struct ast_stream_topology * ast_channel_set_stream_topology(struct ast_channel *chan, struct ast_stream_topology *topology)
Set the topology of streams on a channel.
void * ast_channel_tech_pvt(const struct ast_channel *chan)
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1258
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
#define ast_channel_lock(chan)
Definition: channel.h:2922
int ast_channel_stream_topology_changed(struct ast_channel *chan, struct ast_stream_topology *topology)
Provide notice to a channel that the stream topology has changed.
Definition: channel.c:10996
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1139
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:5144
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4257
struct ast_frame * ast_read_stream(struct ast_channel *chan)
Reads a frame, but does not filter to just the default streams.
Definition: channel.c:4262
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
void ast_channel_fdno_set(struct ast_channel *chan, int value)
struct ast_readq_list * ast_channel_readq(struct ast_channel *chan)
int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame *frame)
Write a frame to a stream This function writes the given frame to the indicated stream on the channel...
Definition: channel.c:5149
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
#define ast_channel_unlock(chan)
Definition: channel.h:2923
@ AST_STATE_DOWN
Definition: channelstate.h:36
ast_media_type
Types of media.
Definition: codec.h:30
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
@ AST_MEDIA_TYPE_UNKNOWN
Definition: codec.h:31
@ AST_MEDIA_TYPE_VIDEO
Definition: codec.h:33
@ AST_MEDIA_TYPE_END
Definition: codec.h:36
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:348
char * end
Definition: eagi_proxy.c:73
Media Format API.
Media Format Cache API.
struct ast_format * ast_format_h264
Built-in cached h264 format.
Definition: format_cache.c:176
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
Format Capabilities API.
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:324
void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Remove all formats matching a specific format type.
Definition: format_cap.c:523
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:734
int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
Determine if two capabilities structures are identical.
Definition: format_cap.c:687
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
#define ast_frdup(fr)
Copies a frame.
#define ast_frfree(fr)
@ AST_FRAME_VIDEO
@ AST_FRAME_NULL
@ AST_FRAME_VOICE
@ AST_FRAME_CONTROL
@ AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE
@ AST_CONTROL_STREAM_TOPOLOGY_CHANGED
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
def info(msg)
static int frames
Definition: parser.c:51
#define NULL
Definition: resample.c:96
Media Stream API.
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
Definition: stream.c:650
struct ast_stream * ast_stream_alloc(const char *name, enum ast_media_type type)
Create a new media stream representation.
Definition: stream.c:233
int ast_stream_topology_set_stream(struct ast_stream_topology *topology, unsigned int position, struct ast_stream *stream)
Set a specific position in a topology.
Definition: stream.c:796
const char * ast_stream_get_metadata(const struct ast_stream *stream, const char *m_key)
Get a stream metadata value.
Definition: stream.c:423
const char * ast_stream_get_name(const struct ast_stream *stream)
Get the name of a stream.
Definition: stream.c:309
int ast_stream_set_metadata(struct ast_stream *stream, const char *m_key, const char *value)
Set a stream metadata value.
Definition: stream.c:460
@ AST_STREAM_STATE_INACTIVE
Set when the stream is not sending OR receiving media.
Definition: stream.h:94
@ AST_STREAM_STATE_REMOVED
Set when the stream has been removed/declined.
Definition: stream.h:78
@ AST_STREAM_STATE_SENDRECV
Set when the stream is sending and receiving media.
Definition: stream.h:82
int ast_stream_get_position(const struct ast_stream *stream)
Get the position of the stream in the topology.
Definition: stream.c:500
void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
Set the state of a stream.
Definition: stream.c:380
int ast_stream_topology_append_stream(struct ast_stream_topology *topology, struct ast_stream *stream)
Append a stream to the topology.
Definition: stream.c:748
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
int ast_stream_topology_del_stream(struct ast_stream_topology *topology, unsigned int position)
Delete a specified stream from the given topology.
Definition: stream.c:825
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
Set the current negotiated formats of a stream.
Definition: stream.c:365
void ast_stream_set_type(struct ast_stream *stream, enum ast_media_type type)
Change the media type of a stream.
Definition: stream.c:323
struct ast_stream_topology * ast_stream_topology_create_from_format_cap(struct ast_format_cap *cap)
A helper function that, given a format capabilities structure, creates a topology and separates the m...
Definition: stream.c:848
struct ast_format_cap * ast_stream_topology_get_formats(struct ast_stream_topology *topology)
Create a format capabilities structure representing the topology.
Definition: stream.c:930
void ast_stream_free(struct ast_stream *stream)
Destroy a media stream representation.
Definition: stream.c:292
void ast_stream_topology_map(const struct ast_stream_topology *topology, struct ast_vector_int *types, struct ast_vector_int *v0, struct ast_vector_int *v1)
Map a given topology's streams to the given types.
Definition: stream.c:985
const struct ast_format_cap * ast_stream_get_formats(const struct ast_stream *stream)
Get the current negotiated formats of a stream.
Definition: stream.c:330
struct ast_stream_topology * ast_stream_topology_clone(const struct ast_stream_topology *topology)
Create a deep clone of an existing stream topology.
Definition: stream.c:667
struct ast_stream * ast_stream_topology_get_first_stream_by_type(const struct ast_stream_topology *topology, enum ast_media_type type)
Gets the first active stream of a specific type from the topology.
Definition: stream.c:964
#define ast_str_alloca(init_len)
Definition: strings.h:848
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition: channel.h:628
int(*const write)(struct ast_channel *chan, struct ast_frame *frame)
Write a frame, in standard format (see frame.h)
Definition: channel.h:750
struct ast_frame *(*const read)(struct ast_channel *chan)
Read a frame (or chain of frames from the same stream), in standard format (see frame....
Definition: channel.h:734
struct ast_frame *(*const read_stream)(struct ast_channel *chan)
Read a frame (or chain of frames from the same stream), in standard format (see frame....
Definition: channel.h:747
Main Channel structure associated with a channel.
const struct ast_channel_tech * tech
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@226 data
enum ast_frame_type frametype
struct ast_frame * next
struct ast_frame::@227 frame_list
Support for dynamic strings.
Definition: strings.h:623
unsigned int position
The position of the stream in the topology.
Definition: stream.c:90
Integer vector definition.
Definition: vector.h:52
unsigned int wrote_stream
Definition: test_stream.c:1099
unsigned int indicated_changed
Definition: test_stream.c:1106
unsigned int indicated_change_request
Definition: test_stream.c:1105
unsigned int wrote
Definition: test_stream.c:1098
Test Framework API.
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
ast_test_result_state
Definition: test.h:193
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
int done
Definition: test_amihooks.c:48
static int mock_channel_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame *fr)
Definition: test_stream.c:1167
static enum ast_test_result_state read_test(struct ast_test *test, struct ast_channel_tech *tech, enum CHANNEL_READ_TYPE rt, int streams, int frames, int frames_per_read, int expected_nulls)
Definition: test_stream.c:1716
static const struct ast_channel_tech mock_stream_channel_tech
Definition: test_stream.c:1177
static struct ast_frame * mock_channel_read(struct ast_channel *chan)
Definition: test_stream.c:1109
static int mock_channel_write(struct ast_channel *chan, struct ast_frame *fr)
Definition: test_stream.c:1145
static int mock_channel_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Definition: test_stream.c:1154
static int load_stream_readqueue(struct ast_channel *chan, int frames)
Definition: test_stream.c:1623
static const struct ast_channel_tech mock_channel_write_stream_tech
Definition: test_stream.c:1335
#define topology_append_stream(topology, name, type, res, label)
Definition: test_stream.c:2162
static struct ast_frame * read_from_chan(enum CHANNEL_READ_TYPE rt, struct ast_channel *chan)
Definition: test_stream.c:1707
static struct ast_channel * make_channel(struct ast_test *test, int streams, struct ast_channel_tech *tech)
Definition: test_stream.c:1650
CHANNEL_READ_TYPE
Definition: test_stream.c:1702
@ CHANNEL_READ_STREAM
Definition: test_stream.c:1704
@ CHANNEL_READ
Definition: test_stream.c:1703
AST_TEST_DEFINE(stream_create)
Definition: test_stream.c:43
static const struct ast_channel_tech mock_channel_tech
Definition: test_stream.c:988
static int load_module(void)
Definition: test_stream.c:2284
static int mock_channel_hangup(struct ast_channel *chan)
Definition: test_stream.c:1227
static int unload_module(void)
Definition: test_stream.c:2253
static const struct ast_channel_tech mock_channel_old_write_tech
Definition: test_stream.c:1239
static int check_stream_positions(struct ast_test *test, const struct ast_stream_topology *topology)
Definition: test_stream.c:650
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
Universally unique identifier support.
#define AST_UUID_STR_LEN
Definition: uuid.h:27
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
Definition: uuid.c:141
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680