Mercurial > hg > waaad
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(); }