view waaad/tests/testmeq.c @ 401:860f41038ea2

Updated copyright information
author Sebastien Decugis <sdecugis@nict.go.jp>
date Tue, 02 Jun 2009 15:10:55 +0900
parents 316bb3f38d04
children
line wrap: on
line source

/*********************************************************************************************************
* Software License Agreement (BSD License)                                                               *
* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
*													 *
* Copyright (c) 2009, WIDE Project and NICT								 *
* All rights reserved.											 *
* 													 *
* Redistribution and use of this software in source and binary forms, with or without modification, are  *
* permitted provided that the following conditions are met:						 *
* 													 *
* * Redistributions of source code must retain the above 						 *
*   copyright notice, this list of conditions and the 							 *
*   following disclaimer.										 *
*    													 *
* * Redistributions in binary form must reproduce the above 						 *
*   copyright notice, this list of conditions and the 							 *
*   following disclaimer in the documentation and/or other						 *
*   materials provided with the distribution.								 *
* 													 *
* * Neither the name of the WIDE Project or NICT nor the 						 *
*   names of its contributors may be used to endorse or 						 *
*   promote products derived from this software without 						 *
*   specific prior written permission of WIDE Project and 						 *
*   NICT.												 *
* 													 *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
*********************************************************************************************************/

#include "tests.h"

/* Test for the message queues */

/* Structure that is passed to the test function */
typedef struct {
	meq_t             * queue; /* pointer to the queue */
	pthread_barrier_t * bar;   /* if not NULL, barrier to synchronize before getting messages */
	struct timespec   * ts;	   /* if not NULL, use a timedget instead of a get */
	int		  nbr;	   /* number of messages to retrieve from the queue */
} test_data_t;

/* The test function to be threaded */
static void * test_fct(void * data)
{
	int ret = 0, i;
	msg_t * msg = NULL;
	
	test_data_t * td = (test_data_t *) data;
	
	if (td->bar != NULL) {
		ret = pthread_barrier_wait(td->bar);
		if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
			CHECK( 0, ret);
		}
	}
	
	for (i=0; i< td->nbr; i++) {
		if (td->ts != NULL) {
			CHECK( 0, meq_timedget(td->queue, &msg, td->ts) );
		} else {
			CHECK( 0, meq_get(td->queue, &msg) );
		}
	}
	
	return NULL;
}

/* Main test routine */
int main(int argc, char *argv[])
{
	struct timespec ts;
	
	msg_t * msg1 = NULL;
	msg_t * msg2 = NULL;
	msg_t * msg3 = NULL;
	
	/* First, initialize the daemon modules */
	INIT_WAAAD();
	
	/* Set an alarm */
	alarm(5);
	
	/* Prolog: create the messages */
	{
		dict_object_t * acr_model = NULL;
		dict_object_t * cer_model = NULL;
		dict_object_t * dwr_model = NULL;

		CHECK( 0, dict_search ( DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", 		&acr_model, ENOENT ) );
		CHECK( 0, dict_search ( DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", 	&cer_model, ENOENT ) );
		CHECK( 0, dict_search ( DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request",		&dwr_model, ENOENT ) );
		CHECK( 0, msg_new ( acr_model, MSGFL_FROM_TEMPLATE, &msg1 ) );
		CHECK( 0, msg_new ( cer_model, MSGFL_FROM_TEMPLATE, &msg2 ) );
		CHECK( 0, msg_new ( dwr_model, MSGFL_FROM_TEMPLATE, &msg3 ) );
	}

	/* Basic operation */
	{
		meq_t * queue = NULL;
		int count;
		msg_t * msg  = NULL;
		
		/* Create the queue */
		CHECK( 0, meq_new(&queue) );
		
		/* Check the count is 0 */
		CHECK( 0, meq_length(queue, &count) );
		CHECK( 0, count);
		
		/* Now enqueue */
		CHECK( 0, meq_post(queue, msg1) );
		CHECK( 0, meq_post(queue, msg2) );
		CHECK( 0, meq_post(queue, msg3) );
		
		/* Check the count is 3 */
		CHECK( 0, meq_length(queue, &count) );
		CHECK( 3, count);
		
		/* Retrieve the first message using meq_get */
		CHECK( 0, meq_get(queue, &msg) );
		CHECK( msg1, msg);
		CHECK( 0, meq_length(queue, &count) );
		CHECK( 2, count);
		
		/* Retrieve the second message using meq_timedget */
		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
		ts.tv_sec += 1; /* Set the timeout to 1 second */
		CHECK( 0, meq_timedget(queue, &msg, &ts) );
		CHECK( msg2, msg);
		CHECK( 0, meq_length(queue, &count) );
		CHECK( 1, count);
		
		/* Retrieve the third message using meq_tryget */
		CHECK( 0, meq_tryget(queue, &msg) );
		CHECK( msg3, msg);
		CHECK( 0, meq_length(queue, &count) );
		CHECK( 0, count);
		
		/* Check that another meq_tryget does not block */
		CHECK( EWOULDBLOCK, meq_tryget(queue, &msg) );
		CHECK( 0, meq_length(queue, &count) );
		CHECK( 0, count);
		
		/* We're done for basic tests */
		CHECK( 0, meq_del(&queue) );
	}
	
	/* Test robustness, ensure no messages are lost */
	{
#define NBR_MSG		200
#define NBR_THREADS	60
		meq_t      		*queue = NULL;
		pthread_barrier_t	 bar;
		test_data_t		 td_1;
		test_data_t		 td_2;
		msg_t	   		*msgs[NBR_MSG * NBR_THREADS * 2];
		pthread_t  		 thr [NBR_THREADS * 2];
		dict_object_t 		*dwr_model = NULL;
		int 			 count;
		int			 i;
		
		/* Create the queue */
		CHECK( 0, meq_new(&queue) );
		
		/* Create the barrier */
		CHECK( 0, pthread_barrier_init(&bar, NULL, NBR_THREADS * 2 + 1) );
		
		/* Initialize the ts */
		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
		ts.tv_sec += 2; /* Set the timeout to 2 second */
		
		/* Create the messages */
		CHECK( 0, dict_search ( DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request", &dwr_model, ENOENT ) );
		for (i = 0; i < NBR_MSG * NBR_THREADS * 2; i++) {
			CHECK( 0, msg_new ( dwr_model, 0, &msgs[i] ) );
		}
		
		/* Initialize the test data structures */
		td_1.queue = queue;
		td_1.bar = &bar;
		td_1.ts  = &ts;
		td_1.nbr = NBR_MSG;
		td_2.queue = queue;
		td_2.bar = &bar;
		td_2.ts  = NULL;
		td_2.nbr = NBR_MSG;
		
		/* Create the threads */
		for (i=0; i < NBR_THREADS * 2; i++) {
			CHECK( 0, pthread_create( &thr[i], NULL, test_fct, (i & 1) ? &td_1 : &td_2 ) );
		}
		
		/* Synchronize everyone */
		{
			int ret = pthread_barrier_wait(&bar);
			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
				CHECK( 0, ret);
			}
		}
		
		/* Now post all the messages */
		for (i=0; i < NBR_MSG * NBR_THREADS * 2; i++) {
			CHECK( 0, meq_post(queue, msgs[i]) );
		}
		
		/* Join all threads. This would block if messages are lost... */
		for (i=0; i < NBR_THREADS * 2; i++) {
			CHECK( 0, pthread_join( thr[i], NULL ) );
		}
		
		/* Check the count of the queue is back to 0 */
		CHECK( 0, meq_length(queue, &count) );
		CHECK( 0, count);
		
		/* Destroy this queue and the messages */
		CHECK( 0, meq_del(&queue) );
		for (i=0; i < NBR_MSG * NBR_THREADS * 2; i++) {
			CHECK( 0, msg_free(  msgs[i], 1 ) );
		}
	}
	
	/* Test thread cancelation */
	{
		meq_t      		*queue = NULL;
		pthread_barrier_t	 bar;
		test_data_t		 td;
		pthread_t		 th;
		
		/* Create the queue */
		CHECK( 0, meq_new(&queue) );
		
		/* Create the barrier */
		CHECK( 0, pthread_barrier_init(&bar, NULL, 2) );
		
		/* Initialize the ts */
		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
		ts.tv_sec += 2; /* Set the timeout to 2 second */
		
		/* Initialize the test data structures */
		td.queue = queue;
		td.bar = &bar;
		td.ts  = &ts;
		td.nbr = 1;
		
		/* Create the thread */
		CHECK( 0, pthread_create( &th, NULL, test_fct, &td ) );
		
		/* Wait for the thread to be running */
		{
			int ret = pthread_barrier_wait(&bar);
			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
				CHECK( 0, ret);
			}
		}
		
		/* Now cancel the thread */
		CHECK( 0, pthread_cancel( th ) );
		
		/* Join it */
		CHECK( 0, pthread_join( th, NULL ) );
		
		/* Do the same with the other function */
		td.ts  = NULL;
		
		/* Create the thread */
		CHECK( 0, pthread_create( &th, NULL, test_fct, &td ) );
		
		/* Wait for the thread to be running */
		{
			int ret = pthread_barrier_wait(&bar);
			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
				CHECK( 0, ret);
			}
		}
		
		/* Now cancel the thread */
		CHECK( 0, pthread_cancel( th ) );
		
		/* Join it */
		CHECK( 0, pthread_join( th, NULL ) );
		
		/* Destroy the queue */
		CHECK( 0, meq_del(&queue) );
	}
	
	/* Delete the messages */
	CHECK( 0, msg_free( msg1, 1 ) );
	CHECK( 0, msg_free( msg2, 1 ) );
	CHECK( 0, msg_free( msg3, 1 ) );

	/* That's all for the tests yet */
	PASSTEST();
} 
	
"Welcome to our mercurial repository"