view waaad/tests/testrt.c @ 411:7b3d4431610a

Improved support for creating error messages, even when no dictionary definition is present
author Sebastien Decugis <sdecugis@nict.go.jp>
date Thu, 11 Jun 2009 18:08:17 +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 routing module */

#include <peer-internal.h>

pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cnd = PTHREAD_COND_INITIALIZER;
_peer_t * peer = NULL;

int testnr = 0;

#define FR	0x1
#define FA	0x2
#define FL	0x4
#define ON	0x8
#define OL	0x10

static int cb_fwd_req(void * data, msg_t * msg)
{
	CHECK( 0, pthread_mutex_lock(&mtx) );
	*(int *)data |= FR;
	CHECK( 0, pthread_cond_signal(&cnd) );
	CHECK( 0, pthread_mutex_unlock(&mtx) );
	return 0;
}
static int cb_fwd_ans(void * data, msg_t * msg)
{
	CHECK( 0, pthread_mutex_lock(&mtx) );
	*(int *)data |= FA;
	CHECK( 0, pthread_cond_signal(&cnd) );
	CHECK( 0, pthread_mutex_unlock(&mtx) );
	return 0;
}
static int cb_fwd_all(void * data, msg_t * msg)
{
	CHECK( 0, pthread_mutex_lock(&mtx) );
	*(int *)data |= FL;
	CHECK( 0, pthread_cond_signal(&cnd) );
	CHECK( 0, pthread_mutex_unlock(&mtx) );
	return 0;
}
static int cb_out_norm(void * data, msg_t * msg, rt_dpl_t * list )
{
	CHECK( 0, pthread_mutex_lock(&mtx) );
	*(int *)data |= ON;
	CHECK( 0, pthread_cond_signal(&cnd) );
	CHECK( 0, pthread_mutex_unlock(&mtx) );
	return 0;
}
static int cb_out_late(void * data, msg_t * msg, rt_dpl_t * list )
{
	CHECK( 0, pthread_mutex_lock(&mtx) );
	*(int *)data |= OL;
	CHECK( 0, pthread_cond_signal(&cnd) );
	
	switch (testnr) {
		case 1:
			CHECK( 0, list->next == NULL ? 1 : 0 );
			break;
		
		case 2:
			CHECK( 1, list->next == NULL ? 1 : 0 );
			break;
	}
		
	
	list->score += 1; /* so that we can find the message */
	peer = (_peer_t *)(list->peer);
	
	CHECK( 0, pthread_mutex_unlock(&mtx) );
	return 0;
}



/* Main test routine */
int main(int argc, char *argv[])
{
	msg_t * msg = NULL;
	rt_fwd_hdl_t * req = NULL;
	rt_fwd_hdl_t * ans = NULL;
	rt_fwd_hdl_t * all = NULL;
	rt_out_hdl_t * norm = NULL;
	rt_out_hdl_t * late = NULL;
	int tmpval = 0;
	_peer_t * peer1 = NULL;
	_peer_t * peer2 = NULL;
	
	/* First, initialize the daemon modules */
	INIT_WAAAD();
	CONFIG_WAAAD();
	
	CHECK( 0, pthread_mutex_lock(&mtx) );
	
	/* Register rt callbacks */
	{
		CHECK( 0, rt_fwd_register( cb_fwd_req, &tmpval, RT_FWD_REQ, &req ) );
		CHECK( 0, rt_fwd_register( cb_fwd_ans, &tmpval, RT_FWD_ANS, &ans ) );
		CHECK( 0, rt_fwd_register( cb_fwd_all, &tmpval, RT_FWD_ALL, &all ) );
		CHECK( 0, rt_out_register( cb_out_norm, &tmpval, RT_OUT_NORMAL, &norm ) );
		CHECK( 0, rt_out_register( cb_out_late, &tmpval, RT_OUT_LATE, &late ) );
		
		/* Try unregister */
		CHECK( 0, rt_fwd_unregister ( ans ));
		CHECK( 0, rt_out_unregister ( late ));
		
		/* Register once again */
		CHECK( 0, rt_fwd_register( cb_fwd_ans, &tmpval, RT_FWD_ANS, &ans ) );
		CHECK( 0, rt_out_register( cb_out_late, &tmpval, RT_OUT_LATE, &late ) );
	}
	
	/* Check the CB were not called yet */
	CHECK( 0, tmpval);
	
	/* Create two peers in (false) OPEN state */
	{
		peer_add_t data;
		char * p1 = strdup("p1.localhost");
		char * p2 = strdup("p2.localhost");
		uti_list_t * l = NULL;
		
		memset(&data, 0, sizeof(data));
		
		data.pa_proto = IPPROTO_TCP;
		CHECK( 0, peer_add( p1, strlen(p1), &data ) );
		
#ifndef DISABLE_SCTP
		data.pa_proto = IPPROTO_SCTP;
#else /* DISABLE_SCTP */
		data.pa_proto = IPPROTO_TCP;
#endif /* DISABLE_SCTP */
		data.pa_streams = 20;
		CHECK( 0, peer_add( p2, strlen(p2), &data ) );
		
		/* Move the peers to OPEN state */
		CHECK( 0, _peer_struct_search(p1, 0, NULL, &l)  );
		peer1 = _P(l->o);
		CHECK( 0, pthread_mutex_unlock( &((_peer_hash_t *)(l->head))->lock )  );
		_psm_change_state( peer1, STATE_OPEN );
		
		CHECK( 0, _peer_struct_search(p2, 0, NULL, &l)  );
		peer2 = _P(l->o);
		CHECK( 0, pthread_mutex_unlock( &((_peer_hash_t *)(l->head))->lock )  );
		_psm_change_state( peer2, STATE_OPEN );
		
		CHECK( 2, peer_dump_hash(FULL) );
		free(p1);
		free(p2);
	}
	
	/* Create a message */
	{
		dict_object_t * model = NULL;
		msg_avp_t * avp = NULL;
		avp_value_t val;
		sess_id_t * session = NULL;

		/* Now find the dictionary objects */
		CHECK( 0, dict_search ( DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &model, ENOENT ) );

		/* Create the instance */
		CHECK( 0, msg_new ( model, MSGFL_ALLOW_ETEID, &msg ) );
		
		/* Add a new session id */
		CHECK( 0, sess_new( &session, SESSION_NEW_DEFAULT, __FILE__ ) );
		CHECK( 0, dict_search ( DICT_AVP, AVP_BY_NAME, "Session-Id", &model, ENOENT ) );
		CHECK( 0, msg_avp_new( model, 0, &avp ) );
		memset(&val, 0, sizeof(val));
		CHECK( 0, sess_getsid( session, (void *) &val.os.data ) );
		val.os.len = strlen((char *)val.os.data);
		CHECK( 0, msg_avp_setvalue( avp, &val ) );
		CHECK( 0, msg_avp_add( msg, MSG_BRW_FIRST_CHILD, avp ) );
		
		/* Add destination info */
		CHECK( 0, dict_search ( DICT_AVP, AVP_BY_NAME, "Destination-Realm", &model, ENOENT ) );
		CHECK( 0, msg_avp_new( model, 0, &avp ) );
		memset(&val, 0, sizeof(val));
		val.os.data = (unsigned char *)"otherrealm";
		val.os.len = 10;
		CHECK( 0, msg_avp_setvalue( avp, &val ) );
		CHECK( 0, msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );
		
		/* Add origin info */
		CHECK( 0, msg_add_origin( msg, 1 )  );
		
		/* Add record info */
		CHECK( 0, dict_search ( DICT_AVP, AVP_BY_NAME, "Accounting-Record-Type", &model, ENOENT ) );
		CHECK( 0, msg_avp_new( model, 0, &avp ) );
		memset(&val, 0, sizeof(val));
		val.i32 = 2;
		CHECK( 0, msg_avp_setvalue( avp, &val ) );
		CHECK( 0, msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );

		CHECK( 0, dict_search ( DICT_AVP, AVP_BY_NAME, "Accounting-Record-Number", &model, ENOENT ) );
		CHECK( 0, msg_avp_new( model, 0, &avp ) );
		memset(&val, 0, sizeof(val));
		val.u32 = 1;
		CHECK( 0, msg_avp_setvalue( avp, &val ) );
		CHECK( 0, msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );
		
		CHECK( 0, msg_parse_rules( msg, NULL ) );
		
		#if 1
		msg_dump_walk(INFO, msg);
		#endif
	}
	
	{
		testnr = 1;
		
		/* Set a timer in case something goes wrong */
		alarm(2);

		/* Now push the message as if it was just received */
		CHECK( 0, meq_post( g_meq_incoming, msg ) );

		/* Wait for all the expected cb to be called */
		do {
			CHECK( 0, pthread_cond_wait(&cnd, &mtx) );
		} while (tmpval != (ON | OL | FR | FL));

		/* Ok, get the message back from the peer */
		CHECK( 0, meq_get( peer->p_out_q, &msg ) );
		
		CHECK( (ON | OL | FR | FL), tmpval );
		tmpval = 0;
	}
	
	{
		testnr = 2;
		alarm(2);
		
		/* Now pretend the message was received from peer1 */
		CHECK( 0, msg_source_set( msg, peer1->p_diamid, peer1->p_hash, 1 ) );

		CHECK( 0, meq_post( g_meq_incoming, msg ) );

		/* Since the Route-Record is added, the list only contains 1 peer (checked in the cb) */
		do {
			CHECK( 0, pthread_cond_wait(&cnd, &mtx) );
		} while (tmpval != (ON | OL | FR | FL));
		
		/* Ok, get the message back from the peer */
		CHECK( 0, meq_get( peer->p_out_q, &msg ) );
		
		CHECK( (ON | OL | FR | FL), tmpval );
		tmpval = 0;
	}
	
	{
		testnr = 3;
		alarm(2);
		
		/* Now create an answer to that message */
		CHECK( 0, msg_new_answer_from_req( &msg, 0 ) );
		CHECK( 0, msg_rescode_set( msg, "DIAMETER_SUCCESS", NULL, NULL, 1 )  );
		
		/* Do as if we had received this answer; it must be forwarded to peer1 */
		CHECK( 0, meq_post( g_meq_incoming, msg ) );
		
		/* Ensure the FW callbacks registered for answers are called */
		do {
			CHECK( 0, pthread_cond_wait(&cnd, &mtx) );
		} while (tmpval != (FA | FL));
		
		/* Check the message is queued to the proper peer */
		CHECK( 0, meq_get( peer1->p_out_q, &msg ) );
		
		CHECK( (FA | FL), tmpval );
		tmpval = 0;
	}
	
	/* Ok, we may add new tests later, that's all for now... */
	
	/* cleanups */
	{
		CHECK( 0, pthread_mutex_unlock(&mtx) );
	
		CHECK( 0, msg_free(msg, 1) );
		
		CHECK( 0, rt_fwd_unregister ( req ));
		CHECK( 0, rt_fwd_unregister ( ans ));
		CHECK( 0, rt_fwd_unregister ( all ));
		CHECK( 0, rt_out_unregister ( norm ));
		CHECK( 0, rt_out_unregister ( late ));
	}
	
	/* That's all for the tests yet */
	PASSTEST();
} 
	
"Welcome to our mercurial repository"