unittests/switch_manager/switch_manager_test.c
/*
* Unit tests for switch_manager_test.
*
* Author: Kazushi SUGYO
*
* Copyright (C) 2008-2013 NEC Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
#include <netinet/tcp.h>
#include "unittest.h"
#include "trema.h"
#include "switch_manager.h"
#include "secure_channel_listener.h"
extern struct listener_info listener_info;
void usage();
void handle_sigchld( int signum );
void secure_channel_fd_set( fd_set *read_set, fd_set *write_set );
void secure_channel_fd_isset( fd_set *read_set, fd_set *write_set );
char *absolute_path( const char *dir, const char *file );
int switch_manager_main( int argc, char *argv[] );
void wait_child( void );
/*************************************************************************
* Setup and teardown function.
*************************************************************************/
static void
setup() {
init_log( "switch_manager_test", false );
}
static void
teardown() {
}
/******************************************************************************
* Mock
******************************************************************************/
void
mock_die( char *format, ... ) {
UNUSED( format );
}
int
mock_printf2( char *format, ... ) {
UNUSED( format );
return ( int ) mock();
}
/*************************************************************************
* Mock for switch_manager.c
*************************************************************************/
int mock_wait3_status = 0;
pid_t
mock_wait3( int *status, int options, struct rusage *rusage ) {
check_expected( status );
check_expected( options );
check_expected( rusage );
*status = mock_wait3_status;
return ( pid_t ) mock();
}
void
mock_secure_channel_accept( struct listener_info *listener_info ) {
check_expected( listener_info );
( void ) mock();
}
int
mock_access( const char *pathname, int mode) {
UNUSED( pathname );
UNUSED( mode );
return ( int ) mock();
}
char *
mock_get_current_dir_name( void ) {
return ( char * ) mock();
}
void
mock_init_trema( int *argc, char ***argv ) {
UNUSED( argc );
UNUSED( argv );
( void ) mock();
}
void
mock_set_fd_set_callback( void ( *callback )( fd_set *read_set, fd_set *write_set ) ) {
UNUSED( callback );
( void ) mock();
}
void
mock_set_check_fd_isset_callback( void ( *callback )( fd_set *read_set, fd_set *write_set ) ) {
UNUSED( callback );
( void ) mock();
}
bool
mock_secure_channel_listen_start( struct listener_info *listener_info ) {
UNUSED( listener_info );
return ( bool ) mock();
}
char *
mock_get_trema_home( void ) {
return ( char * ) mock();
}
void
mock_start_trema( void ) {
( void ) mock();
}
const char *
mock_get_executable_name( void ) {
return "switch_manager";
}
void
mock_set_external_callback( void ( *callback ) ( void ) ) {
check_expected( callback );
}
/*************************************************************************
* Mock for secure_channel_listener.c
*************************************************************************/
int
mock_close( int fd ) {
check_expected( fd );
return ( int ) mock();
}
int
mock_socket( int domain, int type, int protocol ) {
check_expected( domain );
check_expected( type );
check_expected( protocol );
return ( int ) mock();
}
int
mock_bind( int sockfd, /* const */ struct sockaddr *addr, socklen_t addrlen ) {
struct sockaddr_in *addr_in = ( struct sockaddr_in * ) addr;
uint32_t sin_family32;
uint32_t sin_port32;
check_expected( sockfd );
check_expected( addr_in );
check_expected( addrlen );
sin_family32 = addr_in->sin_family;
check_expected( sin_family32 );
sin_port32 = addr_in->sin_port;
check_expected( sin_port32 );
check_expected( addr_in->sin_addr.s_addr );
return ( int ) mock();
}
int
mock_listen( int sockfd, int backlog ) {
check_expected( sockfd );
check_expected( backlog );
return ( int ) mock();
}
int
mock_accept( int sockfd, struct sockaddr *addr, socklen_t *addrlen ) {
check_expected( sockfd );
check_expected( addr );
check_expected( addrlen );
check_expected( *addrlen );
return ( int ) mock();
}
int
mock_setsockopt( int sockfd, int level, int optname, /* const */ void *optval,
socklen_t optlen ) {
check_expected( sockfd );
check_expected( level );
check_expected( optname );
check_expected( optval );
check_expected( optlen );
return ( int ) mock();
}
pid_t
mock_fork( void ) {
return ( pid_t ) mock();
}
int
mock_dup2( int oldfd, int newfd ) {
check_expected( oldfd );
check_expected( newfd );
return ( int ) mock();
}
int
mock_open( /* const */ char *pathname, int flags ) {
check_expected( pathname );
check_expected( flags );
return ( int ) mock();
}
int
mock_execvp( /* const */ char *file, char * /* const */ argv[] ) {
check_expected( file );
check_expected( argv );
check_expected( argv[ 0 ] );
check_expected( argv[ 1 ] );
return ( int ) mock();
}
void
mock_exit( int status ) {
check_expected( status );
( void ) mock();
}
/*************************************************************************
* Test functions for switch_manager.c
*************************************************************************/
static void
test_usage() {
setup();
will_return( mock_printf2, 1 );
usage();
teardown();
}
static void
test_handle_sigchld_succeeded() {
setup();
expect_value( mock_set_external_callback, callback, wait_child );
handle_sigchld( 3 );
teardown();
}
static void
test_wait_child_succeeded() {
setup();
expect_not_value( mock_wait3, status, NULL );
expect_value( mock_wait3, options, WNOHANG );
expect_value( mock_wait3, rusage, NULL );
mock_wait3_status = 0;
will_return( mock_wait3, 1234 );
expect_not_value( mock_wait3, status, NULL );
expect_value( mock_wait3, options, WNOHANG );
expect_value( mock_wait3, rusage, NULL );
will_return( mock_wait3, 0 );
wait_child();
teardown();
}
static void
test_wait_child_wait3_failed() {
setup();
expect_not_value( mock_wait3, status, NULL );
expect_value( mock_wait3, options, WNOHANG );
expect_value( mock_wait3, rusage, NULL );
mock_wait3_status = 0;
will_return( mock_wait3, -1 );
wait_child();
teardown();
}
static void
test_wait_child_wait3_zero_return() {
setup();
expect_not_value( mock_wait3, status, NULL );
expect_value( mock_wait3, options, WNOHANG );
expect_value( mock_wait3, rusage, NULL );
mock_wait3_status = 0;
will_return( mock_wait3, 0 );
wait_child();
teardown();
}
static void
test_wait_child_wait3_exit() {
setup();
expect_not_value( mock_wait3, status, NULL );
expect_value( mock_wait3, options, WNOHANG );
expect_value( mock_wait3, rusage, NULL );
mock_wait3_status = 1 << 8;
will_return( mock_wait3, 1234 );
expect_not_value( mock_wait3, status, NULL );
expect_value( mock_wait3, options, WNOHANG );
expect_value( mock_wait3, rusage, NULL );
will_return( mock_wait3, 0 );
wait_child();
teardown();
}
static void
test_wait_child_wait3_coredump() {
setup();
expect_not_value( mock_wait3, status, NULL );
expect_value( mock_wait3, options, WNOHANG );
expect_value( mock_wait3, rusage, NULL );
mock_wait3_status = 0x80 | 11;
will_return( mock_wait3, 5678 );
expect_not_value( mock_wait3, status, NULL );
expect_value( mock_wait3, options, WNOHANG );
expect_value( mock_wait3, rusage, NULL );
will_return( mock_wait3, 0 );
wait_child();
teardown();
}
static void
test_wait_child_wait3_signaled() {
setup();
expect_not_value( mock_wait3, status, NULL );
expect_value( mock_wait3, options, WNOHANG );
expect_value( mock_wait3, rusage, NULL );
mock_wait3_status = 3;
will_return( mock_wait3, 4444 );
expect_not_value( mock_wait3, status, NULL );
expect_value( mock_wait3, options, WNOHANG );
expect_value( mock_wait3, rusage, NULL );
will_return( mock_wait3, 0 );
wait_child();
teardown();
}
static void
test_secure_channel_fd_set_succeeded() {
setup();
fd_set read_set, write_set;
listener_info.listen_fd = 1;
FD_ZERO( &read_set );
FD_ZERO( &write_set );
secure_channel_fd_set( &read_set, &write_set );
assert_true( FD_ISSET( listener_info.listen_fd, &read_set ) );
FD_CLR( listener_info.listen_fd, &read_set );
assert_true( FD_ISZERO( &read_set ) );
assert_true( FD_ISZERO( &write_set ) );
teardown();
}
static void
test_secure_channel_fd_set_failed() {
setup();
fd_set read_set, write_set;
listener_info.listen_fd = -1;
FD_ZERO( &read_set );
FD_ZERO( &write_set );
secure_channel_fd_set( &read_set, &write_set );
assert_true( FD_ISZERO( &read_set ) );
assert_true( FD_ISZERO( &write_set ) );
teardown();
}
static void
test_secure_channel_fd_isset_succeeded() {
setup();
fd_set read_set, write_set;
expect_value( mock_secure_channel_accept, listener_info, &listener_info );
will_return_void( mock_secure_channel_accept );
listener_info.listen_fd = 1;
FD_ZERO( &read_set );
FD_ZERO( &write_set );
FD_SET( listener_info.listen_fd, &read_set );
secure_channel_fd_isset( &read_set, &write_set );
teardown();
}
static void
test_secure_channel_fd_isset_failed() {
setup();
fd_set read_set, write_set;
listener_info.listen_fd = -1;
FD_ZERO( &read_set );
FD_ZERO( &write_set );
FD_SET( 1, &read_set );
secure_channel_fd_isset( &read_set, &write_set );
teardown();
}
static void
test_absolute_path_absolute() {
setup();
char *path;
will_return( mock_access, 0 );
path = absolute_path( "/tmp", "/file" );
assert_string_equal( path, "/file" );
xfree( path );
teardown();
}
static void
test_absolute_path_access_failed() {
setup();
char *path;
will_return( mock_access, -1 );
path = absolute_path( "/tmp", "/file" );
assert_true( path == NULL );
teardown();
}
static void
test_absolute_path_relative() {
setup();
char *path;
will_return( mock_access, 0 );
path = absolute_path( "/tmp", "file" );
assert_string_equal( path, "/tmp/file" );
xfree( path );
will_return( mock_access, 0 );
path = absolute_path( "/tmp/", "./file" );
assert_string_equal( path, "/tmp/./file" );
xfree( path );
will_return( mock_access, 0 );
path = absolute_path( "/tmp", "../tmp/file" );
assert_string_equal( path, "/tmp/../tmp/file" );
xfree( path );
will_return( mock_access, 0 );
path = absolute_path( "/tmp/", "../../tmp/file" );
assert_string_equal( path, "/tmp/../../tmp/file" );
xfree( path );
teardown();
}
static void
test_switch_manager_main_succeeded() {
setup();
char *argv[] = {
( char * )( uintptr_t )"switch_manager",
( char * )( uintptr_t )"--switch_manager=switch_manager",
NULL,
};
int argc = ARRAY_SIZE( argv ) - 1;
int ret;
will_return( mock_get_current_dir_name, strdup( "/tmp" ) );
will_return_void( mock_init_trema );
will_return( mock_access, 0 );
will_return_void( mock_set_fd_set_callback );
will_return_void( mock_set_check_fd_isset_callback );
will_return( mock_secure_channel_listen_start, true );
will_return( mock_get_trema_home, strdup( "/tmp" ) );
will_return_void( mock_start_trema );
optind = 1;
ret = switch_manager_main( argc, argv );
assert_true( ret == EXIT_SUCCESS );
teardown();
}
static void
test_switch_manager_main_and_port_option_succeeded() {
setup();
char *argv[] = {
( char * )( uintptr_t )"switch_manager",
( char * )( uintptr_t )"--port=6653",
NULL,
};
int argc = ARRAY_SIZE( argv ) - 1;
int ret;
will_return( mock_get_current_dir_name, strdup( "/tmp" ) );
will_return_void( mock_init_trema );
will_return( mock_access, 0 );
will_return_void( mock_set_fd_set_callback );
will_return_void( mock_set_check_fd_isset_callback );
will_return( mock_secure_channel_listen_start, true );
will_return( mock_get_trema_home, strdup( "/tmp" ) );
will_return_void( mock_start_trema );
optind = 1;
ret = switch_manager_main( argc, argv );
assert_true( ret == EXIT_SUCCESS );
teardown();
}
static void
test_switch_manager_main_and_port_option_failed() {
setup();
char *argv[] = {
( char * )( uintptr_t )"switch_manager",
( char * )( uintptr_t )"--port=0",
NULL,
};
int argc = ARRAY_SIZE( argv ) - 1;
int ret;
will_return( mock_get_current_dir_name, strdup( "/tmp" ) );
will_return_void( mock_init_trema );
will_return( mock_get_trema_home, strdup( "/tmp" ) );
optind = 1;
ret = switch_manager_main( argc, argv );
assert_true( ret == EXIT_FAILURE );
teardown();
}
static void
test_switch_manager_main_help_and_exit() {
setup();
char *argv[] = {
( char * )( uintptr_t )"switch_manager",
( char * )( uintptr_t )"-x",
NULL,
};
int argc = ARRAY_SIZE( argv ) - 1;
int ret;
will_return( mock_printf2, 1 );
will_return( mock_get_current_dir_name, strdup( "/tmp" ) );
will_return_void( mock_init_trema );
will_return( mock_get_trema_home, strdup( "/tmp" ) );
expect_value( mock_exit, status, EXIT_SUCCESS );
will_return_void( mock_exit );
optind = 1;
ret = switch_manager_main( argc, argv );
assert_true( ret == EXIT_FAILURE );
teardown();
}
static void
test_switch_manager_main_get_current_dir_name_failed() {
setup();
char *argv[] = {
( char * )( uintptr_t )"switch_manager",
NULL,
};
int argc = ARRAY_SIZE( argv ) - 1;
int ret;
will_return( mock_get_current_dir_name, NULL );
optind = 1;
ret = switch_manager_main( argc, argv );
assert_true( ret == EXIT_FAILURE );
teardown();
}
static void
test_switch_manager_main_secure_channel_listen_start_failed() {
setup();
char *argv[] = {
( char * )( uintptr_t )"switch_manager",
NULL,
};
int argc = ARRAY_SIZE( argv ) - 1;
int ret;
will_return( mock_get_current_dir_name, strdup( "/tmp" ) );
will_return_void( mock_init_trema );
will_return( mock_get_trema_home, strdup( "/tmp" ) );
will_return( mock_access, 0 );
will_return_void( mock_set_fd_set_callback );
will_return_void( mock_set_check_fd_isset_callback );
will_return( mock_secure_channel_listen_start, false );
optind = 1;
ret = switch_manager_main( argc, argv );
assert_true( ret == EXIT_FAILURE );
teardown();
}
/*************************************************************************
* Test functions for secure_channel_listener.c
*************************************************************************/
static void
test_secure_channel_listen_start_succeeded() {
setup();
int listen_fd = 1;
listener_info.listen_fd = -1;
expect_value( mock_socket, domain, PF_INET );
expect_value( mock_socket, type, SOCK_STREAM );
expect_value( mock_socket, protocol, 0 );
will_return( mock_socket, listen_fd );
expect_value_count( mock_setsockopt, sockfd, listen_fd, 1 );
expect_value_count( mock_setsockopt, level, SOL_SOCKET, 1 );
expect_value_count( mock_setsockopt, optname, SO_REUSEADDR, 1 );
expect_not_value_count( mock_setsockopt, optval, NULL, 1 );
expect_value_count( mock_setsockopt, optlen, sizeof( int ), 1 );
will_return_count( mock_setsockopt, 0, 1 );
expect_value_count( mock_setsockopt, sockfd, listen_fd, 1 );
expect_value_count( mock_setsockopt, level, IPPROTO_TCP, 1 );
expect_value_count( mock_setsockopt, optname, TCP_NODELAY, 1 );
expect_not_value_count( mock_setsockopt, optval, NULL, 1 );
expect_value_count( mock_setsockopt, optlen, sizeof( int ), 1 );
will_return_count( mock_setsockopt, 0, 1 );
expect_value( mock_bind, sockfd, listen_fd );
expect_not_value( mock_bind, addr_in, NULL );
expect_value( mock_bind, addrlen, sizeof( struct sockaddr_in ) );
expect_value( mock_bind, sin_family32, AF_INET );
expect_value( mock_bind, sin_port32, ( uint32_t ) htons( OFP_TCP_PORT ) );
expect_value( mock_bind, addr_in->sin_addr.s_addr, htonl( INADDR_ANY ) );
will_return( mock_bind, 0 );
expect_value( mock_listen, sockfd, listen_fd );
expect_value( mock_listen, backlog, 128 );
will_return( mock_listen, 0 );
assert_true( secure_channel_listen_start( &listener_info ) );
assert_true( listener_info.listen_fd == listen_fd );
teardown();
}
static void
test_secure_channel_listen_start_socket_failed() {
setup();
int listen_fd = 1;
listener_info.listen_fd = listen_fd;
expect_value( mock_close, fd, listen_fd );
will_return_void( mock_close );
expect_value( mock_socket, domain, PF_INET );
expect_value( mock_socket, type, SOCK_STREAM );
expect_value( mock_socket, protocol, 0 );
will_return( mock_socket, -1 );
assert_false( secure_channel_listen_start( &listener_info ) );
assert_true( listener_info.listen_fd == -1 );
teardown();
}
static void
test_secure_channel_listen_start_setsockopt_bind_failed() {
setup();
int listen_fd = 1;
listener_info.listen_fd = -1;
expect_value( mock_socket, domain, PF_INET );
expect_value( mock_socket, type, SOCK_STREAM );
expect_value( mock_socket, protocol, 0 );
will_return( mock_socket, listen_fd );
expect_value_count( mock_setsockopt, sockfd, listen_fd, 1 );
expect_value_count( mock_setsockopt, level, SOL_SOCKET, 1 );
expect_value_count( mock_setsockopt, optname, SO_REUSEADDR, 1 );
expect_not_value_count( mock_setsockopt, optval, NULL, 1 );
expect_value_count( mock_setsockopt, optlen, sizeof( int ), 1 );
will_return_count( mock_setsockopt, -1, 1 );
expect_value_count( mock_setsockopt, sockfd, listen_fd, 1 );
expect_value_count( mock_setsockopt, level, IPPROTO_TCP, 1 );
expect_value_count( mock_setsockopt, optname, TCP_NODELAY, 1 );
expect_not_value_count( mock_setsockopt, optval, NULL, 1 );
expect_value_count( mock_setsockopt, optlen, sizeof( int ), 1 );
will_return_count( mock_setsockopt, -1, 1 );
expect_value( mock_bind, sockfd, listen_fd );
expect_not_value( mock_bind, addr_in, NULL );
expect_value( mock_bind, addrlen, sizeof( struct sockaddr_in ) );
expect_value( mock_bind, sin_family32, AF_INET );
expect_value( mock_bind, sin_port32, ( uint32_t ) htons( OFP_TCP_PORT ) );
expect_value( mock_bind, addr_in->sin_addr.s_addr, htonl( INADDR_ANY ) );
will_return( mock_bind, -1 );
expect_value( mock_close, fd, listen_fd );
will_return_void( mock_close );
assert_false( secure_channel_listen_start( &listener_info ) );
assert_true( listener_info.listen_fd == -1 );
teardown();
}
static void
test_secure_channel_listen_start_listen_failed() {
setup();
int listen_fd = 1;
listener_info.listen_fd = -1;
expect_value( mock_socket, domain, PF_INET );
expect_value( mock_socket, type, SOCK_STREAM );
expect_value( mock_socket, protocol, 0 );
will_return( mock_socket, listen_fd );
expect_value_count( mock_setsockopt, sockfd, listen_fd, 1 );
expect_value_count( mock_setsockopt, level, SOL_SOCKET, 1 );
expect_value_count( mock_setsockopt, optname, SO_REUSEADDR, 1 );
expect_not_value_count( mock_setsockopt, optval, NULL, 1 );
expect_value_count( mock_setsockopt, optlen, sizeof( int ), 1 );
will_return_count( mock_setsockopt, 0, 1 );
expect_value_count( mock_setsockopt, sockfd, listen_fd, 1 );
expect_value_count( mock_setsockopt, level, IPPROTO_TCP, 1 );
expect_value_count( mock_setsockopt, optname, TCP_NODELAY, 1 );
expect_not_value_count( mock_setsockopt, optval, NULL, 1 );
expect_value_count( mock_setsockopt, optlen, sizeof( int ), 1 );
will_return_count( mock_setsockopt, 0, 1 );
expect_value( mock_bind, sockfd, listen_fd );
expect_not_value( mock_bind, addr_in, NULL );
expect_value( mock_bind, addrlen, sizeof( struct sockaddr_in ) );
expect_value( mock_bind, sin_family32, AF_INET );
expect_value( mock_bind, sin_port32, ( uint32_t ) htons( OFP_TCP_PORT ) );
expect_value( mock_bind, addr_in->sin_addr.s_addr, htonl( INADDR_ANY ) );
will_return( mock_bind, 0 );
expect_value( mock_listen, sockfd, listen_fd );
expect_value( mock_listen, backlog, 128 );
will_return( mock_listen, -1 );
expect_value( mock_close, fd, listen_fd );
will_return_void( mock_close );
assert_false( secure_channel_listen_start( &listener_info ) );
assert_true( listener_info.listen_fd == -1 );
teardown();
}
static void
test_secure_channel_accept_parent_succeeded() {
setup();
int listen_fd = 0;
int accept_fd = 1;
int pid = 1; /* parent */
listener_info.listen_fd = listen_fd;
expect_value( mock_accept, sockfd, listen_fd );
expect_not_value( mock_accept, addr, NULL );
expect_not_value( mock_accept, addrlen, NULL );
expect_value( mock_accept, *addrlen, sizeof( struct sockaddr_in ) );
will_return( mock_accept, accept_fd );
will_return( mock_fork, pid );
expect_value( mock_close, fd, accept_fd );
will_return_void( mock_close );
secure_channel_accept( &listener_info );
}
static void
test_secure_channel_accept_accept_failed() {
int listen_fd = 0;
listener_info.listen_fd = listen_fd;
expect_value( mock_accept, sockfd, listen_fd );
expect_not_value( mock_accept, addr, NULL );
expect_not_value( mock_accept, addrlen, NULL );
expect_value( mock_accept, *addrlen, sizeof( struct sockaddr_in ) );
will_return( mock_accept, -1 );
secure_channel_accept( &listener_info );
teardown();
}
static void
test_secure_channel_accept_fork_failed() {
setup();
int listen_fd = 0;
int accept_fd = 3;
listener_info.listen_fd = listen_fd;
expect_value( mock_accept, sockfd, listen_fd );
expect_not_value( mock_accept, addr, NULL );
expect_not_value( mock_accept, addrlen, NULL );
expect_value( mock_accept, *addrlen, sizeof( struct sockaddr_in ) );
will_return( mock_accept, accept_fd );
will_return( mock_fork, -1 );
expect_value( mock_close, fd, accept_fd );
will_return_void( mock_close );
secure_channel_accept( &listener_info );
teardown();
}
static void
test_secure_channel_accept_child_succeeded() {
setup();
int listen_fd = 0;
int accept_fd = 3;
int pid = 0; /* child */
listener_info.switch_manager = "switch_manager";
listener_info.switch_manager_argc = 0;
listener_info.listen_fd = listen_fd;
expect_value( mock_accept, sockfd, listen_fd );
expect_not_value( mock_accept, addr, NULL );
expect_not_value( mock_accept, addrlen, NULL );
expect_value( mock_accept, *addrlen, sizeof( struct sockaddr_in ) );
will_return( mock_accept, accept_fd );
will_return( mock_fork, pid );
expect_string( mock_open, pathname, "/dev/null" );
expect_value( mock_open, flags, O_RDONLY );
will_return( mock_open, 1 );
expect_value( mock_dup2, oldfd, 1 );
expect_value( mock_dup2, newfd, 0 );
will_return( mock_dup2, 0 );
expect_value( mock_close, fd, 1 );
will_return_void( mock_close );
expect_string( mock_open, pathname, "/dev/null" );
expect_value( mock_open, flags, O_WRONLY );
will_return( mock_open, 2 );
expect_value( mock_dup2, oldfd, 2 );
expect_value( mock_dup2, newfd, 1 );
will_return( mock_dup2, 1 );
expect_value( mock_close, fd, 2 );
will_return_void( mock_close );
expect_string( mock_open, pathname, "/dev/null" );
expect_value( mock_open, flags, O_WRONLY );
will_return( mock_open, 3 );
expect_value( mock_dup2, oldfd, 3 );
expect_value( mock_dup2, newfd, 2 );
will_return( mock_dup2, 2 );
expect_value( mock_close, fd, 3 );
will_return_void( mock_close );
expect_string( mock_execvp, file, listener_info.switch_manager );
expect_not_value( mock_execvp, argv, NULL );
expect_not_value( mock_execvp, argv[ 0 ], NULL );
expect_not_value( mock_execvp, argv[ 1 ], NULL );
will_return( mock_execvp, 0 );
expect_value( mock_exit, status, EXIT_FAILURE );
will_return_void( mock_exit );
secure_channel_accept( &listener_info );
teardown();
}
static void
test_secure_channel_accept_child_and_args_succeeded() {
setup();
int listen_fd = 0;
int accept_fd = 3;
int pid = 0; /* child */
static char const *argv[] = { "a", "b" };
listener_info.switch_manager = "switch_manager";
listener_info.switch_manager_argc = 2;
listener_info.switch_manager_argv = ( char ** )( uintptr_t )argv;
listener_info.listen_fd = listen_fd;
expect_value( mock_accept, sockfd, listen_fd );
expect_not_value( mock_accept, addr, NULL );
expect_not_value( mock_accept, addrlen, NULL );
expect_value( mock_accept, *addrlen, sizeof( struct sockaddr_in ) );
will_return( mock_accept, accept_fd );
will_return( mock_fork, pid );
expect_string( mock_open, pathname, "/dev/null" );
expect_value( mock_open, flags, O_RDONLY );
will_return( mock_open, 1 );
expect_value( mock_dup2, oldfd, 1 );
expect_value( mock_dup2, newfd, 0 );
will_return( mock_dup2, 0 );
expect_value( mock_close, fd, 1 );
will_return_void( mock_close );
expect_string( mock_open, pathname, "/dev/null" );
expect_value( mock_open, flags, O_WRONLY );
will_return( mock_open, 2 );
expect_value( mock_dup2, oldfd, 2 );
expect_value( mock_dup2, newfd, 1 );
will_return( mock_dup2, 1 );
expect_value( mock_close, fd, 2 );
will_return_void( mock_close );
expect_string( mock_open, pathname, "/dev/null" );
expect_value( mock_open, flags, O_WRONLY );
will_return( mock_open, 3 );
expect_value( mock_dup2, oldfd, 3 );
expect_value( mock_dup2, newfd, 2 );
will_return( mock_dup2, 2 );
expect_value( mock_close, fd, 3 );
will_return_void( mock_close );
expect_string( mock_execvp, file, listener_info.switch_manager );
expect_not_value( mock_execvp, argv, NULL );
expect_not_value( mock_execvp, argv[ 0 ], NULL );
expect_not_value( mock_execvp, argv[ 1 ], NULL );
will_return( mock_execvp, 0 );
expect_value( mock_exit, status, EXIT_FAILURE );
will_return_void( mock_exit );
secure_channel_accept( &listener_info );
teardown();
}
/*************************************************************************
* Run tests.
*************************************************************************/
int
main() {
const UnitTest tests[] = {
/* Test functions for switch_manager.c */
unit_test( test_usage ),
unit_test( test_handle_sigchld_succeeded ),
unit_test( test_wait_child_succeeded ),
unit_test( test_wait_child_wait3_failed ),
unit_test( test_wait_child_wait3_zero_return ),
unit_test( test_wait_child_wait3_exit ),
unit_test( test_wait_child_wait3_coredump ),
unit_test( test_wait_child_wait3_signaled ),
unit_test( test_secure_channel_fd_set_succeeded ),
unit_test( test_secure_channel_fd_set_failed ),
unit_test( test_secure_channel_fd_isset_succeeded ),
unit_test( test_secure_channel_fd_isset_failed ),
unit_test( test_absolute_path_absolute ),
unit_test( test_absolute_path_access_failed ),
unit_test( test_absolute_path_relative ),
unit_test( test_switch_manager_main_succeeded ),
unit_test( test_switch_manager_main_and_port_option_succeeded ),
unit_test( test_switch_manager_main_and_port_option_failed ),
unit_test( test_switch_manager_main_help_and_exit ),
unit_test( test_switch_manager_main_get_current_dir_name_failed ),
unit_test( test_switch_manager_main_secure_channel_listen_start_failed ),
/* Test functions for secure_channel_listener.c */
unit_test( test_secure_channel_listen_start_succeeded ),
unit_test( test_secure_channel_listen_start_socket_failed ),
unit_test( test_secure_channel_listen_start_setsockopt_bind_failed ),
unit_test( test_secure_channel_listen_start_listen_failed ),
unit_test( test_secure_channel_accept_parent_succeeded ),
unit_test( test_secure_channel_accept_accept_failed ),
unit_test( test_secure_channel_accept_fork_failed ),
unit_test( test_secure_channel_accept_child_succeeded ),
unit_test( test_secure_channel_accept_child_and_args_succeeded ),
};
return run_tests( tests );
}
/*
* Local variables:
* c-basic-offset: 2
* indent-tabs-mode: nil
* End:
*/