2017-02-07 12:56:41 +00:00
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2017, Digium, Inc.
*
* Joshua Colp <jcolp@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*!
* \file
* \brief Media Stream API Unit Tests
*
* \author Joshua Colp <jcolp@digium.com>
*
*/
/*** MODULEINFO
<depend>TEST_FRAMEWORK</depend>
<support_level>core</support_level>
***/
#include "asterisk.h"
#include "asterisk/test.h"
#include "asterisk/module.h"
#include "asterisk/stream.h"
#include "asterisk/format.h"
#include "asterisk/format_cap.h"
2017-02-13 17:00:42 +00:00
#include "asterisk/format_cache.h"
2017-02-14 18:33:57 +00:00
#include "asterisk/channel.h"
2017-02-07 12:56:41 +00:00
AST_TEST_DEFINE ( stream_create )
{
2017-02-16 07:28:33 -07:00
RAII_VAR ( struct ast_stream * , stream , NULL , ast_stream_free );
2017-02-07 12:56:41 +00:00
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_create" ;
info -> category = "/main/stream/" ;
info -> summary = "stream create unit test" ;
info -> description =
"Test that creating a stream results in a stream with the expected values" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
2017-02-16 07:28:33 -07:00
stream = ast_stream_alloc ( "test" , AST_MEDIA_TYPE_AUDIO );
2017-02-07 12:56:41 +00:00
if ( ! stream ) {
ast_test_status_update ( test , "Failed to create media stream given proper arguments \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_get_state ( stream ) != AST_STREAM_STATE_INACTIVE ) {
ast_test_status_update ( test , "Newly created stream does not have expected inactive stream state \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_get_type ( stream ) != AST_MEDIA_TYPE_AUDIO ) {
ast_test_status_update ( test , "Newly created stream does not have expected audio media type \n " );
return AST_TEST_FAIL ;
}
if ( strcmp ( ast_stream_get_name ( stream ), "test" )) {
ast_test_status_update ( test , "Newly created stream does not have expected name of test \n " );
return AST_TEST_FAIL ;
}
return AST_TEST_PASS ;
}
AST_TEST_DEFINE ( stream_create_no_name )
{
2017-02-16 07:28:33 -07:00
RAII_VAR ( struct ast_stream * , stream , NULL , ast_stream_free );
2017-02-07 12:56:41 +00:00
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_create_no_name" ;
info -> category = "/main/stream/" ;
info -> summary = "stream create (without a name) unit test" ;
info -> description =
"Test that creating a stream with no name works" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
2017-02-16 07:28:33 -07:00
stream = ast_stream_alloc ( NULL , AST_MEDIA_TYPE_AUDIO );
2017-02-07 12:56:41 +00:00
if ( ! stream ) {
ast_test_status_update ( test , "Failed to create media stream given proper arguments \n " );
return AST_TEST_FAIL ;
}
return AST_TEST_PASS ;
}
AST_TEST_DEFINE ( stream_set_type )
{
2017-02-16 07:28:33 -07:00
RAII_VAR ( struct ast_stream * , stream , NULL , ast_stream_free );
2017-02-07 12:56:41 +00:00
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_set_type" ;
info -> category = "/main/stream/" ;
info -> summary = "stream type setting unit test" ;
info -> description =
"Test that changing the type of a stream works" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
2017-02-16 07:28:33 -07:00
stream = ast_stream_alloc ( "test" , AST_MEDIA_TYPE_AUDIO );
2017-02-07 12:56:41 +00:00
if ( ! stream ) {
ast_test_status_update ( test , "Failed to create media stream given proper arguments \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_get_type ( stream ) != AST_MEDIA_TYPE_AUDIO ) {
ast_test_status_update ( test , "Newly created stream does not have expected audio media type \n " );
return AST_TEST_FAIL ;
}
ast_stream_set_type ( stream , AST_MEDIA_TYPE_VIDEO );
if ( ast_stream_get_type ( stream ) != AST_MEDIA_TYPE_VIDEO ) {
ast_test_status_update ( test , "Changed stream does not have expected video media type \n " );
return AST_TEST_FAIL ;
}
return AST_TEST_PASS ;
}
AST_TEST_DEFINE ( stream_set_formats )
{
2017-02-16 07:28:33 -07:00
RAII_VAR ( struct ast_stream * , stream , NULL , ast_stream_free );
2017-02-07 12:56:41 +00:00
RAII_VAR ( struct ast_format_cap * , caps , NULL , ao2_cleanup );
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_set_formats" ;
info -> category = "/main/stream/" ;
info -> summary = "stream formats setting unit test" ;
info -> description =
"Test that changing the formats of a stream works" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
caps = ast_format_cap_alloc ( AST_FORMAT_CAP_FLAG_DEFAULT );
if ( ! caps ) {
ast_test_status_update ( test , "Failed to create a format capabilities structure for testing \n " );
return AST_TEST_FAIL ;
}
2017-02-16 07:28:33 -07:00
stream = ast_stream_alloc ( "test" , AST_MEDIA_TYPE_AUDIO );
2017-02-07 12:56:41 +00:00
if ( ! stream ) {
ast_test_status_update ( test , "Failed to create media stream given proper arguments \n " );
return AST_TEST_FAIL ;
}
ast_stream_set_formats ( stream , caps );
if ( ast_stream_get_formats ( stream ) != caps ) {
ast_test_status_update ( test , "Changed stream does not have expected formats \n " );
return AST_TEST_FAIL ;
}
ast_stream_set_formats ( stream , NULL );
if ( ast_stream_get_formats ( stream )) {
ast_test_status_update ( test , "Retrieved formats from stream despite removing them \n " );
return AST_TEST_FAIL ;
}
return AST_TEST_PASS ;
}
AST_TEST_DEFINE ( stream_set_state )
{
2017-02-16 07:28:33 -07:00
RAII_VAR ( struct ast_stream * , stream , NULL , ast_stream_free );
2017-02-07 12:56:41 +00:00
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_set_state" ;
info -> category = "/main/stream/" ;
info -> summary = "stream state setting unit test" ;
info -> description =
"Test that changing the state of a stream works" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
2017-02-16 07:28:33 -07:00
stream = ast_stream_alloc ( "test" , AST_MEDIA_TYPE_AUDIO );
2017-02-07 12:56:41 +00:00
if ( ! stream ) {
ast_test_status_update ( test , "Failed to create media stream given proper arguments \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_get_state ( stream ) != AST_STREAM_STATE_INACTIVE ) {
ast_test_status_update ( test , "Newly created stream does not have expected inactive stream state \n " );
return AST_TEST_FAIL ;
}
ast_stream_set_state ( stream , AST_STREAM_STATE_SENDRECV );
if ( ast_stream_get_state ( stream ) != AST_STREAM_STATE_SENDRECV ) {
ast_test_status_update ( test , "Changed stream does not have expected sendrecv state \n " );
return AST_TEST_FAIL ;
}
return AST_TEST_PASS ;
}
2017-02-13 17:00:42 +00:00
AST_TEST_DEFINE ( stream_topology_create )
{
2017-02-16 07:28:33 -07:00
RAII_VAR ( struct ast_stream_topology * , topology , NULL , ast_stream_topology_free );
2017-02-13 17:00:42 +00:00
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_topology_create" ;
info -> category = "/main/stream/" ;
info -> summary = "stream topology creation unit test" ;
info -> description =
"Test that creating a stream topology works" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
2017-02-16 07:28:33 -07:00
topology = ast_stream_topology_alloc ();
2017-02-13 17:00:42 +00:00
if ( ! topology ) {
ast_test_status_update ( test , "Failed to create media stream topology \n " );
return AST_TEST_FAIL ;
}
return AST_TEST_PASS ;
}
AST_TEST_DEFINE ( stream_topology_clone )
{
2017-02-16 07:28:33 -07:00
RAII_VAR ( struct ast_stream_topology * , topology , NULL , ast_stream_topology_free );
RAII_VAR ( struct ast_stream_topology * , cloned , NULL , ast_stream_topology_free );
2017-02-13 17:00:42 +00:00
struct ast_stream * audio_stream , * video_stream ;
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_topology_clone" ;
info -> category = "/main/stream/" ;
info -> summary = "stream topology cloning unit test" ;
info -> description =
"Test that cloning a stream topology results in a clone with the same contents" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
2017-02-16 07:28:33 -07:00
topology = ast_stream_topology_alloc ();
2017-02-13 17:00:42 +00:00
if ( ! topology ) {
ast_test_status_update ( test , "Failed to create media stream topology \n " );
return AST_TEST_FAIL ;
}
2017-02-16 07:28:33 -07:00
audio_stream = ast_stream_alloc ( "audio" , AST_MEDIA_TYPE_AUDIO );
2017-02-13 17:00:42 +00:00
if ( ! audio_stream ) {
ast_test_status_update ( test , "Failed to create an audio stream for testing stream topology \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_append_stream ( topology , audio_stream ) == - 1 ) {
ast_test_status_update ( test , "Failed to append valid audio stream to stream topology \n " );
2017-02-16 07:28:33 -07:00
ast_stream_free ( audio_stream );
2017-02-13 17:00:42 +00:00
return AST_TEST_FAIL ;
}
2017-02-16 07:28:33 -07:00
video_stream = ast_stream_alloc ( "video" , AST_MEDIA_TYPE_VIDEO );
2017-02-13 17:00:42 +00:00
if ( ! video_stream ) {
ast_test_status_update ( test , "Failed to create a video stream for testing stream topology \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_append_stream ( topology , video_stream ) == - 1 ) {
ast_test_status_update ( test , "Failed to append valid video stream to stream topology \n " );
2017-02-16 07:28:33 -07:00
ast_stream_free ( video_stream );
2017-02-13 17:00:42 +00:00
return AST_TEST_FAIL ;
}
cloned = ast_stream_topology_clone ( topology );
if ( ! cloned ) {
ast_test_status_update ( test , "Failed to clone a perfectly good stream topology \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_get_count ( cloned ) != ast_stream_topology_get_count ( topology )) {
ast_test_status_update ( test , "Cloned stream topology does not contain same number of streams as original \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_get_type ( ast_stream_topology_get_stream ( cloned , 0 )) != ast_stream_get_type ( ast_stream_topology_get_stream ( topology , 0 ))) {
ast_test_status_update ( test , "Cloned audio stream does not contain same type as original \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_get_type ( ast_stream_topology_get_stream ( cloned , 1 )) != ast_stream_get_type ( ast_stream_topology_get_stream ( topology , 1 ))) {
ast_test_status_update ( test , "Cloned video stream does not contain same type as original \n " );
return AST_TEST_FAIL ;
}
return AST_TEST_PASS ;
}
AST_TEST_DEFINE ( stream_topology_append_stream )
{
2017-02-16 07:28:33 -07:00
RAII_VAR ( struct ast_stream_topology * , topology , NULL , ast_stream_topology_free );
2017-02-13 17:00:42 +00:00
struct ast_stream * audio_stream , * video_stream ;
int position ;
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_topology_append_stream" ;
info -> category = "/main/stream/" ;
info -> summary = "stream topology stream appending unit test" ;
info -> description =
"Test that appending streams to a stream topology works" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
2017-02-16 07:28:33 -07:00
topology = ast_stream_topology_alloc ();
2017-02-13 17:00:42 +00:00
if ( ! topology ) {
ast_test_status_update ( test , "Failed to create media stream topology \n " );
return AST_TEST_FAIL ;
}
2017-02-16 07:28:33 -07:00
audio_stream = ast_stream_alloc ( "audio" , AST_MEDIA_TYPE_AUDIO );
2017-02-13 17:00:42 +00:00
if ( ! audio_stream ) {
ast_test_status_update ( test , "Failed to create an audio stream for testing stream topology \n " );
return AST_TEST_FAIL ;
}
position = ast_stream_topology_append_stream ( topology , audio_stream );
if ( position == - 1 ) {
ast_test_status_update ( test , "Failed to append valid audio stream to stream topology \n " );
2017-02-16 07:28:33 -07:00
ast_stream_free ( audio_stream );
2017-02-13 17:00:42 +00:00
return AST_TEST_FAIL ;
} else if ( position != 0 ) {
ast_test_status_update ( test , "Appended audio stream to stream topology but position is '%d' instead of 0 \n " ,
position );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_get_count ( topology ) != 1 ) {
ast_test_status_update ( test , "Appended an audio stream to the stream topology but stream count is '%d' on it, not 1 \n " ,
ast_stream_topology_get_count ( topology ));
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_get_stream ( topology , 0 ) != audio_stream ) {
ast_test_status_update ( test , "Appended an audio stream to the stream topology but returned stream doesn't match \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_get_position ( audio_stream ) != 0 ) {
ast_test_status_update ( test , "Appended audio stream says it is at position '%d' instead of 0 \n " ,
ast_stream_get_position ( audio_stream ));
return AST_TEST_FAIL ;
}
2017-02-16 07:28:33 -07:00
video_stream = ast_stream_alloc ( "video" , AST_MEDIA_TYPE_VIDEO );
2017-02-13 17:00:42 +00:00
if ( ! video_stream ) {
ast_test_status_update ( test , "Failed to create a video stream for testing stream topology \n " );
return AST_TEST_FAIL ;
}
position = ast_stream_topology_append_stream ( topology , video_stream );
if ( position == - 1 ) {
ast_test_status_update ( test , "Failed to append valid video stream to stream topology \n " );
2017-02-16 07:28:33 -07:00
ast_stream_free ( video_stream );
2017-02-13 17:00:42 +00:00
return AST_TEST_FAIL ;
} else if ( position != 1 ) {
ast_test_status_update ( test , "Appended video stream to stream topology but position is '%d' instead of 1 \n " ,
position );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_get_count ( topology ) != 2 ) {
ast_test_status_update ( test , "Appended a video stream to the stream topology but stream count is '%d' on it, not 2 \n " ,
ast_stream_topology_get_count ( topology ));
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_get_stream ( topology , 1 ) != video_stream ) {
ast_test_status_update ( test , "Appended a video stream to the stream topology but returned stream doesn't match \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_get_position ( video_stream ) != 1 ) {
ast_test_status_update ( test , "Appended video stream says it is at position '%d' instead of 1 \n " ,
ast_stream_get_position ( video_stream ));
return AST_TEST_FAIL ;
}
return AST_TEST_PASS ;
}
AST_TEST_DEFINE ( stream_topology_set_stream )
{
2017-02-16 07:28:33 -07:00
RAII_VAR ( struct ast_stream_topology * , topology , NULL , ast_stream_topology_free );
2017-02-13 17:00:42 +00:00
struct ast_stream * audio_stream , * video_stream ;
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_topology_set_stream" ;
info -> category = "/main/stream/" ;
info -> summary = "stream topology stream setting unit test" ;
info -> description =
"Test that setting streams at a specific position in a topology works" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
2017-02-16 07:28:33 -07:00
topology = ast_stream_topology_alloc ();
2017-02-13 17:00:42 +00:00
if ( ! topology ) {
ast_test_status_update ( test , "Failed to create media stream topology \n " );
return AST_TEST_FAIL ;
}
2017-02-16 07:28:33 -07:00
audio_stream = ast_stream_alloc ( "audio" , AST_MEDIA_TYPE_AUDIO );
2017-02-13 17:00:42 +00:00
if ( ! audio_stream ) {
ast_test_status_update ( test , "Failed to create an audio stream for testing stream topology \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_set_stream ( topology , 0 , audio_stream )) {
ast_test_status_update ( test , "Failed to set an audio stream to a position where it is permitted \n " );
2017-02-16 07:28:33 -07:00
ast_stream_free ( audio_stream );
2017-02-13 17:00:42 +00:00
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_get_count ( topology ) != 1 ) {
ast_test_status_update ( test , "Set an audio stream on the stream topology but stream count is '%d' on it, not 1 \n " ,
ast_stream_topology_get_count ( topology ));
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_get_stream ( topology , 0 ) != audio_stream ) {
ast_test_status_update ( test , "Set an audio stream on the stream topology but returned stream doesn't match \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_get_position ( audio_stream ) != 0 ) {
ast_test_status_update ( test , "Set audio stream says it is at position '%d' instead of 0 \n " ,
ast_stream_get_position ( audio_stream ));
return AST_TEST_FAIL ;
}
2017-02-16 07:28:33 -07:00
video_stream = ast_stream_alloc ( "video" , AST_MEDIA_TYPE_VIDEO );
2017-02-13 17:00:42 +00:00
if ( ! video_stream ) {
ast_test_status_update ( test , "Failed to create a video stream for testing stream topology \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_set_stream ( topology , 0 , video_stream )) {
ast_test_status_update ( test , "Failed to set a video stream to a position where it is permitted \n " );
2017-02-16 07:28:33 -07:00
ast_stream_free ( video_stream );
2017-02-13 17:00:42 +00:00
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_get_count ( topology ) != 1 ) {
ast_test_status_update ( test , "Set a video stream on the stream topology but stream count is '%d' on it, not 1 \n " ,
ast_stream_topology_get_count ( topology ));
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_get_stream ( topology , 0 ) != video_stream ) {
ast_test_status_update ( test , "Set a video stream on the stream topology but returned stream doesn't match \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_get_position ( video_stream ) != 0 ) {
ast_test_status_update ( test , "Set video stream says it is at position '%d' instead of 0 \n " ,
ast_stream_get_position ( video_stream ));
return AST_TEST_FAIL ;
}
2017-02-16 07:28:33 -07:00
audio_stream = ast_stream_alloc ( "audio" , AST_MEDIA_TYPE_AUDIO );
2017-02-13 17:00:42 +00:00
if ( ! audio_stream ) {
ast_test_status_update ( test , "Failed to create an audio stream for testing stream topology \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_set_stream ( topology , 1 , audio_stream )) {
ast_test_status_update ( test , "Failed to set an audio stream to a position where it is permitted \n " );
2017-02-16 07:28:33 -07:00
ast_stream_free ( audio_stream );
2017-02-13 17:00:42 +00:00
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_get_count ( topology ) != 2 ) {
ast_test_status_update ( test , "Set an audio stream on the stream topology but stream count is '%d' on it, not 2 \n " ,
ast_stream_topology_get_count ( topology ));
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_get_stream ( topology , 1 ) != audio_stream ) {
ast_test_status_update ( test , "Set an audio stream on the stream topology but returned stream doesn't match \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_get_position ( audio_stream ) != 1 ) {
ast_test_status_update ( test , "Set audio stream says it is at position '%d' instead of 1 \n " ,
ast_stream_get_position ( audio_stream ));
return AST_TEST_FAIL ;
}
return AST_TEST_PASS ;
}
2017-06-09 19:03:05 -05:00
static int check_stream_positions ( struct ast_test * test , const struct ast_stream_topology * topology )
{
const struct ast_stream * stream ;
int idx ;
int pos ;
enum ast_media_type type ;
for ( idx = 0 ; idx < ast_stream_topology_get_count ( topology ); ++ idx ) {
stream = ast_stream_topology_get_stream ( topology , idx );
pos = ast_stream_get_position ( stream );
if ( idx != pos ) {
type = ast_stream_get_type ( stream );
ast_test_status_update ( test , "Failed: '%s' stream says it is at position %d instead of %d \n " ,
ast_codec_media_type2str ( type ), pos , idx );
return - 1 ;
}
}
return 0 ;
}
AST_TEST_DEFINE ( stream_topology_del_stream )
{
RAII_VAR ( struct ast_stream_topology * , topology , NULL , ast_stream_topology_free );
struct ast_stream * stream ;
enum ast_media_type type ;
int idx ;
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_topology_del_stream" ;
info -> category = "/main/stream/" ;
info -> summary = "stream topology stream delete unit test" ;
info -> description =
"Test that deleting streams at a specific position in a topology works" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
topology = ast_stream_topology_alloc ();
if ( ! topology ) {
ast_test_status_update ( test , "Failed to create media stream topology \n " );
return AST_TEST_FAIL ;
}
/* Create streams */
for ( type = AST_MEDIA_TYPE_UNKNOWN ; type < AST_MEDIA_TYPE_END ; ++ type ) {
stream = ast_stream_alloc ( ast_codec_media_type2str ( type ), type );
if ( ! stream ) {
ast_test_status_update ( test , "Failed to create '%s' stream for testing stream topology \n " ,
ast_codec_media_type2str ( type ));
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_append_stream ( topology , stream ) == - 1 ) {
ast_test_status_update ( test , "Failed to append '%s' stream to topology \n " ,
ast_codec_media_type2str ( type ));
ast_stream_free ( stream );
return AST_TEST_FAIL ;
}
}
/* Check initial stream positions and types for sanity. */
type = AST_MEDIA_TYPE_UNKNOWN ;
for ( idx = 0 ; idx < ast_stream_topology_get_count ( topology ); ++ idx , ++ type ) {
stream = ast_stream_topology_get_stream ( topology , idx );
if ( type != ast_stream_get_type ( stream )) {
ast_test_status_update ( test , "Initial topology types failed: Expected:%s Got:%s \n " ,
ast_codec_media_type2str ( type ),
ast_codec_media_type2str ( ast_stream_get_type ( stream )));
return AST_TEST_FAIL ;
}
}
if ( check_stream_positions ( test , topology )) {
ast_test_status_update ( test , "Initial topology positions failed. \n " );
return AST_TEST_FAIL ;
}
/* Try to delete outside of topology size */
if ( ! ast_stream_topology_del_stream ( topology , ast_stream_topology_get_count ( topology ))) {
ast_test_status_update ( test , "Deleting stream outside of topology succeeded! \n " );
return AST_TEST_FAIL ;
}
/* Try to delete the last topology stream */
if ( ast_stream_topology_del_stream ( topology , ast_stream_topology_get_count ( topology ) - 1 )) {
ast_test_status_update ( test , "Failed deleting last stream of topology. \n " );
return AST_TEST_FAIL ;
}
if ( check_stream_positions ( test , topology )) {
ast_test_status_update ( test , "Last stream delete topology positions failed. \n " );
return AST_TEST_FAIL ;
}
stream = ast_stream_topology_get_stream ( topology , ast_stream_topology_get_count ( topology ) - 1 );
type = ast_stream_get_type ( stream );
if ( type != AST_MEDIA_TYPE_END - 2 ) {
ast_test_status_update ( test , "Last stream delete types failed: Expected:%s Got:%s \n " ,
ast_codec_media_type2str ( AST_MEDIA_TYPE_END - 2 ),
ast_codec_media_type2str ( type ));
return AST_TEST_FAIL ;
}
/* Try to delete the second stream in the topology */
if ( ast_stream_topology_del_stream ( topology , 1 )) {
ast_test_status_update ( test , "Failed deleting second stream in topology. \n " );
return AST_TEST_FAIL ;
}
if ( check_stream_positions ( test , topology )) {
ast_test_status_update ( test , "Second stream delete topology positions failed. \n " );
return AST_TEST_FAIL ;
}
stream = ast_stream_topology_get_stream ( topology , 1 );
type = ast_stream_get_type ( stream );
if ( type != AST_MEDIA_TYPE_UNKNOWN + 2 ) {
ast_test_status_update ( test , "Second stream delete types failed: Expected:%s Got:%s \n " ,
ast_codec_media_type2str ( AST_MEDIA_TYPE_UNKNOWN + 2 ),
ast_codec_media_type2str ( type ));
return AST_TEST_FAIL ;
}
/* Try to delete the first stream in the topology */
if ( ast_stream_topology_del_stream ( topology , 0 )) {
ast_test_status_update ( test , "Failed deleting first stream in topology. \n " );
return AST_TEST_FAIL ;
}
if ( check_stream_positions ( test , topology )) {
ast_test_status_update ( test , "First stream delete topology positions failed. \n " );
return AST_TEST_FAIL ;
}
stream = ast_stream_topology_get_stream ( topology , 0 );
type = ast_stream_get_type ( stream );
if ( type != AST_MEDIA_TYPE_UNKNOWN + 2 ) {
ast_test_status_update ( test , "First stream delete types failed: Expected:%s Got:%s \n " ,
ast_codec_media_type2str ( AST_MEDIA_TYPE_UNKNOWN + 2 ),
ast_codec_media_type2str ( type ));
return AST_TEST_FAIL ;
}
return AST_TEST_PASS ;
}
2017-02-13 17:00:42 +00:00
AST_TEST_DEFINE ( stream_topology_create_from_format_cap )
{
2017-02-16 07:28:33 -07:00
RAII_VAR ( struct ast_stream_topology * , topology , NULL , ast_stream_topology_free );
2017-02-13 17:00:42 +00:00
RAII_VAR ( struct ast_format_cap * , caps , NULL , ao2_cleanup );
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_topology_create_from_format_cap" ;
info -> category = "/main/stream/" ;
info -> summary = "stream topology creation from format capabilities unit test" ;
info -> description =
"Test that creating a stream topology from format capabilities results in the expected streams" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
caps = ast_format_cap_alloc ( AST_FORMAT_CAP_FLAG_DEFAULT );
if ( ! caps ) {
ast_test_status_update ( test , "Could not allocate an empty format capabilities structure \n " );
return AST_TEST_FAIL ;
}
if ( ast_format_cap_append ( caps , ast_format_ulaw , 0 )) {
ast_test_status_update ( test , "Failed to append a ulaw format to capabilities for stream topology creation \n " );
return AST_TEST_FAIL ;
}
if ( ast_format_cap_append ( caps , ast_format_alaw , 0 )) {
ast_test_status_update ( test , "Failed to append an alaw format to capabilities for stream topology creation \n " );
return AST_TEST_FAIL ;
}
topology = ast_stream_topology_create_from_format_cap ( caps );
if ( ! topology ) {
ast_test_status_update ( test , "Failed to create a stream topology using a perfectly good format capabilities \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_get_count ( topology ) != 1 ) {
ast_test_status_update ( test , "Expected a stream topology with 1 stream but it has %d streams \n " ,
ast_stream_topology_get_count ( topology ));
return AST_TEST_FAIL ;
}
if ( ast_stream_get_type ( ast_stream_topology_get_stream ( topology , 0 )) != AST_MEDIA_TYPE_AUDIO ) {
ast_test_status_update ( test , "Produced stream topology has a single stream of type %s instead of audio \n " ,
ast_codec_media_type2str ( ast_stream_get_type ( ast_stream_topology_get_stream ( topology , 0 ))));
return AST_TEST_FAIL ;
}
2017-02-16 07:28:33 -07:00
ast_stream_topology_free ( topology );
2017-02-13 17:00:42 +00:00
topology = NULL ;
ast_format_cap_append ( caps , ast_format_h264 , 0 );
topology = ast_stream_topology_create_from_format_cap ( caps );
if ( ! topology ) {
ast_test_status_update ( test , "Failed to create a stream topology using a perfectly good format capabilities \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_get_count ( topology ) != 2 ) {
ast_test_status_update ( test , "Expected a stream topology with 2 streams but it has %d streams \n " ,
ast_stream_topology_get_count ( topology ));
return AST_TEST_FAIL ;
}
if ( ast_stream_get_type ( ast_stream_topology_get_stream ( topology , 0 )) != AST_MEDIA_TYPE_AUDIO ) {
ast_test_status_update ( test , "Produced stream topology has a first stream of type %s instead of audio \n " ,
ast_codec_media_type2str ( ast_stream_get_type ( ast_stream_topology_get_stream ( topology , 0 ))));
return AST_TEST_FAIL ;
}
if ( ast_stream_get_type ( ast_stream_topology_get_stream ( topology , 1 )) != AST_MEDIA_TYPE_VIDEO ) {
ast_test_status_update ( test , "Produced stream topology has a second stream of type %s instead of video \n " ,
ast_codec_media_type2str ( ast_stream_get_type ( ast_stream_topology_get_stream ( topology , 1 ))));
return AST_TEST_FAIL ;
}
return AST_TEST_PASS ;
}
2017-02-14 18:33:57 +00:00
AST_TEST_DEFINE ( stream_topology_get_first_stream_by_type )
{
2017-02-16 07:28:33 -07:00
RAII_VAR ( struct ast_stream_topology * , topology , NULL , ast_stream_topology_free );
2017-06-14 13:07:17 -05:00
struct ast_stream * first_stream ;
struct ast_stream * second_stream ;
struct ast_stream * third_stream ;
struct ast_stream * fourth_stream ;
struct ast_stream * fifth_stream ;
struct ast_stream * sixth_stream ;
2017-02-14 18:33:57 +00:00
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_topology_get_first_stream_by_type" ;
info -> category = "/main/stream/" ;
info -> summary = "stream topology getting first stream by type unit test" ;
info -> description =
"Test that getting the first stream by type from a topology actually returns the first stream" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
2017-02-16 07:28:33 -07:00
topology = ast_stream_topology_alloc ();
2017-02-14 18:33:57 +00:00
if ( ! topology ) {
ast_test_status_update ( test , "Failed to create media stream topology \n " );
return AST_TEST_FAIL ;
}
2017-02-16 07:28:33 -07:00
first_stream = ast_stream_alloc ( "audio" , AST_MEDIA_TYPE_AUDIO );
2017-02-14 18:33:57 +00:00
if ( ! first_stream ) {
ast_test_status_update ( test , "Failed to create an audio stream for testing stream topology \n " );
return AST_TEST_FAIL ;
}
2017-06-14 13:07:17 -05:00
ast_stream_set_state ( first_stream , AST_STREAM_STATE_REMOVED );
2017-02-14 18:33:57 +00:00
if ( ast_stream_topology_append_stream ( topology , first_stream ) == - 1 ) {
ast_test_status_update ( test , "Failed to append a perfectly good stream to a topology \n " );
2017-02-16 07:28:33 -07:00
ast_stream_free ( first_stream );
2017-02-14 18:33:57 +00:00
return AST_TEST_FAIL ;
}
2017-02-16 07:28:33 -07:00
second_stream = ast_stream_alloc ( "audio2" , AST_MEDIA_TYPE_AUDIO );
2017-02-14 18:33:57 +00:00
if ( ! second_stream ) {
ast_test_status_update ( test , "Failed to create a second audio stream for testing stream topology \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_append_stream ( topology , second_stream ) == - 1 ) {
ast_test_status_update ( test , "Failed to append a perfectly good stream to a topology \n " );
2017-02-16 07:28:33 -07:00
ast_stream_free ( second_stream );
2017-02-14 18:33:57 +00:00
return AST_TEST_FAIL ;
}
2017-06-14 13:07:17 -05:00
third_stream = ast_stream_alloc ( "audio3" , AST_MEDIA_TYPE_AUDIO );
2017-02-14 18:33:57 +00:00
if ( ! third_stream ) {
2017-06-14 13:07:17 -05:00
ast_test_status_update ( test , "Failed to create a third audio stream for testing stream topology \n " );
2017-02-14 18:33:57 +00:00
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_append_stream ( topology , third_stream ) == - 1 ) {
ast_test_status_update ( test , "Failed to append a perfectly good stream to a topology \n " );
2017-02-16 07:28:33 -07:00
ast_stream_free ( third_stream );
2017-02-14 18:33:57 +00:00
return AST_TEST_FAIL ;
}
2017-06-14 13:07:17 -05:00
fourth_stream = ast_stream_alloc ( "video" , AST_MEDIA_TYPE_VIDEO );
2017-02-14 18:33:57 +00:00
if ( ! fourth_stream ) {
2017-06-14 13:07:17 -05:00
ast_test_status_update ( test , "Failed to create a video stream for testing stream topology \n " );
2017-02-14 18:33:57 +00:00
return AST_TEST_FAIL ;
}
2017-06-14 13:07:17 -05:00
ast_stream_set_state ( fourth_stream , AST_STREAM_STATE_REMOVED );
2017-02-14 18:33:57 +00:00
if ( ast_stream_topology_append_stream ( topology , fourth_stream ) == - 1 ) {
ast_test_status_update ( test , "Failed to append a perfectly good stream to a topology \n " );
2017-02-16 07:28:33 -07:00
ast_stream_free ( fourth_stream );
2017-02-14 18:33:57 +00:00
return AST_TEST_FAIL ;
}
2017-06-14 13:07:17 -05:00
fifth_stream = ast_stream_alloc ( "video2" , AST_MEDIA_TYPE_VIDEO );
if ( ! fifth_stream ) {
ast_test_status_update ( test , "Failed to create a second video stream for testing stream topology \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_append_stream ( topology , fifth_stream ) == - 1 ) {
ast_test_status_update ( test , "Failed to append a perfectly good stream to a topology \n " );
ast_stream_free ( fifth_stream );
return AST_TEST_FAIL ;
}
sixth_stream = ast_stream_alloc ( "video3" , AST_MEDIA_TYPE_VIDEO );
if ( ! sixth_stream ) {
ast_test_status_update ( test , "Failed to create a third video stream for testing stream topology \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_append_stream ( topology , sixth_stream ) == - 1 ) {
ast_test_status_update ( test , "Failed to append a perfectly good stream to a topology \n " );
ast_stream_free ( sixth_stream );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_get_first_stream_by_type ( topology , AST_MEDIA_TYPE_AUDIO ) != second_stream ) {
2017-02-14 18:33:57 +00:00
ast_test_status_update ( test , "Retrieved first audio stream from topology but it is not the correct one \n " );
return AST_TEST_FAIL ;
}
2017-06-14 13:07:17 -05:00
if ( ast_stream_topology_get_first_stream_by_type ( topology , AST_MEDIA_TYPE_VIDEO ) != fifth_stream ) {
2017-02-14 18:33:57 +00:00
ast_test_status_update ( test , "Retrieved first video stream from topology but it is not the correct one \n " );
return AST_TEST_FAIL ;
}
return AST_TEST_PASS ;
}
static const struct ast_channel_tech mock_channel_tech = {
};
AST_TEST_DEFINE ( stream_topology_create_from_channel_nativeformats )
{
2017-02-16 07:28:33 -07:00
RAII_VAR ( struct ast_stream_topology * , topology , NULL , ast_stream_topology_free );
2017-02-14 18:33:57 +00:00
RAII_VAR ( struct ast_format_cap * , caps , NULL , ao2_cleanup );
struct ast_channel * mock_channel ;
enum ast_test_result_state res = AST_TEST_FAIL ;
struct ast_str * codec_have_buf = ast_str_alloca ( AST_FORMAT_CAP_NAMES_LEN );
struct ast_str * codec_wanted_buf = ast_str_alloca ( AST_FORMAT_CAP_NAMES_LEN );
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_topology_create_from_channel_nativeformats" ;
info -> category = "/main/stream/" ;
info -> summary = "stream topology creation from channel native formats unit test" ;
info -> description =
"Test that creating a stream topology from the setting of channel nativeformats results in the expected streams" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
caps = ast_format_cap_alloc ( AST_FORMAT_CAP_FLAG_DEFAULT );
if ( ! caps ) {
ast_test_status_update ( test , "Could not allocate an empty format capabilities structure \n " );
return AST_TEST_FAIL ;
}
if ( ast_format_cap_append ( caps , ast_format_ulaw , 0 )) {
ast_test_status_update ( test , "Failed to append a ulaw format to capabilities for channel nativeformats \n " );
return AST_TEST_FAIL ;
}
if ( ast_format_cap_append ( caps , ast_format_alaw , 0 )) {
ast_test_status_update ( test , "Failed to append an alaw format to capabilities for channel nativeformats \n " );
return AST_TEST_FAIL ;
}
if ( ast_format_cap_append ( caps , ast_format_h264 , 0 )) {
ast_test_status_update ( test , "Failed to append an h264 format to capabilities for channel nativeformats \n " );
return AST_TEST_FAIL ;
}
mock_channel = ast_channel_alloc ( 0 , AST_STATE_DOWN , NULL , NULL , NULL , NULL , NULL , NULL , NULL , 0 , "TestChannel" );
if ( ! mock_channel ) {
ast_test_status_update ( test , "Failed to create a mock channel for testing \n " );
return AST_TEST_FAIL ;
}
ast_channel_tech_set ( mock_channel , & mock_channel_tech );
ast_channel_nativeformats_set ( mock_channel , caps );
if ( ! ast_channel_get_stream_topology ( mock_channel )) {
ast_test_status_update ( test , "Set nativeformats with ulaw, alaw, and h264 on channel but it did not create a topology \n " );
goto end ;
}
if ( ast_stream_topology_get_count ( ast_channel_get_stream_topology ( mock_channel )) != 2 ) {
ast_test_status_update ( test , "Set nativeformats on a channel to ulaw, alaw, and h264 and received '%d' streams instead of expected 2 \n " ,
ast_stream_topology_get_count ( ast_channel_get_stream_topology ( mock_channel )));
goto end ;
}
if ( ast_stream_get_type ( ast_stream_topology_get_stream ( ast_channel_get_stream_topology ( mock_channel ), 0 )) != AST_MEDIA_TYPE_AUDIO ) {
ast_test_status_update ( test , "First stream on channel is of %s when it should be audio \n " ,
ast_codec_media_type2str ( ast_stream_get_type ( ast_stream_topology_get_stream ( ast_channel_get_stream_topology ( mock_channel ), 0 ))));
goto end ;
}
ast_format_cap_remove_by_type ( caps , AST_MEDIA_TYPE_VIDEO );
if ( ! ast_format_cap_identical ( ast_stream_get_formats ( ast_stream_topology_get_stream ( ast_channel_get_stream_topology ( mock_channel ), 0 )), caps )) {
ast_test_status_update ( test , "Formats on audio stream of channel are '%s' when they should be '%s' \n " ,
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 ),
ast_format_cap_get_names ( caps , & codec_wanted_buf ));
goto end ;
}
if ( ast_stream_get_type ( ast_stream_topology_get_stream ( ast_channel_get_stream_topology ( mock_channel ), 1 )) != AST_MEDIA_TYPE_VIDEO ) {
ast_test_status_update ( test , "Second stream on channel is of type %s when it should be video \n " ,
ast_codec_media_type2str ( ast_stream_get_type ( ast_stream_topology_get_stream ( ast_channel_get_stream_topology ( mock_channel ), 1 ))));
goto end ;
}
ast_format_cap_remove_by_type ( caps , AST_MEDIA_TYPE_AUDIO );
if ( ast_format_cap_append ( caps , ast_format_h264 , 0 )) {
ast_test_status_update ( test , "Failed to append h264 video codec to capabilities for capabilities comparison \n " );
goto end ;
}
if ( ! ast_format_cap_identical ( ast_stream_get_formats ( ast_stream_topology_get_stream ( ast_channel_get_stream_topology ( mock_channel ), 1 )), caps )) {
ast_test_status_update ( test , "Formats on video stream of channel are '%s' when they should be '%s' \n " ,
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 ),
ast_format_cap_get_names ( caps , & codec_wanted_buf ));
goto end ;
}
res = AST_TEST_PASS ;
end :
ast_channel_unlock ( mock_channel );
ast_hangup ( mock_channel );
return res ;
}
2017-02-24 14:30:33 -07:00
struct mock_channel_pvt {
int mallocd ;
unsigned int wrote ;
unsigned int wrote_stream ;
int stream_num ;
int frame_limit ;
int frame_count ;
int streams ;
int frames_per_read ;
2017-03-07 11:22:18 +00:00
unsigned int indicated_change_request ;
unsigned int indicated_changed ;
2017-02-24 14:30:33 -07:00
};
static struct ast_frame * mock_channel_read ( struct ast_channel * chan )
{
struct mock_channel_pvt * pvt = ast_channel_tech_pvt ( chan );
struct ast_frame f = { 0 , };
struct ast_frame * head_frame = NULL ;
struct ast_frame * tail_frame = NULL ;
int i ;
if ( pvt -> frames_per_read == 0 ) {
pvt -> frames_per_read = 1 ;
}
for ( i = 0 ; i < pvt -> frames_per_read && pvt -> frame_count < pvt -> frame_limit ; i ++ ) {
struct ast_frame * fr ;
if ( pvt -> frame_count % 2 == 0 ) {
f . frametype = AST_FRAME_VOICE ;
f . subclass . format = ast_format_ulaw ;
} else {
f . frametype = AST_FRAME_VIDEO ;
f . subclass . format = ast_format_h264 ;
}
f . seqno = pvt -> frame_count ;
f . stream_num = pvt -> frame_count % pvt -> streams ;
pvt -> frame_count ++ ;
fr = ast_frdup ( & f );
if ( ! head_frame ) {
head_frame = fr ;
} else {
tail_frame -> frame_list . next = fr ;
}
tail_frame = fr ;
}
return ( head_frame );
}
static int mock_channel_write ( struct ast_channel * chan , struct ast_frame * fr )
{
struct mock_channel_pvt * pvt = ast_channel_tech_pvt ( chan );
pvt -> wrote = 1 ;
return 0 ;
}
2017-03-07 11:22:18 +00:00
static int mock_channel_indicate ( struct ast_channel * chan , int condition , const void * data , size_t datalen )
{
struct mock_channel_pvt * pvt = ast_channel_tech_pvt ( chan );
if ( condition == AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE ) {
pvt -> indicated_change_request = 1 ;
} else if ( condition == AST_CONTROL_STREAM_TOPOLOGY_CHANGED ) {
pvt -> indicated_changed = 1 ;
}
return 0 ;
}
2017-02-24 14:30:33 -07:00
static int mock_channel_write_stream ( struct ast_channel * chan , int stream_num , struct ast_frame * fr )
{
struct mock_channel_pvt * pvt = ast_channel_tech_pvt ( chan );
pvt -> wrote_stream = 1 ;
pvt -> stream_num = stream_num ;
return 0 ;
}
2017-02-14 18:33:57 +00:00
static const struct ast_channel_tech mock_stream_channel_tech = {
2017-02-24 14:30:33 -07:00
. read_stream = mock_channel_read ,
. write_stream = mock_channel_write_stream ,
2017-02-14 18:33:57 +00:00
};
AST_TEST_DEFINE ( stream_topology_channel_set )
{
2017-02-16 07:28:33 -07:00
RAII_VAR ( struct ast_stream_topology * , topology , NULL , ast_stream_topology_free );
2017-02-14 18:33:57 +00:00
struct ast_channel * mock_channel ;
enum ast_test_result_state res = AST_TEST_PASS ;
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_topology_channel_set" ;
info -> category = "/main/stream/" ;
info -> summary = "stream topology setting on a channel unit test" ;
info -> description =
"Test that setting a stream topology on a channel works" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
2017-02-16 07:28:33 -07:00
topology = ast_stream_topology_alloc ();
2017-02-14 18:33:57 +00:00
if ( ! topology ) {
ast_test_status_update ( test , "Failed to create media stream topology \n " );
return AST_TEST_FAIL ;
}
mock_channel = ast_channel_alloc ( 0 , AST_STATE_DOWN , NULL , NULL , NULL , NULL , NULL , NULL , NULL , 0 , "TestChannel" );
if ( ! mock_channel ) {
ast_test_status_update ( test , "Failed to create a mock channel for testing \n " );
return AST_TEST_FAIL ;
}
ast_channel_tech_set ( mock_channel , & mock_stream_channel_tech );
ast_channel_set_stream_topology ( mock_channel , topology );
if ( ast_channel_get_stream_topology ( mock_channel ) != topology ) {
ast_test_status_update ( test , "Set an explicit stream topology on a channel but the returned one did not match it \n " );
res = AST_TEST_FAIL ;
}
topology = NULL ;
ast_channel_unlock ( mock_channel );
ast_hangup ( mock_channel );
return res ;
}
2017-02-24 14:30:33 -07:00
static int mock_channel_hangup ( struct ast_channel * chan )
2017-02-22 11:00:57 +00:00
{
struct mock_channel_pvt * pvt = ast_channel_tech_pvt ( chan );
2017-02-24 14:30:33 -07:00
if ( pvt -> mallocd ) {
ast_free ( pvt );
}
2017-02-22 11:00:57 +00:00
ast_channel_tech_pvt_set ( chan , NULL );
return 0 ;
}
static const struct ast_channel_tech mock_channel_old_write_tech = {
. write = mock_channel_write ,
. write_video = mock_channel_write ,
. hangup = mock_channel_hangup ,
};
AST_TEST_DEFINE ( stream_write_non_multistream )
{
RAII_VAR ( struct ast_format_cap * , caps , NULL , ao2_cleanup );
struct ast_channel * mock_channel ;
2017-02-24 14:30:33 -07:00
struct mock_channel_pvt pvt = { 0 , };
2017-02-22 11:00:57 +00:00
enum ast_test_result_state res = AST_TEST_FAIL ;
struct ast_frame frame = { 0 , };
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_write_non_multistream" ;
info -> category = "/main/stream/" ;
info -> summary = "stream writing to non-multistream capable channel test" ;
info -> description =
"Test that writing frames to a non-multistream channel works as expected" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
caps = ast_format_cap_alloc ( AST_FORMAT_CAP_FLAG_DEFAULT );
if ( ! caps ) {
ast_test_status_update ( test , "Could not allocate an empty format capabilities structure \n " );
return AST_TEST_FAIL ;
}
if ( ast_format_cap_append ( caps , ast_format_ulaw , 0 )) {
ast_test_status_update ( test , "Failed to append a ulaw format to capabilities for channel nativeformats \n " );
return AST_TEST_FAIL ;
}
if ( ast_format_cap_append ( caps , ast_format_h264 , 0 )) {
ast_test_status_update ( test , "Failed to append an h264 format to capabilities for channel nativeformats \n " );
return AST_TEST_FAIL ;
}
mock_channel = ast_channel_alloc ( 0 , AST_STATE_DOWN , NULL , NULL , NULL , NULL , NULL , NULL , NULL , 0 , "TestChannel" );
if ( ! mock_channel ) {
ast_test_status_update ( test , "Failed to create a mock channel for testing \n " );
return AST_TEST_FAIL ;
}
ast_channel_tech_set ( mock_channel , & mock_channel_old_write_tech );
ast_channel_nativeformats_set ( mock_channel , caps );
pvt . wrote = 0 ;
ast_channel_tech_pvt_set ( mock_channel , & pvt );
ast_channel_unlock ( mock_channel );
frame . frametype = AST_FRAME_VOICE ;
frame . subclass . format = ast_format_ulaw ;
if ( ast_write ( mock_channel , & frame )) {
ast_test_status_update ( test , "Failed to write a ulaw frame to the mock channel when it should be fine \n " );
goto end ;
}
if ( ! pvt . wrote ) {
ast_test_status_update ( test , "Successfully wrote a frame of ulaw but it never reached the channel driver \n " );
goto end ;
}
pvt . wrote = 0 ;
if ( ! ast_write_stream ( mock_channel , 2 , & frame ) || pvt . wrote ) {
ast_test_status_update ( test , "Successfully wrote a frame of ulaw to a non-existent stream \n " );
goto end ;
}
frame . frametype = AST_FRAME_VIDEO ;
frame . subclass . format = ast_format_h264 ;
if ( ast_write ( mock_channel , & frame )) {
ast_test_status_update ( test , "Failed to write an h264 frame to the mock channel when it should be fine \n " );
goto end ;
}
if ( ! pvt . wrote ) {
ast_test_status_update ( test , "Successfully wrote a frame of h264 but it never reached the channel driver \n " );
goto end ;
}
res = AST_TEST_PASS ;
end :
ast_hangup ( mock_channel );
return res ;
}
static const struct ast_channel_tech mock_channel_write_stream_tech = {
. write = mock_channel_write ,
. write_video = mock_channel_write ,
. write_stream = mock_channel_write_stream ,
2017-02-24 14:30:33 -07:00
. read_stream = mock_channel_read ,
2017-02-22 11:00:57 +00:00
. hangup = mock_channel_hangup ,
};
AST_TEST_DEFINE ( stream_write_multistream )
{
RAII_VAR ( struct ast_format_cap * , caps , NULL , ao2_cleanup );
RAII_VAR ( struct ast_stream_topology * , topology , NULL , ast_stream_topology_free );
struct ast_stream * stream ;
struct ast_channel * mock_channel ;
struct mock_channel_pvt pvt = { 0 , };
enum ast_test_result_state res = AST_TEST_FAIL ;
struct ast_frame frame = { 0 , };
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_write_multistream" ;
info -> category = "/main/stream/" ;
info -> summary = "stream writing to multistream capable channel test" ;
info -> description =
"Test that writing frames to a multistream channel works as expected" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
topology = ast_stream_topology_alloc ();
if ( ! topology ) {
ast_test_status_update ( test , "Failed to create media stream topology \n " );
return AST_TEST_FAIL ;
}
stream = ast_stream_alloc ( "audio" , AST_MEDIA_TYPE_AUDIO );
if ( ! stream ) {
ast_test_status_update ( test , "Failed to create an audio stream for testing multistream writing \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_append_stream ( topology , stream ) == - 1 ) {
ast_test_status_update ( test , "Failed to append a perfectly good stream to a topology \n " );
ast_stream_free ( stream );
return AST_TEST_FAIL ;
}
stream = ast_stream_alloc ( "audio2" , AST_MEDIA_TYPE_AUDIO );
if ( ! stream ) {
ast_test_status_update ( test , "Failed to create an audio stream for testing multistream writing \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_append_stream ( topology , stream ) == - 1 ) {
ast_test_status_update ( test , "Failed to append a perfectly good stream to a topology \n " );
ast_stream_free ( stream );
return AST_TEST_FAIL ;
}
stream = ast_stream_alloc ( "video" , AST_MEDIA_TYPE_VIDEO );
if ( ! stream ) {
ast_test_status_update ( test , "Failed to create a video stream for testing multistream writing \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_append_stream ( topology , stream ) == - 1 ) {
ast_test_status_update ( test , "Failed to append a perfectly good stream to a topology \n " );
ast_stream_free ( stream );
return AST_TEST_FAIL ;
}
stream = ast_stream_alloc ( "video2" , AST_MEDIA_TYPE_VIDEO );
if ( ! stream ) {
ast_test_status_update ( test , "Failed to create a video stream for testing multistream writing \n " );
return AST_TEST_FAIL ;
}
if ( ast_stream_topology_append_stream ( topology , stream ) == - 1 ) {
ast_test_status_update ( test , "Failed to append a perfectly good stream to a topology \n " );
ast_stream_free ( stream );
return AST_TEST_FAIL ;
}
caps = ast_format_cap_alloc ( AST_FORMAT_CAP_FLAG_DEFAULT );
if ( ! caps ) {
ast_test_status_update ( test , "Could not allocate an empty format capabilities structure \n " );
return AST_TEST_FAIL ;
}
if ( ast_format_cap_append ( caps , ast_format_ulaw , 0 )) {
ast_test_status_update ( test , "Failed to append a ulaw format to capabilities for channel nativeformats \n " );
return AST_TEST_FAIL ;
}
if ( ast_format_cap_append ( caps , ast_format_h264 , 0 )) {
ast_test_status_update ( test , "Failed to append an h264 format to capabilities for channel nativeformats \n " );
return AST_TEST_FAIL ;
}
mock_channel = ast_channel_alloc ( 0 , AST_STATE_DOWN , NULL , NULL , NULL , NULL , NULL , NULL , NULL , 0 , "TestChannel" );
if ( ! mock_channel ) {
ast_test_status_update ( test , "Failed to create a mock channel for testing \n " );
return AST_TEST_FAIL ;
}
ast_channel_tech_set ( mock_channel , & mock_channel_write_stream_tech );
ast_channel_set_stream_topology ( mock_channel , topology );
ast_channel_nativeformats_set ( mock_channel , caps );
topology = NULL ;
ast_channel_tech_pvt_set ( mock_channel , & pvt );
ast_channel_unlock ( mock_channel );
frame . frametype = AST_FRAME_VOICE ;
frame . subclass . format = ast_format_ulaw ;
pvt . stream_num = - 1 ;
if ( ast_write ( mock_channel , & frame )) {
ast_test_status_update ( test , "Failed to write a ulaw frame to the mock channel when it should be fine \n " );
goto end ;
}
if ( pvt . wrote ) {
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 " );
goto end ;
}
if ( ! pvt . wrote_stream ) {
ast_test_status_update ( test , "Successfully wrote a frame of ulaw but it never reached the channel driver \n " );
goto end ;
}
if ( pvt . stream_num != 0 ) {
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 " ,
pvt . stream_num );
goto end ;
}
pvt . wrote_stream = 0 ;
pvt . stream_num = - 1 ;
if ( ast_write_stream ( mock_channel , 0 , & frame )) {
ast_test_status_update ( test , "Failed to write a ulaw frame to the first audio stream \n " );
goto end ;
}
if ( pvt . wrote ) {
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 " );
goto end ;
}
if ( ! pvt . wrote_stream ) {
ast_test_status_update ( test , "Successfully wrote a frame of ulaw to the first audio stream but it never reached the channel driver \n " );
goto end ;
}
if ( pvt . stream_num != 0 ) {
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 " ,
pvt . stream_num );
goto end ;
}
pvt . wrote_stream = 0 ;
pvt . stream_num = - 1 ;
if ( ast_write_stream ( mock_channel , 1 , & frame )) {
ast_test_status_update ( test , "Failed to write a ulaw frame to the second audio stream \n " );
goto end ;
}
if ( pvt . wrote ) {
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 " );
goto end ;
}
if ( ! pvt . wrote_stream ) {
ast_test_status_update ( test , "Successfully wrote a frame of ulaw to the second audio stream but it never reached the channel driver \n " );
goto end ;
}
if ( pvt . stream_num != 1 ) {
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 " ,
pvt . stream_num );
goto end ;
}
pvt . wrote_stream = 0 ;
pvt . stream_num = - 1 ;
frame . frametype = AST_FRAME_VIDEO ;
frame . subclass . format = ast_format_h264 ;
if ( ast_write ( mock_channel , & frame )) {
ast_test_status_update ( test , "Failed to write an h264 frame to the mock channel when it should be fine \n " );
goto end ;
}
if ( pvt . wrote ) {
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 " );
goto end ;
}
if ( ! pvt . wrote_stream ) {
ast_test_status_update ( test , "Successfully wrote a frame of h264 but it never reached the channel driver \n " );
goto end ;
}
if ( pvt . stream_num != 2 ) {
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 " ,
pvt . stream_num );
goto end ;
}
pvt . wrote_stream = 0 ;
pvt . stream_num = - 1 ;
if ( ast_write_stream ( mock_channel , 2 , & frame )) {
ast_test_status_update ( test , "Failed to write an h264 frame to the first video stream \n " );
goto end ;
}
if ( pvt . wrote ) {
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 " );
goto end ;
}
if ( ! pvt . wrote_stream ) {
ast_test_status_update ( test , "Successfully wrote a frame of h264 to the first video stream but it never reached the channel driver \n " );
goto end ;
}
if ( pvt . stream_num != 2 ) {
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 " ,
pvt . stream_num );
goto end ;
}
pvt . wrote_stream = 0 ;
pvt . stream_num = - 1 ;
if ( ast_write_stream ( mock_channel , 3 , & frame )) {
ast_test_status_update ( test , "Failed to write an h264 frame to the second video stream \n " );
goto end ;
}
if ( pvt . wrote ) {
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 " );
goto end ;
}
if ( ! pvt . wrote_stream ) {
ast_test_status_update ( test , "Successfully wrote a frame of h264 to the second video stream but it never reached the channel driver \n " );
goto end ;
}
if ( pvt . stream_num != 3 ) {
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 " ,
pvt . stream_num );
goto end ;
}
pvt . wrote_stream = 0 ;
pvt . stream_num = - 1 ;
if ( ! ast_write_stream ( mock_channel , 9 , & frame )) {
ast_test_status_update ( test , "Successfully wrote a frame of h264 to a non-existent stream \n " );
goto end ;
}
if ( pvt . wrote ) {
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 " );
goto end ;
}
if ( pvt . wrote_stream ) {
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 " );
goto end ;
}
res = AST_TEST_PASS ;
end :
ast_hangup ( mock_channel );
return res ;
}
2017-02-24 14:30:33 -07:00
static int load_stream_readqueue ( struct ast_channel * chan , int frames )
{
struct mock_channel_pvt * pvt = ast_channel_tech_pvt ( chan );
struct ast_frame f = { 0 , };
struct ast_frame * frame = NULL ;
int i ;
while (( frame = AST_LIST_REMOVE_HEAD ( ast_channel_readq ( chan ), frame_list )))
ast_frfree ( frame );
for ( i = 0 ; i < frames ; i ++ ) {
if ( pvt -> frame_count % 2 == 0 ) {
f . frametype = AST_FRAME_VOICE ;
f . subclass . format = ast_format_ulaw ;
} else {
f . frametype = AST_FRAME_VIDEO ;
f . subclass . format = ast_format_h264 ;
}
f . stream_num = pvt -> frame_count % pvt -> streams ;
f . seqno = pvt -> frame_count ;
2017-08-03 21:58:25 -04:00
ast_queue_frame ( chan , & f );
2017-02-24 14:30:33 -07:00
pvt -> frame_count ++ ;
}
return 0 ;
}
static struct ast_channel * make_channel ( struct ast_test * test , int streams ,
struct ast_channel_tech * tech )
{
RAII_VAR ( struct ast_format_cap * , caps , NULL , ao2_cleanup );
struct ast_channel * mock_channel = NULL ;
struct mock_channel_pvt * pvt = NULL ;
struct ast_stream_topology * topology = NULL ;
struct ast_stream * stream ;
enum ast_test_result_state res = AST_TEST_PASS ;
int i ;
mock_channel = ast_channel_alloc ( 0 , AST_STATE_DOWN , NULL , NULL , NULL , NULL , NULL , NULL , NULL , 0 , "TestChannel" );
ast_test_validate_cleanup ( test , mock_channel , res , done );
ast_channel_tech_set ( mock_channel , tech );
if ( tech -> read_stream ) {
topology = ast_stream_topology_alloc ();
ast_test_validate_cleanup ( test , topology , res , done );
for ( i = 0 ; i < streams ; i ++ ) {
stream = ast_stream_alloc (( i % 2 ? "video" : "audio" ), ( i % 2 ? AST_MEDIA_TYPE_VIDEO : AST_MEDIA_TYPE_AUDIO ));
ast_test_validate_cleanup ( test , stream , res , done );
ast_test_validate_cleanup ( test , ast_stream_topology_append_stream ( topology , stream ) == i , res , done );
}
ast_test_validate_cleanup ( test , ast_stream_topology_get_count ( topology ) == streams , res , done );
ast_channel_set_stream_topology ( mock_channel , topology );
topology = NULL ;
} else {
caps = ast_format_cap_alloc ( AST_FORMAT_CAP_FLAG_DEFAULT );
ast_test_validate_cleanup ( test , caps , res , done );
ast_test_validate_cleanup ( test , ast_format_cap_append ( caps , ast_format_ulaw , 0 ) == 0 , res , done );
ast_test_validate_cleanup ( test , ast_format_cap_append ( caps , ast_format_h264 , 0 ) == 0 , res , done );
ast_channel_nativeformats_set ( mock_channel , caps );
}
pvt = ast_calloc ( 1 , sizeof ( * pvt ));
ast_test_validate_cleanup ( test , pvt , res , done );
pvt -> mallocd = 1 ;
ast_channel_tech_pvt_set ( mock_channel , pvt );
ast_channel_unlock ( mock_channel );
done :
ast_stream_topology_free ( topology );
if ( res == AST_TEST_FAIL && mock_channel ) {
ast_hangup ( mock_channel );
}
return mock_channel ;
}
enum CHANNEL_READ_TYPE {
CHANNEL_READ ,
CHANNEL_READ_STREAM
};
static struct ast_frame * read_from_chan ( enum CHANNEL_READ_TYPE rt , struct ast_channel * chan )
{
if ( rt == CHANNEL_READ_STREAM ) {
return ast_read_stream ( chan );
} else {
return ast_read ( chan );
}
}
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 )
{
struct ast_channel * mock_channel ;
struct mock_channel_pvt * pvt ;
struct ast_frame * fr = NULL ;
enum ast_test_result_state res = AST_TEST_PASS ;
int i = 0 ;
int null_frames = 0 ;
ast_test_status_update ( test , "ChanType: %s ReadType: %s Streams: %d Frames: %d Frames per read: %d Expected Nulls: %d \n " ,
tech -> read_stream ? "MULTI" : "NON-MULTI" ,
rt == CHANNEL_READ_STREAM ? "STREAM" : "NON-STREAM" ,
streams , frames , frames_per_read , expected_nulls );
mock_channel = make_channel ( test , 4 , tech );
ast_test_validate_cleanup ( test , mock_channel , res , done );
pvt = ast_channel_tech_pvt ( mock_channel );
pvt -> frame_count = 0 ;
pvt -> frame_limit = frames ;
pvt -> streams = streams ;
pvt -> frames_per_read = frames_per_read ;
load_stream_readqueue ( mock_channel , frames / 2 );
ast_channel_fdno_set ( mock_channel , 0 );
while (( fr = read_from_chan ( rt , mock_channel ))) {
ast_channel_fdno_set ( mock_channel , 0 );
if ( fr -> frametype != AST_FRAME_NULL ) {
ast_test_validate_cleanup ( test , i == fr -> seqno , res , done );
ast_test_validate_cleanup ( test , fr -> frametype == ( i % 2 ? AST_FRAME_VIDEO : AST_FRAME_VOICE ), res , done );
ast_test_validate_cleanup ( test , fr -> stream_num == ( i % streams ), res , done );
ast_frfree ( fr );
} else {
null_frames ++ ;
}
fr = NULL ;
i ++ ;
}
ast_test_validate_cleanup ( test , i == frames , res , done );
ast_test_validate_cleanup ( test , null_frames == expected_nulls , res , done );
done :
ast_test_status_update ( test , " Frames read: %d NULL frames: %d \n " , i , null_frames );
ast_hangup ( mock_channel );
return res ;
}
AST_TEST_DEFINE ( stream_read_non_multistream )
{
struct ast_channel_tech tech = {
. read = mock_channel_read ,
. hangup = mock_channel_hangup ,
};
enum ast_test_result_state res = AST_TEST_PASS ;
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_read_non_multistream" ;
info -> category = "/main/stream/" ;
info -> summary = "stream reading from non-multistream capable channel test" ;
info -> description =
"Test that reading frames from a non-multistream channel works as expected" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
res = read_test ( test , & tech , CHANNEL_READ , 2 , 16 , 1 , 0 );
ast_test_validate ( test , res == AST_TEST_PASS , "non multi, non read stream, 2 stream" );
res = read_test ( test , & tech , CHANNEL_READ_STREAM , 2 , 16 , 1 , 0 );
ast_test_validate ( test , res == AST_TEST_PASS , "non multi, read stream, 2 stream" );
res = read_test ( test , & tech , CHANNEL_READ , 2 , 16 , 3 , 0 );
ast_test_validate ( test , res == AST_TEST_PASS , "non multi, non read stream, 2 stream, 3 frames per read" );
res = read_test ( test , & tech , CHANNEL_READ_STREAM , 2 , 16 , 3 , 0 );
ast_test_validate ( test , res == AST_TEST_PASS , "non multi, read stream, 2 stream, 3 frames per read" );
return res ;
}
AST_TEST_DEFINE ( stream_read_multistream )
{
struct ast_channel_tech tech = {
. read_stream = mock_channel_read ,
. write_stream = mock_channel_write_stream ,
. hangup = mock_channel_hangup ,
};
enum ast_test_result_state res = AST_TEST_PASS ;
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_read_multistream" ;
info -> category = "/main/stream/" ;
info -> summary = "stream reading from multistream capable channel test" ;
info -> description =
"Test that reading frames from a multistream channel works as expected" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
res = read_test ( test , & tech , CHANNEL_READ , 2 , 16 , 1 , 0 );
ast_test_validate ( test , res == AST_TEST_PASS , "multi, non read stream, 2 stream" );
res = read_test ( test , & tech , CHANNEL_READ_STREAM , 2 , 16 , 1 , 0 );
ast_test_validate ( test , res == AST_TEST_PASS , "multi, read stream, 2 stream" );
res = read_test ( test , & tech , CHANNEL_READ , 4 , 16 , 1 , 8 );
ast_test_validate ( test , res == AST_TEST_PASS , "multi, non read stream, 4 stream" );
res = read_test ( test , & tech , CHANNEL_READ_STREAM , 4 , 16 , 1 , 0 );
ast_test_validate ( test , res == AST_TEST_PASS , "multi, read stream, 4 stream" );
res = read_test ( test , & tech , CHANNEL_READ , 2 , 16 , 3 , 0 );
ast_test_validate ( test , res == AST_TEST_PASS , "multi, non read stream, 2 stream, 3 frames per read" );
res = read_test ( test , & tech , CHANNEL_READ_STREAM , 2 , 16 , 3 , 0 );
ast_test_validate ( test , res == AST_TEST_PASS , "multi, read stream, 2 stream, 3 frames per read" );
res = read_test ( test , & tech , CHANNEL_READ , 4 , 16 , 3 , 8 );
ast_test_validate ( test , res == AST_TEST_PASS , "multi, non read stream, 4 stream, 3 frames per read" );
res = read_test ( test , & tech , CHANNEL_READ_STREAM , 4 , 16 , 3 , 0 );
ast_test_validate ( test , res == AST_TEST_PASS , "multi, read stream, 4 stream, 3 frames per read" );
return res ;
}
2017-03-07 11:22:18 +00:00
AST_TEST_DEFINE ( stream_topology_change_request_from_application_non_multistream )
{
struct ast_channel_tech tech = {
. read = mock_channel_read ,
. indicate = mock_channel_indicate ,
. hangup = mock_channel_hangup ,
};
struct ast_channel * mock_channel ;
struct mock_channel_pvt * pvt ;
enum ast_test_result_state res = AST_TEST_PASS ;
int change_res ;
RAII_VAR ( struct ast_stream_topology * , topology , NULL , ast_stream_topology_free );
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_topology_change_request_from_application_non_multistream" ;
info -> category = "/main/stream/" ;
info -> summary = "stream topology changing on non-multistream channel test" ;
info -> description =
"Test that an application trying to change the stream topology of a non-multistream channel gets a failure" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
mock_channel = make_channel ( test , 1 , & tech );
ast_test_validate_cleanup ( test , mock_channel , res , done );
pvt = ast_channel_tech_pvt ( mock_channel );
pvt -> indicated_change_request = 0 ;
pvt -> indicated_changed = 0 ;
topology = ast_stream_topology_alloc ();
ast_test_validate_cleanup ( test , topology , res , done );
2017-04-25 11:49:16 -05:00
change_res = ast_channel_request_stream_topology_change ( mock_channel , topology , NULL );
2017-03-07 11:22:18 +00:00
ast_test_validate_cleanup ( test , change_res == - 1 , res , done );
ast_test_validate_cleanup ( test , ! pvt -> indicated_change_request , res , done );
2017-08-11 16:31:45 -05:00
ast_channel_lock ( mock_channel );
2017-03-07 11:22:18 +00:00
change_res = ast_channel_stream_topology_changed ( mock_channel , topology );
2017-08-11 16:31:45 -05:00
ast_channel_unlock ( mock_channel );
2017-03-07 11:22:18 +00:00
ast_test_validate_cleanup ( test , change_res == - 1 , res , done );
ast_test_validate_cleanup ( test , ! pvt -> indicated_changed , res , done );
done :
ast_hangup ( mock_channel );
return res ;
}
AST_TEST_DEFINE ( stream_topology_change_request_from_channel_non_multistream )
{
struct ast_channel_tech tech = {
. read_stream = mock_channel_read ,
. write_stream = mock_channel_write_stream ,
. indicate = mock_channel_indicate ,
. hangup = mock_channel_hangup ,
};
struct ast_channel * mock_channel ;
struct mock_channel_pvt * pvt ;
enum ast_test_result_state res = AST_TEST_PASS ;
RAII_VAR ( struct ast_stream_topology * , topology , NULL , ast_stream_topology_free );
struct ast_frame request_change = {
. frametype = AST_FRAME_CONTROL ,
. subclass . integer = AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE ,
};
struct ast_frame * fr = NULL ;
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_topology_change_request_from_channel_non_multistream" ;
info -> category = "/main/stream/" ;
info -> summary = "channel requesting stream topology change to non-multistream application test" ;
info -> description =
"Test that a channel requesting a stream topology change from a non-multistream application does not work" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
mock_channel = make_channel ( test , 1 , & tech );
ast_test_validate_cleanup ( test , mock_channel , res , done );
pvt = ast_channel_tech_pvt ( mock_channel );
pvt -> indicated_changed = 0 ;
topology = ast_stream_topology_alloc ();
ast_test_validate_cleanup ( test , topology , res , done );
request_change . data . ptr = topology ;
ast_queue_frame ( mock_channel , & request_change );
fr = ast_read ( mock_channel );
ast_test_validate_cleanup ( test , fr , res , done );
ast_test_validate_cleanup ( test , fr == & ast_null_frame , res , done );
ast_test_validate_cleanup ( test , pvt -> indicated_changed , res , done );
done :
if ( fr ) {
ast_frfree ( fr );
}
ast_hangup ( mock_channel );
return res ;
}
AST_TEST_DEFINE ( stream_topology_change_request_from_application )
{
struct ast_channel_tech tech = {
. read_stream = mock_channel_read ,
. write_stream = mock_channel_write_stream ,
. indicate = mock_channel_indicate ,
. hangup = mock_channel_hangup ,
};
struct ast_channel * mock_channel ;
struct mock_channel_pvt * pvt ;
enum ast_test_result_state res = AST_TEST_PASS ;
int change_res ;
RAII_VAR ( struct ast_stream_topology * , topology , NULL , ast_stream_topology_free );
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_topology_change_request_from_application" ;
info -> category = "/main/stream/" ;
info -> summary = "stream topology change request from application test" ;
info -> description =
"Test that an application changing the stream topology of a multistream capable channel receives success" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
mock_channel = make_channel ( test , 1 , & tech );
ast_test_validate_cleanup ( test , mock_channel , res , done );
pvt = ast_channel_tech_pvt ( mock_channel );
pvt -> indicated_change_request = 0 ;
pvt -> indicated_changed = 0 ;
topology = ast_stream_topology_alloc ();
ast_test_validate_cleanup ( test , topology , res , done );
2017-04-25 11:49:16 -05:00
change_res = ast_channel_request_stream_topology_change ( mock_channel , topology , NULL );
2017-03-07 11:22:18 +00:00
ast_test_validate_cleanup ( test , ! change_res , res , done );
ast_test_validate_cleanup ( test , pvt -> indicated_change_request , res , done );
2017-08-11 16:31:45 -05:00
ast_channel_lock ( mock_channel );
2017-03-07 11:22:18 +00:00
change_res = ast_channel_stream_topology_changed ( mock_channel , topology );
2017-08-11 16:31:45 -05:00
ast_channel_unlock ( mock_channel );
2017-03-07 11:22:18 +00:00
ast_test_validate_cleanup ( test , ! change_res , res , done );
ast_test_validate_cleanup ( test , pvt -> indicated_changed , res , done );
done :
ast_hangup ( mock_channel );
return res ;
}
AST_TEST_DEFINE ( stream_topology_change_request_from_channel )
{
struct ast_channel_tech tech = {
. read_stream = mock_channel_read ,
. write_stream = mock_channel_write_stream ,
. indicate = mock_channel_indicate ,
. hangup = mock_channel_hangup ,
};
struct ast_channel * mock_channel ;
struct mock_channel_pvt * pvt ;
enum ast_test_result_state res = AST_TEST_PASS ;
RAII_VAR ( struct ast_stream_topology * , topology , NULL , ast_stream_topology_free );
struct ast_frame request_change = {
. frametype = AST_FRAME_CONTROL ,
. subclass . integer = AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE ,
};
struct ast_frame * fr = NULL ;
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_topology_change_request_from_channel" ;
info -> category = "/main/stream/" ;
info -> summary = "channel requesting stream topology change to multistream application test" ;
info -> description =
"Test that a channel requesting a stream topology change from a multistream application works" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
mock_channel = make_channel ( test , 1 , & tech );
ast_test_validate_cleanup ( test , mock_channel , res , done );
pvt = ast_channel_tech_pvt ( mock_channel );
pvt -> indicated_changed = 0 ;
topology = ast_stream_topology_alloc ();
ast_test_validate_cleanup ( test , topology , res , done );
request_change . data . ptr = topology ;
ast_queue_frame ( mock_channel , & request_change );
fr = ast_read_stream ( mock_channel );
ast_test_validate_cleanup ( test , fr , res , done );
ast_test_validate_cleanup ( test , fr -> frametype == AST_FRAME_CONTROL , res , done );
ast_test_validate_cleanup ( test , fr -> subclass . integer == AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE , res , done );
ast_test_validate_cleanup ( test , ! pvt -> indicated_changed , res , done );
done :
if ( fr ) {
ast_frfree ( fr );
}
ast_hangup ( mock_channel );
return res ;
}
2017-04-24 15:59:44 +00:00
AST_TEST_DEFINE ( format_cap_from_stream_topology )
{
RAII_VAR ( struct ast_format_cap * , caps , NULL , ao2_cleanup );
RAII_VAR ( struct ast_format_cap * , stream_caps , NULL , ao2_cleanup );
struct ast_stream_topology * topology ;
2017-06-14 13:07:17 -05:00
struct ast_stream * stream ;
struct ast_format_cap * new_cap ;
2017-04-24 15:59:44 +00:00
switch ( cmd ) {
case TEST_INIT :
info -> name = "format_cap_from_stream_topology" ;
info -> category = "/main/stream/" ;
info -> summary = "stream topology to format capabilities conversion test" ;
info -> description =
"Test that converting a stream topology to format capabilities results in expected formats" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
caps = ast_format_cap_alloc ( AST_FORMAT_CAP_FLAG_DEFAULT );
if ( ! caps ) {
ast_test_status_update ( test , "Could not allocate an empty format capabilities structure \n " );
return AST_TEST_FAIL ;
}
if ( ast_format_cap_append ( caps , ast_format_ulaw , 0 )) {
2017-06-14 13:07:17 -05:00
ast_test_status_update ( test , "Failed to append ulaw format to capabilities \n " );
2017-04-24 15:59:44 +00:00
return AST_TEST_FAIL ;
}
if ( ast_format_cap_append ( caps , ast_format_h264 , 0 )) {
2017-06-14 13:07:17 -05:00
ast_test_status_update ( test , "Failed to append h264 format to capabilities \n " );
2017-04-24 15:59:44 +00:00
return AST_TEST_FAIL ;
}
topology = ast_stream_topology_create_from_format_cap ( caps );
if ( ! topology ) {
ast_test_status_update ( test , "Failed to create a stream topology from format capabilities of ulaw and h264 \n " );
return AST_TEST_FAIL ;
}
2017-06-14 13:07:17 -05:00
/*
* Append declined stream with formats that should not be included
* in combined topology caps.
*/
stream = ast_stream_alloc ( "audio" , AST_MEDIA_TYPE_AUDIO );
if ( ! stream ) {
ast_test_status_update ( test , "Failed to create an audio stream for testing stream topology \n " );
ast_stream_topology_free ( topology );
return AST_TEST_FAIL ;
}
ast_stream_set_state ( stream , AST_STREAM_STATE_REMOVED );
new_cap = ast_format_cap_alloc ( AST_FORMAT_CAP_FLAG_DEFAULT );
if ( ! new_cap ) {
ast_test_status_update ( test , "Could not allocate an empty format capabilities structure \n " );
ast_stream_free ( stream );
ast_stream_topology_free ( topology );
return AST_TEST_FAIL ;
}
if ( ast_format_cap_append ( new_cap , ast_format_alaw , 0 )) {
ast_test_status_update ( test , "Failed to append alaw format to capabilities \n " );
ao2_cleanup ( new_cap );
ast_stream_free ( stream );
ast_stream_topology_free ( topology );
return AST_TEST_FAIL ;
}
ast_stream_set_formats ( stream , new_cap );
ao2_cleanup ( new_cap );
if ( ast_stream_topology_append_stream ( topology , stream ) == - 1 ) {
ast_test_status_update ( test , "Failed to append a perfectly good stream to a topology \n " );
ast_stream_free ( stream );
ast_stream_topology_free ( topology );
return AST_TEST_FAIL ;
}
2017-04-24 15:59:44 +00:00
stream_caps = ast_format_cap_from_stream_topology ( topology );
if ( ! stream_caps ) {
ast_test_status_update ( test , "Failed to create a format capabilities from a stream topology \n " );
ast_stream_topology_free ( topology );
return AST_TEST_FAIL ;
}
ast_stream_topology_free ( topology );
if ( ! ast_format_cap_identical ( caps , stream_caps )) {
ast_test_status_update ( test , "Converting format capabilities into topology and back resulted in different formats \n " );
return AST_TEST_FAIL ;
}
return AST_TEST_PASS ;
}
2017-04-25 11:49:16 -05:00
#define topology_append_stream(topology, name, type, res, label) \
do { \
struct ast_stream *__stream = ast_stream_alloc((name), (type)); \
ast_test_validate_cleanup(test, __stream, res, label); \
if (ast_stream_topology_append_stream((topology), __stream) < 0) { \
ast_stream_free(__stream); \
res = AST_TEST_FAIL; \
goto label; \
} \
} while(0)
AST_TEST_DEFINE ( stream_topology_map_create )
{
RAII_VAR ( struct ast_stream_topology * , t0 , NULL , ast_stream_topology_free );
struct ast_vector_int types = { NULL };
struct ast_vector_int v0 = { NULL };
struct ast_vector_int v1 = { NULL };
enum ast_test_result_state res = AST_TEST_PASS ;
switch ( cmd ) {
case TEST_INIT :
info -> name = "stream_topology_map_create" ;
info -> category = "/main/stream/" ;
info -> summary = "stream topology map creation unit test" ;
info -> description =
"Test that creating a stream topology map works" ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
ast_test_validate ( test , AST_VECTOR_INIT ( & types , 5 ) == 0 );
/* Map a first topology and check that it mapped one to one */
ast_test_validate_cleanup ( test , ( t0 = ast_stream_topology_alloc ()), res , done );
topology_append_stream ( t0 , "audio" , AST_MEDIA_TYPE_AUDIO , res , done );
topology_append_stream ( t0 , "video" , AST_MEDIA_TYPE_VIDEO , res , done );
ast_stream_topology_map ( t0 , & types , & v0 , & v1 );
ast_test_validate_cleanup ( test , AST_VECTOR_SIZE ( & types ) == 2 , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & types , 0 ) == AST_MEDIA_TYPE_AUDIO , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & types , 1 ) == AST_MEDIA_TYPE_VIDEO , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & v0 , 0 ) == 0 , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & v0 , 1 ) == 1 , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & v1 , 0 ) == 0 , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & v1 , 1 ) == 1 , res , done );
/* Map a second topology and check that it merged */
ast_stream_topology_free ( t0 );
ast_test_validate_cleanup ( test , ( t0 = ast_stream_topology_alloc ()), res , done );
topology_append_stream ( t0 , "video" , AST_MEDIA_TYPE_VIDEO , res , done );
topology_append_stream ( t0 , "audio" , AST_MEDIA_TYPE_AUDIO , res , done );
ast_stream_topology_map ( t0 , & types , & v0 , & v1 );
ast_test_validate_cleanup ( test , AST_VECTOR_SIZE ( & types ) == 2 , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & types , 0 ) == AST_MEDIA_TYPE_AUDIO , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & types , 1 ) == AST_MEDIA_TYPE_VIDEO , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & v0 , 0 ) == 1 , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & v0 , 1 ) == 0 , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & v1 , 0 ) == 1 , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & v1 , 1 ) == 0 , res , done );
/* Map a third topology with more streams and check that it merged */
ast_stream_topology_free ( t0 );
ast_test_validate_cleanup ( test , ( t0 = ast_stream_topology_alloc ()), res , done );
topology_append_stream ( t0 , "video" , AST_MEDIA_TYPE_VIDEO , res , done );
topology_append_stream ( t0 , "audio" , AST_MEDIA_TYPE_AUDIO , res , done );
topology_append_stream ( t0 , "audio" , AST_MEDIA_TYPE_AUDIO , res , done );
ast_stream_topology_map ( t0 , & types , & v0 , & v1 );
ast_test_validate_cleanup ( test , AST_VECTOR_SIZE ( & types ) == 3 , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & types , 0 ) == AST_MEDIA_TYPE_AUDIO , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & types , 1 ) == AST_MEDIA_TYPE_VIDEO , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & types , 2 ) == AST_MEDIA_TYPE_AUDIO , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & v0 , 0 ) == 1 , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & v0 , 1 ) == 0 , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & v0 , 2 ) == 2 , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & v1 , 0 ) == 1 , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & v1 , 1 ) == 0 , res , done );
ast_test_validate_cleanup ( test , AST_VECTOR_GET ( & v1 , 2 ) == 2 , res , done );
done :
AST_VECTOR_FREE ( & v1 );
AST_VECTOR_FREE ( & v0 );
AST_VECTOR_FREE ( & types );
return res ;
}
2017-02-07 12:56:41 +00:00
static int unload_module ( void )
{
AST_TEST_UNREGISTER ( stream_create );
AST_TEST_UNREGISTER ( stream_create_no_name );
AST_TEST_UNREGISTER ( stream_set_type );
AST_TEST_UNREGISTER ( stream_set_formats );
AST_TEST_UNREGISTER ( stream_set_state );
2017-02-13 17:00:42 +00:00
AST_TEST_UNREGISTER ( stream_topology_create );
AST_TEST_UNREGISTER ( stream_topology_clone );
AST_TEST_UNREGISTER ( stream_topology_clone );
AST_TEST_UNREGISTER ( stream_topology_append_stream );
AST_TEST_UNREGISTER ( stream_topology_set_stream );
2017-06-09 19:03:05 -05:00
AST_TEST_UNREGISTER ( stream_topology_del_stream );
2017-02-13 17:00:42 +00:00
AST_TEST_UNREGISTER ( stream_topology_create_from_format_cap );
2017-02-14 18:33:57 +00:00
AST_TEST_UNREGISTER ( stream_topology_get_first_stream_by_type );
AST_TEST_UNREGISTER ( stream_topology_create_from_channel_nativeformats );
AST_TEST_UNREGISTER ( stream_topology_channel_set );
2017-02-22 11:00:57 +00:00
AST_TEST_UNREGISTER ( stream_write_non_multistream );
AST_TEST_UNREGISTER ( stream_write_multistream );
2017-02-24 14:30:33 -07:00
AST_TEST_UNREGISTER ( stream_read_non_multistream );
AST_TEST_UNREGISTER ( stream_read_multistream );
2017-03-07 11:22:18 +00:00
AST_TEST_UNREGISTER ( stream_topology_change_request_from_application_non_multistream );
AST_TEST_UNREGISTER ( stream_topology_change_request_from_channel_non_multistream );
AST_TEST_UNREGISTER ( stream_topology_change_request_from_application );
AST_TEST_UNREGISTER ( stream_topology_change_request_from_channel );
2017-04-24 15:59:44 +00:00
AST_TEST_UNREGISTER ( format_cap_from_stream_topology );
2017-04-25 11:49:16 -05:00
AST_TEST_UNREGISTER ( stream_topology_map_create );
2017-02-07 12:56:41 +00:00
return 0 ;
}
static int load_module ( void )
{
AST_TEST_REGISTER ( stream_create );
AST_TEST_REGISTER ( stream_create_no_name );
AST_TEST_REGISTER ( stream_set_type );
AST_TEST_REGISTER ( stream_set_formats );
AST_TEST_REGISTER ( stream_set_state );
2017-02-13 17:00:42 +00:00
AST_TEST_REGISTER ( stream_topology_create );
AST_TEST_REGISTER ( stream_topology_clone );
AST_TEST_REGISTER ( stream_topology_append_stream );
AST_TEST_REGISTER ( stream_topology_set_stream );
2017-06-09 19:03:05 -05:00
AST_TEST_REGISTER ( stream_topology_del_stream );
2017-02-13 17:00:42 +00:00
AST_TEST_REGISTER ( stream_topology_create_from_format_cap );
2017-02-14 18:33:57 +00:00
AST_TEST_REGISTER ( stream_topology_get_first_stream_by_type );
AST_TEST_REGISTER ( stream_topology_create_from_channel_nativeformats );
AST_TEST_REGISTER ( stream_topology_channel_set );
2017-02-22 11:00:57 +00:00
AST_TEST_REGISTER ( stream_write_non_multistream );
AST_TEST_REGISTER ( stream_write_multistream );
2017-02-24 14:30:33 -07:00
AST_TEST_REGISTER ( stream_read_non_multistream );
AST_TEST_REGISTER ( stream_read_multistream );
2017-03-07 11:22:18 +00:00
AST_TEST_REGISTER ( stream_topology_change_request_from_application_non_multistream );
AST_TEST_REGISTER ( stream_topology_change_request_from_channel_non_multistream );
AST_TEST_REGISTER ( stream_topology_change_request_from_application );
AST_TEST_REGISTER ( stream_topology_change_request_from_channel );
2017-04-24 15:59:44 +00:00
AST_TEST_REGISTER ( format_cap_from_stream_topology );
2017-04-25 11:49:16 -05:00
AST_TEST_REGISTER ( stream_topology_map_create );
2017-02-07 12:56:41 +00:00
return AST_MODULE_LOAD_SUCCESS ;
}
AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY , "Media Stream API test module" );