Files
rtems/testsuites/psxtests/psxmsgq01/init.c
Joel Sherrill fc0756e8d9 Add test assertion for allocator mutex being unlocked
The Allocator Mutex should not be locked outside a tested
service call. In an SMP test or heavily multithreaded test,
this is possible since another thread could have the lock
for an extended period of time but this is not the norm
for the tests.

updates 2319.
2015-04-14 11:17:10 -05:00

1408 lines
38 KiB
C

/*
* COPYRIGHT (c) 1989-2012.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define CONFIGURE_INIT
#include "system.h"
#include <sched.h>
#include <fcntl.h>
#include <time.h>
#include <tmacros.h>
#include <signal.h> /* signal facilities */
#include "test_support.h"
const char rtems_test_name[] = "PSXMSGQ 1";
/* forward declarations to avoid warnings */
void Start_Test(char *description);
void Validate_attributes(mqd_t mq, int oflag, int msg_count);
char *Build_Queue_Name(int i);
void open_test_queues(void);
void validate_mq_open_error_codes(void);
void validate_mq_unlink_error_codes(void);
void validate_mq_close_error_codes(void);
void validate_mq_getattr_error_codes(void);
void Send_msg_to_que(int que, int msg);
void Show_send_msg_to_que(char *task_name, int que, int msg);
void verify_queues_full(char *task_name);
void verify_queues_empty(char *task_name);
int empty_message_queues(char *task_name);
int fill_message_queues(char *task_name);
void Read_msg_from_que(int que, int msg);
int validate_mq_send_error_codes(void);
void validate_mq_receive_error_codes(void);
void verify_open_functionality(void);
void verify_unlink_functionality(void);
void verify_close_functionality(void);
void verify_timed_send_queue(int que, int is_blocking);
void verify_timed_send(void);
void verify_timed_receive_queue(char *task_name, int que, int is_blocking);
void verify_timed_receive(void);
void wait_for_signal(sigset_t *waitset, int sec, int expect_signal);
void verify_notify(void);
void verify_with_threads(void);
void verify_timedout_mq_timedreceive(char *task_name, int que, int is_blocking);
void verify_timedout_mq_timedsend(int que, int is_blocking);
void verify_timed_receive(void);
void validate_mq_setattr(void);
void verify_timedout_mq_timedreceive(
char *task_name, int que, int is_blocking);
void verify_mq_receive(void);
void verify_timedout_mq_timedsend(int que, int is_blocking);
void verify_mq_send(void);
void verify_timed_receive(void);
typedef struct {
char msg[ 50 ];
int size;
unsigned int priority;
} Test_Message_t;
Test_Message_t Predefined_Msgs[MAXMSG+1];
Test_Message_t Predefined_Msgs[MAXMSG+1] = {
{ "12345678", 9, MQ_PRIO_MAX-1 }, /* Max Length Message med */
{ "", 1, 1 }, /* NULL Message low */
{ "Last", 5, MQ_PRIO_MAX }, /* Queue Full Message hi */
{ "No Message", 0, MQ_PRIO_MAX-1 }, /* 0 length Message med */
{ "1", 2, 0 }, /* Cause Overflow Behavior */
};
int Priority_Order[MAXMSG+1] = { 2, 0, 3, 1, MAXMSG };
typedef struct {
mqd_t mq;
Test_Queue_Types index;
char *name;
int oflag;
int maxmsg;
int msgsize;
int count;
} Test_queue_type;
Test_queue_type Test_q[ NUMBER_OF_TEST_QUEUES + 1 ] =
{
{ 0, 0, "Qread", ( O_CREAT | O_RDONLY | O_NONBLOCK ), MAXMSG, MSGSIZE, 0 },
{ 0, 1, "Qwrite", ( O_CREAT | O_WRONLY | O_NONBLOCK ), MAXMSG, MSGSIZE, 0 },
{ 0, 2, "Qnoblock", ( O_CREAT | O_RDWR | O_NONBLOCK ), MAXMSG, MSGSIZE, 0 },
{ 0, 3, "Qblock", ( O_CREAT | O_RDWR ) , MAXMSG, MSGSIZE, 0 },
{ 0, 4, "Qdefault", ( O_CREAT | O_RDWR ) , 10, 16, 0 },
{ 0, 5, "mq6", ( O_CREAT | O_WRONLY | O_NONBLOCK ), MAXMSG, MSGSIZE, 0 },
{ 0, 6, "Qblock", ( O_RDWR ) , MAXMSG, MSGSIZE, 0 },
};
#define RW_NAME Test_q[ RW_QUEUE ].name
#define DEFAULT_NAME Test_q[ DEFAULT_RW ].name
#define RD_NAME Test_q[ RD_QUEUE ].name
#define WR_NAME Test_q[ WR_QUEUE ].name
#define BLOCKING_NAME Test_q[ BLOCKING ].name
#define CLOSED_NAME Test_q[ CLOSED ].name
#define RW_ATTR Test_q[ RW_QUEUE ].oflag
#define DEFAULT_ATTR Test_q[ DEFAULT_RW ].oflag
#define RD_ATTR Test_q[ RD_QUEUE ].oflag
#define WR_ATTR Test_q[ WR_QUEUE ].oflag
#define BLOCK_ATTR Test_q[ BLOCKING ].oflag
#define CLOSED_ATTR Test_q[ CLOSED ].oflag
/*
* Outputs a header at each test section.
*/
void Start_Test(
char *description
)
{
printf( "_______________%s\n", description );
}
void Validate_attributes(
mqd_t mq,
int oflag,
int msg_count
)
{
int status;
struct mq_attr attr;
status = mq_getattr( mq, &attr );
fatal_posix_service_status( status, 0, "mq_getattr valid return status");
if ( mq != Test_q[ DEFAULT_RW ].mq ){
fatal_int_service_status((int)attr.mq_maxmsg, MAXMSG, "maxmsg attribute" );
fatal_int_service_status((int)attr.mq_msgsize,MSGSIZE,"msgsize attribute");
}
fatal_int_service_status((int)attr.mq_curmsgs, msg_count, "count attribute" );
fatal_int_service_status((int)attr.mq_flags, oflag, "flag attribute" );
}
#define Get_Queue_Name( i ) Test_q[i].name
char *Build_Queue_Name(int i)
{
static char Queue_Name[PATH_MAX + 2];
sprintf(Queue_Name,"mq%d", i+1 );
return Queue_Name;
}
void open_test_queues(void)
{
struct mq_attr attr;
int status;
Test_queue_type *tq;
int que;
attr.mq_maxmsg = MAXMSG;
attr.mq_msgsize = MSGSIZE;
puts( "Init: Open Test Queues" );
for( que = 0; que < NUMBER_OF_TEST_QUEUES+1; que++ ) {
tq = &Test_q[ que ];
if ( que == DEFAULT_RW)
Test_q[que].mq = mq_open( tq->name, tq->oflag, 0x777, NULL );
else
Test_q[que].mq = mq_open( tq->name, tq->oflag, 0x777, &attr );
rtems_test_assert( Test_q[que].mq != (-1) );
}
status = mq_close( Test_q[NUMBER_OF_TEST_QUEUES].mq );
fatal_posix_service_status( status, 0, "mq_close duplicate message queue");
status = mq_close( Test_q[CLOSED].mq );
fatal_posix_service_status( status, 0, "mq_close message queue");
status = mq_unlink( CLOSED_NAME );
fatal_posix_service_status( status, 0, "mq_unlink message queue");
}
/*
* Opens CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES then leaves size queues
* opened but closes the rest.
*/
void validate_mq_open_error_codes(void)
{
int i;
mqd_t n_mq2;
struct mq_attr attr;
int status;
mqd_t open_mq[CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES + 1];
attr.mq_maxmsg = MAXMSG;
attr.mq_msgsize = MSGSIZE;
Start_Test( "mq_open errors" );
/*
* XXX EINVAL - inappropriate name was given for the message queue
*/
/*
* EINVAL - Create with negative maxmsg.
*/
attr.mq_maxmsg = -1;
puts( "Init: mq_open - Create with maxmsg (-1) (EINVAL)" );
n_mq2 = mq_open( "mq2", O_CREAT | O_RDONLY, 0x777, &attr);
fatal_posix_mqd( n_mq2, "mq_open error return status" );
fatal_posix_service_status( errno, EINVAL, "mq_open errno EINVAL");
attr.mq_maxmsg = MAXMSG;
/*
* EINVAL - Create withnegative msgsize.
*/
attr.mq_msgsize = -1;
puts( "Init: mq_open - Create with msgsize (-1) (EINVAL)" );
n_mq2 = mq_open( "mq2", O_CREAT | O_RDONLY, 0x777, &attr);
fatal_posix_mqd( n_mq2, "mq_open error return status" );
fatal_posix_service_status( errno, EINVAL, "mq_open errno EINVAL");
attr.mq_msgsize = MSGSIZE;
/*
* ENOENT - Open a non-created file.
*/
puts( "Init: mq_open - Open new mq without create flag (ENOENT)" );
n_mq2 = mq_open( "mq3", O_EXCL | O_RDONLY, 0x777, NULL);
fatal_posix_mqd( n_mq2, "mq_open error return status" );
fatal_posix_service_status( errno, ENOENT, "mq_open errno ENOENT");
/*
* XXX EINTR - call was interrupted by a signal
*/
/*
* ENAMETOOLONG - Give a name greater than PATH_MAX.
*/
puts( "Init: mq_open - Open with too long of a name (ENAMETOOLONG)" );
n_mq2 = mq_open( Get_Too_Long_Name(), O_CREAT | O_RDONLY, 0x777, NULL );
fatal_posix_mqd( n_mq2, "mq_open error return status" );
fatal_posix_service_status( errno, ENAMETOOLONG, "mq_open errno ENAMETOOLONG");
/*
* XXX - ENAMETOOLONG - Give a name greater than NAME_MAX
* Per implementation not possible.
*/
/*
* EEXIST - Create an existing queue.
*/
puts( "Init: mq_open - Create an Existing mq (EEXIST)" );
open_mq[0] = mq_open(
Build_Queue_Name(0), O_CREAT | O_RDWR | O_NONBLOCK, 0x777, NULL );
rtems_test_assert( open_mq[0] != (-1) );
n_mq2 = mq_open(
Build_Queue_Name(0), O_CREAT | O_EXCL | O_RDONLY, 0x777, NULL);
fatal_posix_mqd( n_mq2, "mq_open error return status" );
fatal_posix_service_status( errno, EEXIST, "mq_open errno EEXIST");
status = mq_unlink( Build_Queue_Name(0) );
fatal_posix_service_status( status, 0, "mq_unlink message queue");
status = mq_close( open_mq[0]);
fatal_posix_service_status( status, 0, "mq_close message queue");
/*
* Open maximum number of message queues
*/
puts( "Init: mq_open - SUCCESSFUL" );
for (i = 0; i < CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES; i++) {
open_mq[i] = mq_open(
Build_Queue_Name(i), O_CREAT | O_RDWR | O_NONBLOCK, 0x777, NULL );
rtems_test_assert( open_mq[i] != (-1) );
rtems_test_assert( open_mq[i] );
/*XXX - Isn't there a more general check */
/* JRS printf( "mq_open 0x%x %s\n", open_mq[i], Build_Queue_Name(i) ); */
}
/*
* XXX EACCES - permission to create is denied.
*/
/*
* XXX EACCES - queue exists permissions specified by o_flag are denied.
*/
/*
* XXX EMFILE - Too many message queues in use by the process
*/
/*
* ENFILE - Too many message queues open in the system
*/
puts( "Init: mq_open - system is out of resources (ENFILE)" );
n_mq2 = mq_open( Build_Queue_Name(i), O_CREAT | O_RDONLY, 0x777, NULL );
fatal_posix_mqd( n_mq2, "mq_open error return status" );
fatal_posix_service_status( errno, ENFILE, "mq_open errno ENFILE");
/*
* Unlink and Close all queues.
*/
puts( "Init: mq_close and mq_unlink (mq3...mqn) - SUCCESSFUL" );
for (i = 0; i < CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES; i++) {
status = mq_close( open_mq[i]);
fatal_posix_service_status( status, 0, "mq_close message queue");
status = mq_unlink( Build_Queue_Name(i) );
if ( status == -1 )
perror( "mq_unlink" );
fatal_posix_service_status( status, 0, "mq_unlink message queue");
/* JRS printf( "mq_close/mq_unlink 0x%x %s\n", open_mq[i], Build_Queue_Name(i) ); */
}
}
void validate_mq_unlink_error_codes(void)
{
int status;
Start_Test( "mq_unlink errors" );
/*
* XXX - EACCES Permission Denied
*/
/*
* ENAMETOOLONG - Give a name greater than PATH_MAX.
*/
puts( "Init: mq_unlink - mq_unlink with too long of a name (ENAMETOOLONG)" );
status = mq_unlink( Get_Too_Long_Name() );
fatal_posix_service_status( status, -1, "mq_unlink error return status");
fatal_posix_service_status( errno, ENAMETOOLONG, "mq_unlink errno ENAMETOOLONG");
/*
* XXX - ENAMETOOLONG - Give a name greater than NAME_MAX
* Per implementation not possible.
*/
/*
* ENOENT - Unlink an unopened queue
*/
puts( "Init: mq_unlink - A Queue not opened (ENOENT)" );
status = mq_unlink( CLOSED_NAME );
fatal_posix_service_status( status, -1, "mq_unlink error return status");
fatal_posix_service_status( errno, ENOENT, "mq_unlink errno ENOENT");
/*
* XXX - The following were not listed in the POSIX document as
* possible errors. Under other commands the EINVAL is
* given for these conditions.
*/
/*
* EINVAL - Unlink a queue with no name
*/
puts( "Init: mq_unlink (NULL) - EINVAL" );
status = mq_unlink( NULL );
fatal_posix_service_status( status, -1, "mq_unlink error return status");
fatal_posix_service_status( errno, EINVAL, "mq_unlink errno value");
/*
* EINVAL - Unlink a queue with a null name
*/
puts( "Init: mq_unlink (\"\") - EINVAL" );
status = mq_unlink( "" );
fatal_posix_service_status( status, -1, "mq_unlink error return status");
fatal_posix_service_status( errno, EINVAL, "mq_unlink errno value");
}
void validate_mq_close_error_codes(void)
{
int status;
Start_Test( "mq_close errors" );
/*
* EBADF - Close a queue that is not open.
*/
puts( "Init: mq_close - unopened queue (EBADF)" );
status = mq_close( Test_q[CLOSED].mq );
fatal_posix_service_status( status, -1, "mq_close error return status");
fatal_posix_service_status( errno, EBADF, "mq_close errno EBADF");
}
void validate_mq_getattr_error_codes(void)
{
struct mq_attr attr;
int status;
Start_Test( "mq_getattr errors" );
/*
* EBADF - Get the attributes from a closed queue.
*/
puts( "Init: mq_getattr - unopened queue (EBADF)" );
status = mq_getattr( Test_q[CLOSED].mq, &attr );
fatal_posix_service_status( status, -1, "mq_close error return status");
fatal_posix_service_status( errno, EBADF, "mq_close errno EBADF");
/*
* XXX - The following are not listed in the POSIX manual but
* may occur.
*/
/*
* EINVAL - NULL attributes
*/
puts( "Init: mq_getattr - NULL attributes (EINVAL)" );
status = mq_getattr( Test_q[RW_QUEUE].mq, NULL );
fatal_posix_service_status( status, -1, "mq_close error return status");
fatal_posix_service_status( errno, EINVAL, "mq_close errno EINVAL");
}
void Send_msg_to_que(
int que,
int msg
)
{
Test_Message_t *ptr = &Predefined_Msgs[msg];
int status;
status = mq_send( Test_q[que].mq, ptr->msg, ptr->size , ptr->priority );
fatal_posix_service_status( status, 0, "mq_send valid return status");
Test_q[que].count++;
}
void Show_send_msg_to_que(
char *task_name,
int que,
int msg
)
{
Test_Message_t *ptr = &Predefined_Msgs[msg];
printf( "%s mq_send - to %s msg: %s priority %d\n",
task_name, Test_q[que].name, ptr->msg, ptr->priority);
Send_msg_to_que( que, msg );
}
void verify_queues_full(
char *task_name
)
{
int que;
/*
* Validate that the queues are full.
*/
printf( "%s Verify Queues are full\n", task_name );
for( que = RW_QUEUE; que < CLOSED; que++ )
Validate_attributes( Test_q[que].mq, Test_q[que].oflag, Test_q[que].count );
}
void verify_queues_empty(
char *task_name
)
{
int que;
printf( "%s Verify Queues are empty\n", task_name );
for( que = RW_QUEUE; que < CLOSED; que++ )
Validate_attributes( Test_q[que].mq, Test_q[que].oflag, 0 );
}
int fill_message_queues(
char *task_name
)
{
int msg;
int que;
verify_queues_empty( task_name );
/*
* Fill Queue with predefined messages.
*/
printf( "%s Fill Queues with messages\n", task_name );
for(msg=0; msg<MAXMSG; msg++){
for( que = RW_QUEUE; que < CLOSED; que++ ) {
Send_msg_to_que( que, msg );
}
}
verify_queues_full( "Init:" );
return msg;
}
void Read_msg_from_que(
int que,
int msg
)
{
unsigned int priority;
Test_Message_t *ptr;
int status;
char message[100];
char err_msg[100];
ptr = &Predefined_Msgs[msg];
status = mq_receive(Test_q[ que ].mq, message, 100, &priority );
Test_q[que].count--;
sprintf( err_msg, "%s msg %s size failure", Test_q[ que ].name, ptr->msg );
fatal_int_service_status( status, ptr->size, err_msg );
rtems_test_assert( !strcmp( message, ptr->msg ) );
strcpy( message, "No Message" );
sprintf( err_msg,"%s msg %s size failure", Test_q[ que ].name, ptr->msg );
fatal_int_service_status(priority, ptr->priority, err_msg );
}
int empty_message_queues(
char *task_name
)
{
int que;
int i;
printf( "%s Empty all Queues\n", task_name );
for( que = RW_QUEUE; que < CLOSED; que++ ) {
for(i=0; Test_q[que].count != 0; i++ )
Read_msg_from_que( que, Priority_Order[i] );
Validate_attributes( Test_q[ que].mq, Test_q[ que ].oflag, 0 );
}
return 0;
}
/*
* Returns the number of messages queued after the test on the
* first queue.
*/
int validate_mq_send_error_codes(void)
{
int status;
int i;
char *str;
Start_Test( "mq_send errors" );
/*
* EBADF - Write to a closed queue.
*/
puts( "Init: mq_send - Closed message queue (EBADF)" );
status = mq_send( Test_q[CLOSED].mq, "", 1, 0 );
fatal_posix_service_status( status, -1, "mq_send error return status");
fatal_posix_service_status( errno, EBADF, "mq_send errno EBADF");
/*
* EBADF - Write to a read only queue.
*/
puts( "Init: mq_send - Read only message queue (EBADF)" );
status = mq_send( Test_q[ RD_QUEUE ].mq, "", 1, 0 );
fatal_posix_service_status( status, -1, "mq_send error return status");
fatal_posix_service_status( errno, EBADF, "mq_send errno EBADF");
/*
* XXX - EINTR Signal interrupted the call.
*
puts( "Init: mq_send - UNSUCCESSFUL (EINTR)" );
status = mq_send( Test_q, "", 0xffff, 0 );
fatal_posix_service_status( status, -1, "mq_send error return status");
fatal_posix_service_status( errno, E, "mq_send errno E");
*/
/*
* EINVAL priority is out of range.
*/
puts( "Init: mq_send - Priority out of range (EINVAL)" );
status = mq_send( Test_q[ RW_QUEUE ].mq, "", 1, MQ_PRIO_MAX + 1 );
fatal_posix_service_status( status, -1, "mq_send error return status");
fatal_posix_service_status( errno, EINVAL, "mq_send errno EINVAL");
/*
* EMSGSIZE - Message size larger than msg_len
* Validates that msgsize is stored correctly.
*/
puts( "Init: mq_send - Message longer than msg_len (EMSGSIZE)" );
status = mq_send( Test_q[ RW_QUEUE ].mq, "", MSGSIZE+1, 0 );
fatal_posix_service_status( status, -1, "mq_send error return status");
fatal_posix_service_status( errno, EMSGSIZE, "mq_send errno EMSGSIZE");
i = fill_message_queues( "Init:" );
/*
* ENOSYS - send not supported
puts( "Init: mq_send - Blocking Queue overflow (ENOSYS)" );
status = mq_send( n_mq1, Predefined_Msgs[i], 0, 0 );
fatal_posix_service_status( status, -1, "mq_send error return status");
fatal_posix_service_status( errno, EBADF, "mq_send errno EBADF");
status = mq_close( n_mq1 );
fatal_posix_service_status( status, 0, "mq_close message queue");
status = mq_unlink( "read_only" );
fatal_posix_service_status( status, 0, "mq_unlink message queue");
*/
/*
* EAGAIN - O_NONBLOCK and message queue is full.
*/
puts( "Init: mq_send - on a FULL non-blocking queue with (EAGAIN)" );
str = Predefined_Msgs[i].msg;
status = mq_send(Test_q[RW_QUEUE].mq, str, 0, 0 );
fatal_posix_service_status( status, -1, "mq_send error return status");
fatal_posix_service_status( errno, EAGAIN, "mq_send errno EAGAIN");
return i-1;
}
void validate_mq_receive_error_codes(void)
{
int status;
char message[100];
unsigned int priority;
Start_Test( "mq_receive errors" );
/*
* EBADF - Not A Valid Message Queue
*/
puts( "Init: mq_receive - Unopened message queue (EBADF)" );
status = mq_receive( Test_q[CLOSED].mq, message, 100, &priority );
fatal_posix_service_status( status, -1, "mq_ error return status");
fatal_posix_service_status( errno, EBADF, "mq_receive errno EBADF");
/*
* EBADF - Queue not opened to read
*/
puts( "Init: mq_receive - Write only queue (EBADF)" );
status = mq_receive( Test_q[WR_QUEUE].mq, message, 100, &priority );
fatal_posix_service_status( status, -1, "mq_ error return status");
fatal_posix_service_status( errno, EBADF, "mq_receive errno EBADF");
/*
* EMSGSIZE - Size is less than the message size attribute
*/
puts( "Init: mq_receive - Size is less than the message (EMSGSIZE)" );
status = mq_receive(
Test_q[RW_QUEUE].mq, message, Predefined_Msgs[0].size-1, &priority );
fatal_posix_service_status( status, -1, "mq_ error return status");
fatal_posix_service_status( errno, EMSGSIZE, "mq_receive errno EMSGSIZE");
/*
* EAGAIN - O_NONBLOCK and Queue is empty
*/
verify_queues_full( "Init:" );
empty_message_queues( "Init:" );
puts( "Init: mq_receive - Queue is empty (EAGAIN)" );
status = mq_receive( Test_q[RW_QUEUE].mq, message, 100, &priority );
fatal_posix_service_status( status, -1, "mq_ error return status");
fatal_posix_service_status( errno, EAGAIN, "mq_receive errno EAGAIN");
/*
* XXX - EINTR - Interrupted by a signal
*/
/*
* XXX - EBADMSG - a data corruption problem.
*/
/*
* XXX - ENOSYS - mq_receive not supported
*/
}
void verify_open_functionality(void)
{
#if 0
mqd_t n_mq;
#endif
Start_Test( "mq_open functionality" );
/*
* Validate a second open returns the same message queue.
*/
#if 0
puts( "Init: mq_open - Open an existing mq ( same id )" );
n_mq = mq_open( RD_NAME, 0 );
fatal_posix_service_status(
rtems_test_assert( n_mq == Test_q[RD_QUEUE].mq );
#endif
}
void verify_unlink_functionality(void)
{
mqd_t n_mq;
int status;
Start_Test( "mq_unlink functionality" );
/*
* Unlink the message queue, then verify an open of the same name produces a
* different message queue.
*/
puts( "Init: Unlink and Open without closing SUCCESSFUL" );
status = mq_unlink( DEFAULT_NAME );
fatal_posix_service_status( status, 0, "mq_unlink locked message queue");
n_mq = mq_open( DEFAULT_NAME, DEFAULT_ATTR, 0x777, NULL );
rtems_test_assert( n_mq != (-1) );
rtems_test_assert( n_mq != Test_q[ DEFAULT_RW ].mq );
status = mq_unlink( DEFAULT_NAME );
fatal_posix_service_status( status, 0, "mq_unlink locked message queue");
status = mq_close( Test_q[ DEFAULT_RW ].mq );
fatal_posix_service_status( status, 0, "mq_close message queue");
Test_q[ DEFAULT_RW ].mq = n_mq;
}
void verify_close_functionality(void)
{
int i;
int status;
Start_Test( "Unlink and Close All Files" );
for (i=0; i<DEFAULT_RW; i++) {
status = mq_unlink( Get_Queue_Name(i) );
fatal_posix_service_status( status, 0, "mq_unlink message queue");
status = mq_close( Test_q[i].mq );
fatal_posix_service_status( status, 0, "mq_close message queue");
}
}
void verify_timed_send_queue(
int que,
int is_blocking
)
{
struct timespec timeout;
struct timeval tv1, tv2, tv3;
struct timezone tz1, tz2;
int len;
int status;
char *msg;
printf( "Init: mq_timedsend - on queue %s ", Test_q[que].name);
len = Predefined_Msgs[MAXMSG].size;
msg = Predefined_Msgs[MAXMSG].msg;
gettimeofday( &tv1, &tz1 );
timeout.tv_sec = tv1.tv_sec + 1;
timeout.tv_nsec = tv1.tv_usec * 1000;
status = mq_timedsend( Test_q[que].mq, msg, len , 0, &timeout );
gettimeofday( &tv2, &tz2 );
tv3.tv_sec = tv2.tv_sec - tv1.tv_sec;
tv3.tv_usec = tv2.tv_usec - tv1.tv_usec;
if ( is_blocking ) { /* Don't verify the non-blocking queue */
fatal_int_service_status( status, -1, "mq_timedsend status" );
fatal_posix_service_status( errno, ETIMEDOUT, "errno ETIMEDOUT" );
}
printf( "Init: %ld sec %ld us\n", (long)tv3.tv_sec, (long)tv3.tv_usec );
if ( que == DEFAULT_RW )
Test_q[que].count++;
}
void verify_timed_send(void)
{
int que;
Start_Test( "mq_timedsend" );
for( que = RW_QUEUE; que < CLOSED; que++ ) {
if ( que == BLOCKING )
verify_timed_send_queue( que, 1 );
else
verify_timed_send_queue( que, 0 );
}
}
void verify_timed_receive_queue(
char *task_name,
int que,
int is_blocking
)
{
char message[ 100 ];
unsigned int priority;
struct timespec tm;
struct timeval tv1, tv2, tv3;
struct timezone tz1, tz2;
int status;
printf(
"Init: %s mq_timedreceive - on queue %s ",
task_name,
Test_q[que].name
);
gettimeofday( &tv1, &tz1 );
tm.tv_sec = tv1.tv_sec + 1;
tm.tv_nsec = tv1.tv_usec * 1000;
status = mq_timedreceive( Test_q[ que ].mq, message, 100, &priority, &tm );
gettimeofday( &tv2, &tz2 );
tv3.tv_sec = tv2.tv_sec - tv1.tv_sec;
tv3.tv_usec = tv2.tv_usec - tv1.tv_usec;
fatal_int_service_status( status, -1, "mq_timedreceive status");
if ( is_blocking )
fatal_posix_service_status( errno, ETIMEDOUT, "errno ETIMEDOUT");
printf( "Init: %ld sec %ld us\n", (long)tv3.tv_sec, (long)tv3.tv_usec );
}
void verify_timed_receive(void)
{
int que;
Start_Test( "mq_timedreceive" );
for( que = RW_QUEUE; que < CLOSED; que++ ) {
if (( que == BLOCKING ) || ( que == DEFAULT_RW ))
verify_timed_receive_queue( "Init:", que, 1 );
else
verify_timed_receive_queue( "Init:", que, 0 );
}
}
#if (0)
void verify_set_attr(void)
{
struct mq_attr save_attr[ NUMBER_OF_TEST_QUEUES ];
struct mq_attr attr;
int i;
int status;
attr.mq_maxmsg = 0;
attr.mq_msgsize = 0;
Start_Test( "mq_setattr" );
puts( "Init: set_attr all queues to blocking" );
for(i=0; i<CLOSED; i++) {
attr.mq_flags = Test_q[i].oflag & (~O_NONBLOCK );
status = mq_setattr( Test_q[i].mq, &attr, &save_attr[i] );
fatal_int_service_status( status, 0, "mq_setattr valid return status");
Validate_attributes( Test_q[i].mq, attr.mq_flags, 0 );
}
for( i = RW_QUEUE; i < CLOSED; i++ ) {
verify_timed_receive_queue( "Init:", i, 1 );
}
for(i=0; i<CLOSED; i++) {
attr.mq_flags = Test_q[i].oflag & (~O_NONBLOCK );
status = mq_setattr( Test_q[i].mq, &save_attr[i], NULL );
fatal_int_service_status( status, 0, "mq_setattr valid return status");
Validate_attributes( Test_q[i].mq, Test_q[i].oflag, 0 );
}
}
#endif
void wait_for_signal(
sigset_t *waitset,
int sec,
int expect_signal
)
{
siginfo_t siginfo;
int status;
struct timespec timeout;
int signo;
siginfo.si_code = -1;
siginfo.si_signo = -1;
siginfo.si_value.sival_int = -1;
timeout.tv_sec = sec;
timeout.tv_nsec = 0;
status = sigemptyset( waitset );
rtems_test_assert( !status );
status = sigaddset( waitset, SIGUSR1 );
rtems_test_assert( !status );
printf( "waiting on any signal for %d seconds.\n", sec );
signo = sigtimedwait( waitset, &siginfo, &timeout );
if (expect_signal) {
fatal_int_service_status( signo, SIGUSR1, "got SISUSR1" );
} else {
fatal_int_service_status( signo, -1, "error return status");
fatal_posix_service_status( errno, EAGAIN, "errno EAGAIN");
}
}
void verify_notify(void)
{
struct sigevent event;
int status;
timer_t timer_id;
sigset_t set;
Start_Test( "mq_notify" );
/* timer create */
event.sigev_notify = SIGEV_SIGNAL;
event.sigev_signo = SIGUSR1;
if (timer_create (CLOCK_REALTIME, &event, &timer_id) == -1)
fatal_posix_service_status( errno, 0, "errno ETIMEDOUT");
/* block the timer signal */
sigemptyset( &set );
sigaddset( &set, SIGUSR1 );
pthread_sigmask( SIG_BLOCK, &set, NULL );
/*
* EBADF - Not A Valid Message Queue
*/
puts( "Init: mq_notify - Unopened message queue (EBADF)" );
status = mq_notify( Test_q[CLOSED].mq, NULL );
fatal_posix_service_status( status, -1, "mq_ error return status");
fatal_posix_service_status( errno, EBADF, "mq_receive errno EBADF");
/*
* Create ...
*/
/*
* XXX setup notification
*/
printf( "_____mq_notify - notify when %s gets a message\n",RW_NAME);
status = mq_notify( Test_q[RW_QUEUE].mq, &event );
fatal_posix_service_status( status, 0, "mq_notify valid status");
wait_for_signal( &set, 3, 0 );
/*
* Send and verify signal occurs and registration is removed.
*/
puts( "Init: Verify Signal when send" );
Show_send_msg_to_que( "Init:", RW_QUEUE, 0 );
wait_for_signal( &set, 3, 1 );
Read_msg_from_que( RW_QUEUE, 0 );
puts( "Init: Verify No Signal when send" );
Show_send_msg_to_que( "Init:", RW_QUEUE, 0 );
wait_for_signal( &set, 3, 0 );
Read_msg_from_que( RW_QUEUE, 0 );
/*
* EBUSY - Already Registered
*/
printf( "____mq_notify - notify when %s gets a message\n",RD_NAME);
status = mq_notify( Test_q[RW_QUEUE].mq, &event );
fatal_posix_service_status( status, 0, "mq_notify valid status");
wait_for_signal( &set, 3, 0 );
puts( "Init: mq_notify - (EBUSY)" );
status = mq_notify( Test_q[RW_QUEUE].mq, &event );
fatal_posix_service_status( status, -1, "mq_notify error return status");
fatal_posix_service_status( errno, EBUSY, "mq_notify errno EBUSY");
/*
* Verify NULL removes registration.
*/
puts( "Init: mq_notify - Remove notification with null" );
status = mq_notify( Test_q[RW_QUEUE].mq, NULL );
fatal_posix_service_status( status, 0, "mq_notify valid status");
puts( "Init: Verify No Signal when send" );
Show_send_msg_to_que( "Init:", RW_QUEUE, 0 );
wait_for_signal( &set, 3, 0 );
Read_msg_from_que( RW_QUEUE, 0 );
}
void verify_with_threads(void)
{
int status;
pthread_t id;
Test_Message_t *ptr;
#if 0
unsigned int priority;
char message[100];
#endif
#if 0
/*
* Create a task then block until the task sends the message.
* Task tests set attributes so one queue will have a thread
* blocked while attributes are changed.
*/
Start_Test( "multi-thread Task 4 Receive Test" );
status = pthread_create( &id, NULL, Task_4, NULL );
rtems_test_assert( !status );
puts( "Init: mq_receive - Empty queue changes to non-blocking (EAGAIN)" );
status = mq_receive( Test_q[BLOCKING].mq, message, 100, &priority );
fatal_int_service_status( status, -1, "mq_receive error return status");
fatal_posix_service_status( errno, EAGAIN, "mq_receive errno EAGAIN");
print_current_time( "Init: ", "" );
#endif
/*
* Create a task then block until the task sends the message.
* Task tests set attributes so one queue will have a thread
* blocked while attributes are changed.
*/
Start_Test( "multi-thread Task 1 Test" );
status = pthread_create( &id, NULL, Task_1, NULL );
rtems_test_assert( !status );
Read_msg_from_que( BLOCKING, 0 ); /* Block until init writes */
print_current_time( "Init: ", "" );
#if 0
/*
* Fill the queue then create a task then block until the task receives a message.
* Task tests set attributes so one queue will have a thread
* blocked while attributes are changed.
*/
Start_Test( "multi-thread Task 4 Send Test" );
fill_message_queues( "Init:" );
status = pthread_create( &id, NULL, Task_4, NULL );
rtems_test_assert( !status );
puts( "Init: mq_send - Full queue changes to non-blocking (EAGAIN)" );
status = mq_send(Test_q[BLOCKING].mq, message, 0, 0 );
fatal_posix_service_status( status, -1, "mq_send error return status");
fatal_posix_service_status( errno, EAGAIN, "mq_send errno EAGAIN");
verify_queues_full( "Init:" );
empty_message_queues( "Init:" );
#endif
/*
* Create a task then block until the task reads a message.
*/
Start_Test( "multi-thread Task 2 Test" );
fill_message_queues( "Init:" );
status = pthread_create( &id, NULL, Task_2, NULL );
rtems_test_assert( !status );
Show_send_msg_to_que( "Init:", BLOCKING, Priority_Order[0] );
print_current_time( "Init: ", "" );
verify_queues_full( "Init:" );
empty_message_queues( "Init:" );
/*
* Create a task then block until it deletes and closes all queues.
* EBADF - Queue unlinked and closed while blocked
*/
Start_Test( "multi-thread Task 3 Test" );
fill_message_queues( "Init:" );
status = pthread_create( &id, NULL, Task_3, NULL );
rtems_test_assert( !status );
puts( "Init: mq_send - Block while thread deletes queue (EBADF)" );
ptr = &Predefined_Msgs[0];
status = mq_send( Test_q[BLOCKING].mq, ptr->msg, ptr->size , ptr->priority );
fatal_posix_service_status( status, -1, "mq_send error return status");
fatal_posix_service_status( errno, EBADF, "mq_send errno EBADF");
}
void validate_mq_setattr(void)
{
struct mq_attr attr;
struct mq_attr save_attr[ NUMBER_OF_TEST_QUEUES ];
int status;
int i;
/*
* EBADF - Get the attributes from a closed queue.
*/
puts( "Task1:mq_setattr - unopened queue (EBADF)" );
status = mq_setattr( Test_q[CLOSED].mq, &attr, NULL );
fatal_posix_service_status( status, -1, "mq_setattr error return status");
fatal_posix_service_status( errno, EBADF, "mq_setattr errno EBADF");
/*
* XXX - The following are not listed in the POSIX manual but
* may occur.
*/
/*
* EINVAL - NULL attributes
*/
puts( "Task1:mq_setattr - NULL attributes (EINVAL)" );
status = mq_setattr( Test_q[RW_QUEUE].mq, NULL, NULL );
fatal_posix_service_status( status, -1, "mq_setattr error return status");
fatal_posix_service_status( errno, EINVAL, "mq_setattr errno EINVAL");
/*
* Verify change queues to blocking, by verifying all queues block
* for a timed receive.
*/
puts( "Init: set_attr all queues to blocking" );
for(i=0; i<CLOSED; i++) {
attr.mq_flags = Test_q[i].oflag & (~O_NONBLOCK );
status = mq_setattr( Test_q[i].mq, &attr, &save_attr[i] );
fatal_int_service_status( status, 0, "mq_setattr valid return status");
Validate_attributes( Test_q[i].mq, attr.mq_flags, 0 );
}
for( i = RW_QUEUE; i < CLOSED; i++ ) {
verify_timed_receive_queue( "Init:", i, 1 );
}
/*
* Restore restore all queues to their old attribute.
*/
for(i=0; i<CLOSED; i++) {
status = mq_setattr( Test_q[i].mq, &save_attr[i], NULL );
fatal_int_service_status( status, 0, "mq_setattr valid return status");
Validate_attributes( Test_q[i].mq, Test_q[i].oflag, 0 );
}
}
void verify_timedout_mq_timedreceive(
char *task_name,
int que,
int is_blocking
)
{
char message[ 100 ];
struct timespec tm;
struct timeval tv1, tv2, tv3;
struct timezone tz1, tz2;
int status;
printf(
"Init: %s verify_timedout_mq_timedreceive - on queue %s ",
task_name,
Test_q[que].name
);
gettimeofday( &tv1, &tz1 );
tm.tv_sec = tv1.tv_sec - 1;
tm.tv_nsec = tv1.tv_usec * 1000;
status = mq_timedreceive( Test_q[ que ].mq, message, 100, NULL, &tm );
gettimeofday( &tv2, &tz2 );
tv3.tv_sec = tv2.tv_sec - tv1.tv_sec;
tv3.tv_usec = tv2.tv_usec - tv1.tv_usec;
fatal_int_service_status( status, -1, "mq_timedreceive status");
/* FIXME: This is wrong. */
printf( "Init: %ld sec %ld us\n", (long)tv3.tv_sec, (long)tv3.tv_usec );
}
void verify_mq_receive(void)
{
int que;
Start_Test( "mq_timedout_receive" );
for( que = RW_QUEUE; que < CLOSED; que++ ) {
if (( que == BLOCKING ) || ( que == DEFAULT_RW ))
break;
else
verify_timedout_mq_timedreceive( "Init:", que, 0 );
}
}
void verify_timedout_mq_timedsend(
int que,
int is_blocking
)
{
struct timespec timeout;
struct timeval tv1, tv2, tv3;
struct timezone tz1, tz2;
int len;
char *msg;
printf( "Init: verify_timedout_mq_timedsend - on queue %s ", Test_q[que].name);
len = Predefined_Msgs[MAXMSG].size;
msg = Predefined_Msgs[MAXMSG].msg;
gettimeofday( &tv1, &tz1 );
timeout.tv_sec = tv1.tv_sec - 1;
timeout.tv_nsec = tv1.tv_usec * 1000;
(void) mq_timedsend( Test_q[que].mq, msg, len , 0, &timeout );
gettimeofday( &tv2, &tz2 );
tv3.tv_sec = tv2.tv_sec - tv1.tv_sec;
tv3.tv_usec = tv2.tv_usec - tv1.tv_usec;
printf( "Init: %ld sec %ld us\n", (long)tv3.tv_sec, (long)tv3.tv_usec );
if ( que == DEFAULT_RW )
Test_q[que].count++;
}
void verify_mq_send(void)
{
int que;
Start_Test( "verify_timedout_mq_timedsend" );
for( que = RW_QUEUE; que < CLOSED; que++ ) {
if ( que == BLOCKING )
verify_timedout_mq_timedsend( que, 1 );
else
verify_timedout_mq_timedsend( que, 0 );
}
}
void *POSIX_Init(
void *argument
)
{
TEST_BEGIN();
validate_mq_open_error_codes( );
open_test_queues();
validate_mq_unlink_error_codes();
validate_mq_close_error_codes();
verify_unlink_functionality();
validate_mq_setattr( );
validate_mq_send_error_codes();
validate_mq_getattr_error_codes();
verify_timed_send();
validate_mq_receive_error_codes();
verify_timed_receive();
verify_open_functionality();
verify_notify();
verify_with_threads();
verify_mq_receive();
verify_mq_send();
TEST_END();
rtems_test_exit( 0 );
return NULL; /* just so the compiler thinks we returned something */
}
void *Task_1 (
void *argument
)
{
/* Block Waiting for a message */
print_current_time( "Task_1: ", "" );
Show_send_msg_to_que( "Task_1:", BLOCKING, 0 );
puts( "Task_1: pthread_exit" );
pthread_exit( NULL );
/* switch to Init */
rtems_test_assert( 0 );
return NULL; /* just so the compiler thinks we returned something */
}
void *Task_2(
void *argument
)
{
print_current_time( "Task_2: ", "" );
/* Block waiting to send a message */
verify_queues_full( "Task_2:" );
Read_msg_from_que( BLOCKING, Priority_Order[0] ); /* Cause context switch */
puts( "Task_2: pthread_exit" );
pthread_exit( NULL );
/* switch to Init */
return NULL; /* just so the compiler thinks we returned something */
}
void *Task_3 (
void *argument
)
{
print_current_time( "Task_3: ", "" );
/*
* close and unlink all queues.
*/
verify_close_functionality();
puts( "Task_3: pthread_exit" );
pthread_exit( NULL );
/* switch to Init */
return NULL; /* just so the compiler thinks we returned something */
}
void *Task_4 (
void *argument
)
{
struct mq_attr attr;
int status;
int count;
print_current_time( "Task_4: ", "" );
/*
* Set the count to the number of messages in the queue.
*/
status = mq_getattr( Test_q[BLOCKING].mq, &attr );
fatal_posix_service_status( status, 0, "mq_getattr valid return status");
count = attr.mq_curmsgs;
puts("Task_4: Set queue to non-blocking");
attr.mq_flags = Test_q[BLOCKING].oflag | O_NONBLOCK;
status = mq_setattr( Test_q[BLOCKING].mq, &attr, NULL );
fatal_int_service_status( status, 0, "mq_setattr valid return status");
Validate_attributes( Test_q[BLOCKING].mq, attr.mq_flags, count );
puts("Task_4: Return queue to blocking");
attr.mq_flags = Test_q[BLOCKING].oflag;
status = mq_setattr( Test_q[BLOCKING].mq, &attr, NULL );
fatal_int_service_status( status, 0, "mq_setattr valid return status");
Validate_attributes( Test_q[BLOCKING].mq, attr.mq_flags, count );
puts( "Task_4: pthread_exit" );
pthread_exit( NULL );
/* switch to Init */
return NULL; /* just so the compiler thinks we returned something */
}
void *Task_5 (
void *argument
)
{
print_current_time( "Task_5: ", "" );
puts( "Task_5: pthread_exit" );
pthread_exit( NULL );
/* switch to Init */
return NULL; /* just so the compiler thinks we returned something */
}