channel: Add support for writing to a specific stream.
[asterisk/asterisk.git] / tests / test_stream.c
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"
39 #include "asterisk/format_cache.h"
40 #include "asterisk/channel.h"
41
42 AST_TEST_DEFINE(stream_create)
43 {
44         RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
45
46         switch (cmd) {
47         case TEST_INIT:
48                 info->name = "stream_create";
49                 info->category = "/main/stream/";
50                 info->summary = "stream create unit test";
51                 info->description =
52                         "Test that creating a stream results in a stream with the expected values";
53                 return AST_TEST_NOT_RUN;
54         case TEST_EXECUTE:
55                 break;
56         }
57
58         stream = ast_stream_alloc("test", AST_MEDIA_TYPE_AUDIO);
59         if (!stream) {
60                 ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
61                 return AST_TEST_FAIL;
62         }
63
64         if (ast_stream_get_state(stream) != AST_STREAM_STATE_INACTIVE) {
65                 ast_test_status_update(test, "Newly created stream does not have expected inactive stream state\n");
66                 return AST_TEST_FAIL;
67         }
68
69         if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO) {
70                 ast_test_status_update(test, "Newly created stream does not have expected audio media type\n");
71                 return AST_TEST_FAIL;
72         }
73
74         if (strcmp(ast_stream_get_name(stream), "test")) {
75                 ast_test_status_update(test, "Newly created stream does not have expected name of test\n");
76                 return AST_TEST_FAIL;
77         }
78
79         return AST_TEST_PASS;
80 }
81
82 AST_TEST_DEFINE(stream_create_no_name)
83 {
84         RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
85
86         switch (cmd) {
87         case TEST_INIT:
88                 info->name = "stream_create_no_name";
89                 info->category = "/main/stream/";
90                 info->summary = "stream create (without a name) unit test";
91                 info->description =
92                         "Test that creating a stream with no name works";
93                 return AST_TEST_NOT_RUN;
94         case TEST_EXECUTE:
95                 break;
96         }
97
98         stream = ast_stream_alloc(NULL, AST_MEDIA_TYPE_AUDIO);
99         if (!stream) {
100                 ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
101                 return AST_TEST_FAIL;
102         }
103
104         return AST_TEST_PASS;
105 }
106
107 AST_TEST_DEFINE(stream_set_type)
108 {
109         RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
110
111         switch (cmd) {
112         case TEST_INIT:
113                 info->name = "stream_set_type";
114                 info->category = "/main/stream/";
115                 info->summary = "stream type setting unit test";
116                 info->description =
117                         "Test that changing the type of a stream works";
118                 return AST_TEST_NOT_RUN;
119         case TEST_EXECUTE:
120                 break;
121         }
122
123         stream = ast_stream_alloc("test", AST_MEDIA_TYPE_AUDIO);
124         if (!stream) {
125                 ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
126                 return AST_TEST_FAIL;
127         }
128
129         if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO) {
130                 ast_test_status_update(test, "Newly created stream does not have expected audio media type\n");
131                 return AST_TEST_FAIL;
132         }
133
134         ast_stream_set_type(stream, AST_MEDIA_TYPE_VIDEO);
135
136         if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_VIDEO) {
137                 ast_test_status_update(test, "Changed stream does not have expected video media type\n");
138                 return AST_TEST_FAIL;
139         }
140
141         return AST_TEST_PASS;
142 }
143
144 AST_TEST_DEFINE(stream_set_formats)
145 {
146         RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
147         RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
148
149         switch (cmd) {
150         case TEST_INIT:
151                 info->name = "stream_set_formats";
152                 info->category = "/main/stream/";
153                 info->summary = "stream formats setting unit test";
154                 info->description =
155                         "Test that changing the formats of a stream works";
156                 return AST_TEST_NOT_RUN;
157         case TEST_EXECUTE:
158                 break;
159         }
160
161         caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
162         if (!caps) {
163                 ast_test_status_update(test, "Failed to create a format capabilities structure for testing\n");
164                 return AST_TEST_FAIL;
165         }
166
167         stream = ast_stream_alloc("test", AST_MEDIA_TYPE_AUDIO);
168         if (!stream) {
169                 ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
170                 return AST_TEST_FAIL;
171         }
172
173         ast_stream_set_formats(stream, caps);
174
175         if (ast_stream_get_formats(stream) != caps) {
176                 ast_test_status_update(test, "Changed stream does not have expected formats\n");
177                 return AST_TEST_FAIL;
178         }
179
180         ast_stream_set_formats(stream, NULL);
181
182         if (ast_stream_get_formats(stream)) {
183                 ast_test_status_update(test, "Retrieved formats from stream despite removing them\n");
184                 return AST_TEST_FAIL;
185         }
186
187         return AST_TEST_PASS;
188 }
189
190 AST_TEST_DEFINE(stream_set_state)
191 {
192         RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
193
194         switch (cmd) {
195         case TEST_INIT:
196                 info->name = "stream_set_state";
197                 info->category = "/main/stream/";
198                 info->summary = "stream state setting unit test";
199                 info->description =
200                         "Test that changing the state of a stream works";
201                 return AST_TEST_NOT_RUN;
202         case TEST_EXECUTE:
203                 break;
204         }
205
206         stream = ast_stream_alloc("test", AST_MEDIA_TYPE_AUDIO);
207         if (!stream) {
208                 ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
209                 return AST_TEST_FAIL;
210         }
211
212         if (ast_stream_get_state(stream) != AST_STREAM_STATE_INACTIVE) {
213                 ast_test_status_update(test, "Newly created stream does not have expected inactive stream state\n");
214                 return AST_TEST_FAIL;
215         }
216
217         ast_stream_set_state(stream, AST_STREAM_STATE_SENDRECV);
218
219         if (ast_stream_get_state(stream) != AST_STREAM_STATE_SENDRECV) {
220                 ast_test_status_update(test, "Changed stream does not have expected sendrecv state\n");
221                 return AST_TEST_FAIL;
222         }
223
224         return AST_TEST_PASS;
225 }
226
227 AST_TEST_DEFINE(stream_topology_create)
228 {
229         RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);
230
231         switch (cmd) {
232         case TEST_INIT:
233                 info->name = "stream_topology_create";
234                 info->category = "/main/stream/";
235                 info->summary = "stream topology creation unit test";
236                 info->description =
237                         "Test that creating a stream topology works";
238                 return AST_TEST_NOT_RUN;
239         case TEST_EXECUTE:
240                 break;
241         }
242
243         topology = ast_stream_topology_alloc();
244         if (!topology) {
245                 ast_test_status_update(test, "Failed to create media stream topology\n");
246                 return AST_TEST_FAIL;
247         }
248
249         return AST_TEST_PASS;
250 }
251
252 AST_TEST_DEFINE(stream_topology_clone)
253 {
254         RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);
255         RAII_VAR(struct ast_stream_topology *, cloned, NULL, ast_stream_topology_free);
256         struct ast_stream *audio_stream, *video_stream;
257
258         switch (cmd) {
259         case TEST_INIT:
260                 info->name = "stream_topology_clone";
261                 info->category = "/main/stream/";
262                 info->summary = "stream topology cloning unit test";
263                 info->description =
264                         "Test that cloning a stream topology results in a clone with the same contents";
265                 return AST_TEST_NOT_RUN;
266         case TEST_EXECUTE:
267                 break;
268         }
269
270         topology = ast_stream_topology_alloc();
271         if (!topology) {
272                 ast_test_status_update(test, "Failed to create media stream topology\n");
273                 return AST_TEST_FAIL;
274         }
275
276         audio_stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
277         if (!audio_stream) {
278                 ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
279                 return AST_TEST_FAIL;
280         }
281
282         if (ast_stream_topology_append_stream(topology, audio_stream) == -1) {
283                 ast_test_status_update(test, "Failed to append valid audio stream to stream topology\n");
284                 ast_stream_free(audio_stream);
285                 return AST_TEST_FAIL;
286         }
287
288         video_stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
289         if (!video_stream) {
290                 ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
291                 return AST_TEST_FAIL;
292         }
293
294         if (ast_stream_topology_append_stream(topology, video_stream) == -1) {
295                 ast_test_status_update(test, "Failed to append valid video stream to stream topology\n");
296                 ast_stream_free(video_stream);
297                 return AST_TEST_FAIL;
298         }
299
300         cloned = ast_stream_topology_clone(topology);
301         if (!cloned) {
302                 ast_test_status_update(test, "Failed to clone a perfectly good stream topology\n");
303                 return AST_TEST_FAIL;
304         }
305
306         if (ast_stream_topology_get_count(cloned) != ast_stream_topology_get_count(topology)) {
307                 ast_test_status_update(test, "Cloned stream topology does not contain same number of streams as original\n");
308                 return AST_TEST_FAIL;
309         }
310
311         if (ast_stream_get_type(ast_stream_topology_get_stream(cloned, 0)) != ast_stream_get_type(ast_stream_topology_get_stream(topology, 0))) {
312                 ast_test_status_update(test, "Cloned audio stream does not contain same type as original\n");
313                 return AST_TEST_FAIL;
314         }
315
316         if (ast_stream_get_type(ast_stream_topology_get_stream(cloned, 1)) != ast_stream_get_type(ast_stream_topology_get_stream(topology, 1))) {
317                 ast_test_status_update(test, "Cloned video stream does not contain same type as original\n");
318                 return AST_TEST_FAIL;
319         }
320
321         return AST_TEST_PASS;
322 }
323
324 AST_TEST_DEFINE(stream_topology_append_stream)
325 {
326         RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);
327         struct ast_stream *audio_stream, *video_stream;
328         int position;
329
330         switch (cmd) {
331         case TEST_INIT:
332                 info->name = "stream_topology_append_stream";
333                 info->category = "/main/stream/";
334                 info->summary = "stream topology stream appending unit test";
335                 info->description =
336                         "Test that appending streams to a stream topology works";
337                 return AST_TEST_NOT_RUN;
338         case TEST_EXECUTE:
339                 break;
340         }
341
342         topology = ast_stream_topology_alloc();
343         if (!topology) {
344                 ast_test_status_update(test, "Failed to create media stream topology\n");
345                 return AST_TEST_FAIL;
346         }
347
348         audio_stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
349         if (!audio_stream) {
350                 ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
351                 return AST_TEST_FAIL;
352         }
353
354         position = ast_stream_topology_append_stream(topology, audio_stream);
355         if (position == -1) {
356                 ast_test_status_update(test, "Failed to append valid audio stream to stream topology\n");
357                 ast_stream_free(audio_stream);
358                 return AST_TEST_FAIL;
359         } else if (position != 0) {
360                 ast_test_status_update(test, "Appended audio stream to stream topology but position is '%d' instead of 0\n",
361                         position);
362                 return AST_TEST_FAIL;
363         }
364
365         if (ast_stream_topology_get_count(topology) != 1) {
366                 ast_test_status_update(test, "Appended an audio stream to the stream topology but stream count is '%d' on it, not 1\n",
367                         ast_stream_topology_get_count(topology));
368                 return AST_TEST_FAIL;
369         }
370
371         if (ast_stream_topology_get_stream(topology, 0) != audio_stream) {
372                 ast_test_status_update(test, "Appended an audio stream to the stream topology but returned stream doesn't match\n");
373                 return AST_TEST_FAIL;
374         }
375
376         if (ast_stream_get_position(audio_stream) != 0) {
377                 ast_test_status_update(test, "Appended audio stream says it is at position '%d' instead of 0\n",
378                         ast_stream_get_position(audio_stream));
379                 return AST_TEST_FAIL;
380         }
381
382         video_stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
383         if (!video_stream) {
384                 ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
385                 return AST_TEST_FAIL;
386         }
387
388         position = ast_stream_topology_append_stream(topology, video_stream);
389         if (position == -1) {
390                 ast_test_status_update(test, "Failed to append valid video stream to stream topology\n");
391                 ast_stream_free(video_stream);
392                 return AST_TEST_FAIL;
393         } else if (position != 1) {
394                 ast_test_status_update(test, "Appended video stream to stream topology but position is '%d' instead of 1\n",
395                         position);
396                 return AST_TEST_FAIL;
397         }
398
399         if (ast_stream_topology_get_count(topology) != 2) {
400                 ast_test_status_update(test, "Appended a video stream to the stream topology but stream count is '%d' on it, not 2\n",
401                         ast_stream_topology_get_count(topology));
402                 return AST_TEST_FAIL;
403         }
404
405         if (ast_stream_topology_get_stream(topology, 1) != video_stream) {
406                 ast_test_status_update(test, "Appended a video stream to the stream topology but returned stream doesn't match\n");
407                 return AST_TEST_FAIL;
408         }
409
410         if (ast_stream_get_position(video_stream) != 1) {
411                 ast_test_status_update(test, "Appended video stream says it is at position '%d' instead of 1\n",
412                         ast_stream_get_position(video_stream));
413                 return AST_TEST_FAIL;
414         }
415
416         return AST_TEST_PASS;
417 }
418
419 AST_TEST_DEFINE(stream_topology_set_stream)
420 {
421         RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);
422         struct ast_stream *audio_stream, *video_stream;
423
424         switch (cmd) {
425         case TEST_INIT:
426                 info->name = "stream_topology_set_stream";
427                 info->category = "/main/stream/";
428                 info->summary = "stream topology stream setting unit test";
429                 info->description =
430                         "Test that setting streams at a specific position in a topology works";
431                 return AST_TEST_NOT_RUN;
432         case TEST_EXECUTE:
433                 break;
434         }
435
436         topology = ast_stream_topology_alloc();
437         if (!topology) {
438                 ast_test_status_update(test, "Failed to create media stream topology\n");
439                 return AST_TEST_FAIL;
440         }
441
442         audio_stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
443         if (!audio_stream) {
444                 ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
445                 return AST_TEST_FAIL;
446         }
447
448         if (ast_stream_topology_set_stream(topology, 0, audio_stream)) {
449                 ast_test_status_update(test, "Failed to set an audio stream to a position where it is permitted\n");
450                 ast_stream_free(audio_stream);
451                 return AST_TEST_FAIL;
452         }
453
454         if (ast_stream_topology_get_count(topology) != 1) {
455                 ast_test_status_update(test, "Set an audio stream on the stream topology but stream count is '%d' on it, not 1\n",
456                         ast_stream_topology_get_count(topology));
457                 return AST_TEST_FAIL;
458         }
459
460         if (ast_stream_topology_get_stream(topology, 0) != audio_stream) {
461                 ast_test_status_update(test, "Set an audio stream on the stream topology but returned stream doesn't match\n");
462                 return AST_TEST_FAIL;
463         }
464
465         if (ast_stream_get_position(audio_stream) != 0) {
466                 ast_test_status_update(test, "Set audio stream says it is at position '%d' instead of 0\n",
467                         ast_stream_get_position(audio_stream));
468                 return AST_TEST_FAIL;
469         }
470
471         video_stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
472         if (!video_stream) {
473                 ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
474                 return AST_TEST_FAIL;
475         }
476
477         if (ast_stream_topology_set_stream(topology, 0, video_stream)) {
478                 ast_test_status_update(test, "Failed to set a video stream to a position where it is permitted\n");
479                 ast_stream_free(video_stream);
480                 return AST_TEST_FAIL;
481         }
482
483         if (ast_stream_topology_get_count(topology) != 1) {
484                 ast_test_status_update(test, "Set a video stream on the stream topology but stream count is '%d' on it, not 1\n",
485                         ast_stream_topology_get_count(topology));
486                 return AST_TEST_FAIL;
487         }
488
489         if (ast_stream_topology_get_stream(topology, 0) != video_stream) {
490                 ast_test_status_update(test, "Set a video stream on the stream topology but returned stream doesn't match\n");
491                 return AST_TEST_FAIL;
492         }
493
494         if (ast_stream_get_position(video_stream) != 0) {
495                 ast_test_status_update(test, "Set video stream says it is at position '%d' instead of 0\n",
496                         ast_stream_get_position(video_stream));
497                 return AST_TEST_FAIL;
498         }
499
500         audio_stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
501         if (!audio_stream) {
502                 ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
503                 return AST_TEST_FAIL;
504         }
505
506         if (ast_stream_topology_set_stream(topology, 1, audio_stream)) {
507                 ast_test_status_update(test, "Failed to set an audio stream to a position where it is permitted\n");
508                 ast_stream_free(audio_stream);
509                 return AST_TEST_FAIL;
510         }
511
512         if (ast_stream_topology_get_count(topology) != 2) {
513                 ast_test_status_update(test, "Set an audio stream on the stream topology but stream count is '%d' on it, not 2\n",
514                         ast_stream_topology_get_count(topology));
515                 return AST_TEST_FAIL;
516         }
517
518         if (ast_stream_topology_get_stream(topology, 1) != audio_stream) {
519                 ast_test_status_update(test, "Set an audio stream on the stream topology but returned stream doesn't match\n");
520                 return AST_TEST_FAIL;
521         }
522
523         if (ast_stream_get_position(audio_stream) != 1) {
524                 ast_test_status_update(test, "Set audio stream says it is at position '%d' instead of 1\n",
525                         ast_stream_get_position(audio_stream));
526                 return AST_TEST_FAIL;
527         }
528
529         return AST_TEST_PASS;
530 }
531
532 AST_TEST_DEFINE(stream_topology_create_from_format_cap)
533 {
534         RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);
535         RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
536
537         switch (cmd) {
538         case TEST_INIT:
539                 info->name = "stream_topology_create_from_format_cap";
540                 info->category = "/main/stream/";
541                 info->summary = "stream topology creation from format capabilities unit test";
542                 info->description =
543                         "Test that creating a stream topology from format capabilities results in the expected streams";
544                 return AST_TEST_NOT_RUN;
545         case TEST_EXECUTE:
546                 break;
547         }
548
549         caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
550         if (!caps) {
551                 ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
552                 return AST_TEST_FAIL;
553         }
554
555         if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
556                 ast_test_status_update(test, "Failed to append a ulaw format to capabilities for stream topology creation\n");
557                 return AST_TEST_FAIL;
558         }
559
560         if (ast_format_cap_append(caps, ast_format_alaw, 0)) {
561                 ast_test_status_update(test, "Failed to append an alaw format to capabilities for stream topology creation\n");
562                 return AST_TEST_FAIL;
563         }
564
565         topology = ast_stream_topology_create_from_format_cap(caps);
566         if (!topology) {
567                 ast_test_status_update(test, "Failed to create a stream topology using a perfectly good format capabilities\n");
568                 return AST_TEST_FAIL;
569         }
570
571         if (ast_stream_topology_get_count(topology) != 1) {
572                 ast_test_status_update(test, "Expected a stream topology with 1 stream but it has %d streams\n",
573                         ast_stream_topology_get_count(topology));
574                 return AST_TEST_FAIL;
575         }
576
577         if (ast_stream_get_type(ast_stream_topology_get_stream(topology, 0)) != AST_MEDIA_TYPE_AUDIO) {
578                 ast_test_status_update(test, "Produced stream topology has a single stream of type %s instead of audio\n",
579                         ast_codec_media_type2str(ast_stream_get_type(ast_stream_topology_get_stream(topology, 0))));
580                 return AST_TEST_FAIL;
581         }
582
583         ast_stream_topology_free(topology);
584         topology = NULL;
585
586         ast_format_cap_append(caps, ast_format_h264, 0);
587
588         topology = ast_stream_topology_create_from_format_cap(caps);
589         if (!topology) {
590                 ast_test_status_update(test, "Failed to create a stream topology using a perfectly good format capabilities\n");
591                 return AST_TEST_FAIL;
592         }
593
594         if (ast_stream_topology_get_count(topology) != 2) {
595                 ast_test_status_update(test, "Expected a stream topology with 2 streams but it has %d streams\n",
596                         ast_stream_topology_get_count(topology));
597                 return AST_TEST_FAIL;
598         }
599
600         if (ast_stream_get_type(ast_stream_topology_get_stream(topology, 0)) != AST_MEDIA_TYPE_AUDIO) {
601                 ast_test_status_update(test, "Produced stream topology has a first stream of type %s instead of audio\n",
602                         ast_codec_media_type2str(ast_stream_get_type(ast_stream_topology_get_stream(topology, 0))));
603                 return AST_TEST_FAIL;
604         }
605
606         if (ast_stream_get_type(ast_stream_topology_get_stream(topology, 1)) != AST_MEDIA_TYPE_VIDEO) {
607                 ast_test_status_update(test, "Produced stream topology has a second stream of type %s instead of video\n",
608                         ast_codec_media_type2str(ast_stream_get_type(ast_stream_topology_get_stream(topology, 1))));
609                 return AST_TEST_FAIL;
610         }
611
612         return AST_TEST_PASS;
613 }
614
615 AST_TEST_DEFINE(stream_topology_get_first_stream_by_type)
616 {
617         RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);
618         struct ast_stream *first_stream, *second_stream, *third_stream, *fourth_stream;
619
620         switch (cmd) {
621         case TEST_INIT:
622                 info->name = "stream_topology_get_first_stream_by_type";
623                 info->category = "/main/stream/";
624                 info->summary = "stream topology getting first stream by type unit test";
625                 info->description =
626                         "Test that getting the first stream by type from a topology actually returns the first stream";
627                 return AST_TEST_NOT_RUN;
628         case TEST_EXECUTE:
629                 break;
630         }
631
632         topology = ast_stream_topology_alloc();
633         if (!topology) {
634                 ast_test_status_update(test, "Failed to create media stream topology\n");
635                 return AST_TEST_FAIL;
636         }
637
638         first_stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
639         if (!first_stream) {
640                 ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
641                 return AST_TEST_FAIL;
642         }
643
644         if (ast_stream_topology_append_stream(topology, first_stream) == -1) {
645                 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
646                 ast_stream_free(first_stream);
647                 return AST_TEST_FAIL;
648         }
649
650         second_stream = ast_stream_alloc("audio2", AST_MEDIA_TYPE_AUDIO);
651         if (!second_stream) {
652                 ast_test_status_update(test, "Failed to create a second audio stream for testing stream topology\n");
653                 return AST_TEST_FAIL;
654         }
655
656         if (ast_stream_topology_append_stream(topology, second_stream) == -1) {
657                 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
658                 ast_stream_free(second_stream);
659                 return AST_TEST_FAIL;
660         }
661
662         third_stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
663         if (!third_stream) {
664                 ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
665                 return AST_TEST_FAIL;
666         }
667
668         if (ast_stream_topology_append_stream(topology, third_stream) == -1) {
669                 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
670                 ast_stream_free(third_stream);
671                 return AST_TEST_FAIL;
672         }
673
674         fourth_stream = ast_stream_alloc("video2", AST_MEDIA_TYPE_VIDEO);
675         if (!fourth_stream) {
676                 ast_test_status_update(test, "Failed to create a second video stream for testing stream topology\n");
677                 return AST_TEST_FAIL;
678         }
679
680         if (ast_stream_topology_append_stream(topology, fourth_stream) == -1) {
681                 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
682                 ast_stream_free(fourth_stream);
683                 return AST_TEST_FAIL;
684         }
685
686         if (ast_stream_topology_get_first_stream_by_type(topology, AST_MEDIA_TYPE_AUDIO) != first_stream) {
687                 ast_test_status_update(test, "Retrieved first audio stream from topology but it is not the correct one\n");
688                 return AST_TEST_FAIL;
689         }
690
691         if (ast_stream_topology_get_first_stream_by_type(topology, AST_MEDIA_TYPE_VIDEO) != third_stream) {
692                 ast_test_status_update(test, "Retrieved first video stream from topology but it is not the correct one\n");
693                 return AST_TEST_FAIL;
694         }
695
696         return AST_TEST_PASS;
697 }
698
699 static const struct ast_channel_tech mock_channel_tech = {
700 };
701
702 AST_TEST_DEFINE(stream_topology_create_from_channel_nativeformats)
703 {
704         RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);
705         RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
706         struct ast_channel *mock_channel;
707         enum ast_test_result_state res = AST_TEST_FAIL;
708         struct ast_str *codec_have_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
709         struct ast_str *codec_wanted_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
710
711         switch (cmd) {
712         case TEST_INIT:
713                 info->name = "stream_topology_create_from_channel_nativeformats";
714                 info->category = "/main/stream/";
715                 info->summary = "stream topology creation from channel native formats unit test";
716                 info->description =
717                         "Test that creating a stream topology from the setting of channel nativeformats results in the expected streams";
718                 return AST_TEST_NOT_RUN;
719         case TEST_EXECUTE:
720                 break;
721         }
722
723         caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
724         if (!caps) {
725                 ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
726                 return AST_TEST_FAIL;
727         }
728
729         if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
730                 ast_test_status_update(test, "Failed to append a ulaw format to capabilities for channel nativeformats\n");
731                 return AST_TEST_FAIL;
732         }
733
734         if (ast_format_cap_append(caps, ast_format_alaw, 0)) {
735                 ast_test_status_update(test, "Failed to append an alaw format to capabilities for channel nativeformats\n");
736                 return AST_TEST_FAIL;
737         }
738
739         if (ast_format_cap_append(caps, ast_format_h264, 0)) {
740                 ast_test_status_update(test, "Failed to append an h264 format to capabilities for channel nativeformats\n");
741                 return AST_TEST_FAIL;
742         }
743
744         mock_channel = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "TestChannel");
745         if (!mock_channel) {
746                 ast_test_status_update(test, "Failed to create a mock channel for testing\n");
747                 return AST_TEST_FAIL;
748         }
749
750         ast_channel_tech_set(mock_channel, &mock_channel_tech);
751         ast_channel_nativeformats_set(mock_channel, caps);
752
753         if (!ast_channel_get_stream_topology(mock_channel)) {
754                 ast_test_status_update(test, "Set nativeformats with ulaw, alaw, and h264 on channel but it did not create a topology\n");
755                 goto end;
756         }
757
758         if (ast_stream_topology_get_count(ast_channel_get_stream_topology(mock_channel)) != 2) {
759                 ast_test_status_update(test, "Set nativeformats on a channel to ulaw, alaw, and h264 and received '%d' streams instead of expected 2\n",
760                         ast_stream_topology_get_count(ast_channel_get_stream_topology(mock_channel)));
761                 goto end;
762         }
763
764         if (ast_stream_get_type(ast_stream_topology_get_stream(ast_channel_get_stream_topology(mock_channel), 0)) != AST_MEDIA_TYPE_AUDIO) {
765                 ast_test_status_update(test, "First stream on channel is of %s when it should be audio\n",
766                         ast_codec_media_type2str(ast_stream_get_type(ast_stream_topology_get_stream(ast_channel_get_stream_topology(mock_channel), 0))));
767                 goto end;
768         }
769
770         ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_VIDEO);
771         if (!ast_format_cap_identical(ast_stream_get_formats(ast_stream_topology_get_stream(ast_channel_get_stream_topology(mock_channel), 0)), caps)) {
772                 ast_test_status_update(test, "Formats on audio stream of channel are '%s' when they should be '%s'\n",
773                         ast_format_cap_get_names(ast_stream_get_formats(ast_stream_topology_get_stream(ast_channel_get_stream_topology(mock_channel), 0)), &codec_have_buf),
774                         ast_format_cap_get_names(caps, &codec_wanted_buf));
775                 goto end;
776         }
777
778         if (ast_stream_get_type(ast_stream_topology_get_stream(ast_channel_get_stream_topology(mock_channel), 1)) != AST_MEDIA_TYPE_VIDEO) {
779                 ast_test_status_update(test, "Second stream on channel is of type %s when it should be video\n",
780                         ast_codec_media_type2str(ast_stream_get_type(ast_stream_topology_get_stream(ast_channel_get_stream_topology(mock_channel), 1))));
781                 goto end;
782         }
783
784         ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_AUDIO);
785
786         if (ast_format_cap_append(caps, ast_format_h264, 0)) {
787                 ast_test_status_update(test, "Failed to append h264 video codec to capabilities for capabilities comparison\n");
788                 goto end;
789         }
790
791         if (!ast_format_cap_identical(ast_stream_get_formats(ast_stream_topology_get_stream(ast_channel_get_stream_topology(mock_channel), 1)), caps)) {
792                 ast_test_status_update(test, "Formats on video stream of channel are '%s' when they should be '%s'\n",
793                         ast_format_cap_get_names(ast_stream_get_formats(ast_stream_topology_get_stream(ast_channel_get_stream_topology(mock_channel), 1)), &codec_wanted_buf),
794                         ast_format_cap_get_names(caps, &codec_wanted_buf));
795                 goto end;
796         }
797
798         res = AST_TEST_PASS;
799
800 end:
801         ast_channel_unlock(mock_channel);
802         ast_hangup(mock_channel);
803
804         return res;
805 }
806
807 static const struct ast_channel_tech mock_stream_channel_tech = {
808         .properties = AST_CHAN_TP_MULTISTREAM,
809 };
810
811 AST_TEST_DEFINE(stream_topology_channel_set)
812 {
813         RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);
814         struct ast_channel *mock_channel;
815         enum ast_test_result_state res = AST_TEST_PASS;
816
817         switch (cmd) {
818         case TEST_INIT:
819                 info->name = "stream_topology_channel_set";
820                 info->category = "/main/stream/";
821                 info->summary = "stream topology setting on a channel unit test";
822                 info->description =
823                         "Test that setting a stream topology on a channel works";
824                 return AST_TEST_NOT_RUN;
825         case TEST_EXECUTE:
826                 break;
827         }
828
829         topology = ast_stream_topology_alloc();
830         if (!topology) {
831                 ast_test_status_update(test, "Failed to create media stream topology\n");
832                 return AST_TEST_FAIL;
833         }
834
835         mock_channel = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "TestChannel");
836         if (!mock_channel) {
837                 ast_test_status_update(test, "Failed to create a mock channel for testing\n");
838                 return AST_TEST_FAIL;
839         }
840
841         ast_channel_tech_set(mock_channel, &mock_stream_channel_tech);
842         ast_channel_set_stream_topology(mock_channel, topology);
843
844         if (ast_channel_get_stream_topology(mock_channel) != topology) {
845                 ast_test_status_update(test, "Set an explicit stream topology on a channel but the returned one did not match it\n");
846                 res = AST_TEST_FAIL;
847         }
848
849         topology = NULL;
850         ast_channel_unlock(mock_channel);
851         ast_hangup(mock_channel);
852
853         return res;
854 }
855
856 struct mock_channel_pvt {
857         unsigned int wrote;
858         unsigned int wrote_stream;
859         int stream_num;
860 };
861
862 static int mock_channel_write(struct ast_channel *chan, struct ast_frame *fr)
863 {
864         struct mock_channel_pvt *pvt = ast_channel_tech_pvt(chan);
865
866         pvt->wrote = 1;
867
868         return 0;
869 }
870
871 static int mock_channel_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame *fr)
872 {
873         struct mock_channel_pvt *pvt = ast_channel_tech_pvt(chan);
874
875         pvt->wrote_stream = 1;
876         pvt->stream_num = stream_num;
877
878         return 0;
879 }
880
881 static int mock_channel_hangup(struct ast_channel *chan)
882 {
883         ast_channel_tech_pvt_set(chan, NULL);
884         return 0;
885 }
886
887 static const struct ast_channel_tech mock_channel_old_write_tech = {
888         .write = mock_channel_write,
889         .write_video = mock_channel_write,
890         .hangup = mock_channel_hangup,
891 };
892
893 AST_TEST_DEFINE(stream_write_non_multistream)
894 {
895         RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
896         struct ast_channel *mock_channel;
897         struct mock_channel_pvt pvt;
898         enum ast_test_result_state res = AST_TEST_FAIL;
899         struct ast_frame frame = { 0, };
900
901         switch (cmd) {
902         case TEST_INIT:
903                 info->name = "stream_write_non_multistream";
904                 info->category = "/main/stream/";
905                 info->summary = "stream writing to non-multistream capable channel test";
906                 info->description =
907                         "Test that writing frames to a non-multistream channel works as expected";
908                 return AST_TEST_NOT_RUN;
909         case TEST_EXECUTE:
910                 break;
911         }
912
913         caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
914         if (!caps) {
915                 ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
916                 return AST_TEST_FAIL;
917         }
918
919         if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
920                 ast_test_status_update(test, "Failed to append a ulaw format to capabilities for channel nativeformats\n");
921                 return AST_TEST_FAIL;
922         }
923
924         if (ast_format_cap_append(caps, ast_format_h264, 0)) {
925                 ast_test_status_update(test, "Failed to append an h264 format to capabilities for channel nativeformats\n");
926                 return AST_TEST_FAIL;
927         }
928
929         mock_channel = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "TestChannel");
930         if (!mock_channel) {
931                 ast_test_status_update(test, "Failed to create a mock channel for testing\n");
932                 return AST_TEST_FAIL;
933         }
934
935         ast_channel_tech_set(mock_channel, &mock_channel_old_write_tech);
936         ast_channel_nativeformats_set(mock_channel, caps);
937
938         pvt.wrote = 0;
939         ast_channel_tech_pvt_set(mock_channel, &pvt);
940         ast_channel_unlock(mock_channel);
941
942         frame.frametype = AST_FRAME_VOICE;
943         frame.subclass.format = ast_format_ulaw;
944
945         if (ast_write(mock_channel, &frame)) {
946                 ast_test_status_update(test, "Failed to write a ulaw frame to the mock channel when it should be fine\n");
947                 goto end;
948         }
949
950         if (!pvt.wrote) {
951                 ast_test_status_update(test, "Successfully wrote a frame of ulaw but it never reached the channel driver\n");
952                 goto end;
953         }
954
955         pvt.wrote = 0;
956
957         if (!ast_write_stream(mock_channel, 2, &frame) || pvt.wrote) {
958                 ast_test_status_update(test, "Successfully wrote a frame of ulaw to a non-existent stream\n");
959                 goto end;
960         }
961
962         frame.frametype = AST_FRAME_VIDEO;
963         frame.subclass.format = ast_format_h264;
964
965         if (ast_write(mock_channel, &frame)) {
966                 ast_test_status_update(test, "Failed to write an h264 frame to the mock channel when it should be fine\n");
967                 goto end;
968         }
969
970         if (!pvt.wrote) {
971                 ast_test_status_update(test, "Successfully wrote a frame of h264 but it never reached the channel driver\n");
972                 goto end;
973         }
974
975         res = AST_TEST_PASS;
976
977 end:
978         ast_hangup(mock_channel);
979
980         return res;
981 }
982
983 static const struct ast_channel_tech mock_channel_write_stream_tech = {
984         .properties = AST_CHAN_TP_MULTISTREAM,
985         .write = mock_channel_write,
986         .write_video = mock_channel_write,
987         .write_stream = mock_channel_write_stream,
988         .hangup = mock_channel_hangup,
989 };
990
991 AST_TEST_DEFINE(stream_write_multistream)
992 {
993         RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
994         RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);
995         struct ast_stream *stream;
996         struct ast_channel *mock_channel;
997         struct mock_channel_pvt pvt = { 0, };
998         enum ast_test_result_state res = AST_TEST_FAIL;
999         struct ast_frame frame = { 0, };
1000
1001         switch (cmd) {
1002         case TEST_INIT:
1003                 info->name = "stream_write_multistream";
1004                 info->category = "/main/stream/";
1005                 info->summary = "stream writing to multistream capable channel test";
1006                 info->description =
1007                         "Test that writing frames to a multistream channel works as expected";
1008                 return AST_TEST_NOT_RUN;
1009         case TEST_EXECUTE:
1010                 break;
1011         }
1012
1013         topology = ast_stream_topology_alloc();
1014         if (!topology) {
1015                 ast_test_status_update(test, "Failed to create media stream topology\n");
1016                 return AST_TEST_FAIL;
1017         }
1018
1019         stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
1020         if (!stream) {
1021                 ast_test_status_update(test, "Failed to create an audio stream for testing multistream writing\n");
1022                 return AST_TEST_FAIL;
1023         }
1024
1025         if (ast_stream_topology_append_stream(topology, stream) == -1) {
1026                 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
1027                 ast_stream_free(stream);
1028                 return AST_TEST_FAIL;
1029         }
1030
1031         stream = ast_stream_alloc("audio2", AST_MEDIA_TYPE_AUDIO);
1032         if (!stream) {
1033                 ast_test_status_update(test, "Failed to create an audio stream for testing multistream writing\n");
1034                 return AST_TEST_FAIL;
1035         }
1036
1037         if (ast_stream_topology_append_stream(topology, stream) == -1) {
1038                 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
1039                 ast_stream_free(stream);
1040                 return AST_TEST_FAIL;
1041         }
1042
1043         stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
1044         if (!stream) {
1045                 ast_test_status_update(test, "Failed to create a video stream for testing multistream writing\n");
1046                 return AST_TEST_FAIL;
1047         }
1048
1049         if (ast_stream_topology_append_stream(topology, stream) == -1) {
1050                 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
1051                 ast_stream_free(stream);
1052                 return AST_TEST_FAIL;
1053         }
1054
1055         stream = ast_stream_alloc("video2", AST_MEDIA_TYPE_VIDEO);
1056         if (!stream) {
1057                 ast_test_status_update(test, "Failed to create a video stream for testing multistream writing\n");
1058                 return AST_TEST_FAIL;
1059         }
1060
1061         if (ast_stream_topology_append_stream(topology, stream) == -1) {
1062                 ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
1063                 ast_stream_free(stream);
1064                 return AST_TEST_FAIL;
1065         }
1066
1067         caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
1068         if (!caps) {
1069                 ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
1070                 return AST_TEST_FAIL;
1071         }
1072
1073         if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
1074                 ast_test_status_update(test, "Failed to append a ulaw format to capabilities for channel nativeformats\n");
1075                 return AST_TEST_FAIL;
1076         }
1077
1078         if (ast_format_cap_append(caps, ast_format_h264, 0)) {
1079                 ast_test_status_update(test, "Failed to append an h264 format to capabilities for channel nativeformats\n");
1080                 return AST_TEST_FAIL;
1081         }
1082
1083         mock_channel = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "TestChannel");
1084         if (!mock_channel) {
1085                 ast_test_status_update(test, "Failed to create a mock channel for testing\n");
1086                 return AST_TEST_FAIL;
1087         }
1088
1089         ast_channel_tech_set(mock_channel, &mock_channel_write_stream_tech);
1090         ast_channel_set_stream_topology(mock_channel, topology);
1091         ast_channel_nativeformats_set(mock_channel, caps);
1092         topology = NULL;
1093
1094         ast_channel_tech_pvt_set(mock_channel, &pvt);
1095         ast_channel_unlock(mock_channel);
1096
1097         frame.frametype = AST_FRAME_VOICE;
1098         frame.subclass.format = ast_format_ulaw;
1099         pvt.stream_num = -1;
1100
1101         if (ast_write(mock_channel, &frame)) {
1102                 ast_test_status_update(test, "Failed to write a ulaw frame to the mock channel when it should be fine\n");
1103                 goto end;
1104         }
1105
1106         if (pvt.wrote) {
1107                 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");
1108                 goto end;
1109         }
1110
1111         if (!pvt.wrote_stream) {
1112                 ast_test_status_update(test, "Successfully wrote a frame of ulaw but it never reached the channel driver\n");
1113                 goto end;
1114         }
1115
1116         if (pvt.stream_num != 0) {
1117                 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",
1118                         pvt.stream_num);
1119                 goto end;
1120         }
1121
1122         pvt.wrote_stream = 0;
1123         pvt.stream_num = -1;
1124
1125         if (ast_write_stream(mock_channel, 0, &frame)) {
1126                 ast_test_status_update(test, "Failed to write a ulaw frame to the first audio stream\n");
1127                 goto end;
1128         }
1129
1130         if (pvt.wrote) {
1131                 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");
1132                 goto end;
1133         }
1134
1135         if (!pvt.wrote_stream) {
1136                 ast_test_status_update(test, "Successfully wrote a frame of ulaw to the first audio stream but it never reached the channel driver\n");
1137                 goto end;
1138         }
1139
1140         if (pvt.stream_num != 0) {
1141                 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",
1142                         pvt.stream_num);
1143                 goto end;
1144         }
1145
1146         pvt.wrote_stream = 0;
1147         pvt.stream_num = -1;
1148
1149         if (ast_write_stream(mock_channel, 1, &frame)) {
1150                 ast_test_status_update(test, "Failed to write a ulaw frame to the second audio stream\n");
1151                 goto end;
1152         }
1153
1154         if (pvt.wrote) {
1155                 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");
1156                 goto end;
1157         }
1158
1159         if (!pvt.wrote_stream) {
1160                 ast_test_status_update(test, "Successfully wrote a frame of ulaw to the second audio stream but it never reached the channel driver\n");
1161                 goto end;
1162         }
1163
1164         if (pvt.stream_num != 1) {
1165                 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",
1166                         pvt.stream_num);
1167                 goto end;
1168         }
1169
1170         pvt.wrote_stream = 0;
1171         pvt.stream_num = -1;
1172
1173         frame.frametype = AST_FRAME_VIDEO;
1174         frame.subclass.format = ast_format_h264;
1175
1176         if (ast_write(mock_channel, &frame)) {
1177                 ast_test_status_update(test, "Failed to write an h264 frame to the mock channel when it should be fine\n");
1178                 goto end;
1179         }
1180
1181         if (pvt.wrote) {
1182                 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");
1183                 goto end;
1184         }
1185
1186         if (!pvt.wrote_stream) {
1187                 ast_test_status_update(test, "Successfully wrote a frame of h264 but it never reached the channel driver\n");
1188                 goto end;
1189         }
1190
1191         if (pvt.stream_num != 2) {
1192                 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",
1193                         pvt.stream_num);
1194                 goto end;
1195         }
1196
1197         pvt.wrote_stream = 0;
1198         pvt.stream_num = -1;
1199
1200         if (ast_write_stream(mock_channel, 2, &frame)) {
1201                 ast_test_status_update(test, "Failed to write an h264 frame to the first video stream\n");
1202                 goto end;
1203         }
1204
1205         if (pvt.wrote) {
1206                 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");
1207                 goto end;
1208         }
1209
1210         if (!pvt.wrote_stream) {
1211                 ast_test_status_update(test, "Successfully wrote a frame of h264 to the first video stream but it never reached the channel driver\n");
1212                 goto end;
1213         }
1214
1215         if (pvt.stream_num != 2) {
1216                 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",
1217                         pvt.stream_num);
1218                 goto end;
1219         }
1220
1221         pvt.wrote_stream = 0;
1222         pvt.stream_num = -1;
1223
1224         if (ast_write_stream(mock_channel, 3, &frame)) {
1225                 ast_test_status_update(test, "Failed to write an h264 frame to the second video stream\n");
1226                 goto end;
1227         }
1228
1229         if (pvt.wrote) {
1230                 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");
1231                 goto end;
1232         }
1233
1234         if (!pvt.wrote_stream) {
1235                 ast_test_status_update(test, "Successfully wrote a frame of h264 to the second video stream but it never reached the channel driver\n");
1236                 goto end;
1237         }
1238
1239         if (pvt.stream_num != 3) {
1240                 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",
1241                         pvt.stream_num);
1242                 goto end;
1243         }
1244
1245         pvt.wrote_stream = 0;
1246         pvt.stream_num = -1;
1247
1248         if (!ast_write_stream(mock_channel, 9, &frame)) {
1249                 ast_test_status_update(test, "Successfully wrote a frame of h264 to a non-existent stream\n");
1250                 goto end;
1251         }
1252
1253         if (pvt.wrote) {
1254                 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");
1255                 goto end;
1256         }
1257
1258         if (pvt.wrote_stream) {
1259                 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");
1260                 goto end;
1261         }
1262
1263         res = AST_TEST_PASS;
1264
1265 end:
1266         ast_hangup(mock_channel);
1267
1268         return res;
1269 }
1270
1271 static int unload_module(void)
1272 {
1273         AST_TEST_UNREGISTER(stream_create);
1274         AST_TEST_UNREGISTER(stream_create_no_name);
1275         AST_TEST_UNREGISTER(stream_set_type);
1276         AST_TEST_UNREGISTER(stream_set_formats);
1277         AST_TEST_UNREGISTER(stream_set_state);
1278         AST_TEST_UNREGISTER(stream_topology_create);
1279         AST_TEST_UNREGISTER(stream_topology_clone);
1280         AST_TEST_UNREGISTER(stream_topology_clone);
1281         AST_TEST_UNREGISTER(stream_topology_append_stream);
1282         AST_TEST_UNREGISTER(stream_topology_set_stream);
1283         AST_TEST_UNREGISTER(stream_topology_create_from_format_cap);
1284         AST_TEST_UNREGISTER(stream_topology_get_first_stream_by_type);
1285         AST_TEST_UNREGISTER(stream_topology_create_from_channel_nativeformats);
1286         AST_TEST_UNREGISTER(stream_topology_channel_set);
1287         AST_TEST_UNREGISTER(stream_write_non_multistream);
1288         AST_TEST_UNREGISTER(stream_write_multistream);
1289         return 0;
1290 }
1291
1292 static int load_module(void)
1293 {
1294         AST_TEST_REGISTER(stream_create);
1295         AST_TEST_REGISTER(stream_create_no_name);
1296         AST_TEST_REGISTER(stream_set_type);
1297         AST_TEST_REGISTER(stream_set_formats);
1298         AST_TEST_REGISTER(stream_set_state);
1299         AST_TEST_REGISTER(stream_topology_create);
1300         AST_TEST_REGISTER(stream_topology_clone);
1301         AST_TEST_REGISTER(stream_topology_append_stream);
1302         AST_TEST_REGISTER(stream_topology_set_stream);
1303         AST_TEST_REGISTER(stream_topology_create_from_format_cap);
1304         AST_TEST_REGISTER(stream_topology_get_first_stream_by_type);
1305         AST_TEST_REGISTER(stream_topology_create_from_channel_nativeformats);
1306         AST_TEST_REGISTER(stream_topology_channel_set);
1307         AST_TEST_REGISTER(stream_write_non_multistream);
1308         AST_TEST_REGISTER(stream_write_multistream);
1309         return AST_MODULE_LOAD_SUCCESS;
1310 }
1311
1312 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Media Stream API test module");