Mercurial > hg > freeDiameter
changeset 5:c2d2729e3603
Completed new session module tests; some bugs fixed
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Thu, 03 Sep 2009 14:33:45 +0900 |
parents | 883311bf7df3 |
children | b0d377c79d80 |
files | freeDiameter/tests/testsess.c include/freeDiameter/libfreeDiameter.h libfreeDiameter/sessions.c |
diffstat | 3 files changed, 247 insertions(+), 46 deletions(-) [+] |
line wrap: on
line diff
--- a/freeDiameter/tests/testsess.c Wed Sep 02 18:28:27 2009 +0900 +++ b/freeDiameter/tests/testsess.c Thu Sep 03 14:33:45 2009 +0900 @@ -46,7 +46,7 @@ int * freed; /* location where to write the freed status */ }; -void mycleanup( char * sid, struct mystate * data ) +static void mycleanup( char * sid, struct mystate * data ) { /* sanity */ CHECK( 1, sid ? 1 : 0 ); @@ -60,6 +60,20 @@ free(data); } +static __inline__ struct mystate * new_state(char * sid, int *freed) +{ + struct mystate *new; + new = malloc(sizeof(struct mystate)); + CHECK( 1, new ? 1 : 0 ); + memset(new, 0, sizeof(struct mystate)); + new->eyec = TEST_EYEC; + new->sid = strdup(sid); + CHECK( 1, new->sid ? 1 : 0 ); + new->freed = freed; + return new; +} + + /* Main test routine */ int main(int argc, char *argv[]) { @@ -77,7 +91,7 @@ CHECK( 0, fd_sess_handler_create ( &hdl2, mycleanup ) ); CHECK( 0, fd_sess_handler_destroy( &hdl2 ) ); CHECK( 0, fd_sess_handler_create ( &hdl2, mycleanup ) ); - #if 1 + #if 0 fd_sess_dump_hdl(0, hdl1); fd_sess_dump_hdl(0, hdl2); #endif @@ -88,7 +102,7 @@ /* DiamId is provided, not opt */ CHECK( 0, fd_sess_new( &sess1, TEST_DIAM_ID, NULL, 0 ) ); CHECK( 0, fd_sess_new( &sess2, TEST_DIAM_ID, NULL, 0 ) ); - #if 1 + #if 0 fd_sess_dump(0, sess1); fd_sess_dump(0, sess2); #endif @@ -105,7 +119,7 @@ /* diamId and opt */ CHECK( 0, fd_sess_new( &sess1, TEST_DIAM_ID, TEST_OPT, 0 ) ); CHECK( 0, fd_sess_new( &sess2, TEST_DIAM_ID, TEST_OPT, strlen(TEST_OPT) - 1 ) ); - #if 1 + #if 0 fd_sess_dump(0, sess1); fd_sess_dump(0, sess2); #endif @@ -129,7 +143,7 @@ CHECK( EALREADY, fd_sess_new( &sess3, NULL, TEST_SID, strlen(TEST_SID) ) ); CHECK( sess3, sess1 ); CHECK( 0, fd_sess_new( &sess2, NULL, TEST_SID, strlen(TEST_SID) - 1 ) ); - #if 1 + #if 0 fd_sess_dump(0, sess1); fd_sess_dump(0, sess2); #endif @@ -139,18 +153,176 @@ CHECK( 0, strcmp( str1, TEST_SID ) ); CHECK( 0, fd_sess_destroy( &sess2 ) ); + CHECK( 0, fd_sess_destroy( &sess1 ) ); } + /* Test fd_sess_fromsid */ + { + CHECK( 0, fd_sess_fromsid( TEST_SID, strlen(TEST_SID), &sess1, &new ) ); + CHECK( 1, new ? 1 : 0 ); + CHECK( 0, fd_sess_fromsid( TEST_SID, strlen(TEST_SID), &sess2, &new ) ); + CHECK( 0, new ); + CHECK( sess1, sess2 ); + + CHECK( 0, fd_sess_fromsid( TEST_SID, strlen(TEST_SID), &sess3, NULL ) ); + CHECK( sess1, sess3 ); + + CHECK( 0, fd_sess_destroy( &sess1 ) ); + } + + /* Test timeout function */ + { + struct timespec timeout; + + CHECK( 0, fd_sess_fromsid( TEST_SID, strlen(TEST_SID), &sess1, &new ) ); + CHECK( 1, new ? 1 : 0 ); + + CHECK( 0, clock_gettime(CLOCK_REALTIME, &timeout) ); + CHECK( 0, fd_sess_settimeout( sess1, &timeout) ); + timeout.tv_sec = 0; + timeout.tv_nsec= 50000000; /* 50 ms */ + CHECK( 0, clock_nanosleep(CLOCK_REALTIME, 0, &timeout, NULL) ); + + CHECK( 0, fd_sess_fromsid( TEST_SID, strlen(TEST_SID), &sess1, &new ) ); + CHECK( 1, new ? 1 : 0 ); + + CHECK( 0, clock_gettime(CLOCK_REALTIME, &timeout) ); + timeout.tv_sec += 2678500; /* longer that SESS_DEFAULT_LIFETIME */ + CHECK( 0, fd_sess_settimeout( sess1, &timeout) ); + + /* Create a second session */ + CHECK( 0, fd_sess_new( &sess2, TEST_DIAM_ID, NULL, 0 ) ); + + /* We don't really have away to verify the expiry list is in proper order automatically here... */ + + CHECK( 0, fd_sess_destroy( &sess2 ) ); + CHECK( 0, fd_sess_destroy( &sess1 ) ); + } + -/* -int fd_sess_new ( struct session ** session, char * diamId, char * opt, size_t optlen ); -int fd_sess_fromsid ( char * sid, size_t len, struct session ** session, int * new); -int fd_sess_getsid ( struct session * session, char ** sid ); -int fd_sess_settimeout( struct session * session, const struct timespec * timeout ); -int fd_sess_destroy ( struct session ** session ); -*/ + /* Test states operations */ + { + struct mystate * ms[6], *tms; + int freed[6]; + int i; + struct timespec timeout; + + /* Create three sessions */ + CHECK( 0, fd_sess_new( &sess1, TEST_DIAM_ID, NULL, 0 ) ); + CHECK( 0, fd_sess_new( &sess2, TEST_DIAM_ID, NULL, 0 ) ); + CHECK( 0, fd_sess_new( &sess3, TEST_DIAM_ID, NULL, 0 ) ); + + /* Create 2 states */ + CHECK( 0, fd_sess_getsid(sess1, &str1) ); + freed[0] = 0; + ms[0] = new_state(str1, &freed[0]); + ms[1] = new_state(str1, NULL); + tms = ms[0]; /* save a copy */ + CHECK( 0, fd_sess_state_store ( hdl1, sess1, &ms[0] ) ); + CHECK( NULL, ms[0] ); + CHECK( EINVAL, fd_sess_state_store ( hdl1, sess1, NULL ) ); + CHECK( EALREADY, fd_sess_state_store ( hdl1, sess1, &ms[1] ) ); + CHECK( 1, ms[1] ? 1 : 0 ); + + #if 0 + fd_sess_dump(0, sess1); + #endif + + CHECK( 0, fd_sess_state_retrieve( hdl1, sess1, &ms[0] ) ); + CHECK( tms, ms[0] ); + CHECK( 0, freed[0] ); + + CHECK( 0, fd_sess_state_retrieve( hdl1, sess2, &tms ) ); + CHECK( NULL, tms ); + + mycleanup(str1, ms[0]); + mycleanup(str1, ms[1]); + + /* Now create 6 states */ + memset(&freed[0], 0, sizeof(freed)); + CHECK( 0, fd_sess_getsid(sess1, &str1) ); + ms[0] = new_state(str1, &freed[0]); + ms[1] = new_state(str1, &freed[1]); + CHECK( 0, fd_sess_getsid(sess2, &str1) ); + ms[2] = new_state(str1, &freed[2]); + ms[3] = new_state(str1, &freed[3]); + CHECK( 0, fd_sess_getsid(sess3, &str1) ); + ms[4] = new_state(str1, &freed[4]); + ms[5] = new_state(str1, &freed[5]); + str2 = strdup(str1); + CHECK( 1, str2 ? 1 : 0 ); + + /* Store the six states */ + CHECK( 0, fd_sess_state_store ( hdl1, sess1, &ms[0] ) ); + CHECK( 0, fd_sess_state_store ( hdl2, sess1, &ms[1] ) ); + CHECK( 0, fd_sess_state_store ( hdl1, sess2, &ms[2] ) ); + CHECK( 0, fd_sess_state_store ( hdl2, sess2, &ms[3] ) ); + CHECK( 0, fd_sess_state_store ( hdl1, sess3, &ms[4] ) ); + CHECK( 0, fd_sess_state_store ( hdl2, sess3, &ms[5] ) ); + + #if 0 + fd_sess_dump(0, sess1); + fd_sess_dump(0, sess2); + fd_sess_dump(0, sess3); + #endif + + /* Destroy session 3 */ + CHECK( 0, fd_sess_destroy( &sess3 ) ); + CHECK( 0, freed[0] ); + CHECK( 0, freed[1] ); + CHECK( 0, freed[2] ); + CHECK( 0, freed[3] ); + CHECK( 1, freed[4] ); + CHECK( 1, freed[5] ); + + /* Destroy handler 2 */ + CHECK( 0, fd_sess_handler_destroy( &hdl2 ) ); + CHECK( 0, freed[0] ); + CHECK( 1, freed[1] ); + CHECK( 0, freed[2] ); + CHECK( 1, freed[3] ); + CHECK( 1, freed[4] ); + CHECK( 1, freed[5] ); + + #if 1 + fd_sess_dump(0, sess1); + fd_sess_dump(0, sess2); + #endif + + /* Create again session 3, check that no data is associated to it */ + CHECK( 0, fd_sess_fromsid( str2, strlen(str2), &sess3, &new ) ); + CHECK( 1, new ? 1 : 0 ); + CHECK( 0, fd_sess_state_retrieve( hdl1, sess3, &tms ) ); + CHECK( NULL, tms ); + CHECK( 0, fd_sess_destroy( &sess3 ) ); + free(str2); + + /* Timeout does call cleanups */ + CHECK( 0, clock_gettime(CLOCK_REALTIME, &timeout) ); + CHECK( 0, fd_sess_settimeout( sess2, &timeout) ); + #if 1 + fd_sess_dump(0, sess1); + fd_sess_dump(0, sess2); + #endif + timeout.tv_sec = 0; + timeout.tv_nsec= 50000000; /* 50 ms */ + CHECK( 0, clock_nanosleep(CLOCK_REALTIME, 0, &timeout, NULL) ); + CHECK( 0, freed[0] ); + CHECK( 1, freed[1] ); + CHECK( 1, freed[2] ); + CHECK( 1, freed[3] ); + CHECK( 1, freed[4] ); + CHECK( 1, freed[5] ); + + /* Check the last data can still be retrieved */ + CHECK( 0, fd_sess_state_retrieve( hdl1, sess1, &tms ) ); + CHECK( 0, fd_sess_getsid(sess1, &str1) ); + mycleanup(str1, tms); + } + + /* That's all for the tests yet */ PASSTEST(); }
--- a/include/freeDiameter/libfreeDiameter.h Wed Sep 02 18:28:27 2009 +0900 +++ b/include/freeDiameter/libfreeDiameter.h Thu Sep 03 14:33:45 2009 +0900 @@ -364,7 +364,7 @@ /* Compare timespec structures */ #define TS_IS_INFERIOR( ts1, ts2 ) \ ( ((ts1)->tv_sec < (ts2)->tv_sec ) \ - || ((ts1)->tv_nsec < (ts2)->tv_nsec) ) + || (((ts1)->tv_sec == (ts2)->tv_sec ) && ((ts1)->tv_nsec < (ts2)->tv_nsec) )) /*============================================================*/ @@ -1458,7 +1458,9 @@ * EALREADY : Data was already associated with this session and client. * ENOMEM : Not enough memory to complete the operation */ -int fd_sess_state_store ( struct session_handler * handler, struct session * session, session_state ** state ); +int fd_sess_state_store_int ( struct session_handler * handler, struct session * session, session_state ** state ); +#define fd_sess_state_store( _handler, _session, _state ) \ + fd_sess_state_store_int( (_handler), (_session), (void *)(_state) ) /* * FUNCTION: fd_sess_state_retrieve @@ -1478,7 +1480,9 @@ * 0 : *state is updated (NULL or points to the state if it was found). * EINVAL : A parameter is invalid. */ -int fd_sess_state_retrieve ( struct session_handler * handler, struct session * session, session_state ** state ); +int fd_sess_state_retrieve_int ( struct session_handler * handler, struct session * session, session_state ** state ); +#define fd_sess_state_retrieve( _handler, _session, _state ) \ + fd_sess_state_retrieve_int( (_handler), (_session), (void *)(_state) ) /* For debug */
--- a/libfreeDiameter/sessions.c Wed Sep 02 18:28:27 2009 +0900 +++ b/libfreeDiameter/sessions.c Thu Sep 03 14:33:45 2009 +0900 @@ -295,12 +295,13 @@ /* The list is ordered */ if (st->hdl->id < del->id) continue; - if (st->hdl->id > del->id) - break; - /* This state belongs to the handler we are deleting, move the item to the deleted_states list */ - fd_list_unlink(&st->chain); - CHECK_MALLOC( st->sid = strdup(sess->sid) ); - fd_list_insert_before(&deleted_states, &st->chain); + if (st->hdl->id == del->id) { + /* This state belongs to the handler we are deleting, move the item to the deleted_states list */ + fd_list_unlink(&st->chain); + CHECK_MALLOC( st->sid = strdup(sess->sid) ); + fd_list_insert_before(&deleted_states, &st->chain); + } + break; } CHECK_POSIX( pthread_mutex_unlock(&sess->stlock) ); } @@ -399,9 +400,9 @@ break; } - /* If the session did not exist, we can add it into the hash table */ + /* If the session did not exist, we can link it in global tables */ if (!found) { - fd_list_insert_before(li, &sess->chain_h); + fd_list_insert_before(li, &sess->chain_h); /* hash table */ /* We must also insert in the expiry list */ CHECK_POSIX( pthread_mutex_lock( &exp_lock ) ); @@ -409,13 +410,21 @@ /* Find the position in that list. We take it in reverse order */ for (li = exp_sentinel.prev; li != &exp_sentinel; li = li->prev) { struct session * s = (struct session *)(li->o); - if (TS_IS_INFERIOR( &s->timeout, &sess->timeout ) ) break; - - continue; } fd_list_insert_after( li, &sess->expire ); + + #if 0 + if (TRACE_BOOL(ANNOYING)) { + TRACE_DEBUG(FULL, "-- Updated session expiry list --"); + for (li = exp_sentinel.next; li != &exp_sentinel; li = li->next) { + struct session * s = (struct session *)(li->o); + fd_sess_dump(FULL, s); + } + TRACE_DEBUG(FULL, "-- end of expiry list --"); + } + #endif /* We added a new expiring element, we must signal */ CHECK_POSIX( pthread_cond_signal(&exp_cond) ); @@ -502,6 +511,17 @@ /* We added a new expiring element, we must signal */ CHECK_POSIX( pthread_cond_signal(&exp_cond) ); + #if 0 + if (TRACE_BOOL(ANNOYING)) { + TRACE_DEBUG(FULL, "-- Updated session expiry list --"); + for (li = exp_sentinel.next; li != &exp_sentinel; li = li->next) { + struct session * s = (struct session *)(li->o); + fd_sess_dump(FULL, s); + } + TRACE_DEBUG(FULL, "-- end of expiry list --"); + } + #endif + /* We're done */ CHECK_POSIX( pthread_mutex_unlock( &exp_lock ) ); @@ -547,7 +567,7 @@ /* Save a state information with a session */ -int fd_sess_state_store ( struct session_handler * handler, struct session * session, session_state ** state ) +int fd_sess_state_store_int ( struct session_handler * handler, struct session * session, session_state ** state ) { struct state *new; struct fd_list * li; @@ -596,7 +616,7 @@ } /* Get the data back */ -int fd_sess_state_retrieve ( struct session_handler * handler, struct session * session, session_state ** state ) +int fd_sess_state_retrieve_int ( struct session_handler * handler, struct session * session, session_state ** state ) { struct fd_list * li; struct state * st = NULL; @@ -631,29 +651,34 @@ } - /* Dump functions */ void fd_sess_dump(int level, struct session * session) { struct fd_list * li; + char buf[30]; + struct tm tm; + if (!TRACE_BOOL(level)) return; - fd_log_debug("Session @%p:\n", session); + fd_log_debug("\t %*s -- Session @%p --\n", level, "", session); if (!VALIDATE_SI(session)) { - fd_log_debug(" Invalid session object\n"); - return; - } + fd_log_debug("\t %*s Invalid session object\n", level, ""); + } else { - fd_log_debug(" sid '%s', hash %x\n", session->sid, session->hash); - fd_log_debug(" timeout %d.%09d\n", session->timeout.tv_sec, session->timeout.tv_nsec); - - CHECK_POSIX_DO( pthread_mutex_lock(&session->stlock), /* ignore */ ); - for (li = session->states.next; li != &session->states; li = li->next) { - struct state * st = (struct state *)(li->o); - fd_log_debug(" handler %d registered data %p\n", st->hdl->id, st->state); + fd_log_debug("\t %*s sid '%s', hash %x\n", level, "", session->sid, session->hash); + + strftime(buf, sizeof(buf), "%D,%T", localtime_r( &session->timeout.tv_sec , &tm )); + fd_log_debug("\t %*s timeout %s.%09ld\n", level, "", buf, session->timeout.tv_nsec); + + CHECK_POSIX_DO( pthread_mutex_lock(&session->stlock), /* ignore */ ); + for (li = session->states.next; li != &session->states; li = li->next) { + struct state * st = (struct state *)(li->o); + fd_log_debug("\t %*s handler %d registered data %p\n", level, "", st->hdl->id, st->state); + } + CHECK_POSIX_DO( pthread_mutex_unlock(&session->stlock), /* ignore */ ); } - CHECK_POSIX_DO( pthread_mutex_unlock(&session->stlock), /* ignore */ ); + fd_log_debug("\t %*s -- end of session @%p --\n", level, "", session); } void fd_sess_dump_hdl(int level, struct session_handler * handler) @@ -661,11 +686,11 @@ if (!TRACE_BOOL(level)) return; - fd_log_debug("Handler @%p:\n", handler); + fd_log_debug("\t %*s -- Handler @%p --\n", level, "", handler); if (!VALIDATE_SH(handler)) { - fd_log_debug(" Invalid session handler object\n"); - return; + fd_log_debug("\t %*s Invalid session handler object\n", level, ""); + } else { + fd_log_debug("\t %*s id %d, cleanup %p\n", level, "", handler->id, handler->cleanup); } - - fd_log_debug(" id %d, cleanup %p\n", handler->id, handler->cleanup); + fd_log_debug("\t %*s -- end of handler @%p --\n", level, "", handler); }